@burdenoff/microfe-assethandler 2026.713.2 → 2026.714.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/assethandler/components/AttachmentsPanel.d.ts.map +1 -1
  2. package/dist/assethandler/components/AttachmentsPanel.js.map +1 -1
  3. package/dist/assethandler/hooks/useCopy.d.ts +28 -0
  4. package/dist/assethandler/hooks/useCopy.d.ts.map +1 -0
  5. package/dist/assethandler/hooks/useCopy.js +33 -0
  6. package/dist/assethandler/hooks/useCopy.js.map +1 -0
  7. package/dist/assethandler/index.d.ts +1 -1
  8. package/dist/assethandler/index.d.ts.map +1 -1
  9. package/dist/assethandler/pages/AnalyticsPage.d.ts.map +1 -1
  10. package/dist/assethandler/pages/AnalyticsPage.js +259 -258
  11. package/dist/assethandler/pages/AnalyticsPage.js.map +1 -1
  12. package/dist/assethandler/pages/AssetsAssetCategoriesPage.d.ts.map +1 -1
  13. package/dist/assethandler/pages/AssetsAssetCategoriesPage.js +1 -2
  14. package/dist/assethandler/pages/AssetsAssetCategoriesPage.js.map +1 -1
  15. package/dist/assethandler/pages/AssetsAssetListPage.d.ts.map +1 -1
  16. package/dist/assethandler/pages/AssetsAssetListPage.js +47 -48
  17. package/dist/assethandler/pages/AssetsAssetListPage.js.map +1 -1
  18. package/dist/assethandler/pages/DashboardPage.d.ts.map +1 -1
  19. package/dist/assethandler/pages/DashboardPage.js +236 -236
  20. package/dist/assethandler/pages/DashboardPage.js.map +1 -1
  21. package/dist/assethandler/pages/PortfolioPortfolioOverviewPage.d.ts.map +1 -1
  22. package/dist/assethandler/pages/PortfolioPortfolioOverviewPage.js +126 -125
  23. package/dist/assethandler/pages/PortfolioPortfolioOverviewPage.js.map +1 -1
  24. package/dist/assethandler/pages/TransactionsTransactionListPage.js +127 -127
  25. package/dist/assethandler/pages/TransactionsTransactionListPage.js.map +1 -1
  26. package/dist/assethandler/store/assethandlerStore.d.ts.map +1 -1
  27. package/dist/assethandler/store/assethandlerStore.js.map +1 -1
  28. package/dist/assethandler/types/index.d.ts +20 -0
  29. package/dist/assethandler/types/index.d.ts.map +1 -1
  30. package/dist/types/assistant.d.ts.map +1 -1
  31. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"DashboardPage.js","names":[],"sources":["../../../src/assethandler/pages/DashboardPage.tsx"],"sourcesContent":["import { useMemo, useState, type ComponentType } from 'react';\nimport { useAssetHandlerNavigate } from '../hooks/useAssetHandlerNavigate';\nimport {\n GlassCard,\n AuroraBackground,\n GradientText,\n CTAOverflowMenu,\n PagePurpose,\n NextSteps,\n IllustratedEmptyState,\n} from '@burdenoff/fe-libs/ui';\nimport {\n Activity,\n AlertTriangle,\n Box,\n Clock,\n ClipboardList,\n Receipt,\n Wrench,\n CheckCircle,\n ArrowRight,\n CalendarClock,\n} from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useAssetHandlerStore } from '../store/assethandlerStore';\nimport { tWithFallback } from '../utils/i18n';\nimport { cn } from '../utils/cn';\nimport {\n StatTile,\n ChartCard,\n DonutChart,\n BarsChart,\n TrendChart,\n formatCompact,\n formatCurrencyCompact,\n seriesColor,\n type ChartDatum,\n type ChartSeries,\n type DonutSlice,\n} from '../components';\n\n// ─── Time-series helpers (all derived from real store timestamps) ─────────────\nfunction monthKey(date: Date): string {\n return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`;\n}\nfunction monthLabel(key: string): string {\n const [year, month] = key.split('-').map(Number);\n return new Date(year, month - 1, 1).toLocaleString(undefined, { month: 'short' });\n}\nfunction parseDate(value: string | undefined | null): Date | null {\n if (!value) return null;\n const d = new Date(value);\n return Number.isNaN(d.getTime()) ? null : d;\n}\nfunction titleCase(value: string): string {\n return value.replace(/_/g, ' ').replace(/\\b\\w/g, (c) => c.toUpperCase());\n}\n\n/** Group items into ordered monthly buckets, counting by a category accessor. */\nfunction monthlyGrouped<T>(\n items: T[],\n getDate: (item: T) => string | undefined | null,\n getGroup: (item: T) => string,\n maxMonths = 8,\n maxGroups = 6\n): { rows: ChartDatum[]; series: ChartSeries[] } {\n const byMonth = new Map<string, Map<string, number>>();\n const groupTotals = new Map<string, number>();\n for (const item of items) {\n const d = parseDate(getDate(item));\n if (!d) continue;\n const key = monthKey(d);\n const group = getGroup(item) || 'other';\n if (!byMonth.has(key)) byMonth.set(key, new Map());\n const bucket = byMonth.get(key)!;\n bucket.set(group, (bucket.get(group) ?? 0) + 1);\n groupTotals.set(group, (groupTotals.get(group) ?? 0) + 1);\n }\n if (byMonth.size === 0) return { rows: [], series: [] };\n\n const orderedGroups = [...groupTotals.entries()].sort((a, b) => b[1] - a[1]).map(([g]) => g);\n const topGroups = orderedGroups.slice(0, maxGroups);\n const hasOther = orderedGroups.length > maxGroups;\n const keptGroups = new Set(topGroups);\n\n const keys = [...byMonth.keys()].sort().slice(-maxMonths);\n const rows: ChartDatum[] = keys.map((key) => {\n const row: ChartDatum = { month: monthLabel(key) };\n for (const g of topGroups) row[g] = 0;\n if (hasOther) row.other = 0;\n for (const [group, count] of byMonth.get(key)!) {\n if (keptGroups.has(group)) row[group] = ((row[group] as number) ?? 0) + count;\n else if (hasOther) row.other = ((row.other as number) ?? 0) + count;\n }\n return row;\n });\n\n const series: ChartSeries[] = topGroups.map((g, i) => ({\n key: g,\n label: titleCase(g),\n color: seriesColor(i),\n }));\n if (hasOther) {\n series.push({ key: 'other', label: 'Other', color: seriesColor(topGroups.length) });\n }\n return { rows, series };\n}\n\nfunction relativeTime(value: string | undefined | null): string {\n const d = parseDate(value);\n if (!d) return '';\n const diff = Date.now() - d.getTime();\n const mins = Math.round(diff / 60000);\n if (mins < 1) return 'just now';\n if (mins < 60) return `${mins}m ago`;\n const hours = Math.round(mins / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.round(hours / 24);\n if (days < 30) return `${days}d ago`;\n const months = Math.round(days / 30);\n if (months < 12) return `${months}mo ago`;\n return `${Math.round(months / 12)}y ago`;\n}\n\ntype PillTone = 'success' | 'warning' | 'error' | 'info' | 'neutral';\nconst PILL_CLASS: Record<PillTone, string> = {\n success: 'bg-status-success-bg-subtle text-status-success-text',\n warning: 'bg-status-warning-bg-subtle text-status-warning-text',\n error: 'bg-status-error-bg-subtle text-status-error-text',\n info: 'bg-status-info-bg-subtle text-status-info-text',\n neutral: 'bg-bg-sunken text-text-secondary',\n};\n\nfunction StatusPill({ tone, children }: { tone: PillTone; children: React.ReactNode }) {\n return (\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2 py-0.5 text-[11px] font-medium capitalize whitespace-nowrap',\n PILL_CLASS[tone]\n )}\n >\n {children}\n </span>\n );\n}\n\nconst priorityTone = (p: string): PillTone =>\n p === 'critical' ? 'error' : p === 'high' ? 'warning' : p === 'medium' ? 'info' : 'neutral';\nconst maintenanceTone = (status: string): PillTone =>\n status === 'completed' ? 'success' : status === 'in_progress' ? 'info' : 'warning';\n\ninterface FeedItem {\n id: string;\n icon: ComponentType<{ className?: string }>;\n title: string;\n meta: string;\n at: string;\n tone: PillTone;\n statusLabel: string;\n}\n\nexport function DashboardPage() {\n const { t } = useI18n();\n const navigate = useAssetHandlerNavigate();\n const {\n hydrated,\n overview,\n assets,\n incidents,\n maintenanceRecords,\n changeRequests,\n workOrders,\n transactions,\n } = useAssetHandlerStore();\n\n const [assetsMode, setAssetsMode] = useState<'status' | 'category'>('status');\n\n const activeIncidents = incidents.filter((i) => i.status !== 'resolved' && i.status !== 'closed');\n const criticalIncidents = incidents.filter(\n (i) => i.priority === 'critical' && i.status !== 'resolved' && i.status !== 'closed'\n );\n const pendingMaintenance = maintenanceRecords.filter(\n (m) => m.status === 'scheduled' || m.status === 'in_progress'\n );\n const openWorkOrders = workOrders.filter(\n (w) => w.status !== 'completed' && w.status !== 'cancelled'\n );\n const pendingChanges = changeRequests.filter(\n (c) => c.status === 'approved' || c.status === 'submitted'\n );\n\n // Cumulative asset-count sparkline — the only KPI with real history.\n const assetSpark = useMemo(() => {\n const byMonth = new Map<string, number>();\n for (const a of assets) {\n const d = parseDate(a.createdAt);\n if (!d) continue;\n const key = monthKey(d);\n byMonth.set(key, (byMonth.get(key) ?? 0) + 1);\n }\n const keys = [...byMonth.keys()].sort();\n return keys.reduce<number[]>((acc, k) => {\n const prev = acc.length ? acc[acc.length - 1] : 0;\n acc.push(prev + (byMonth.get(k) ?? 0));\n return acc;\n }, []);\n }, [assets]);\n\n const metrics = [\n {\n label: tWithFallback(t, 'assethandler.dashboard.metrics.totalAssets', 'Total Assets'),\n value: overview?.totalAssets ?? assets.length,\n icon: Box,\n spark: assetSpark.length > 1 ? assetSpark : undefined,\n hero: true,\n },\n {\n label: tWithFallback(t, 'assethandler.dashboard.metrics.openIncidents', 'Open Incidents'),\n value: overview?.openIncidents ?? activeIncidents.length,\n icon: AlertTriangle,\n },\n {\n label: tWithFallback(t, 'assethandler.dashboard.metrics.openWorkOrders', 'Open Work Orders'),\n value: overview?.openWorkOrders ?? openWorkOrders.length,\n icon: ClipboardList,\n },\n {\n label: tWithFallback(t, 'assethandler.dashboard.metrics.transactions', 'Transactions'),\n value: overview?.totalTransactions ?? transactions.length,\n icon: Receipt,\n },\n ];\n\n // Portfolio-by-category donut (real asset counts).\n const categoryDonut = useMemo<DonutSlice[]>(() => {\n const counts = assets.reduce<Record<string, number>>((acc, a) => {\n const key = a.category || 'uncategorized';\n acc[key] = (acc[key] ?? 0) + 1;\n return acc;\n }, {});\n return Object.entries(counts)\n .sort((a, b) => b[1] - a[1])\n .map(([name, value]) => ({ name: titleCase(name), value }));\n }, [assets]);\n\n // Assets-added-over-time (stacked by status or category via the toggle).\n const assetsSeries = useMemo(\n () =>\n monthlyGrouped(\n assets,\n (a) => a.createdAt,\n (a) => (assetsMode === 'status' ? a.status : a.category),\n 8,\n 6\n ),\n [assets, assetsMode]\n );\n\n // Cumulative transaction value over time (real transaction amounts).\n const valueTrend = useMemo<ChartDatum[]>(() => {\n const byMonth = new Map<string, number>();\n for (const tx of transactions) {\n const d = parseDate(tx.date);\n if (!d) continue;\n const key = monthKey(d);\n byMonth.set(key, (byMonth.get(key) ?? 0) + tx.amount);\n }\n const keys = [...byMonth.keys()].sort();\n const raw = keys.reduce<number[]>((acc, k) => {\n const prev = acc.length ? acc[acc.length - 1] : 0;\n acc.push(prev + (byMonth.get(k) ?? 0));\n return acc;\n }, []);\n return keys.map((k, i) => ({ month: monthLabel(k), value: Math.round(raw[i]) }));\n }, [transactions]);\n const txCurrency = transactions[0]?.currency ?? 'USD';\n\n // Unified recent-activity feed (merged real records, newest first).\n const feed = useMemo<FeedItem[]>(() => {\n const items: FeedItem[] = [];\n for (const a of assets) {\n items.push({\n id: `asset-${a.id}`,\n icon: Box,\n title: a.name,\n meta: 'Asset registered',\n at: a.createdAt,\n tone:\n a.status === 'active' ? 'success' : a.status === 'maintenance' ? 'warning' : 'neutral',\n statusLabel: a.status.replace(/_/g, ' '),\n });\n }\n for (const inc of incidents) {\n items.push({\n id: `inc-${inc.id}`,\n icon: AlertTriangle,\n title: inc.title,\n meta: `Incident · ${inc.priority}`,\n at: inc.createdAt,\n tone:\n inc.status === 'resolved' || inc.status === 'closed'\n ? 'success'\n : inc.priority === 'critical' || inc.priority === 'high'\n ? 'error'\n : 'warning',\n statusLabel: inc.status.replace(/_/g, ' '),\n });\n }\n for (const wo of workOrders) {\n items.push({\n id: `wo-${wo.id}`,\n icon: ClipboardList,\n title: wo.title,\n meta: `Work order · ${wo.type}`,\n at: wo.createdAt,\n tone:\n wo.status === 'completed'\n ? 'success'\n : wo.status === 'in_progress'\n ? 'info'\n : wo.status === 'cancelled'\n ? 'neutral'\n : 'warning',\n statusLabel: wo.status.replace(/_/g, ' '),\n });\n }\n for (const m of maintenanceRecords) {\n const at = m.completedDate ?? m.scheduledDate;\n if (!at) continue;\n items.push({\n id: `mnt-${m.id}`,\n icon: Wrench,\n title: m.title,\n meta: 'Maintenance',\n at,\n tone:\n m.status === 'completed' ? 'success' : m.status === 'in_progress' ? 'info' : 'warning',\n statusLabel: m.status.replace(/_/g, ' '),\n });\n }\n return items\n .filter((i) => parseDate(i.at))\n .sort((a, b) => b.at.localeCompare(a.at))\n .slice(0, 7);\n }, [assets, incidents, workOrders, maintenanceRecords]);\n\n const upcomingMaintenance = [...maintenanceRecords]\n .filter((m) => m.status !== 'completed' && m.status !== 'cancelled')\n .sort((a, b) => (a.scheduledDate ?? '').localeCompare(b.scheduledDate ?? ''))\n .slice(0, 8);\n\n return (\n <div className=\"space-y-6 p-4 sm:p-6\">\n {/* Header */}\n <div className=\"relative overflow-hidden rounded-xl border border-border-seam bg-gloss-card p-5 sm:p-6\">\n <AuroraBackground intensity=\"subtle\" />\n <div className=\"relative flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <h1 className=\"text-2xl font-bold sm:text-3xl\">\n <GradientText>\n {tWithFallback(t, 'assethandler.dashboard.title', 'Dashboard')}\n </GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary mt-1\">\n {tWithFallback(\n t,\n 'assethandler.dashboard.description',\n 'Overview of your IT asset portfolio and operations'\n )}\n </p>\n </div>\n <CTAOverflowMenu\n primary={{\n label: tWithFallback(t, 'assethandler.dashboard.actions.addAsset', 'Add Asset'),\n onSelect: () => navigate('/assets/asset-create'),\n }}\n actions={[\n {\n label: tWithFallback(\n t,\n 'assethandler.dashboard.actions.viewAnalytics',\n 'View Analytics'\n ),\n onSelect: () => navigate('/analytics'),\n },\n ]}\n />\n </div>\n </div>\n\n <PagePurpose>\n {tWithFallback(\n t,\n 'assethandler.dashboard.purpose',\n 'Your command center for the whole asset estate — see what needs attention (open incidents, due maintenance, critical alerts) and recent activity at a glance, then jump straight to the area that needs you. Start here every day to know where to act.'\n )}\n </PagePurpose>\n\n {/* KPI Metrics */}\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-4\">\n {metrics.map((metric) => (\n <StatTile\n key={metric.label}\n label={metric.label}\n value={hydrated ? metric.value : '—'}\n format={formatCompact}\n icon={metric.icon}\n spark={metric.spark}\n hero={metric.hero}\n />\n ))}\n </div>\n\n {/* Assets-over-time + Recent activity rail */}\n <div className=\"grid gap-6 lg:grid-cols-3\">\n <ChartCard\n className=\"lg:col-span-2\"\n title={tWithFallback(t, 'assethandler.dashboard.assetsChart.title', 'Assets over time')}\n subtitle={tWithFallback(\n t,\n 'assethandler.dashboard.assetsChart.subtitle',\n 'Assets added each month, from real registration dates'\n )}\n icon={Box}\n actions={\n <div className=\"inline-flex rounded-lg bg-bg-sunken p-0.5\">\n {(['status', 'category'] as const).map((mode) => (\n <button\n key={mode}\n type=\"button\"\n onClick={() => setAssetsMode(mode)}\n className={cn(\n 'rounded-md px-3 py-1 text-xs font-medium transition-colors',\n assetsMode === mode\n ? 'bg-bg-surface text-text-primary shadow-sm'\n : 'text-text-secondary hover:text-text-primary'\n )}\n >\n {mode === 'status' ? 'By status' : 'By category'}\n </button>\n ))}\n </div>\n }\n >\n {assetsSeries.rows.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={tWithFallback(\n t,\n 'assethandler.dashboard.assetsChart.empty.title',\n 'No history yet'\n )}\n description={tWithFallback(\n t,\n 'assethandler.dashboard.assetsChart.empty.description',\n 'Register assets and their monthly trend will appear here.'\n )}\n />\n ) : (\n <BarsChart\n data={assetsSeries.rows}\n xKey=\"month\"\n series={assetsSeries.series}\n stacked\n height={280}\n ariaLabel=\"Assets added per month\"\n />\n )}\n </ChartCard>\n\n {/* Recent Activity rail */}\n <GlassCard treatment=\"insight\" className=\"border-border-seam\">\n <div className=\"flex flex-col gap-4 p-5\">\n <div className=\"flex items-center justify-between\">\n <h3 className=\"flex items-center gap-2 text-base font-semibold text-text-primary\">\n <Activity className=\"h-4 w-4 text-text-secondary\" />\n {tWithFallback(t, 'assethandler.dashboard.activity.title', 'Recent activity')}\n </h3>\n <button\n type=\"button\"\n onClick={() => navigate('/analytics')}\n className=\"inline-flex items-center gap-1 text-xs font-medium text-primary hover:underline\"\n >\n {tWithFallback(t, 'assethandler.dashboard.activity.viewAll', 'View all')}\n <ArrowRight className=\"h-3 w-3\" />\n </button>\n </div>\n {feed.length === 0 ? (\n <p className=\"py-6 text-center text-sm text-text-secondary\">\n {tWithFallback(\n t,\n 'assethandler.dashboard.activity.empty',\n 'Activity across your estate will show up here.'\n )}\n </p>\n ) : (\n <ul className=\"space-y-1\">\n {feed.map((item) => {\n const Icon = item.icon;\n return (\n <li\n key={item.id}\n className=\"flex items-start gap-3 rounded-lg px-2 py-2 hover:bg-bg-sunken/60\"\n >\n <span className=\"mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-bg-sunken text-text-secondary\">\n <Icon className=\"h-4 w-4\" />\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center justify-between gap-2\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {item.title}\n </p>\n <StatusPill tone={item.tone}>{item.statusLabel}</StatusPill>\n </div>\n <p className=\"mt-0.5 flex items-center gap-1.5 text-xs text-text-secondary capitalize\">\n <span className=\"truncate\">{item.meta}</span>\n <span aria-hidden=\"true\">·</span>\n <span className=\"shrink-0 normal-case text-text-muted\">\n {relativeTime(item.at)}\n </span>\n </p>\n </div>\n </li>\n );\n })}\n </ul>\n )}\n </div>\n </GlassCard>\n </div>\n\n {/* Transaction value trend (full width) */}\n <ChartCard\n title={tWithFallback(t, 'assethandler.dashboard.value.title', 'Transaction value')}\n subtitle={tWithFallback(\n t,\n 'assethandler.dashboard.value.subtitle',\n 'Cumulative transaction amount over time'\n )}\n icon={Receipt}\n >\n {valueTrend.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={tWithFallback(\n t,\n 'assethandler.dashboard.value.empty.title',\n 'No transactions yet'\n )}\n description={tWithFallback(\n t,\n 'assethandler.dashboard.value.empty.description',\n 'Asset purchases, leases and disposals will chart here as they are recorded.'\n )}\n />\n ) : (\n <TrendChart\n data={valueTrend}\n xKey=\"month\"\n series={[{ key: 'value', label: 'Cumulative value' }]}\n valueFormat={formatCurrencyCompact(txCurrency)}\n height={260}\n ariaLabel=\"Cumulative transaction value over time\"\n />\n )}\n </ChartCard>\n\n {/* Portfolio donut + Operations summary */}\n <div className=\"grid gap-6 lg:grid-cols-3\">\n <ChartCard\n className=\"lg:col-span-2\"\n title={tWithFallback(\n t,\n 'assethandler.dashboard.portfolio.title',\n 'Portfolio by category'\n )}\n subtitle={tWithFallback(\n t,\n 'assethandler.dashboard.portfolio.description',\n 'Asset distribution by category'\n )}\n icon={Box}\n >\n {categoryDonut.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={tWithFallback(\n t,\n 'assethandler.dashboard.portfolio.empty.title',\n 'No assets yet'\n )}\n description={tWithFallback(\n t,\n 'assethandler.dashboard.portfolio.empty.description',\n 'Register your first asset and category distribution will appear here.'\n )}\n />\n ) : (\n <DonutChart\n data={categoryDonut}\n centerLabel=\"Assets\"\n centerValue={assets.length}\n height={260}\n ariaLabel=\"Assets by category\"\n />\n )}\n </ChartCard>\n\n <GlassCard treatment=\"glass\" className=\"border-border-seam\">\n <div className=\"flex flex-col gap-4 p-5\">\n <h3 className=\"text-base font-semibold text-text-primary\">\n {tWithFallback(t, 'assethandler.dashboard.operations.title', 'Operations summary')}\n </h3>\n <div className=\"grid grid-cols-2 gap-3\">\n {[\n { icon: Wrench, value: pendingMaintenance.length, label: 'Pending Maintenance' },\n { icon: Activity, value: openWorkOrders.length, label: 'Open Work Orders' },\n { icon: Clock, value: pendingChanges.length, label: 'Pending Changes' },\n { icon: CheckCircle, value: criticalIncidents.length, label: 'Critical Alerts' },\n ].map((op) => {\n const Icon = op.icon;\n return (\n <div\n key={op.label}\n className=\"rounded-lg border border-border-seam bg-gloss-card p-4 text-center\"\n >\n <Icon className=\"mx-auto mb-2 h-5 w-5 text-text-secondary\" />\n <p className=\"text-2xl font-bold tabular-nums\">{op.value}</p>\n <p className=\"text-xs text-text-secondary\">{op.label}</p>\n </div>\n );\n })}\n </div>\n </div>\n </GlassCard>\n </div>\n\n {/* Active incidents + Open work orders */}\n <div className=\"grid gap-6 lg:grid-cols-2\">\n <GlassCard treatment=\"glass\" className=\"border-border-seam\">\n <div className=\"flex flex-col gap-4 p-5\">\n <div>\n <h3 className=\"flex items-center gap-2 text-base font-semibold text-text-primary\">\n <AlertTriangle className=\"h-4 w-4 text-status-error-text\" />\n {tWithFallback(t, 'assethandler.dashboard.incidents.title', 'Active Incidents')}\n </h3>\n <p className=\"mt-0.5 text-sm text-text-secondary\">\n {activeIncidents.length}{' '}\n {tWithFallback(\n t,\n 'assethandler.dashboard.incidents.unresolvedCount',\n 'unresolved incidents'\n )}\n </p>\n </div>\n {activeIncidents.length === 0 ? (\n <p className=\"py-4 text-center text-sm text-text-secondary\">\n {tWithFallback(\n t,\n 'assethandler.dashboard.incidents.empty',\n 'No unresolved incidents — all clear.'\n )}\n </p>\n ) : (\n <div className=\"space-y-2\">\n {activeIncidents.slice(0, 5).map((inc) => (\n <button\n key={inc.id}\n type=\"button\"\n onClick={() => navigate('/itil/incident-management')}\n className=\"flex w-full items-start gap-3 rounded-lg border border-border-seam p-3 text-left hover:bg-bg-sunken/60\"\n >\n <StatusPill tone={priorityTone(inc.priority)}>{inc.priority}</StatusPill>\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium\">{inc.title}</p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">\n {inc.assignedTo ||\n tWithFallback(\n t,\n 'assethandler.dashboard.incidents.unassigned',\n 'Unassigned'\n )}\n </p>\n </div>\n </button>\n ))}\n </div>\n )}\n </div>\n </GlassCard>\n\n <GlassCard treatment=\"glass\" className=\"border-border-seam\">\n <div className=\"flex flex-col gap-4 p-5\">\n <div>\n <h3 className=\"text-base font-semibold text-text-primary\">\n {tWithFallback(t, 'assethandler.dashboard.workOrders.title', 'Open Work Orders')}\n </h3>\n <p className=\"mt-0.5 text-sm text-text-secondary\">\n {tWithFallback(\n t,\n 'assethandler.dashboard.workOrders.description',\n 'Latest work in progress'\n )}\n </p>\n </div>\n {openWorkOrders.length === 0 ? (\n <p className=\"py-4 text-center text-sm text-text-secondary\">\n {tWithFallback(\n t,\n 'assethandler.dashboard.workOrders.empty',\n 'No open work orders. Create one from the Operations hub.'\n )}\n </p>\n ) : (\n <div className=\"space-y-2\">\n {[...openWorkOrders]\n .sort((a, b) => b.createdAt.localeCompare(a.createdAt))\n .slice(0, 5)\n .map((item) => (\n <div\n key={item.id}\n className=\"flex items-center gap-3 rounded-lg border border-border-seam p-3\"\n >\n <StatusPill tone={item.status === 'in_progress' ? 'info' : 'warning'}>\n {item.status.replace(/_/g, ' ')}\n </StatusPill>\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm\">{item.title}</p>\n <p className=\"text-xs text-text-secondary capitalize\">\n {item.type} &middot; {item.priority}\n </p>\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n </GlassCard>\n </div>\n\n {/* Upcoming Maintenance — table on md+, cards on mobile */}\n <GlassCard treatment=\"glass\" className=\"border-border-seam\">\n <div className=\"flex flex-col gap-4 p-5\">\n <div>\n <h3 className=\"flex items-center gap-2 text-base font-semibold text-text-primary\">\n <CalendarClock className=\"h-4 w-4 text-text-secondary\" />\n {tWithFallback(t, 'assethandler.dashboard.maintenance.title', 'Upcoming Maintenance')}\n </h3>\n <p className=\"mt-0.5 text-sm text-text-secondary\">\n {tWithFallback(\n t,\n 'assethandler.dashboard.maintenance.description',\n 'Scheduled maintenance activities'\n )}\n </p>\n </div>\n {upcomingMaintenance.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-tasks\"\n title={tWithFallback(\n t,\n 'assethandler.dashboard.maintenance.empty.title',\n 'No maintenance scheduled'\n )}\n description={tWithFallback(\n t,\n 'assethandler.dashboard.maintenance.empty.description',\n 'Plan preventive maintenance from the scheduler and it will show up here.'\n )}\n />\n ) : (\n <>\n {/* Mobile: stacked cards */}\n <div className=\"space-y-2 md:hidden\">\n {upcomingMaintenance.map((rec) => (\n <div key={rec.id} className=\"rounded-lg border border-border-seam p-3\">\n <div className=\"flex items-start justify-between gap-2\">\n <p className=\"min-w-0 flex-1 truncate text-sm font-medium\">{rec.title}</p>\n <StatusPill tone={maintenanceTone(rec.status)}>\n {rec.status.replace(/_/g, ' ')}\n </StatusPill>\n </div>\n <div className=\"mt-2 flex flex-wrap items-center gap-2 text-xs text-text-secondary\">\n <span className=\"capitalize\">{rec.type}</span>\n <StatusPill tone={priorityTone(rec.priority)}>{rec.priority}</StatusPill>\n <span>\n {rec.scheduledDate ? new Date(rec.scheduledDate).toLocaleDateString() : '—'}\n </span>\n </div>\n </div>\n ))}\n </div>\n {/* md+: table */}\n <div className=\"hidden overflow-x-auto md:block\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b border-border-seam text-text-secondary\">\n <th className=\"py-2 text-left font-medium\">Title</th>\n <th className=\"py-2 text-left font-medium\">Type</th>\n <th className=\"py-2 text-left font-medium\">Priority</th>\n <th className=\"py-2 text-left font-medium\">Scheduled</th>\n <th className=\"py-2 text-left font-medium\">Status</th>\n </tr>\n </thead>\n <tbody>\n {upcomingMaintenance.map((rec) => (\n <tr\n key={rec.id}\n className=\"border-b border-border-seam hover:bg-bg-sunken/50\"\n >\n <td className=\"py-2.5 font-medium\">{rec.title}</td>\n <td className=\"py-2.5 capitalize\">{rec.type}</td>\n <td className=\"py-2.5\">\n <StatusPill tone={priorityTone(rec.priority)}>{rec.priority}</StatusPill>\n </td>\n <td className=\"py-2.5\">\n {rec.scheduledDate\n ? new Date(rec.scheduledDate).toLocaleDateString()\n : '—'}\n </td>\n <td className=\"py-2.5\">\n <StatusPill tone={maintenanceTone(rec.status)}>\n {rec.status.replace(/_/g, ' ')}\n </StatusPill>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </>\n )}\n </div>\n </GlassCard>\n\n <NextSteps\n storageKey=\"assethandler-dashboard\"\n steps={[\n {\n id: 'view-assets',\n label: 'Browse your asset inventory',\n description: 'See every tracked asset, its status and owner.',\n onClick: () => navigate('/assets/asset-list'),\n },\n {\n id: 'add-asset',\n label: 'Register a new asset',\n description: 'Add equipment, hardware or software to start tracking it.',\n onClick: () => navigate('/assets/asset-create'),\n },\n {\n id: 'incidents',\n label: 'Resolve open incidents',\n description: 'Triage service-affecting issues before they breach SLA.',\n onClick: () => navigate('/itil/incident-management'),\n },\n {\n id: 'maintenance',\n label: 'Check the maintenance calendar',\n description: 'Stay ahead of scheduled and overdue maintenance.',\n onClick: () => navigate('/maintenance/maintenance-calendar'),\n },\n ]}\n />\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"DashboardPage.js","names":[],"sources":["../../../src/assethandler/pages/DashboardPage.tsx"],"sourcesContent":["import { useMemo, useState, type ComponentType } from 'react';\nimport { useAssetHandlerNavigate } from '../hooks/useAssetHandlerNavigate';\nimport {\n GlassCard,\n AuroraBackground,\n GradientText,\n CTAOverflowMenu,\n PagePurpose,\n NextSteps,\n IllustratedEmptyState,\n} from '@burdenoff/fe-libs/ui';\nimport {\n Activity,\n AlertTriangle,\n Box,\n Clock,\n ClipboardList,\n Receipt,\n Wrench,\n CheckCircle,\n ArrowRight,\n CalendarClock,\n} from 'lucide-react';\nimport { useAssetHandlerStore } from '../store/assethandlerStore';\nimport { useCopy } from '../hooks/useCopy';\nimport { cn } from '../utils/cn';\nimport {\n StatTile,\n ChartCard,\n DonutChart,\n BarsChart,\n TrendChart,\n formatCompact,\n formatCurrencyCompact,\n seriesColor,\n type ChartDatum,\n type ChartSeries,\n type DonutSlice,\n} from '../components';\n\n// ─── Time-series helpers (all derived from real store timestamps) ─────────────\nfunction monthKey(date: Date): string {\n return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`;\n}\nfunction monthLabel(key: string): string {\n const [year, month] = key.split('-').map(Number);\n return new Date(year, month - 1, 1).toLocaleString(undefined, { month: 'short' });\n}\nfunction parseDate(value: string | undefined | null): Date | null {\n if (!value) return null;\n const d = new Date(value);\n return Number.isNaN(d.getTime()) ? null : d;\n}\nfunction titleCase(value: string): string {\n return value.replace(/_/g, ' ').replace(/\\b\\w/g, (c) => c.toUpperCase());\n}\n\n/** Group items into ordered monthly buckets, counting by a category accessor. */\nfunction monthlyGrouped<T>(\n items: T[],\n getDate: (item: T) => string | undefined | null,\n getGroup: (item: T) => string,\n maxMonths = 8,\n maxGroups = 6\n): { rows: ChartDatum[]; series: ChartSeries[] } {\n const byMonth = new Map<string, Map<string, number>>();\n const groupTotals = new Map<string, number>();\n for (const item of items) {\n const d = parseDate(getDate(item));\n if (!d) continue;\n const key = monthKey(d);\n const group = getGroup(item) || 'other';\n if (!byMonth.has(key)) byMonth.set(key, new Map());\n const bucket = byMonth.get(key)!;\n bucket.set(group, (bucket.get(group) ?? 0) + 1);\n groupTotals.set(group, (groupTotals.get(group) ?? 0) + 1);\n }\n if (byMonth.size === 0) return { rows: [], series: [] };\n\n const orderedGroups = [...groupTotals.entries()].sort((a, b) => b[1] - a[1]).map(([g]) => g);\n const topGroups = orderedGroups.slice(0, maxGroups);\n const hasOther = orderedGroups.length > maxGroups;\n const keptGroups = new Set(topGroups);\n\n const keys = [...byMonth.keys()].sort().slice(-maxMonths);\n const rows: ChartDatum[] = keys.map((key) => {\n const row: ChartDatum = { month: monthLabel(key) };\n for (const g of topGroups) row[g] = 0;\n if (hasOther) row.other = 0;\n for (const [group, count] of byMonth.get(key)!) {\n if (keptGroups.has(group)) row[group] = ((row[group] as number) ?? 0) + count;\n else if (hasOther) row.other = ((row.other as number) ?? 0) + count;\n }\n return row;\n });\n\n const series: ChartSeries[] = topGroups.map((g, i) => ({\n key: g,\n label: titleCase(g),\n color: seriesColor(i),\n }));\n if (hasOther) {\n series.push({ key: 'other', label: 'Other', color: seriesColor(topGroups.length) });\n }\n return { rows, series };\n}\n\nfunction relativeTime(value: string | undefined | null): string {\n const d = parseDate(value);\n if (!d) return '';\n const diff = Date.now() - d.getTime();\n const mins = Math.round(diff / 60000);\n if (mins < 1) return 'just now';\n if (mins < 60) return `${mins}m ago`;\n const hours = Math.round(mins / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.round(hours / 24);\n if (days < 30) return `${days}d ago`;\n const months = Math.round(days / 30);\n if (months < 12) return `${months}mo ago`;\n return `${Math.round(months / 12)}y ago`;\n}\n\ntype PillTone = 'success' | 'warning' | 'error' | 'info' | 'neutral';\nconst PILL_CLASS: Record<PillTone, string> = {\n success: 'bg-status-success-bg-subtle text-status-success-text',\n warning: 'bg-status-warning-bg-subtle text-status-warning-text',\n error: 'bg-status-error-bg-subtle text-status-error-text',\n info: 'bg-status-info-bg-subtle text-status-info-text',\n neutral: 'bg-bg-sunken text-text-secondary',\n};\n\nfunction StatusPill({ tone, children }: { tone: PillTone; children: React.ReactNode }) {\n return (\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2 py-0.5 text-[11px] font-medium capitalize whitespace-nowrap',\n PILL_CLASS[tone]\n )}\n >\n {children}\n </span>\n );\n}\n\nconst priorityTone = (p: string): PillTone =>\n p === 'critical' ? 'error' : p === 'high' ? 'warning' : p === 'medium' ? 'info' : 'neutral';\nconst maintenanceTone = (status: string): PillTone =>\n status === 'completed' ? 'success' : status === 'in_progress' ? 'info' : 'warning';\n\ninterface FeedItem {\n id: string;\n icon: ComponentType<{ className?: string }>;\n title: string;\n meta: string;\n at: string;\n tone: PillTone;\n statusLabel: string;\n}\n\nexport function DashboardPage() {\n const tc = useCopy();\n const navigate = useAssetHandlerNavigate();\n const {\n hydrated,\n overview,\n assets,\n incidents,\n maintenanceRecords,\n changeRequests,\n workOrders,\n transactions,\n } = useAssetHandlerStore();\n\n const [assetsMode, setAssetsMode] = useState<'status' | 'category'>('status');\n\n const activeIncidents = incidents.filter((i) => i.status !== 'resolved' && i.status !== 'closed');\n const criticalIncidents = incidents.filter(\n (i) => i.priority === 'critical' && i.status !== 'resolved' && i.status !== 'closed'\n );\n const pendingMaintenance = maintenanceRecords.filter(\n (m) => m.status === 'scheduled' || m.status === 'in_progress'\n );\n const openWorkOrders = workOrders.filter(\n (w) => w.status !== 'completed' && w.status !== 'cancelled'\n );\n const pendingChanges = changeRequests.filter(\n (c) => c.status === 'approved' || c.status === 'submitted'\n );\n\n // Cumulative asset-count sparkline — the only KPI with real history.\n const assetSpark = useMemo(() => {\n const byMonth = new Map<string, number>();\n for (const a of assets) {\n const d = parseDate(a.createdAt);\n if (!d) continue;\n const key = monthKey(d);\n byMonth.set(key, (byMonth.get(key) ?? 0) + 1);\n }\n const keys = [...byMonth.keys()].sort();\n return keys.reduce<number[]>((acc, k) => {\n const prev = acc.length ? acc[acc.length - 1] : 0;\n acc.push(prev + (byMonth.get(k) ?? 0));\n return acc;\n }, []);\n }, [assets]);\n\n const metrics = [\n {\n label: tc('assethandler.dashboard.metrics.totalAssets', 'Total {{assets}}'),\n value: overview?.totalAssets ?? assets.length,\n icon: Box,\n spark: assetSpark.length > 1 ? assetSpark : undefined,\n hero: true,\n },\n {\n label: tc('assethandler.dashboard.metrics.openIncidents', 'Open Incidents'),\n value: overview?.openIncidents ?? activeIncidents.length,\n icon: AlertTriangle,\n },\n {\n label: tc('assethandler.dashboard.metrics.openWorkOrders', 'Open Work Orders'),\n value: overview?.openWorkOrders ?? openWorkOrders.length,\n icon: ClipboardList,\n },\n {\n label: tc('assethandler.dashboard.metrics.transactions', 'Transactions'),\n value: overview?.totalTransactions ?? transactions.length,\n icon: Receipt,\n },\n ];\n\n // Portfolio-by-category donut (real asset counts).\n const categoryDonut = useMemo<DonutSlice[]>(() => {\n const counts = assets.reduce<Record<string, number>>((acc, a) => {\n const key = a.category || 'uncategorized';\n acc[key] = (acc[key] ?? 0) + 1;\n return acc;\n }, {});\n return Object.entries(counts)\n .sort((a, b) => b[1] - a[1])\n .map(([name, value]) => ({ name: titleCase(name), value }));\n }, [assets]);\n\n // Assets-added-over-time (stacked by status or category via the toggle).\n const assetsSeries = useMemo(\n () =>\n monthlyGrouped(\n assets,\n (a) => a.createdAt,\n (a) => (assetsMode === 'status' ? a.status : a.category),\n 8,\n 6\n ),\n [assets, assetsMode]\n );\n\n // Cumulative transaction value over time (real transaction amounts).\n const valueTrend = useMemo<ChartDatum[]>(() => {\n const byMonth = new Map<string, number>();\n for (const tx of transactions) {\n const d = parseDate(tx.date);\n if (!d) continue;\n const key = monthKey(d);\n byMonth.set(key, (byMonth.get(key) ?? 0) + tx.amount);\n }\n const keys = [...byMonth.keys()].sort();\n const raw = keys.reduce<number[]>((acc, k) => {\n const prev = acc.length ? acc[acc.length - 1] : 0;\n acc.push(prev + (byMonth.get(k) ?? 0));\n return acc;\n }, []);\n return keys.map((k, i) => ({ month: monthLabel(k), value: Math.round(raw[i]) }));\n }, [transactions]);\n const txCurrency = transactions[0]?.currency ?? 'USD';\n\n // Unified recent-activity feed (merged real records, newest first).\n const feed = useMemo<FeedItem[]>(() => {\n const items: FeedItem[] = [];\n for (const a of assets) {\n items.push({\n id: `asset-${a.id}`,\n icon: Box,\n title: a.name,\n meta: tc('assethandler.dashboard.activity.assetRegistered', '{{asset}} registered'),\n at: a.createdAt,\n tone:\n a.status === 'active' ? 'success' : a.status === 'maintenance' ? 'warning' : 'neutral',\n statusLabel: a.status.replace(/_/g, ' '),\n });\n }\n for (const inc of incidents) {\n items.push({\n id: `inc-${inc.id}`,\n icon: AlertTriangle,\n title: inc.title,\n meta: `Incident · ${inc.priority}`,\n at: inc.createdAt,\n tone:\n inc.status === 'resolved' || inc.status === 'closed'\n ? 'success'\n : inc.priority === 'critical' || inc.priority === 'high'\n ? 'error'\n : 'warning',\n statusLabel: inc.status.replace(/_/g, ' '),\n });\n }\n for (const wo of workOrders) {\n items.push({\n id: `wo-${wo.id}`,\n icon: ClipboardList,\n title: wo.title,\n meta: `Work order · ${wo.type}`,\n at: wo.createdAt,\n tone:\n wo.status === 'completed'\n ? 'success'\n : wo.status === 'in_progress'\n ? 'info'\n : wo.status === 'cancelled'\n ? 'neutral'\n : 'warning',\n statusLabel: wo.status.replace(/_/g, ' '),\n });\n }\n for (const m of maintenanceRecords) {\n const at = m.completedDate ?? m.scheduledDate;\n if (!at) continue;\n items.push({\n id: `mnt-${m.id}`,\n icon: Wrench,\n title: m.title,\n meta: 'Maintenance',\n at,\n tone:\n m.status === 'completed' ? 'success' : m.status === 'in_progress' ? 'info' : 'warning',\n statusLabel: m.status.replace(/_/g, ' '),\n });\n }\n return items\n .filter((i) => parseDate(i.at))\n .sort((a, b) => b.at.localeCompare(a.at))\n .slice(0, 7);\n }, [assets, incidents, workOrders, maintenanceRecords, tc]);\n\n const upcomingMaintenance = [...maintenanceRecords]\n .filter((m) => m.status !== 'completed' && m.status !== 'cancelled')\n .sort((a, b) => (a.scheduledDate ?? '').localeCompare(b.scheduledDate ?? ''))\n .slice(0, 8);\n\n return (\n <div className=\"space-y-6 p-4 sm:p-6\">\n {/* Header */}\n <div className=\"relative overflow-hidden rounded-xl border border-border-seam bg-gloss-card p-5 sm:p-6\">\n <AuroraBackground intensity=\"subtle\" />\n <div className=\"relative flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <h1 className=\"text-2xl font-bold sm:text-3xl\">\n <GradientText>{tc('assethandler.dashboard.title', 'Dashboard')}</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary mt-1\">\n {tc(\n 'assethandler.dashboard.description',\n 'Overview of your IT asset portfolio and operations'\n )}\n </p>\n </div>\n <CTAOverflowMenu\n primary={{\n label: tc('assethandler.dashboard.actions.addAsset', 'Add {{asset}}'),\n onSelect: () => navigate('/assets/asset-create'),\n }}\n actions={[\n {\n label: tc('assethandler.dashboard.actions.viewAnalytics', 'View Analytics'),\n onSelect: () => navigate('/analytics'),\n },\n ]}\n />\n </div>\n </div>\n\n <PagePurpose>\n {tc(\n 'assethandler.dashboard.purpose',\n 'Your command center for the whole {{assetLower}} estate — see what needs attention (open incidents, due maintenance, critical alerts) and recent activity at a glance, then jump straight to the area that needs you. Start here every day to know where to act.'\n )}\n </PagePurpose>\n\n {/* KPI Metrics */}\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-4\">\n {metrics.map((metric) => (\n <StatTile\n key={metric.label}\n label={metric.label}\n value={hydrated ? metric.value : '—'}\n format={formatCompact}\n icon={metric.icon}\n spark={metric.spark}\n hero={metric.hero}\n />\n ))}\n </div>\n\n {/* Assets-over-time + Recent activity rail */}\n <div className=\"grid gap-6 lg:grid-cols-3\">\n <ChartCard\n className=\"lg:col-span-2\"\n title={tc('assethandler.dashboard.assetsChart.title', '{{assets}} over time')}\n subtitle={tc(\n 'assethandler.dashboard.assetsChart.subtitle',\n '{{assets}} added each month, from real registration dates'\n )}\n icon={Box}\n actions={\n <div className=\"inline-flex rounded-lg bg-bg-sunken p-0.5\">\n {(['status', 'category'] as const).map((mode) => (\n <button\n key={mode}\n type=\"button\"\n onClick={() => setAssetsMode(mode)}\n className={cn(\n 'rounded-md px-3 py-1 text-xs font-medium transition-colors',\n assetsMode === mode\n ? 'bg-bg-surface text-text-primary shadow-sm'\n : 'text-text-secondary hover:text-text-primary'\n )}\n >\n {mode === 'status' ? 'By status' : 'By category'}\n </button>\n ))}\n </div>\n }\n >\n {assetsSeries.rows.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={tc('assethandler.dashboard.assetsChart.empty.title', 'No history yet')}\n description={tc(\n 'assethandler.dashboard.assetsChart.empty.description',\n 'Register {{assetsLower}} and their monthly trend will appear here.'\n )}\n />\n ) : (\n <BarsChart\n data={assetsSeries.rows}\n xKey=\"month\"\n series={assetsSeries.series}\n stacked\n height={280}\n ariaLabel={tc(\n 'assethandler.dashboard.assetsChart.aria',\n '{{assets}} added per month'\n )}\n />\n )}\n </ChartCard>\n\n {/* Recent Activity rail */}\n <GlassCard treatment=\"insight\" className=\"border-border-seam\">\n <div className=\"flex flex-col gap-4 p-5\">\n <div className=\"flex items-center justify-between\">\n <h3 className=\"flex items-center gap-2 text-base font-semibold text-text-primary\">\n <Activity className=\"h-4 w-4 text-text-secondary\" />\n {tc('assethandler.dashboard.activity.title', 'Recent activity')}\n </h3>\n <button\n type=\"button\"\n onClick={() => navigate('/analytics')}\n className=\"inline-flex items-center gap-1 text-xs font-medium text-primary hover:underline\"\n >\n {tc('assethandler.dashboard.activity.viewAll', 'View all')}\n <ArrowRight className=\"h-3 w-3\" />\n </button>\n </div>\n {feed.length === 0 ? (\n <p className=\"py-6 text-center text-sm text-text-secondary\">\n {tc(\n 'assethandler.dashboard.activity.empty',\n 'Activity across your estate will show up here.'\n )}\n </p>\n ) : (\n <ul className=\"space-y-1\">\n {feed.map((item) => {\n const Icon = item.icon;\n return (\n <li\n key={item.id}\n className=\"flex items-start gap-3 rounded-lg px-2 py-2 hover:bg-bg-sunken/60\"\n >\n <span className=\"mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-bg-sunken text-text-secondary\">\n <Icon className=\"h-4 w-4\" />\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center justify-between gap-2\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {item.title}\n </p>\n <StatusPill tone={item.tone}>{item.statusLabel}</StatusPill>\n </div>\n <p className=\"mt-0.5 flex items-center gap-1.5 text-xs text-text-secondary capitalize\">\n <span className=\"truncate\">{item.meta}</span>\n <span aria-hidden=\"true\">·</span>\n <span className=\"shrink-0 normal-case text-text-muted\">\n {relativeTime(item.at)}\n </span>\n </p>\n </div>\n </li>\n );\n })}\n </ul>\n )}\n </div>\n </GlassCard>\n </div>\n\n {/* Transaction value trend (full width) */}\n <ChartCard\n title={tc('assethandler.dashboard.value.title', 'Transaction value')}\n subtitle={tc(\n 'assethandler.dashboard.value.subtitle',\n 'Cumulative transaction amount over time'\n )}\n icon={Receipt}\n >\n {valueTrend.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={tc('assethandler.dashboard.value.empty.title', 'No transactions yet')}\n description={tc(\n 'assethandler.dashboard.value.empty.description',\n '{{asset}} purchases, leases and disposals will chart here as they are recorded.'\n )}\n />\n ) : (\n <TrendChart\n data={valueTrend}\n xKey=\"month\"\n series={[{ key: 'value', label: 'Cumulative value' }]}\n valueFormat={formatCurrencyCompact(txCurrency)}\n height={260}\n ariaLabel=\"Cumulative transaction value over time\"\n />\n )}\n </ChartCard>\n\n {/* Portfolio donut + Operations summary */}\n <div className=\"grid gap-6 lg:grid-cols-3\">\n <ChartCard\n className=\"lg:col-span-2\"\n title={tc('assethandler.dashboard.portfolio.title', 'Portfolio by category')}\n subtitle={tc(\n 'assethandler.dashboard.portfolio.description',\n '{{asset}} distribution by category'\n )}\n icon={Box}\n >\n {categoryDonut.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={tc('assethandler.dashboard.portfolio.empty.title', 'No {{assetsLower}} yet')}\n description={tc(\n 'assethandler.dashboard.portfolio.empty.description',\n 'Register your first {{assetLower}} and category distribution will appear here.'\n )}\n />\n ) : (\n <DonutChart\n data={categoryDonut}\n centerLabel={tc('assethandler.dashboard.portfolio.centerLabel', '{{assets}}')}\n centerValue={assets.length}\n height={260}\n ariaLabel={tc('assethandler.dashboard.portfolio.aria', '{{assets}} by category')}\n />\n )}\n </ChartCard>\n\n <GlassCard treatment=\"glass\" className=\"border-border-seam\">\n <div className=\"flex flex-col gap-4 p-5\">\n <h3 className=\"text-base font-semibold text-text-primary\">\n {tc('assethandler.dashboard.operations.title', 'Operations summary')}\n </h3>\n <div className=\"grid grid-cols-2 gap-3\">\n {[\n {\n icon: Wrench,\n value: pendingMaintenance.length,\n label: tc(\n 'assethandler.dashboard.operations.pendingMaintenance',\n 'Pending Maintenance'\n ),\n },\n {\n icon: Activity,\n value: openWorkOrders.length,\n label: tc('assethandler.dashboard.operations.openWorkOrders', 'Open Work Orders'),\n },\n {\n icon: Clock,\n value: pendingChanges.length,\n label: tc('assethandler.dashboard.operations.pendingChanges', 'Pending Changes'),\n },\n {\n icon: CheckCircle,\n value: criticalIncidents.length,\n label: tc('assethandler.dashboard.operations.criticalAlerts', 'Critical Alerts'),\n },\n ].map((op) => {\n const Icon = op.icon;\n return (\n <div\n key={op.label}\n className=\"rounded-lg border border-border-seam bg-gloss-card p-4 text-center\"\n >\n <Icon className=\"mx-auto mb-2 h-5 w-5 text-text-secondary\" />\n <p className=\"text-2xl font-bold tabular-nums\">{op.value}</p>\n <p className=\"text-xs text-text-secondary\">{op.label}</p>\n </div>\n );\n })}\n </div>\n </div>\n </GlassCard>\n </div>\n\n {/* Active incidents + Open work orders */}\n <div className=\"grid gap-6 lg:grid-cols-2\">\n <GlassCard treatment=\"glass\" className=\"border-border-seam\">\n <div className=\"flex flex-col gap-4 p-5\">\n <div>\n <h3 className=\"flex items-center gap-2 text-base font-semibold text-text-primary\">\n <AlertTriangle className=\"h-4 w-4 text-status-error-text\" />\n {tc('assethandler.dashboard.incidents.title', 'Active Incidents')}\n </h3>\n <p className=\"mt-0.5 text-sm text-text-secondary\">\n {activeIncidents.length}{' '}\n {tc('assethandler.dashboard.incidents.unresolvedCount', 'unresolved incidents')}\n </p>\n </div>\n {activeIncidents.length === 0 ? (\n <p className=\"py-4 text-center text-sm text-text-secondary\">\n {tc(\n 'assethandler.dashboard.incidents.empty',\n 'No unresolved incidents — all clear.'\n )}\n </p>\n ) : (\n <div className=\"space-y-2\">\n {activeIncidents.slice(0, 5).map((inc) => (\n <button\n key={inc.id}\n type=\"button\"\n onClick={() => navigate('/itil/incident-management')}\n className=\"flex w-full items-start gap-3 rounded-lg border border-border-seam p-3 text-left hover:bg-bg-sunken/60\"\n >\n <StatusPill tone={priorityTone(inc.priority)}>{inc.priority}</StatusPill>\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium\">{inc.title}</p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">\n {inc.assignedTo ||\n tc('assethandler.dashboard.incidents.unassigned', 'Unassigned')}\n </p>\n </div>\n </button>\n ))}\n </div>\n )}\n </div>\n </GlassCard>\n\n <GlassCard treatment=\"glass\" className=\"border-border-seam\">\n <div className=\"flex flex-col gap-4 p-5\">\n <div>\n <h3 className=\"text-base font-semibold text-text-primary\">\n {tc('assethandler.dashboard.workOrders.title', 'Open Work Orders')}\n </h3>\n <p className=\"mt-0.5 text-sm text-text-secondary\">\n {tc('assethandler.dashboard.workOrders.description', 'Latest work in progress')}\n </p>\n </div>\n {openWorkOrders.length === 0 ? (\n <p className=\"py-4 text-center text-sm text-text-secondary\">\n {tc(\n 'assethandler.dashboard.workOrders.empty',\n 'No open work orders. Create one from the Operations hub.'\n )}\n </p>\n ) : (\n <div className=\"space-y-2\">\n {[...openWorkOrders]\n .sort((a, b) => b.createdAt.localeCompare(a.createdAt))\n .slice(0, 5)\n .map((item) => (\n <div\n key={item.id}\n className=\"flex items-center gap-3 rounded-lg border border-border-seam p-3\"\n >\n <StatusPill tone={item.status === 'in_progress' ? 'info' : 'warning'}>\n {item.status.replace(/_/g, ' ')}\n </StatusPill>\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm\">{item.title}</p>\n <p className=\"text-xs text-text-secondary capitalize\">\n {item.type} &middot; {item.priority}\n </p>\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n </GlassCard>\n </div>\n\n {/* Upcoming Maintenance — table on md+, cards on mobile */}\n <GlassCard treatment=\"glass\" className=\"border-border-seam\">\n <div className=\"flex flex-col gap-4 p-5\">\n <div>\n <h3 className=\"flex items-center gap-2 text-base font-semibold text-text-primary\">\n <CalendarClock className=\"h-4 w-4 text-text-secondary\" />\n {tc('assethandler.dashboard.maintenance.title', 'Upcoming Maintenance')}\n </h3>\n <p className=\"mt-0.5 text-sm text-text-secondary\">\n {tc(\n 'assethandler.dashboard.maintenance.description',\n 'Scheduled maintenance activities'\n )}\n </p>\n </div>\n {upcomingMaintenance.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-tasks\"\n title={tc(\n 'assethandler.dashboard.maintenance.empty.title',\n 'No maintenance scheduled'\n )}\n description={tc(\n 'assethandler.dashboard.maintenance.empty.description',\n 'Plan preventive maintenance from the scheduler and it will show up here.'\n )}\n />\n ) : (\n <>\n {/* Mobile: stacked cards */}\n <div className=\"space-y-2 md:hidden\">\n {upcomingMaintenance.map((rec) => (\n <div key={rec.id} className=\"rounded-lg border border-border-seam p-3\">\n <div className=\"flex items-start justify-between gap-2\">\n <p className=\"min-w-0 flex-1 truncate text-sm font-medium\">{rec.title}</p>\n <StatusPill tone={maintenanceTone(rec.status)}>\n {rec.status.replace(/_/g, ' ')}\n </StatusPill>\n </div>\n <div className=\"mt-2 flex flex-wrap items-center gap-2 text-xs text-text-secondary\">\n <span className=\"capitalize\">{rec.type}</span>\n <StatusPill tone={priorityTone(rec.priority)}>{rec.priority}</StatusPill>\n <span>\n {rec.scheduledDate ? new Date(rec.scheduledDate).toLocaleDateString() : '—'}\n </span>\n </div>\n </div>\n ))}\n </div>\n {/* md+: table */}\n <div className=\"hidden overflow-x-auto md:block\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b border-border-seam text-text-secondary\">\n <th className=\"py-2 text-left font-medium\">Title</th>\n <th className=\"py-2 text-left font-medium\">Type</th>\n <th className=\"py-2 text-left font-medium\">Priority</th>\n <th className=\"py-2 text-left font-medium\">Scheduled</th>\n <th className=\"py-2 text-left font-medium\">Status</th>\n </tr>\n </thead>\n <tbody>\n {upcomingMaintenance.map((rec) => (\n <tr\n key={rec.id}\n className=\"border-b border-border-seam hover:bg-bg-sunken/50\"\n >\n <td className=\"py-2.5 font-medium\">{rec.title}</td>\n <td className=\"py-2.5 capitalize\">{rec.type}</td>\n <td className=\"py-2.5\">\n <StatusPill tone={priorityTone(rec.priority)}>{rec.priority}</StatusPill>\n </td>\n <td className=\"py-2.5\">\n {rec.scheduledDate\n ? new Date(rec.scheduledDate).toLocaleDateString()\n : '—'}\n </td>\n <td className=\"py-2.5\">\n <StatusPill tone={maintenanceTone(rec.status)}>\n {rec.status.replace(/_/g, ' ')}\n </StatusPill>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </>\n )}\n </div>\n </GlassCard>\n\n <NextSteps\n storageKey=\"assethandler-dashboard\"\n steps={[\n {\n id: 'view-assets',\n label: tc(\n 'assethandler.dashboard.nextSteps.viewAssets.label',\n 'Browse your {{assetLower}} inventory'\n ),\n description: tc(\n 'assethandler.dashboard.nextSteps.viewAssets.description',\n 'See every tracked {{assetLower}}, its status and owner.'\n ),\n onClick: () => navigate('/assets/asset-list'),\n },\n {\n id: 'add-asset',\n label: tc(\n 'assethandler.dashboard.nextSteps.addAsset.label',\n 'Register a new {{assetLower}}'\n ),\n description: tc(\n 'assethandler.dashboard.nextSteps.addAsset.description',\n 'Add equipment, hardware or software to start tracking it.'\n ),\n onClick: () => navigate('/assets/asset-create'),\n },\n {\n id: 'incidents',\n label: tc('assethandler.dashboard.nextSteps.incidents.label', 'Resolve open incidents'),\n description: tc(\n 'assethandler.dashboard.nextSteps.incidents.description',\n 'Triage service-affecting issues before they breach SLA.'\n ),\n onClick: () => navigate('/itil/incident-management'),\n },\n {\n id: 'maintenance',\n label: tc(\n 'assethandler.dashboard.nextSteps.maintenance.label',\n 'Check the maintenance calendar'\n ),\n description: tc(\n 'assethandler.dashboard.nextSteps.maintenance.description',\n 'Stay ahead of scheduled and overdue maintenance.'\n ),\n onClick: () => navigate('/maintenance/maintenance-calendar'),\n },\n ]}\n />\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"PortfolioPortfolioOverviewPage.d.ts","sourceRoot":"","sources":["../../../src/assethandler/pages/PortfolioPortfolioOverviewPage.tsx"],"names":[],"mappings":"AAgHA,wBAAgB,8BAA8B,gCA2Q7C"}
1
+ {"version":3,"file":"PortfolioPortfolioOverviewPage.d.ts","sourceRoot":"","sources":["../../../src/assethandler/pages/PortfolioPortfolioOverviewPage.tsx"],"names":[],"mappings":"AAiHA,wBAAgB,8BAA8B,gCA4Q7C"}