Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,064 changes: 1,058 additions & 6 deletions RestroHub-FrontEnd/package-lock.json

Large diffs are not rendered by default.

282 changes: 282 additions & 0 deletions RestroHub-FrontEnd/src/components/admin/AdminSkeleton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
import { RefreshCw } from 'lucide-react';

const AdminSkeleton = ({ variant = 'order' }) => {
switch (variant) {

// ============================================
// ORDER SKELETON
// ============================================
case 'order':
return (
<div className="flex items-center justify-between p-4 bg-gray-50 rounded-xl animate-pulse">
<div className="flex items-center gap-4">
<div className="w-12 h-12 bg-gray-200 rounded-xl" />

<div>
<div className="w-32 h-4 bg-gray-200 rounded mb-2" />
<div className="w-48 h-3 bg-gray-200 rounded" />
</div>
</div>

<div className="w-16 h-5 bg-gray-200 rounded" />
</div>
);

// ============================================
// STATS CARD SKELETON
// ============================================
case 'stats':
return (
<div className="bg-white rounded-2xl p-6 shadow-sm border border-gray-100 animate-pulse">
<div className="flex items-center justify-between mb-4">
<div className="w-12 h-12 rounded-xl bg-gray-200" />
<div className="w-16 h-5 rounded bg-gray-200" />
</div>

<div className="w-24 h-4 rounded bg-gray-200 mb-2" />
<div className="w-32 h-7 rounded bg-gray-200" />
</div>
);

// ============================================
// CHART SKELETON
// ============================================
case 'chart':
return (
<div className="w-full h-full bg-gray-100 rounded-xl animate-pulse flex items-center justify-center">
<RefreshCw className="w-8 h-8 text-gray-300 animate-spin" />
</div>
);

case 'category':
return (
<div className="space-y-2">
{[1, 2, 3, 4].map(i => (
<div
key={i}
className="h-12 bg-gray-100 rounded-xl animate-pulse"
/>
))}
</div>
);

case 'food-card':
return (
<div
className="
bg-white rounded-2xl shadow-sm border border-gray-100 animate-pulse
p-4
sm:flex sm:gap-4 sm:p-4
lg:flex-col lg:p-5
"
>
<div
className="
bg-gray-100 rounded-xl
w-full h-36 mb-3
sm:w-32 sm:h-32 sm:min-w-[8rem] sm:mb-0
lg:w-full lg:h-36 lg:mb-4
"
/>

<div className="flex-1">
<div className="w-32 h-5 bg-gray-100 rounded mb-2" />
<div className="w-20 h-6 bg-gray-100 rounded mb-3 sm:mb-2 lg:mb-4" />

<div className="flex justify-between mb-3 sm:mb-2 lg:mb-4">
<div className="w-24 h-4 bg-gray-100 rounded" />
<div className="w-16 h-5 bg-gray-100 rounded-full" />
</div>

<div className="flex gap-2">
<div className="flex-1 h-9 sm:h-8 lg:h-9 bg-gray-100 rounded-xl" />
<div className="flex-1 h-9 sm:h-8 lg:h-9 bg-gray-100 rounded-xl" />
<div className="w-9 sm:w-8 lg:w-9 h-9 sm:h-8 lg:h-9 bg-gray-100 rounded-xl" />
</div>
</div>
</div>
);

case 'menu-card':
return (
<div className="bg-white rounded-2xl shadow-sm border border-gray-100 overflow-hidden animate-pulse">
<div className="h-2 bg-gray-100" />

<div className="p-6">
<div className="flex items-start justify-between mb-4">
<div className="flex items-center gap-3">
<div className="w-12 h-12 bg-gray-100 rounded-2xl" />

<div>
<div className="w-40 h-5 bg-gray-100 rounded-lg mb-2" />
<div className="w-28 h-4 bg-gray-100 rounded-lg" />
</div>
</div>

<div className="w-20 h-7 bg-gray-100 rounded-full" />
</div>

<div className="w-full h-4 bg-gray-100 rounded mb-2" />
<div className="w-2/3 h-4 bg-gray-100 rounded mb-5" />

<div className="flex gap-2 mb-5">
<div className="w-20 h-7 bg-gray-100 rounded-full" />
<div className="w-24 h-7 bg-gray-100 rounded-full" />
<div className="w-16 h-7 bg-gray-100 rounded-full" />
</div>

<div className="flex gap-2 pt-4 border-t border-gray-100">
<div className="flex-1 h-10 bg-gray-100 rounded-xl" />
<div className="flex-1 h-10 bg-gray-100 rounded-xl" />
<div className="w-10 h-10 bg-gray-100 rounded-xl" />
</div>
</div>
</div>
);

case 'order-card':
return (
<div className="bg-white rounded-2xl p-5 shadow-sm border border-gray-100 animate-pulse">
<div className="flex items-start justify-between mb-4">
<div className="flex items-center gap-3">
<div className="w-12 h-12 bg-gray-100 rounded-xl" />

<div>
<div className="w-28 h-5 bg-gray-100 rounded mb-1" />
<div className="w-20 h-3 bg-gray-100 rounded" />
</div>
</div>

<div className="w-8 h-8 bg-gray-100 rounded-lg" />
</div>

<div className="p-3 bg-gray-50 rounded-xl mb-4">
<div className="flex items-center gap-3">
<div className="w-8 h-8 bg-gray-100 rounded-full" />

<div>
<div className="w-24 h-4 bg-gray-100 rounded mb-1" />
<div className="w-20 h-3 bg-gray-100 rounded" />
</div>
</div>
</div>

<div className="space-y-2 mb-4">
<div className="flex justify-between">
<div className="w-32 h-4 bg-gray-100 rounded" />
<div className="w-12 h-4 bg-gray-100 rounded" />
</div>

<div className="flex justify-between">
<div className="w-24 h-4 bg-gray-100 rounded" />
<div className="w-12 h-4 bg-gray-100 rounded" />
</div>

<div className="flex justify-between pt-2 border-t">
<div className="w-16 h-5 bg-gray-100 rounded" />
<div className="w-16 h-6 bg-gray-100 rounded" />
</div>
</div>

<div className="w-full h-10 bg-gray-100 rounded-xl" />
</div>
);

case 'branch':
return (
<div className="overflow-hidden rounded-2xl border border-gray-200 bg-white">
{/* Header skeleton */}
<div className="border-b border-gray-100 px-4 py-4 sm:px-6 sm:py-5 animate-pulse">
<div className="flex items-start gap-3">
<div className="h-10 w-10 shrink-0 rounded-xl bg-gray-100 sm:h-12 sm:w-12" />

<div className="flex-1">
<div className="h-5 w-32 rounded bg-gray-100 mb-2" />
<div className="h-4 w-16 rounded-full bg-gray-100" />
</div>
</div>
</div>

{/* Body skeleton */}
<div className="px-4 py-4 sm:px-6 sm:py-5 animate-pulse">
<div className="space-y-3">
{[1, 2, 3, 4].map((i) => (
<div key={i} className="flex items-center gap-3">
<div className="h-4 w-4 rounded bg-gray-100" />
<div className="h-4 w-44 rounded bg-gray-100" />
</div>
))}
</div>
</div>

{/* Footer skeleton */}
<div className="border-t border-gray-100 px-4 py-3 sm:px-6 sm:py-4 animate-pulse">
<div className="flex items-center gap-2">
<div className="h-10 flex-1 rounded-lg bg-gray-100" />
<div className="h-10 w-10 rounded-lg bg-gray-100" />
<div className="h-10 w-10 rounded-lg bg-gray-100" />
</div>
</div>
</div>
);

case 'table':
return (
<div className="overflow-hidden rounded-2xl border-2 border-gray-200 bg-white animate-pulse">
<div className="px-4 py-5 text-center">
<div className="mx-auto mb-2 h-14 w-14 rounded-xl bg-gray-100" />
<div className="mx-auto mb-1 h-4 w-14 rounded bg-gray-100" />
<div className="mx-auto mb-2 h-3 w-12 rounded bg-gray-100" />
<div className="mx-auto h-5 w-16 rounded-full bg-gray-100" />
</div>

<div className="flex justify-center gap-2 border-t border-gray-100 px-3 py-3">
<div className="h-8 w-8 rounded-lg bg-gray-100" />
<div className="h-8 w-8 rounded-lg bg-gray-100" />
<div className="h-8 w-8 rounded-lg bg-gray-100" />
</div>
</div>
);

case 'upi':
return (
<div className="overflow-hidden rounded-2xl border border-gray-200 bg-white animate-pulse">
{/* Header */}
<div className="border-b border-gray-100 px-4 py-4 sm:px-6 sm:py-5">
<div className="flex items-start gap-3">
<div className="h-10 w-10 shrink-0 rounded-xl bg-gray-100 sm:h-12 sm:w-12" />

<div className="flex-1">
<div className="mb-2 h-5 w-32 rounded bg-gray-100" />
<div className="h-4 w-40 rounded bg-gray-100" />
</div>

<div className="h-9 w-9 rounded-lg bg-gray-100" />
</div>
</div>

{/* Body */}
<div className="px-4 py-4 sm:px-6 sm:py-5">
<div className="grid grid-cols-2 gap-3">
<div className="h-20 rounded-xl bg-gray-100" />
<div className="h-20 rounded-xl bg-gray-100" />
</div>
</div>

{/* Footer */}
<div className="border-t border-gray-100 px-4 py-3 sm:px-6 sm:py-4">
<div className="flex gap-2">
<div className="h-10 flex-1 rounded-lg bg-gray-100" />
<div className="h-10 flex-1 rounded-lg bg-gray-100" />
<div className="h-10 w-10 rounded-lg bg-gray-100" />
</div>
</div>
</div>
);

Comment on lines +223 to +276
default:
return null;
}
};

