Clean up revenue, AOV, brands & categories dialogs
This commit is contained in:
@@ -1,19 +0,0 @@
|
|||||||
{
|
|
||||||
"folders": [
|
|
||||||
{
|
|
||||||
"path": "."
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"settings": {
|
|
||||||
"folder-color.pathColors": [
|
|
||||||
{
|
|
||||||
"folderPath": "Dev/dashboard/",
|
|
||||||
"badge": "🔵"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"folderPath": "Dev/dashboard-server/",
|
|
||||||
"badge": "🟣"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -159,7 +159,7 @@ const DetailDialog = ({
|
|||||||
children
|
children
|
||||||
}) => (
|
}) => (
|
||||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
<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>
|
<DialogHeader>
|
||||||
<DialogTitle>{title}</DialogTitle>
|
<DialogTitle>{title}</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
@@ -180,14 +180,7 @@ const RevenueDetails = ({ data }) => {
|
|||||||
date: DateTime.fromISO(day.timestamp).toFormat('LLL d')
|
date: DateTime.fromISO(day.timestamp).toFormat('LLL d')
|
||||||
})).sort((a, b) => DateTime.fromISO(a.timestamp) - DateTime.fromISO(b.timestamp));
|
})).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 (
|
return (
|
||||||
<div className="space-y-8">
|
|
||||||
<TimeSeriesChart
|
<TimeSeriesChart
|
||||||
data={chartData}
|
data={chartData}
|
||||||
dataKey="revenue"
|
dataKey="revenue"
|
||||||
@@ -196,38 +189,6 @@ const RevenueDetails = ({ data }) => {
|
|||||||
valueFormatter={(value) => formatCurrency(value)}
|
valueFormatter={(value) => formatCurrency(value)}
|
||||||
height={400}
|
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>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -300,7 +261,6 @@ const AverageOrderDetails = ({ data, orderCount }) => {
|
|||||||
if (!data?.length) return <div className="text-muted-foreground">No data available for the selected time range.</div>;
|
if (!data?.length) return <div className="text-muted-foreground">No data available for the selected time range.</div>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
|
||||||
<TimeSeriesChart
|
<TimeSeriesChart
|
||||||
data={data}
|
data={data}
|
||||||
dataKey="averageOrderValue"
|
dataKey="averageOrderValue"
|
||||||
@@ -308,23 +268,6 @@ const AverageOrderDetails = ({ data, orderCount }) => {
|
|||||||
color="hsl(262.1 83.3% 57.8%)"
|
color="hsl(262.1 83.3% 57.8%)"
|
||||||
valueFormatter={(value) => formatCurrency(value)}
|
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>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -419,81 +362,65 @@ const CancellationsDetails = ({ data }) => {
|
|||||||
const BrandsCategoriesDetails = ({ data }) => {
|
const BrandsCategoriesDetails = ({ data }) => {
|
||||||
if (!data?.length) return <div className="text-muted-foreground">No data available for the selected time range.</div>;
|
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 => ({
|
const stats = data[0];
|
||||||
name: brand.name,
|
const brandsList = stats?.brands?.list || [];
|
||||||
count: brand.count,
|
const categoriesList = stats?.categories?.list || [];
|
||||||
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>;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-8">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||||
{brandData.length > 0 && (
|
<div className="flex flex-col h-[30vh] sm:h-[60vh]">
|
||||||
<div>
|
<h3 className="text-md font-medium mb-4 flex items-center gap-2">
|
||||||
<h3 className="text-lg font-medium mb-4">All Brands</h3>
|
<Star className="h-5 w-5 text-yellow-500" />
|
||||||
<div className="rounded-lg border bg-card max-h-[400px] overflow-auto">
|
Brands ({stats?.brands?.total || 0})
|
||||||
|
</h3>
|
||||||
|
<div className="rounded-md border overflow-auto">
|
||||||
<Table>
|
<Table>
|
||||||
<TableHeader className="sticky top-0 bg-background z-10">
|
<TableHeader className="sticky top-0 bg-background z-10">
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableHead>Brand</TableHead>
|
<TableHead>Brand</TableHead>
|
||||||
<TableHead className="text-right">Items</TableHead>
|
<TableHead className="text-right">Items</TableHead>
|
||||||
<TableHead className="text-right">Revenue</TableHead>
|
<TableHead className="text-right">Revenue</TableHead>
|
||||||
<TableHead className="text-right">% of Total</TableHead>
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{brandData.map((brand, index) => (
|
{brandsList.map((brand) => (
|
||||||
<TableRow key={index}>
|
<TableRow key={brand.name}>
|
||||||
<TableCell className="font-medium">{brand.name}</TableCell>
|
<TableCell className="font-medium">{brand.name}</TableCell>
|
||||||
<TableCell className="text-right">{brand.count.toLocaleString()}</TableCell>
|
<TableCell className="text-right">{brand.count?.toLocaleString()}</TableCell>
|
||||||
<TableCell className="text-right">{formatCurrency(brand.revenue)}</TableCell>
|
<TableCell className="text-right">${brand.revenue?.toFixed(2)}</TableCell>
|
||||||
<TableCell className="text-right">{brand.percentage.toFixed(1)}%</TableCell>
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
))}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
|
|
||||||
{categoryData.length > 0 && (
|
<div className="flex flex-col h-[30vh] md:h-[60vh]">
|
||||||
<div>
|
<h3 className="text-md font-medium mb-4 flex items-center gap-2">
|
||||||
<h3 className="text-lg font-medium mb-4">All Categories</h3>
|
<Tags className="h-5 w-5 text-indigo-500" />
|
||||||
<div className="rounded-lg border bg-card max-h-[400px] overflow-auto">
|
Categories ({stats?.categories?.total || 0})
|
||||||
|
</h3>
|
||||||
|
<div className="rounded-md border overflow-auto">
|
||||||
<Table>
|
<Table>
|
||||||
<TableHeader className="sticky top-0 bg-background z-10">
|
<TableHeader className="sticky top-0 bg-background z-10">
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableHead>Category</TableHead>
|
<TableHead>Category</TableHead>
|
||||||
<TableHead className="text-right">Items</TableHead>
|
<TableHead className="text-right">Items</TableHead>
|
||||||
<TableHead className="text-right">Revenue</TableHead>
|
<TableHead className="text-right">Revenue</TableHead>
|
||||||
<TableHead className="text-right">% of Total</TableHead>
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{categoryData.map((category, index) => (
|
{categoriesList.map((category) => (
|
||||||
<TableRow key={index}>
|
<TableRow key={category.name}>
|
||||||
<TableCell className="font-medium">{category.name}</TableCell>
|
<TableCell className="font-medium">{category.name}</TableCell>
|
||||||
<TableCell className="text-right">{category.count.toLocaleString()}</TableCell>
|
<TableCell className="text-right">{category.count?.toLocaleString()}</TableCell>
|
||||||
<TableCell className="text-right">{formatCurrency(category.revenue)}</TableCell>
|
<TableCell className="text-right">${category.revenue?.toFixed(2)}</TableCell>
|
||||||
<TableCell className="text-right">{category.percentage.toFixed(1)}%</TableCell>
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
))}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user