Update loading states

This commit is contained in:
2025-01-02 17:08:57 -05:00
parent 375ef6860b
commit 08ddba358a

View File

@@ -62,43 +62,73 @@ import {
// Mini skeleton components
const MiniSkeletonChart = ({ type = "line" }) => (
<div className="h-[200px] w-full bg-white dark:bg-gray-900/60 backdrop-blur-sm rounded-lg p-4">
<div className={`h-[230px] w-full ${
type === 'revenue' ? 'bg-emerald-50/10' :
type === 'orders' ? 'bg-blue-50/10' :
type === 'average_order' ? 'bg-violet-50/10' :
'bg-orange-50/10'
} rounded-lg p-4`}>
<div className="h-full relative">
{/* Grid lines */}
{[...Array(5)].map((_, i) => (
<div
key={i}
className="absolute w-full h-px bg-muted"
className={`absolute w-full h-px ${
type === 'revenue' ? 'bg-emerald-200/20' :
type === 'orders' ? 'bg-blue-200/20' :
type === 'average_order' ? 'bg-violet-200/20' :
'bg-orange-200/20'
}`}
style={{ top: `${(i + 1) * 20}%` }}
/>
))}
{/* Y-axis labels */}
<div className="absolute left-0 top-0 bottom-0 w-6 flex flex-col justify-between py-2">
<div className="absolute left-0 top-0 bottom-0 w-8 flex flex-col justify-between py-4">
{[...Array(5)].map((_, i) => (
<Skeleton key={i} className="h-2 w-4 bg-muted rounded-sm" />
<Skeleton key={i} className={`h-3 w-6 ${
type === 'revenue' ? 'bg-emerald-200/20' :
type === 'orders' ? 'bg-blue-200/20' :
type === 'average_order' ? 'bg-violet-200/20' :
'bg-orange-200/20'
} rounded-sm`} />
))}
</div>
{/* X-axis labels */}
<div className="absolute left-6 right-2 bottom-0 flex justify-between">
<div className="absolute left-8 right-4 bottom-0 flex justify-between">
{[...Array(6)].map((_, i) => (
<Skeleton key={i} className="h-2 w-6 bg-muted rounded-sm" />
<Skeleton key={i} className={`h-3 w-8 ${
type === 'revenue' ? 'bg-emerald-200/20' :
type === 'orders' ? 'bg-blue-200/20' :
type === 'average_order' ? 'bg-violet-200/20' :
'bg-orange-200/20'
} rounded-sm`} />
))}
</div>
{type === "bar" ? (
<div className="absolute inset-x-6 bottom-4 top-2 flex items-end justify-between gap-1">
<div className="absolute inset-x-8 bottom-6 top-4 flex items-end justify-between gap-1">
{[...Array(24)].map((_, i) => (
<div
key={i}
className="w-1 bg-muted rounded-sm"
className={`w-2 ${
type === 'revenue' ? 'bg-emerald-200/20' :
type === 'orders' ? 'bg-blue-200/20' :
type === 'average_order' ? 'bg-violet-200/20' :
'bg-orange-200/20'
} rounded-sm`}
style={{ height: `${Math.random() * 80 + 10}%` }}
/>
))}
</div>
) : (
<div className="absolute inset-x-6 bottom-4 top-2">
<div className="absolute inset-x-8 bottom-6 top-4">
<div className="h-full w-full relative">
<div
className="absolute inset-0 bg-muted rounded-sm"
className={`absolute inset-0 ${
type === 'revenue' ? 'bg-emerald-200/20' :
type === 'orders' ? 'bg-blue-200/20' :
type === 'average_order' ? 'bg-violet-200/20' :
'bg-orange-200/20'
} rounded-sm`}
style={{
opacity: 0.5,
clipPath: "polygon(0 50%, 100% 20%, 100% 100%, 0 100%)",
@@ -111,33 +141,68 @@ const MiniSkeletonChart = ({ type = "line" }) => (
</div>
);
const MiniSkeletonTable = ({ rows = 8 }) => (
<div className="rounded-lg border bg-white dark:bg-gray-900/60 backdrop-blur-sm">
const MiniSkeletonTable = ({ rows = 8, colorScheme = "orange" }) => (
<div className={`rounded-lg border ${
colorScheme === 'orange' ? 'bg-orange-50/10 border-orange-200/20' :
colorScheme === 'emerald' ? 'bg-emerald-50/10 border-emerald-200/20' :
colorScheme === 'blue' ? 'bg-blue-50/10 border-blue-200/20' :
'bg-violet-50/10 border-violet-200/20'
}`}>
<Table>
<TableHeader>
<TableRow className="dark:border-gray-800">
<TableRow>
<TableHead>
<Skeleton className="h-3 w-24 bg-muted rounded-sm" />
<Skeleton className={`h-4 w-32 ${
colorScheme === 'orange' ? 'bg-orange-200/20' :
colorScheme === 'emerald' ? 'bg-emerald-200/20' :
colorScheme === 'blue' ? 'bg-blue-200/20' :
'bg-violet-200/20'
} rounded-sm`} />
</TableHead>
<TableHead className="text-right">
<Skeleton className="h-3 w-16 ml-auto bg-muted rounded-sm" />
<Skeleton className={`h-4 w-24 ml-auto ${
colorScheme === 'orange' ? 'bg-orange-200/20' :
colorScheme === 'emerald' ? 'bg-emerald-200/20' :
colorScheme === 'blue' ? 'bg-blue-200/20' :
'bg-violet-200/20'
} rounded-sm`} />
</TableHead>
<TableHead className="text-right">
<Skeleton className="h-3 w-16 ml-auto bg-muted rounded-sm" />
<Skeleton className={`h-4 w-24 ml-auto ${
colorScheme === 'orange' ? 'bg-orange-200/20' :
colorScheme === 'emerald' ? 'bg-emerald-200/20' :
colorScheme === 'blue' ? 'bg-blue-200/20' :
'bg-violet-200/20'
} rounded-sm`} />
</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{[...Array(rows)].map((_, i) => (
<TableRow key={i} className="dark:border-gray-800">
<TableRow key={i}>
<TableCell>
<Skeleton className="h-3 w-32 bg-muted rounded-sm" />
<Skeleton className={`h-4 w-48 ${
colorScheme === 'orange' ? 'bg-orange-200/20' :
colorScheme === 'emerald' ? 'bg-emerald-200/20' :
colorScheme === 'blue' ? 'bg-blue-200/20' :
'bg-violet-200/20'
} rounded-sm`} />
</TableCell>
<TableCell className="text-right">
<Skeleton className="h-3 w-12 ml-auto bg-muted rounded-sm" />
<Skeleton className={`h-4 w-16 ml-auto ${
colorScheme === 'orange' ? 'bg-orange-200/20' :
colorScheme === 'emerald' ? 'bg-emerald-200/20' :
colorScheme === 'blue' ? 'bg-blue-200/20' :
'bg-violet-200/20'
} rounded-sm`} />
</TableCell>
<TableCell className="text-right">
<Skeleton className="h-3 w-12 ml-auto bg-muted rounded-sm" />
<Skeleton className={`h-4 w-16 ml-auto ${
colorScheme === 'orange' ? 'bg-orange-200/20' :
colorScheme === 'emerald' ? 'bg-emerald-200/20' :
colorScheme === 'blue' ? 'bg-blue-200/20' :
'bg-violet-200/20'
} rounded-sm`} />
</TableCell>
</TableRow>
))}
@@ -465,7 +530,9 @@ const MiniStatCards = ({
<div className="flex items-center gap-1">
<span>Proj: </span>
{projectionLoading ? (
<Skeleton className="h-4 w-15" />
<div className="w-20">
<Skeleton className="h-4 w-15 bg-emerald-700" />
</div>
) : (
formatCurrency(
projection?.projectedRevenue || stats.projectedRevenue
@@ -476,7 +543,16 @@ const MiniStatCards = ({
}
progress={stats?.periodProgress < 100 ? stats.periodProgress : undefined}
trend={projectionLoading && stats?.periodProgress < 100 ? undefined : revenueTrend?.trend}
trendValue={revenueTrend?.value ? formatPercentage(revenueTrend.value) : null}
trendValue={
projectionLoading && stats?.periodProgress < 100 ? (
<div className="flex items-center gap-1">
<Skeleton className="h-4 w-4 bg-emerald-700 rounded-full" />
<Skeleton className="h-4 w-8 bg-emerald-700" />
</div>
) : revenueTrend?.value ? (
formatPercentage(revenueTrend.value)
) : null
}
colorClass="text-emerald-200"
titleClass="text-emerald-100 font-bold text-md"
descriptionClass="text-emerald-200 text-md font-semibold"
@@ -576,11 +652,20 @@ const MiniStatCards = ({
{detailDataLoading[selectedMetric] ? (
<div className="space-y-4 h-full">
{selectedMetric === "shipping" ? (
<MiniSkeletonTable rows={8} />
<MiniSkeletonTable
rows={8}
colorScheme={
selectedMetric === 'revenue' ? 'emerald' :
selectedMetric === 'orders' ? 'blue' :
selectedMetric === 'average_order' ? 'violet' :
'orange'
}
/>
) : (
<>
<MiniSkeletonChart
type={selectedMetric === "orders" ? "bar" : "line"}
metric={selectedMetric}
/>
{selectedMetric === "orders" && (
<div className="mt-8">
@@ -593,7 +678,7 @@ const MiniStatCards = ({
}`}>
Hourly Distribution
</h3>
<MiniSkeletonChart type="bar" />
<MiniSkeletonChart type="bar" metric={selectedMetric} />
</div>
)}
</>