export default AdminSkeleton;
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
AlertCircle
} from 'lucide-react';
import api from "@services/common/api";
import AdminSkeleton from '../../AdminSkeleton';
import { useAdminTheme } from '@context/AdminThemeContext';

// ============================================
Expand Down Expand Up @@ -54,25 +55,6 @@ const OrderCard = ({ order }) => {
);
};

// ============================================
// SKELETON (Private to this file)
// ============================================
const OrderSkeleton = () => {
const { isDark } = useAdminTheme();
return (
<div className={`flex items-center justify-between p-4 rounded-xl animate-pulse ${isDark ? 'bg-gray-700/50' : 'bg-gray-50'}`}>
<div className="flex items-center gap-4">
<div className={`w-12 h-12 rounded-xl ${isDark ? 'bg-gray-700' : 'bg-gray-200'}`} />
<div>
<div className={`w-32 h-4 rounded mb-2 ${isDark ? 'bg-gray-700' : 'bg-gray-200'}`} />
<div className={`w-48 h-3 rounded ${isDark ? 'bg-gray-700' : 'bg-gray-200'}`} />
</div>
</div>
<div className={`w-16 h-5 rounded ${isDark ? 'bg-gray-700' : 'bg-gray-200'}`} />
</div>
);
};

// ============================================
// MAIN COMPONENT (Exported)
// ============================================
Expand Down Expand Up @@ -158,8 +140,10 @@ const LiveOrders = () => {
{/* Content */}
<div className="space-y-4">
{loading ? (
[1, 2, 3, 4].map(i => <OrderSkeleton key={i} />)
) : error && orders.length === 0 ? (
[1, 2, 3, 4].map(i => (
<AdminSkeleton key={i} variant="order" />))
) : error && orders.length === 0 ? (
// Error State
<div className="text-center py-8">
<AlertCircle className="w-12 h-12 text-red-300 mx-auto mb-3" />
<p className="text-red-500 mb-2">{error}</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
ResponsiveContainer
} from 'recharts';
import api from "@services/common/api";
import AdminSkeleton from '../../AdminSkeleton';
import { useAdminTheme } from '@context/AdminThemeContext';

// ============================================
Expand Down Expand Up @@ -83,9 +84,8 @@ const RevenueChart = () => {
{/* Chart */}
<div className="h-64">
{loading ? (
<div className={`w-full h-full rounded-xl animate-pulse flex items-center justify-center ${isDark ? 'bg-gray-700' : 'bg-gray-100'}`}>
<RefreshCw className={`w-8 h-8 animate-spin ${isDark ? 'text-gray-600' : 'text-gray-300'}`} />
</div>
// Skeleton
<AdminSkeleton variant="chart" />
) : error && data.length === 0 ? (
<div className="w-full h-full flex flex-col items-center justify-center">
<AlertCircle className="w-10 h-10 text-red-300 mb-2" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
TrendingDown
} from 'lucide-react';
import api from "@services/common/api";
import AdminSkeleton from '../../AdminSkeleton';
import { useAdminTheme } from '@context/AdminThemeContext';

// ============================================
Expand Down Expand Up @@ -181,7 +182,7 @@ const StatsSection = () => {
return (
<div className="grid grid-cols-1 gap-5 sm:grid-cols-2 xl:grid-cols-4">
{[1, 2, 3, 4].map(i => (
<StatCardSkeleton key={i} />
<AdminSkeleton key={i} variant="stats" />
))}
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
import { useState, useEffect } from 'react';
import { ChevronRight, RefreshCw, FolderPlus } from 'lucide-react';
import api from "@services/common/api";

// ============================================
// SKELETON (Private)
// ============================================
const CategorySkeleton = () => (
<div className="space-y-2">
{[1, 2, 3, 4].map(i => (
<div key={i} className="h-12 bg-gray-100 rounded-xl animate-pulse" />
))}
</div>
);
import AdminSkeleton from '../../AdminSkeleton';

// ============================================
// MAIN COMPONENT
Expand Down Expand Up @@ -78,7 +68,7 @@ const CategorySidebar = ({ selectedCategory, onCategoryChange, onAddCategory, se

{/* Categories List */}
{loading ? (
<CategorySkeleton />
<AdminSkeleton variant="category" />
) : (
<div className="space-y-2">
{categories.map((cat) => (
Expand Down
Loading