diff --git a/src/components/dashboard/dashboard-shell.tsx b/src/components/dashboard/dashboard-shell.tsx index 0bd6306..7324d7b 100644 --- a/src/components/dashboard/dashboard-shell.tsx +++ b/src/components/dashboard/dashboard-shell.tsx @@ -1,6 +1,7 @@ 'use client'; import { useRealtimeInvalidation } from '@/hooks/use-realtime-invalidation'; +import { PageHeader } from '@/components/shared/page-header'; import { KpiCardsWithBoundary } from './kpi-cards'; import { PipelineChart } from './pipeline-chart'; import { RevenueForecast } from './revenue-forecast'; @@ -8,13 +9,27 @@ import { ActivityFeed } from './activity-feed'; export function DashboardShell() { useRealtimeInvalidation({ - 'interest:stageChanged': [['dashboard', 'pipeline'], ['dashboard', 'forecast']], + 'interest:stageChanged': [ + ['dashboard', 'pipeline'], + ['dashboard', 'forecast'], + ], 'client:created': [['dashboard', 'kpis']], - 'berth:statusChanged': [['dashboard', 'kpis'], ['dashboard', 'forecast']], + 'berth:statusChanged': [ + ['dashboard', 'kpis'], + ['dashboard', 'forecast'], + ], }); return (
+ Last 30 days} + variant="gradient" + /> + {/* Row 1: KPI cards */}
diff --git a/src/components/dashboard/kpi-cards.tsx b/src/components/dashboard/kpi-cards.tsx index 1fd3786..ade422a 100644 --- a/src/components/dashboard/kpi-cards.tsx +++ b/src/components/dashboard/kpi-cards.tsx @@ -1,11 +1,10 @@ 'use client'; import { useQuery } from '@tanstack/react-query'; -import { DollarSign, LayoutGrid, TrendingUp, Users } from 'lucide-react'; import { apiFetch } from '@/lib/api/client'; -import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; -import { CardSkeleton } from '@/components/shared/loading-skeleton'; +import { KPITile } from '@/components/ui/kpi-tile'; +import { Skeleton } from '@/components/ui/skeleton'; import { WidgetErrorBoundary } from './widget-error-boundary'; interface KpiData { @@ -27,6 +26,17 @@ function formatPercent(value: number): string { return `${value.toFixed(1)}%`; } +function KpiTileSkeleton() { + return ( +
+
+ + + +
+ ); +} + export function KpiCards() { const { data, isLoading, isError } = useQuery({ queryKey: ['dashboard', 'kpis'], @@ -38,52 +48,45 @@ export function KpiCards() { if (isLoading) { return ( <> - - - - + + + + ); } - const kpis = [ + const kpis: Array<{ + label: string; + value: string; + accent: 'brand' | 'success' | 'warning' | 'mint' | 'teal' | 'purple'; + }> = [ { label: 'Total Clients', value: isError ? '—' : String(data?.totalClients ?? 0), - icon: Users, + accent: 'brand', }, { label: 'Active Interests', value: isError ? '—' : String(data?.activeInterests ?? 0), - icon: TrendingUp, + accent: 'teal', }, { label: 'Pipeline Value', value: isError ? '—' : formatCurrency(data?.pipelineValueUsd ?? 0), - icon: DollarSign, + accent: 'success', }, { label: 'Occupancy Rate', value: isError ? '—' : formatPercent(data?.occupancyRate ?? 0), - icon: LayoutGrid, + accent: 'purple', }, ]; return ( <> - {kpis.map(({ label, value, icon: Icon }) => ( - - - - {label} - - - - -
{value}
-
- - + {kpis.map(({ label, value, accent }) => ( + ))} );