From f38baa985edf68d9be0e0a2836d043a1f5335ecb Mon Sep 17 00:00:00 2001 From: tonym Date: Thu, 22 Jan 2026 23:32:03 -0600 Subject: [PATCH] feat: Rearrange dashboard - pie chart + stats on top, spools middle, analytics bottom Co-Authored-By: Claude Opus 4.5 --- .../components/MaterialDistributionChart.tsx | 26 +++- .../src/pages/home/components/QuickStats.tsx | 146 ++++++++++-------- client/src/pages/home/index.tsx | 49 +++--- 3 files changed, 125 insertions(+), 96 deletions(-) diff --git a/client/src/pages/home/components/MaterialDistributionChart.tsx b/client/src/pages/home/components/MaterialDistributionChart.tsx index 76b67b0..b2da2f1 100644 --- a/client/src/pages/home/components/MaterialDistributionChart.tsx +++ b/client/src/pages/home/components/MaterialDistributionChart.tsx @@ -20,7 +20,11 @@ const COLORS = [ "#2f54eb", // geekblue ]; -export function MaterialDistributionChart() { +interface MaterialDistributionChartProps { + square?: boolean; +} + +export function MaterialDistributionChart({ square }: MaterialDistributionChartProps) { const t = useTranslate(); const { token } = useToken(); @@ -59,20 +63,21 @@ export function MaterialDistributionChart() { - + `${name} (${((percent ?? 0) * 100).toFixed(0)}%)`} - labelLine={{ stroke: token.colorTextSecondary }} + label={square ? undefined : ({ name, percent }) => `${name} (${((percent ?? 0) * 100).toFixed(0)}%)`} + labelLine={square ? false : { stroke: token.colorTextSecondary }} > {chartData.map((_, index) => ( @@ -86,6 +91,13 @@ export function MaterialDistributionChart() { borderRadius: token.borderRadius, }} /> + {square && ( + + )} diff --git a/client/src/pages/home/components/QuickStats.tsx b/client/src/pages/home/components/QuickStats.tsx index 0aadf66..8c05f5c 100644 --- a/client/src/pages/home/components/QuickStats.tsx +++ b/client/src/pages/home/components/QuickStats.tsx @@ -12,7 +12,11 @@ import { getAPIURL } from "../../../utils/url"; const { useToken } = theme; -export function QuickStats() { +interface QuickStatsProps { + compact?: boolean; +} + +export function QuickStats({ compact }: QuickStatsProps) { const t = useTranslate(); const { token } = useToken(); const currencyFormatter = useCurrencyFormatter(); @@ -70,6 +74,67 @@ export function QuickStats() { return `${Math.round(grams)} g`; }; + const stats = [ + { + title: t("home.quick_stats.total_filaments"), + value: filamentsResult?.total ?? 0, + loading: filamentsQuery.isLoading, + prefix: , + to: "/filament", + }, + { + title: t("home.quick_stats.total_vendors"), + value: vendorsResult?.total ?? 0, + loading: vendorsQuery.isLoading, + prefix: , + to: "/vendor", + }, + { + title: t("home.quick_stats.total_weight"), + value: formatWeight(totalWeight), + loading: spoolsQuery.isLoading, + prefix: , + }, + { + title: t("home.quick_stats.total_value"), + value: currencyFormatter.format(totalValue), + loading: spoolsQuery.isLoading, + prefix: , + }, + { + title: t("home.quick_stats.total_spent"), + value: currencyFormatter.format(costStats?.total_spent ?? 0), + loading: costLoading, + prefix: , + }, + { + title: t("home.quick_stats.avg_cost_per_kg"), + value: costStats?.avg_cost_per_kg != null ? currencyFormatter.format(costStats.avg_cost_per_kg) : "-", + loading: costLoading, + prefix: , + }, + ]; + + if (compact) { + return ( + + {stats.map((stat, i) => ( + + + + + + ))} + + ); + } + return ( @@ -84,70 +149,21 @@ export function QuickStats() { - - - - } - /> - - - - - - - } - /> - - - - - - } - /> - - - - - } - /> - - - - - } - /> - - - - - } - /> - - + {stats.map((stat, i) => ( + + {stat.to ? ( + + + + + + ) : ( + + + + )} + + ))} ); } diff --git a/client/src/pages/home/index.tsx b/client/src/pages/home/index.tsx index ccc4773..6d0cd2a 100644 --- a/client/src/pages/home/index.tsx +++ b/client/src/pages/home/index.tsx @@ -112,37 +112,38 @@ export const Home: React.FC = () => { fontFamily: token.fontFamily, }} > - {/* Header with spool count and add button */} - - - + {/* Top section: Pie chart + stats/alerts side by side */} + + + - - + + + + + + + + + + + - {/* Alert badges */} - - - {/* Material distribution chart */} - - - {/* Usage analytics */} - - {/* Spool list */} {t("buttons.viewAll")}} styles={{ body: { padding: 0 } }} + style={{ marginBottom: 16 }} > dataSource={spoolsResult?.data as ISpool[]} @@ -168,8 +169,8 @@ export const Home: React.FC = () => { - {/* Quick stats */} - + {/* Usage analytics & insights */} + ); };