Clean up revenue, AOV, brands & categories dialogs

This commit is contained in:
2024-12-23 14:14:16 -05:00
parent 8a8589e951
commit fd0e6d1789
2 changed files with 69 additions and 161 deletions

View File

@@ -1,19 +0,0 @@
{
"folders": [
{
"path": "."
}
],
"settings": {
"folder-color.pathColors": [
{
"folderPath": "Dev/dashboard/",
"badge": "🔵"
},
{
"folderPath": "Dev/dashboard-server/",
"badge": "🟣"
}
]
}
}

View File

@@ -159,7 +159,7 @@ const DetailDialog = ({
children
}) => (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-2xl max-h-[80vh] overflow-auto">
<DialogContent className="max-w-2xl max-h-[80vh] overflow-hidden">
<DialogHeader>
<DialogTitle>{title}</DialogTitle>
</DialogHeader>
@@ -180,54 +180,15 @@ const RevenueDetails = ({ data }) => {
date: DateTime.fromISO(day.timestamp).toFormat('LLL d')
})).sort((a, b) => DateTime.fromISO(a.timestamp) - DateTime.fromISO(b.timestamp));
// Calculate summary statistics
const totalRevenue = chartData.reduce((sum, day) => sum + day.revenue, 0);
const averageDailyRevenue = totalRevenue / chartData.length;
const maxRevenue = Math.max(...chartData.map(day => day.revenue));
const minRevenue = Math.min(...chartData.map(day => day.revenue));
return (
<div className="space-y-8">
<TimeSeriesChart
data={chartData}
dataKey="revenue"
name="Revenue"
color="hsl(142.1 76.2% 36.3%)"
valueFormatter={(value) => formatCurrency(value)}
height={400}
/>
<div className="grid grid-cols-2 gap-4">
<StatCard
title="Total Revenue"
value={formatCurrency(totalRevenue)}
description={`${chartData.length} days`}
colorClass="text-green-600 dark:text-green-400"
icon={DollarSign}
/>
<StatCard
title="Average Daily Revenue"
value={formatCurrency(averageDailyRevenue)}
description="per day"
colorClass="text-green-600 dark:text-green-400"
icon={TrendingUp}
/>
<StatCard
title="Highest Day"
value={formatCurrency(maxRevenue)}
description={chartData.find(d => d.revenue === maxRevenue)?.date}
colorClass="text-green-600 dark:text-green-400"
icon={ArrowUp}
/>
<StatCard
title="Lowest Day"
value={formatCurrency(minRevenue)}
description={chartData.find(d => d.revenue === minRevenue)?.date}
colorClass="text-green-600 dark:text-green-400"
icon={ArrowDown}
/>
</div>
</div>
<TimeSeriesChart
data={chartData}
dataKey="revenue"
name="Revenue"
color="hsl(142.1 76.2% 36.3%)"
valueFormatter={(value) => formatCurrency(value)}
height={400}
/>
);
};
@@ -300,31 +261,13 @@ const AverageOrderDetails = ({ data, orderCount }) => {
if (!data?.length) return <div className="text-muted-foreground">No data available for the selected time range.</div>;
return (
<>
<TimeSeriesChart
data={data}
dataKey="averageOrderValue"
name="Average Order Value"
color="hsl(262.1 83.3% 57.8%)"
valueFormatter={(value) => formatCurrency(value)}
/>
<div className="mt-8">
<StatGrid
stats={[
{
label: "Average Items per Order",
value: data[0]?.averageItemsPerOrder?.toFixed(1) || "0",
description: "items"
},
{
label: "Total Orders",
value: orderCount?.toLocaleString() || "0",
description: "orders"
}
]}
/>
</div>
</>
<TimeSeriesChart
data={data}
dataKey="averageOrderValue"
name="Average Order Value"
color="hsl(262.1 83.3% 57.8%)"
valueFormatter={(value) => formatCurrency(value)}
/>
);
};
@@ -419,81 +362,65 @@ const CancellationsDetails = ({ data }) => {
const BrandsCategoriesDetails = ({ data }) => {
if (!data?.length) return <div className="text-muted-foreground">No data available for the selected time range.</div>;
const brandData = data[0]?.brands?.list?.map(brand => ({
name: brand.name,
count: brand.count,
revenue: brand.revenue,
percentage: (brand.count / data[0]?.itemCount * 100) || 0
}))?.sort((a, b) => b.count - a.count) || [];
const categoryData = data[0]?.categories?.list?.map(category => ({
name: category.name,
count: category.count,
revenue: category.revenue,
percentage: (category.count / data[0]?.itemCount * 100) || 0
}))?.sort((a, b) => b.count - a.count) || [];
if (!brandData.length && !categoryData.length) {
return <div className="text-muted-foreground">No brands or categories data available.</div>;
}
const stats = data[0];
const brandsList = stats?.brands?.list || [];
const categoriesList = stats?.categories?.list || [];
return (
<div className="space-y-8">
{brandData.length > 0 && (
<div>
<h3 className="text-lg font-medium mb-4">All Brands</h3>
<div className="rounded-lg border bg-card max-h-[400px] overflow-auto">
<Table>
<TableHeader className="sticky top-0 bg-background z-10">
<TableRow>
<TableHead>Brand</TableHead>
<TableHead className="text-right">Items</TableHead>
<TableHead className="text-right">Revenue</TableHead>
<TableHead className="text-right">% of Total</TableHead>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
<div className="flex flex-col h-[30vh] sm:h-[60vh]">
<h3 className="text-md font-medium mb-4 flex items-center gap-2">
<Star className="h-5 w-5 text-yellow-500" />
Brands ({stats?.brands?.total || 0})
</h3>
<div className="rounded-md border overflow-auto">
<Table>
<TableHeader className="sticky top-0 bg-background z-10">
<TableRow>
<TableHead>Brand</TableHead>
<TableHead className="text-right">Items</TableHead>
<TableHead className="text-right">Revenue</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{brandsList.map((brand) => (
<TableRow key={brand.name}>
<TableCell className="font-medium">{brand.name}</TableCell>
<TableCell className="text-right">{brand.count?.toLocaleString()}</TableCell>
<TableCell className="text-right">${brand.revenue?.toFixed(2)}</TableCell>
</TableRow>
</TableHeader>
<TableBody>
{brandData.map((brand, index) => (
<TableRow key={index}>
<TableCell className="font-medium">{brand.name}</TableCell>
<TableCell className="text-right">{brand.count.toLocaleString()}</TableCell>
<TableCell className="text-right">{formatCurrency(brand.revenue)}</TableCell>
<TableCell className="text-right">{brand.percentage.toFixed(1)}%</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
))}
</TableBody>
</Table>
</div>
)}
{categoryData.length > 0 && (
<div>
<h3 className="text-lg font-medium mb-4">All Categories</h3>
<div className="rounded-lg border bg-card max-h-[400px] overflow-auto">
<Table>
<TableHeader className="sticky top-0 bg-background z-10">
<TableRow>
<TableHead>Category</TableHead>
<TableHead className="text-right">Items</TableHead>
<TableHead className="text-right">Revenue</TableHead>
<TableHead className="text-right">% of Total</TableHead>
</div>
<div className="flex flex-col h-[30vh] md:h-[60vh]">
<h3 className="text-md font-medium mb-4 flex items-center gap-2">
<Tags className="h-5 w-5 text-indigo-500" />
Categories ({stats?.categories?.total || 0})
</h3>
<div className="rounded-md border overflow-auto">
<Table>
<TableHeader className="sticky top-0 bg-background z-10">
<TableRow>
<TableHead>Category</TableHead>
<TableHead className="text-right">Items</TableHead>
<TableHead className="text-right">Revenue</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{categoriesList.map((category) => (
<TableRow key={category.name}>
<TableCell className="font-medium">{category.name}</TableCell>
<TableCell className="text-right">{category.count?.toLocaleString()}</TableCell>
<TableCell className="text-right">${category.revenue?.toFixed(2)}</TableCell>
</TableRow>
</TableHeader>
<TableBody>
{categoryData.map((category, index) => (
<TableRow key={index}>
<TableCell className="font-medium">{category.name}</TableCell>
<TableCell className="text-right">{category.count.toLocaleString()}</TableCell>
<TableCell className="text-right">{formatCurrency(category.revenue)}</TableCell>
<TableCell className="text-right">{category.percentage.toFixed(1)}%</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
))}
</TableBody>
</Table>
</div>
)}
</div>
</div>
);
};