@burdenoff/microfe-assethandler 2026.625.1 → 2026.625.2
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.
- package/dist/assethandler/pages/AiPredictionsPage.js +42 -41
- package/dist/assethandler/pages/AiPredictionsPage.js.map +1 -1
- package/dist/assethandler/pages/AnalyticsPage.js +538 -534
- package/dist/assethandler/pages/AnalyticsPage.js.map +1 -1
- package/dist/assethandler/pages/AssetsAssetCategoriesPage.js +135 -125
- package/dist/assethandler/pages/AssetsAssetCategoriesPage.js.map +1 -1
- package/dist/assethandler/pages/AssetsAssetCheckInOutPage.js +90 -92
- package/dist/assethandler/pages/AssetsAssetCheckInOutPage.js.map +1 -1
- package/dist/assethandler/pages/AssetsAssetCreatePage.js +131 -124
- package/dist/assethandler/pages/AssetsAssetCreatePage.js.map +1 -1
- package/dist/assethandler/pages/AssetsAssetDetailPage.js +214 -185
- package/dist/assethandler/pages/AssetsAssetDetailPage.js.map +1 -1
- package/dist/assethandler/pages/AssetsAssetEditPage.js +168 -156
- package/dist/assethandler/pages/AssetsAssetEditPage.js.map +1 -1
- package/dist/assethandler/pages/AssetsAssetListPage.js +207 -187
- package/dist/assethandler/pages/AssetsAssetListPage.js.map +1 -1
- package/dist/assethandler/pages/AssetsAssetTrackingPage.js +82 -71
- package/dist/assethandler/pages/AssetsAssetTrackingPage.js.map +1 -1
- package/dist/assethandler/pages/AuditTrailPage.js +93 -91
- package/dist/assethandler/pages/AuditTrailPage.js.map +1 -1
- package/dist/assethandler/pages/CmdbBrowserPage.js +32 -33
- package/dist/assethandler/pages/CmdbBrowserPage.js.map +1 -1
- package/dist/assethandler/pages/DashboardPage.js +157 -126
- package/dist/assethandler/pages/DashboardPage.js.map +1 -1
- package/dist/assethandler/pages/DigitalTwinPage.js +25 -26
- package/dist/assethandler/pages/DigitalTwinPage.js.map +1 -1
- package/dist/assethandler/pages/DiscoveryJobsPage.js +50 -50
- package/dist/assethandler/pages/DiscoveryJobsPage.js.map +1 -1
- package/dist/assethandler/pages/EsgDashboardPage.js +43 -42
- package/dist/assethandler/pages/EsgDashboardPage.js.map +1 -1
- package/dist/assethandler/pages/FinanceBudgetDetailPage.js +96 -82
- package/dist/assethandler/pages/FinanceBudgetDetailPage.js.map +1 -1
- package/dist/assethandler/pages/FinanceFinanceHubPage.js +137 -103
- package/dist/assethandler/pages/FinanceFinanceHubPage.js.map +1 -1
- package/dist/assethandler/pages/FinanceInvoiceDetailPage.js +77 -66
- package/dist/assethandler/pages/FinanceInvoiceDetailPage.js.map +1 -1
- package/dist/assethandler/pages/IotDevicesPage.js +34 -35
- package/dist/assethandler/pages/IotDevicesPage.js.map +1 -1
- package/dist/assethandler/pages/ItilChangeDetailPage.js +236 -199
- package/dist/assethandler/pages/ItilChangeDetailPage.js.map +1 -1
- package/dist/assethandler/pages/ItilChangeManagementPage.js +66 -64
- package/dist/assethandler/pages/ItilChangeManagementPage.js.map +1 -1
- package/dist/assethandler/pages/ItilIncidentDetailPage.js +237 -200
- package/dist/assethandler/pages/ItilIncidentDetailPage.js.map +1 -1
- package/dist/assethandler/pages/ItilIncidentManagementPage.js +99 -97
- package/dist/assethandler/pages/ItilIncidentManagementPage.js.map +1 -1
- package/dist/assethandler/pages/ItilItilhubPage.js +166 -122
- package/dist/assethandler/pages/ItilItilhubPage.js.map +1 -1
- package/dist/assethandler/pages/ItilProblemDetailPage.js +193 -156
- package/dist/assethandler/pages/ItilProblemDetailPage.js.map +1 -1
- package/dist/assethandler/pages/ItilProblemManagementPage.js +63 -61
- package/dist/assethandler/pages/ItilProblemManagementPage.js.map +1 -1
- package/dist/assethandler/pages/KnowledgeBasePage.js +45 -43
- package/dist/assethandler/pages/KnowledgeBasePage.js.map +1 -1
- package/dist/assethandler/pages/MaintenanceMaintenanceCalendarPage.js +70 -68
- package/dist/assethandler/pages/MaintenanceMaintenanceCalendarPage.js.map +1 -1
- package/dist/assethandler/pages/MaintenanceMaintenanceSchedulerPage.js +77 -62
- package/dist/assethandler/pages/MaintenanceMaintenanceSchedulerPage.js.map +1 -1
- package/dist/assethandler/pages/MarketplaceMarketplaceDetailPage.js +162 -151
- package/dist/assethandler/pages/MarketplaceMarketplaceDetailPage.js.map +1 -1
- package/dist/assethandler/pages/MarketplaceMarketplaceListPage.js +64 -57
- package/dist/assethandler/pages/MarketplaceMarketplaceListPage.js.map +1 -1
- package/dist/assethandler/pages/MarketplaceMarketplaceOrdersPage.js +125 -108
- package/dist/assethandler/pages/MarketplaceMarketplaceOrdersPage.js.map +1 -1
- package/dist/assethandler/pages/MarketplaceMarketplaceSellPage.js +67 -61
- package/dist/assethandler/pages/MarketplaceMarketplaceSellPage.js.map +1 -1
- package/dist/assethandler/pages/OperationsMaintenanceDetailPage.js +203 -166
- package/dist/assethandler/pages/OperationsMaintenanceDetailPage.js.map +1 -1
- package/dist/assethandler/pages/OperationsOperationsHubPage.js +125 -95
- package/dist/assethandler/pages/OperationsOperationsHubPage.js.map +1 -1
- package/dist/assethandler/pages/OperationsWorkOrderDetailPage.js +165 -151
- package/dist/assethandler/pages/OperationsWorkOrderDetailPage.js.map +1 -1
- package/dist/assethandler/pages/PortfolioPortfolioOverviewPage.js +83 -81
- package/dist/assethandler/pages/PortfolioPortfolioOverviewPage.js.map +1 -1
- package/dist/assethandler/pages/ProvenancePage.js +56 -53
- package/dist/assethandler/pages/ProvenancePage.js.map +1 -1
- package/dist/assethandler/pages/ReportsReportBuilderPage.js +80 -73
- package/dist/assethandler/pages/ReportsReportBuilderPage.js.map +1 -1
- package/dist/assethandler/pages/ReportsReportsDashboardPage.js +112 -77
- package/dist/assethandler/pages/ReportsReportsDashboardPage.js.map +1 -1
- package/dist/assethandler/pages/ReportsReportsListPage.js +119 -103
- package/dist/assethandler/pages/ReportsReportsListPage.js.map +1 -1
- package/dist/assethandler/pages/SamLicensesPage.js +32 -33
- package/dist/assethandler/pages/SamLicensesPage.js.map +1 -1
- package/dist/assethandler/pages/SecurityComplianceDetailPage.js +60 -52
- package/dist/assethandler/pages/SecurityComplianceDetailPage.js.map +1 -1
- package/dist/assethandler/pages/SecurityPolicyDetailPage.js +134 -117
- package/dist/assethandler/pages/SecurityPolicyDetailPage.js.map +1 -1
- package/dist/assethandler/pages/SecurityScheduleBackupPage.js +63 -57
- package/dist/assethandler/pages/SecurityScheduleBackupPage.js.map +1 -1
- package/dist/assethandler/pages/SecuritySecurityEventDetailPage.js +131 -117
- package/dist/assethandler/pages/SecuritySecurityEventDetailPage.js.map +1 -1
- package/dist/assethandler/pages/SecuritySecurityHubPage.js +147 -113
- package/dist/assethandler/pages/SecuritySecurityHubPage.js.map +1 -1
- package/dist/assethandler/pages/TransactionsTransactionDetailPage.js +235 -218
- package/dist/assethandler/pages/TransactionsTransactionDetailPage.js.map +1 -1
- package/dist/assethandler/pages/TransactionsTransactionListPage.js +118 -116
- package/dist/assethandler/pages/TransactionsTransactionListPage.js.map +1 -1
- package/dist/assethandler/pages/UsersPage.js +108 -99
- package/dist/assethandler/pages/UsersPage.js.map +1 -1
- package/dist/assethandler/pages/UsersUserCreatePage.js +74 -67
- package/dist/assethandler/pages/UsersUserCreatePage.js.map +1 -1
- package/dist/assethandler/pages/UsersUserManagementHubPage.js +128 -93
- package/dist/assethandler/pages/UsersUserManagementHubPage.js.map +1 -1
- package/dist/assethandler/pages/WorkflowsWorkflowBuilderPage.js +211 -193
- package/dist/assethandler/pages/WorkflowsWorkflowBuilderPage.js.map +1 -1
- package/dist/assethandler/pages/WorkflowsWorkflowExecutionsPage.js +88 -86
- package/dist/assethandler/pages/WorkflowsWorkflowExecutionsPage.js.map +1 -1
- package/dist/assethandler/pages/WorkflowsWorkflowListPage.js +68 -60
- package/dist/assethandler/pages/WorkflowsWorkflowListPage.js.map +1 -1
- package/dist/assethandler/pages/WorkflowsWorkflowTemplatesPage.js +71 -68
- package/dist/assethandler/pages/WorkflowsWorkflowTemplatesPage.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnalyticsPage.js","names":[],"sources":["../../../src/assethandler/pages/AnalyticsPage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n Badge,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n Separator,\n GradientText,\n GlassCard,\n CTAOverflowMenu,\n EmphasisPanel,\n} from '@burdenoff/fe-libs/ui';\nimport {\n BarChart3,\n TrendingUp,\n TrendingDown,\n DollarSign,\n Box,\n PieChart,\n Activity,\n Download,\n ArrowUpRight,\n ArrowDownRight,\n} from 'lucide-react';\nimport { useAssetHandlerStore } from '../store/assethandlerStore';\n\nexport function AnalyticsPage() {\n const { assets, portfolio, transactions, incidents, maintenanceRecords, workflows } =\n useAssetHandlerStore();\n const [timeRange, setTimeRange] = useState<'7d' | '30d' | '90d' | '1y'>('30d');\n\n const totalValue = assets.reduce((sum, a) => sum + a.currentValue, 0);\n const totalOriginal = assets.reduce((sum, a) => sum + a.value, 0);\n const depreciationTotal = totalOriginal - totalValue;\n const depreciationPct =\n totalOriginal > 0 ? ((depreciationTotal / totalOriginal) * 100).toFixed(1) : '0';\n const avgAssetValue = assets.length > 0 ? Math.round(totalValue / assets.length) : 0;\n\n const categoryBreakdown = assets.reduce<Record<string, { count: number; value: number }>>(\n (acc, a) => {\n const cat = a.category.replace('_', ' ');\n if (!acc[cat]) acc[cat] = { count: 0, value: 0 };\n acc[cat].count++;\n acc[cat].value += a.currentValue;\n return acc;\n },\n {}\n );\n\n const statusBreakdown = assets.reduce<Record<string, number>>((acc, a) => {\n acc[a.status] = (acc[a.status] || 0) + 1;\n return acc;\n }, {});\n\n const departmentBreakdown = assets.reduce<Record<string, { count: number; value: number }>>(\n (acc, a) => {\n if (!acc[a.department]) acc[a.department] = { count: 0, value: 0 };\n acc[a.department].count++;\n acc[a.department].value += a.currentValue;\n return acc;\n },\n {}\n );\n\n const resolvedIncidents = incidents.filter(\n (i) => i.status === 'resolved' || i.status === 'closed'\n );\n const slaBreached = incidents.filter((i) => i.slaBreached);\n const completedMaintenance = maintenanceRecords.filter((m) => m.status === 'completed');\n const totalMaintenanceCost = maintenanceRecords.reduce((sum, m) => sum + m.cost, 0);\n\n return (\n <div className=\"space-y-6 p-6\">\n {/* Header */}\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-3xl font-bold\">\n <GradientText>Analytics & Business Intelligence</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary mt-1\">\n Comprehensive asset management analytics and insights\n </p>\n </div>\n <div className=\"flex gap-2\">\n <select\n value={timeRange}\n onChange={(e) => setTimeRange(e.target.value as typeof timeRange)}\n className=\"rounded-md border border-border-default bg-bg-surface px-3 py-1.5 text-sm\"\n >\n <option value=\"7d\">Last 7 days</option>\n <option value=\"30d\">Last 30 days</option>\n <option value=\"90d\">Last 90 days</option>\n <option value=\"1y\">Last year</option>\n </select>\n <CTAOverflowMenu\n primary={{ label: 'Generate Report', onSelect: () => {} }}\n actions={[\n { label: 'Export', onSelect: () => {}, icon: <Download className=\"h-4 w-4\" /> },\n ]}\n />\n </div>\n </div>\n\n <Tabs defaultValue=\"overview\">\n <TabsList>\n <TabsTrigger value=\"overview\">Overview</TabsTrigger>\n <TabsTrigger value=\"financial\">Financial</TabsTrigger>\n <TabsTrigger value=\"operational\">Operational</TabsTrigger>\n <TabsTrigger value=\"insights\">Insights</TabsTrigger>\n </TabsList>\n\n {/* Overview Tab */}\n <TabsContent value=\"overview\" className=\"space-y-6 mt-6\">\n {/* Key Metrics */}\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-4\">\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Total Portfolio Value</CardTitle>\n <DollarSign className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n ${portfolio.totalValue.toLocaleString()}\n </div>\n <p className=\"text-xs text-text-secondary flex items-center mt-1\">\n <ArrowUpRight className=\"mr-1 h-3 w-3 text-status-success-text\" />\n <span className=\"text-status-success-text\">+5.6%</span> from last quarter\n </p>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Total Depreciation</CardTitle>\n <TrendingDown className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold text-status-error-text\">\n -${depreciationTotal.toLocaleString()}\n </div>\n <p className=\"text-xs text-text-secondary\">{depreciationPct}% of original value</p>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Total Assets</CardTitle>\n <Box className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{portfolio.totalAssets}</div>\n <p className=\"text-xs text-text-secondary\">\n {assets.filter((a) => a.status === 'active').length} currently active\n </p>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Avg. Asset Value</CardTitle>\n <BarChart3 className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n ${avgAssetValue.toLocaleString()}\n </div>\n <p className=\"text-xs text-text-secondary\">Across all categories</p>\n </CardContent>\n </GlassCard>\n </div>\n\n {/* Category & Status Breakdown */}\n <div className=\"grid gap-6 lg:grid-cols-2\">\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <PieChart className=\"h-4 w-4\" />\n Category Distribution\n </CardTitle>\n <CardDescription>Assets by category with values</CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"space-y-3\">\n {Object.entries(categoryBreakdown)\n .sort((a, b) => b[1].value - a[1].value)\n .map(([cat, data]) => {\n const pct = Math.round((data.count / assets.length) * 100);\n return (\n <div key={cat} className=\"space-y-1\">\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"font-medium capitalize\">{cat}</span>\n <span className=\"text-text-secondary\">\n {data.count} · ${(data.value / 1000).toFixed(1)}K\n </span>\n </div>\n <div className=\"h-2 rounded-full bg-bg-sunken overflow-hidden\">\n <div\n className=\"h-full rounded-full bg-action-primary-bg\"\n style={{ width: `${pct}%` }}\n />\n </div>\n </div>\n );\n })}\n </div>\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <Activity className=\"h-4 w-4\" />\n Status Breakdown\n </CardTitle>\n <CardDescription>Current asset status distribution</CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"space-y-3\">\n {Object.entries(statusBreakdown).map(([status, count]) => {\n const pct = Math.round((count / assets.length) * 100);\n return (\n <div key={status} className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <Badge\n variant={\n status === 'active'\n ? 'default'\n : status === 'under_maintenance'\n ? 'secondary'\n : 'outline'\n }\n >\n {status.replace('_', ' ')}\n </Badge>\n </div>\n <div className=\"flex items-center gap-3\">\n <div className=\"h-2 w-24 rounded-full bg-bg-sunken overflow-hidden\">\n <div\n className=\"h-full rounded-full bg-action-primary-bg\"\n style={{ width: `${pct}%` }}\n />\n </div>\n <span className=\"text-sm font-medium w-8 text-right\">{count}</span>\n </div>\n </div>\n );\n })}\n </div>\n\n <Separator className=\"my-4\" />\n\n <div>\n <h4 className=\"text-sm font-medium mb-3\">By Department</h4>\n <div className=\"space-y-2\">\n {Object.entries(departmentBreakdown)\n .sort((a, b) => b[1].count - a[1].count)\n .slice(0, 5)\n .map(([dept, data]) => (\n <div key={dept} className=\"flex items-center justify-between text-sm\">\n <span>{dept}</span>\n <span className=\"text-text-secondary\">{data.count} assets</span>\n </div>\n ))}\n </div>\n </div>\n </CardContent>\n </Card>\n </div>\n\n {/* Depreciation Trend */}\n <Card>\n <CardHeader>\n <CardTitle>Depreciation Trend</CardTitle>\n <CardDescription>Portfolio depreciation over the last 6 months</CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"flex items-end gap-2 h-40\">\n {portfolio.depreciationTrend.map((point) => {\n const maxVal = Math.max(...portfolio.depreciationTrend.map((p) => p.value));\n const height = maxVal > 0 ? (point.value / maxVal) * 100 : 0;\n return (\n <div key={point.month} className=\"flex-1 flex flex-col items-center gap-1\">\n <span className=\"text-[10px] text-text-secondary\">\n ${(point.value / 1000000).toFixed(2)}M\n </span>\n <div\n className=\"w-full bg-action-primary-bg/80 rounded-t\"\n style={{ height: `${height}%` }}\n />\n <span className=\"text-[10px] text-text-secondary\">\n {point.month.replace(' 20', \"'\")}\n </span>\n </div>\n );\n })}\n </div>\n </CardContent>\n </Card>\n </TabsContent>\n\n {/* Financial Tab */}\n <TabsContent value=\"financial\" className=\"space-y-6 mt-6\">\n <div className=\"grid gap-4 md:grid-cols-3\">\n <Card>\n <CardHeader className=\"pb-2\">\n <CardTitle className=\"text-sm font-medium\">Total Transactions</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{transactions.length}</div>\n <p className=\"text-xs text-text-secondary\">\n ${transactions.reduce((s, t) => s + Math.abs(t.amount), 0).toLocaleString()} total\n value\n </p>\n </CardContent>\n </Card>\n <Card>\n <CardHeader className=\"pb-2\">\n <CardTitle className=\"text-sm font-medium\">Maintenance Cost</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n ${totalMaintenanceCost.toLocaleString()}\n </div>\n <p className=\"text-xs text-text-secondary\">\n {maintenanceRecords.length} maintenance records\n </p>\n </CardContent>\n </Card>\n <Card>\n <CardHeader className=\"pb-2\">\n <CardTitle className=\"text-sm font-medium\">Acquisitions (6mo)</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n {portfolio.acquisitionTrend.reduce((s, a) => s + a.count, 0)}\n </div>\n <p className=\"text-xs text-text-secondary\">\n ${(portfolio.acquisitionTrend.reduce((s, a) => s + a.value, 0) / 1000).toFixed(0)}\n K total spend\n </p>\n </CardContent>\n </Card>\n </div>\n\n {/* Acquisition Trend */}\n <Card>\n <CardHeader>\n <CardTitle>Acquisition Trend</CardTitle>\n <CardDescription>New assets acquired over the last 6 months</CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"flex items-end gap-2 h-40\">\n {portfolio.acquisitionTrend.map((point) => {\n const maxVal = Math.max(...portfolio.acquisitionTrend.map((p) => p.count));\n const height = maxVal > 0 ? (point.count / maxVal) * 100 : 0;\n return (\n <div key={point.month} className=\"flex-1 flex flex-col items-center gap-1\">\n <span className=\"text-[10px] text-text-secondary\">{point.count} units</span>\n <div\n className=\"w-full bg-status-success-bg rounded-t\"\n style={{ height: `${height}%` }}\n />\n <span className=\"text-[10px] text-text-secondary\">\n {point.month.replace(' 20', \"'\")}\n </span>\n </div>\n );\n })}\n </div>\n </CardContent>\n </Card>\n\n {/* Recent Transactions */}\n <Card>\n <CardHeader>\n <CardTitle>Recent Transactions</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"overflow-x-auto\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b\">\n <th className=\"text-left py-2 font-medium\">ID</th>\n <th className=\"text-left py-2 font-medium\">Type</th>\n <th className=\"text-left py-2 font-medium\">Description</th>\n <th className=\"text-right py-2 font-medium\">Amount</th>\n <th className=\"text-left py-2 font-medium\">Status</th>\n </tr>\n </thead>\n <tbody>\n {transactions.slice(0, 5).map((txn) => (\n <tr key={txn.id} className=\"border-b hover:bg-bg-sunken/50\">\n <td className=\"py-2 font-mono text-xs\">{txn.id}</td>\n <td className=\"py-2 capitalize\">{txn.type}</td>\n <td className=\"py-2 truncate max-w-xs\">{txn.description}</td>\n <td\n className={`py-2 text-right font-medium ${txn.amount < 0 ? 'text-status-error-text' : ''}`}\n >\n ${Math.abs(txn.amount).toLocaleString()}\n </td>\n <td className=\"py-2\">\n <Badge variant=\"outline\">{txn.status}</Badge>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </CardContent>\n </Card>\n </TabsContent>\n\n {/* Operational Tab */}\n <TabsContent value=\"operational\" className=\"space-y-6 mt-6\">\n <div className=\"grid gap-4 md:grid-cols-4\">\n <Card>\n <CardHeader className=\"pb-2\">\n <CardTitle className=\"text-sm font-medium\">Incidents</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{incidents.length}</div>\n <p className=\"text-xs text-text-secondary\">{resolvedIncidents.length} resolved</p>\n </CardContent>\n </Card>\n <Card>\n <CardHeader className=\"pb-2\">\n <CardTitle className=\"text-sm font-medium\">SLA Breaches</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold text-status-error-text\">\n {slaBreached.length}\n </div>\n <p className=\"text-xs text-text-secondary\">\n {((1 - slaBreached.length / Math.max(incidents.length, 1)) * 100).toFixed(1)}%\n compliance\n </p>\n </CardContent>\n </Card>\n <Card>\n <CardHeader className=\"pb-2\">\n <CardTitle className=\"text-sm font-medium\">Maintenance Done</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{completedMaintenance.length}</div>\n <p className=\"text-xs text-text-secondary\">of {maintenanceRecords.length} total</p>\n </CardContent>\n </Card>\n <Card>\n <CardHeader className=\"pb-2\">\n <CardTitle className=\"text-sm font-medium\">Workflow Success</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n {(\n workflows.reduce((s, w) => s + w.successRate, 0) / Math.max(workflows.length, 1)\n ).toFixed(1)}\n %\n </div>\n <p className=\"text-xs text-text-secondary\">{workflows.length} active workflows</p>\n </CardContent>\n </Card>\n </div>\n </TabsContent>\n\n {/* Insights Tab */}\n <TabsContent value=\"insights\" className=\"space-y-6 mt-6\">\n <div className=\"grid gap-4 md:grid-cols-3\">\n <Card className=\"border-status-info-border bg-status-info-bg-subtle\">\n <CardHeader>\n <CardTitle className=\"text-status-info-text text-base\">Diversification</CardTitle>\n </CardHeader>\n <CardContent>\n <p className=\"text-sm text-status-info-text\">\n Your portfolio spans {Object.keys(categoryBreakdown).length} categories across{' '}\n {Object.keys(departmentBreakdown).length} departments. IT Hardware represents the\n largest segment at {portfolio.byCategory[0]?.count || 0} assets.\n </p>\n </CardContent>\n </Card>\n <Card className=\"border-status-success-border bg-status-success-bg-subtle\">\n <CardHeader>\n <CardTitle className=\"text-status-success-text text-base\">Performance</CardTitle>\n </CardHeader>\n <CardContent>\n <p className=\"text-sm text-status-success-text\">\n Portfolio depreciated value stands at $\n {(portfolio.depreciatedValue / 1000000).toFixed(2)}M. Depreciation rate is within\n expected range at {depreciationPct}% of original cost.\n </p>\n </CardContent>\n </Card>\n <Card className=\"border-status-warning-border bg-status-warning-bg-subtle\">\n <CardHeader>\n <CardTitle className=\"text-status-warning-text text-base\">Maintenance</CardTitle>\n </CardHeader>\n <CardContent>\n <p className=\"text-sm text-status-warning-text\">\n {maintenanceRecords.filter((m) => m.status === 'scheduled').length} maintenance\n tasks are scheduled. Total maintenance spend is $\n {totalMaintenanceCost.toLocaleString()}. Stay on top of preventive maintenance.\n </p>\n </CardContent>\n </Card>\n </div>\n\n {/* Top Assets by Value */}\n <EmphasisPanel>\n <CardHeader className=\"px-0 pt-0\">\n <CardTitle>Top Assets by Value</CardTitle>\n <CardDescription>Highest value assets in your portfolio</CardDescription>\n </CardHeader>\n <CardContent className=\"px-0 pb-0\">\n <div className=\"space-y-3\">\n {[...assets]\n .sort((a, b) => b.currentValue - a.currentValue)\n .slice(0, 5)\n .map((asset, i) => (\n <div\n key={asset.id}\n className=\"flex items-center justify-between p-3 rounded-lg border border-border-seam bg-gloss-card\"\n >\n <div className=\"flex items-center gap-3\">\n <div className=\"w-8 h-8 rounded-full bg-action-primary-bg/10 flex items-center justify-center text-xs font-medium text-primary\">\n {i + 1}\n </div>\n <div>\n <p className=\"text-sm font-medium\">{asset.name}</p>\n <p className=\"text-xs text-text-secondary\">\n {asset.department} · {asset.category.replace('_', ' ')}\n </p>\n </div>\n </div>\n <div className=\"text-right\">\n <p className=\"text-sm font-medium\">\n ${asset.currentValue.toLocaleString()}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {asset.currentValue < asset.value ? (\n <span className=\"text-status-error-text\">\n -{((1 - asset.currentValue / asset.value) * 100).toFixed(1)}%\n </span>\n ) : (\n <span className=\"text-status-success-text\">No depreciation</span>\n )}\n </p>\n </div>\n </div>\n ))}\n </div>\n </CardContent>\n </EmphasisPanel>\n </TabsContent>\n </Tabs>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AnalyticsPage.js","names":[],"sources":["../../../src/assethandler/pages/AnalyticsPage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n Badge,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n Separator,\n GradientText,\n GlassCard,\n CTAOverflowMenu,\n EmphasisPanel,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport {\n BarChart3,\n TrendingUp,\n TrendingDown,\n DollarSign,\n Box,\n PieChart,\n Activity,\n Download,\n ArrowUpRight,\n ArrowDownRight,\n} from 'lucide-react';\nimport { useAssetHandlerStore } from '../store/assethandlerStore';\n\nexport function AnalyticsPage() {\n const { assets, portfolio, transactions, incidents, maintenanceRecords, workflows } =\n useAssetHandlerStore();\n const [timeRange, setTimeRange] = useState<'7d' | '30d' | '90d' | '1y'>('30d');\n\n const totalValue = assets.reduce((sum, a) => sum + a.currentValue, 0);\n const totalOriginal = assets.reduce((sum, a) => sum + a.value, 0);\n const depreciationTotal = totalOriginal - totalValue;\n const depreciationPct =\n totalOriginal > 0 ? ((depreciationTotal / totalOriginal) * 100).toFixed(1) : '0';\n const avgAssetValue = assets.length > 0 ? Math.round(totalValue / assets.length) : 0;\n\n const categoryBreakdown = assets.reduce<Record<string, { count: number; value: number }>>(\n (acc, a) => {\n const cat = a.category.replace('_', ' ');\n if (!acc[cat]) acc[cat] = { count: 0, value: 0 };\n acc[cat].count++;\n acc[cat].value += a.currentValue;\n return acc;\n },\n {}\n );\n\n const statusBreakdown = assets.reduce<Record<string, number>>((acc, a) => {\n acc[a.status] = (acc[a.status] || 0) + 1;\n return acc;\n }, {});\n\n const departmentBreakdown = assets.reduce<Record<string, { count: number; value: number }>>(\n (acc, a) => {\n if (!acc[a.department]) acc[a.department] = { count: 0, value: 0 };\n acc[a.department].count++;\n acc[a.department].value += a.currentValue;\n return acc;\n },\n {}\n );\n\n const resolvedIncidents = incidents.filter(\n (i) => i.status === 'resolved' || i.status === 'closed'\n );\n const slaBreached = incidents.filter((i) => i.slaBreached);\n const completedMaintenance = maintenanceRecords.filter((m) => m.status === 'completed');\n const totalMaintenanceCost = maintenanceRecords.reduce((sum, m) => sum + m.cost, 0);\n\n return (\n <div className=\"space-y-6 p-6\">\n {/* Header */}\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-3xl font-bold\">\n <GradientText>Analytics & Business Intelligence</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary mt-1\">\n Comprehensive asset management analytics and insights\n </p>\n </div>\n <div className=\"flex gap-2\">\n <select\n value={timeRange}\n onChange={(e) => setTimeRange(e.target.value as typeof timeRange)}\n className=\"rounded-md border border-border-default bg-bg-surface px-3 py-1.5 text-sm\"\n >\n <option value=\"7d\">Last 7 days</option>\n <option value=\"30d\">Last 30 days</option>\n <option value=\"90d\">Last 90 days</option>\n <option value=\"1y\">Last year</option>\n </select>\n <CTAOverflowMenu\n primary={{ label: 'Generate Report', onSelect: () => {} }}\n actions={[\n { label: 'Export', onSelect: () => {}, icon: <Download className=\"h-4 w-4\" /> },\n ]}\n />\n </div>\n </div>\n\n <PagePurpose>\n Turn raw asset data into decisions. See where value is concentrated, how it is depreciating,\n which categories cost the most to run, and how operations are trending — so you can plan\n budgets, justify replacements and spot risk before it shows up as downtime.\n </PagePurpose>\n\n <Tabs defaultValue=\"overview\">\n <TabsList>\n <TabsTrigger value=\"overview\">Overview</TabsTrigger>\n <TabsTrigger value=\"financial\">Financial</TabsTrigger>\n <TabsTrigger value=\"operational\">Operational</TabsTrigger>\n <TabsTrigger value=\"insights\">Insights</TabsTrigger>\n </TabsList>\n\n {/* Overview Tab */}\n <TabsContent value=\"overview\" className=\"space-y-6 mt-6\">\n {/* Key Metrics */}\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-4\">\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Total Portfolio Value</CardTitle>\n <DollarSign className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n ${portfolio.totalValue.toLocaleString()}\n </div>\n <p className=\"text-xs text-text-secondary flex items-center mt-1\">\n <ArrowUpRight className=\"mr-1 h-3 w-3 text-status-success-text\" />\n <span className=\"text-status-success-text\">+5.6%</span> from last quarter\n </p>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Total Depreciation</CardTitle>\n <TrendingDown className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold text-status-error-text\">\n -${depreciationTotal.toLocaleString()}\n </div>\n <p className=\"text-xs text-text-secondary\">{depreciationPct}% of original value</p>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Total Assets</CardTitle>\n <Box className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{portfolio.totalAssets}</div>\n <p className=\"text-xs text-text-secondary\">\n {assets.filter((a) => a.status === 'active').length} currently active\n </p>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Avg. Asset Value</CardTitle>\n <BarChart3 className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n ${avgAssetValue.toLocaleString()}\n </div>\n <p className=\"text-xs text-text-secondary\">Across all categories</p>\n </CardContent>\n </GlassCard>\n </div>\n\n {/* Category & Status Breakdown */}\n <div className=\"grid gap-6 lg:grid-cols-2\">\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <PieChart className=\"h-4 w-4\" />\n Category Distribution\n </CardTitle>\n <CardDescription>Assets by category with values</CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"space-y-3\">\n {Object.entries(categoryBreakdown)\n .sort((a, b) => b[1].value - a[1].value)\n .map(([cat, data]) => {\n const pct = Math.round((data.count / assets.length) * 100);\n return (\n <div key={cat} className=\"space-y-1\">\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"font-medium capitalize\">{cat}</span>\n <span className=\"text-text-secondary\">\n {data.count} · ${(data.value / 1000).toFixed(1)}K\n </span>\n </div>\n <div className=\"h-2 rounded-full bg-bg-sunken overflow-hidden\">\n <div\n className=\"h-full rounded-full bg-action-primary-bg\"\n style={{ width: `${pct}%` }}\n />\n </div>\n </div>\n );\n })}\n </div>\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <Activity className=\"h-4 w-4\" />\n Status Breakdown\n </CardTitle>\n <CardDescription>Current asset status distribution</CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"space-y-3\">\n {Object.entries(statusBreakdown).map(([status, count]) => {\n const pct = Math.round((count / assets.length) * 100);\n return (\n <div key={status} className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <Badge\n variant={\n status === 'active'\n ? 'default'\n : status === 'under_maintenance'\n ? 'secondary'\n : 'outline'\n }\n >\n {status.replace('_', ' ')}\n </Badge>\n </div>\n <div className=\"flex items-center gap-3\">\n <div className=\"h-2 w-24 rounded-full bg-bg-sunken overflow-hidden\">\n <div\n className=\"h-full rounded-full bg-action-primary-bg\"\n style={{ width: `${pct}%` }}\n />\n </div>\n <span className=\"text-sm font-medium w-8 text-right\">{count}</span>\n </div>\n </div>\n );\n })}\n </div>\n\n <Separator className=\"my-4\" />\n\n <div>\n <h4 className=\"text-sm font-medium mb-3\">By Department</h4>\n <div className=\"space-y-2\">\n {Object.entries(departmentBreakdown)\n .sort((a, b) => b[1].count - a[1].count)\n .slice(0, 5)\n .map(([dept, data]) => (\n <div key={dept} className=\"flex items-center justify-between text-sm\">\n <span>{dept}</span>\n <span className=\"text-text-secondary\">{data.count} assets</span>\n </div>\n ))}\n </div>\n </div>\n </CardContent>\n </Card>\n </div>\n\n {/* Depreciation Trend */}\n <Card>\n <CardHeader>\n <CardTitle>Depreciation Trend</CardTitle>\n <CardDescription>Portfolio depreciation over the last 6 months</CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"flex items-end gap-2 h-40\">\n {portfolio.depreciationTrend.map((point) => {\n const maxVal = Math.max(...portfolio.depreciationTrend.map((p) => p.value));\n const height = maxVal > 0 ? (point.value / maxVal) * 100 : 0;\n return (\n <div key={point.month} className=\"flex-1 flex flex-col items-center gap-1\">\n <span className=\"text-[10px] text-text-secondary\">\n ${(point.value / 1000000).toFixed(2)}M\n </span>\n <div\n className=\"w-full bg-action-primary-bg/80 rounded-t\"\n style={{ height: `${height}%` }}\n />\n <span className=\"text-[10px] text-text-secondary\">\n {point.month.replace(' 20', \"'\")}\n </span>\n </div>\n );\n })}\n </div>\n </CardContent>\n </Card>\n </TabsContent>\n\n {/* Financial Tab */}\n <TabsContent value=\"financial\" className=\"space-y-6 mt-6\">\n <div className=\"grid gap-4 md:grid-cols-3\">\n <Card>\n <CardHeader className=\"pb-2\">\n <CardTitle className=\"text-sm font-medium\">Total Transactions</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{transactions.length}</div>\n <p className=\"text-xs text-text-secondary\">\n ${transactions.reduce((s, t) => s + Math.abs(t.amount), 0).toLocaleString()} total\n value\n </p>\n </CardContent>\n </Card>\n <Card>\n <CardHeader className=\"pb-2\">\n <CardTitle className=\"text-sm font-medium\">Maintenance Cost</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n ${totalMaintenanceCost.toLocaleString()}\n </div>\n <p className=\"text-xs text-text-secondary\">\n {maintenanceRecords.length} maintenance records\n </p>\n </CardContent>\n </Card>\n <Card>\n <CardHeader className=\"pb-2\">\n <CardTitle className=\"text-sm font-medium\">Acquisitions (6mo)</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n {portfolio.acquisitionTrend.reduce((s, a) => s + a.count, 0)}\n </div>\n <p className=\"text-xs text-text-secondary\">\n ${(portfolio.acquisitionTrend.reduce((s, a) => s + a.value, 0) / 1000).toFixed(0)}\n K total spend\n </p>\n </CardContent>\n </Card>\n </div>\n\n {/* Acquisition Trend */}\n <Card>\n <CardHeader>\n <CardTitle>Acquisition Trend</CardTitle>\n <CardDescription>New assets acquired over the last 6 months</CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"flex items-end gap-2 h-40\">\n {portfolio.acquisitionTrend.map((point) => {\n const maxVal = Math.max(...portfolio.acquisitionTrend.map((p) => p.count));\n const height = maxVal > 0 ? (point.count / maxVal) * 100 : 0;\n return (\n <div key={point.month} className=\"flex-1 flex flex-col items-center gap-1\">\n <span className=\"text-[10px] text-text-secondary\">{point.count} units</span>\n <div\n className=\"w-full bg-status-success-bg rounded-t\"\n style={{ height: `${height}%` }}\n />\n <span className=\"text-[10px] text-text-secondary\">\n {point.month.replace(' 20', \"'\")}\n </span>\n </div>\n );\n })}\n </div>\n </CardContent>\n </Card>\n\n {/* Recent Transactions */}\n <Card>\n <CardHeader>\n <CardTitle>Recent Transactions</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"overflow-x-auto\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b\">\n <th className=\"text-left py-2 font-medium\">ID</th>\n <th className=\"text-left py-2 font-medium\">Type</th>\n <th className=\"text-left py-2 font-medium\">Description</th>\n <th className=\"text-right py-2 font-medium\">Amount</th>\n <th className=\"text-left py-2 font-medium\">Status</th>\n </tr>\n </thead>\n <tbody>\n {transactions.slice(0, 5).map((txn) => (\n <tr key={txn.id} className=\"border-b hover:bg-bg-sunken/50\">\n <td className=\"py-2 font-mono text-xs\">{txn.id}</td>\n <td className=\"py-2 capitalize\">{txn.type}</td>\n <td className=\"py-2 truncate max-w-xs\">{txn.description}</td>\n <td\n className={`py-2 text-right font-medium ${txn.amount < 0 ? 'text-status-error-text' : ''}`}\n >\n ${Math.abs(txn.amount).toLocaleString()}\n </td>\n <td className=\"py-2\">\n <Badge variant=\"outline\">{txn.status}</Badge>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </CardContent>\n </Card>\n </TabsContent>\n\n {/* Operational Tab */}\n <TabsContent value=\"operational\" className=\"space-y-6 mt-6\">\n <div className=\"grid gap-4 md:grid-cols-4\">\n <Card>\n <CardHeader className=\"pb-2\">\n <CardTitle className=\"text-sm font-medium\">Incidents</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{incidents.length}</div>\n <p className=\"text-xs text-text-secondary\">{resolvedIncidents.length} resolved</p>\n </CardContent>\n </Card>\n <Card>\n <CardHeader className=\"pb-2\">\n <CardTitle className=\"text-sm font-medium\">SLA Breaches</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold text-status-error-text\">\n {slaBreached.length}\n </div>\n <p className=\"text-xs text-text-secondary\">\n {((1 - slaBreached.length / Math.max(incidents.length, 1)) * 100).toFixed(1)}%\n compliance\n </p>\n </CardContent>\n </Card>\n <Card>\n <CardHeader className=\"pb-2\">\n <CardTitle className=\"text-sm font-medium\">Maintenance Done</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{completedMaintenance.length}</div>\n <p className=\"text-xs text-text-secondary\">of {maintenanceRecords.length} total</p>\n </CardContent>\n </Card>\n <Card>\n <CardHeader className=\"pb-2\">\n <CardTitle className=\"text-sm font-medium\">Workflow Success</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n {(\n workflows.reduce((s, w) => s + w.successRate, 0) / Math.max(workflows.length, 1)\n ).toFixed(1)}\n %\n </div>\n <p className=\"text-xs text-text-secondary\">{workflows.length} active workflows</p>\n </CardContent>\n </Card>\n </div>\n </TabsContent>\n\n {/* Insights Tab */}\n <TabsContent value=\"insights\" className=\"space-y-6 mt-6\">\n <div className=\"grid gap-4 md:grid-cols-3\">\n <Card className=\"border-status-info-border bg-status-info-bg-subtle\">\n <CardHeader>\n <CardTitle className=\"text-status-info-text text-base\">Diversification</CardTitle>\n </CardHeader>\n <CardContent>\n <p className=\"text-sm text-status-info-text\">\n Your portfolio spans {Object.keys(categoryBreakdown).length} categories across{' '}\n {Object.keys(departmentBreakdown).length} departments. IT Hardware represents the\n largest segment at {portfolio.byCategory[0]?.count || 0} assets.\n </p>\n </CardContent>\n </Card>\n <Card className=\"border-status-success-border bg-status-success-bg-subtle\">\n <CardHeader>\n <CardTitle className=\"text-status-success-text text-base\">Performance</CardTitle>\n </CardHeader>\n <CardContent>\n <p className=\"text-sm text-status-success-text\">\n Portfolio depreciated value stands at $\n {(portfolio.depreciatedValue / 1000000).toFixed(2)}M. Depreciation rate is within\n expected range at {depreciationPct}% of original cost.\n </p>\n </CardContent>\n </Card>\n <Card className=\"border-status-warning-border bg-status-warning-bg-subtle\">\n <CardHeader>\n <CardTitle className=\"text-status-warning-text text-base\">Maintenance</CardTitle>\n </CardHeader>\n <CardContent>\n <p className=\"text-sm text-status-warning-text\">\n {maintenanceRecords.filter((m) => m.status === 'scheduled').length} maintenance\n tasks are scheduled. Total maintenance spend is $\n {totalMaintenanceCost.toLocaleString()}. Stay on top of preventive maintenance.\n </p>\n </CardContent>\n </Card>\n </div>\n\n {/* Top Assets by Value */}\n <EmphasisPanel>\n <CardHeader className=\"px-0 pt-0\">\n <CardTitle>Top Assets by Value</CardTitle>\n <CardDescription>Highest value assets in your portfolio</CardDescription>\n </CardHeader>\n <CardContent className=\"px-0 pb-0\">\n <div className=\"space-y-3\">\n {[...assets]\n .sort((a, b) => b.currentValue - a.currentValue)\n .slice(0, 5)\n .map((asset, i) => (\n <div\n key={asset.id}\n className=\"flex items-center justify-between p-3 rounded-lg border border-border-seam bg-gloss-card\"\n >\n <div className=\"flex items-center gap-3\">\n <div className=\"w-8 h-8 rounded-full bg-action-primary-bg/10 flex items-center justify-center text-xs font-medium text-primary\">\n {i + 1}\n </div>\n <div>\n <p className=\"text-sm font-medium\">{asset.name}</p>\n <p className=\"text-xs text-text-secondary\">\n {asset.department} · {asset.category.replace('_', ' ')}\n </p>\n </div>\n </div>\n <div className=\"text-right\">\n <p className=\"text-sm font-medium\">\n ${asset.currentValue.toLocaleString()}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {asset.currentValue < asset.value ? (\n <span className=\"text-status-error-text\">\n -{((1 - asset.currentValue / asset.value) * 100).toFixed(1)}%\n </span>\n ) : (\n <span className=\"text-status-success-text\">No depreciation</span>\n )}\n </p>\n </div>\n </div>\n ))}\n </div>\n </CardContent>\n </EmphasisPanel>\n </TabsContent>\n </Tabs>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { useAssetHandlerStore as e } from "../store/assethandlerStore.js";
|
|
2
2
|
import { useMemo as t } from "react";
|
|
3
3
|
import { Box as n, Code as r, Monitor as i, Plus as a, Server as o, Truck as s, Wifi as c, Wrench as l } from "lucide-react";
|
|
4
|
-
import { Badge as u, Button as d,
|
|
5
|
-
import { jsx as
|
|
4
|
+
import { Badge as u, Button as d, CardContent as f, CardDescription as p, CardHeader as m, CardTitle as h, GlassCard as g, GradientText as _, IllustratedEmptyState as v, PagePurpose as y, Separator as b } from "@burdenoff/fe-libs/ui";
|
|
5
|
+
import { jsx as x, jsxs as S } from "react/jsx-runtime";
|
|
6
6
|
//#region src/assethandler/pages/AssetsAssetCategoriesPage.tsx
|
|
7
|
-
var
|
|
8
|
-
electronics: /* @__PURE__ */
|
|
9
|
-
it_hardware: /* @__PURE__ */
|
|
10
|
-
furniture: /* @__PURE__ */
|
|
11
|
-
vehicles: /* @__PURE__ */
|
|
12
|
-
equipment: /* @__PURE__ */
|
|
13
|
-
software: /* @__PURE__ */
|
|
14
|
-
networking: /* @__PURE__ */
|
|
15
|
-
servers: /* @__PURE__ */
|
|
16
|
-
},
|
|
7
|
+
var C = {
|
|
8
|
+
electronics: /* @__PURE__ */ x(i, { className: "h-5 w-5" }),
|
|
9
|
+
it_hardware: /* @__PURE__ */ x(i, { className: "h-5 w-5" }),
|
|
10
|
+
furniture: /* @__PURE__ */ x(n, { className: "h-5 w-5" }),
|
|
11
|
+
vehicles: /* @__PURE__ */ x(s, { className: "h-5 w-5" }),
|
|
12
|
+
equipment: /* @__PURE__ */ x(l, { className: "h-5 w-5" }),
|
|
13
|
+
software: /* @__PURE__ */ x(r, { className: "h-5 w-5" }),
|
|
14
|
+
networking: /* @__PURE__ */ x(c, { className: "h-5 w-5" }),
|
|
15
|
+
servers: /* @__PURE__ */ x(o, { className: "h-5 w-5" })
|
|
16
|
+
}, w = {
|
|
17
17
|
electronics: "bg-status-info-bg-subtle text-status-info-text",
|
|
18
18
|
it_hardware: "bg-status-info-bg-subtle text-status-info-text",
|
|
19
19
|
furniture: "bg-status-warning-bg-subtle text-status-warning-text",
|
|
@@ -23,7 +23,7 @@ var x = {
|
|
|
23
23
|
networking: "bg-status-info-bg-subtle text-status-info-text",
|
|
24
24
|
servers: "bg-status-error-bg-subtle text-status-error-text"
|
|
25
25
|
};
|
|
26
|
-
function
|
|
26
|
+
function T() {
|
|
27
27
|
let { assets: r } = e(), i = t(() => {
|
|
28
28
|
let e = {};
|
|
29
29
|
for (let t of r) {
|
|
@@ -40,123 +40,133 @@ function C() {
|
|
|
40
40
|
for (let t of Object.values(e)) t.topAssets.sort((e, t) => t.currentValue - e.currentValue), t.topAssets = t.topAssets.slice(0, 3);
|
|
41
41
|
return e;
|
|
42
42
|
}, [r]), o = r.length, s = r.reduce((e, t) => e + t.currentValue, 0);
|
|
43
|
-
return /* @__PURE__ */
|
|
43
|
+
return /* @__PURE__ */ S("div", {
|
|
44
44
|
className: "space-y-6 p-6",
|
|
45
|
-
children: [
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
children:
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
className: "space-y-3",
|
|
91
|
-
children: [
|
|
92
|
-
/* @__PURE__ */ b("div", {
|
|
93
|
-
className: "flex justify-between text-sm",
|
|
94
|
-
children: [/* @__PURE__ */ y("span", {
|
|
95
|
-
className: "text-text-secondary",
|
|
96
|
-
children: "Current Value"
|
|
97
|
-
}), /* @__PURE__ */ b("span", {
|
|
98
|
-
className: "font-medium",
|
|
99
|
-
children: ["$", t.currentValue.toLocaleString()]
|
|
100
|
-
})]
|
|
101
|
-
}),
|
|
102
|
-
/* @__PURE__ */ b("div", {
|
|
103
|
-
className: "flex justify-between text-sm",
|
|
104
|
-
children: [/* @__PURE__ */ y("span", {
|
|
105
|
-
className: "text-text-secondary",
|
|
106
|
-
children: "Depreciation"
|
|
107
|
-
}), /* @__PURE__ */ b("span", {
|
|
108
|
-
className: "text-status-error-text",
|
|
109
|
-
children: ["-$", i.toLocaleString()]
|
|
110
|
-
})]
|
|
111
|
-
}),
|
|
112
|
-
/* @__PURE__ */ y("div", {
|
|
113
|
-
className: "h-2 rounded-full bg-bg-sunken overflow-hidden",
|
|
114
|
-
children: /* @__PURE__ */ y("div", {
|
|
115
|
-
className: "h-full rounded-full bg-action-primary-bg",
|
|
116
|
-
style: { width: `${r}%` }
|
|
117
|
-
})
|
|
118
|
-
}),
|
|
119
|
-
/* @__PURE__ */ y(v, {}),
|
|
120
|
-
/* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("p", {
|
|
121
|
-
className: "text-xs font-medium text-text-secondary mb-2",
|
|
122
|
-
children: "Status breakdown"
|
|
123
|
-
}), /* @__PURE__ */ y("div", {
|
|
124
|
-
className: "flex flex-wrap gap-1",
|
|
125
|
-
children: Object.entries(t.statuses).map(([e, t]) => /* @__PURE__ */ b(u, {
|
|
126
|
-
variant: "secondary",
|
|
127
|
-
className: "text-[10px]",
|
|
128
|
-
children: [
|
|
129
|
-
e.replace("_", " "),
|
|
130
|
-
": ",
|
|
131
|
-
t
|
|
132
|
-
]
|
|
133
|
-
}, e))
|
|
134
|
-
})] }),
|
|
135
|
-
/* @__PURE__ */ y(v, {}),
|
|
136
|
-
/* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("p", {
|
|
137
|
-
className: "text-xs font-medium text-text-secondary mb-2",
|
|
138
|
-
children: "Top Assets"
|
|
139
|
-
}), /* @__PURE__ */ y("div", {
|
|
140
|
-
className: "space-y-1.5",
|
|
141
|
-
children: t.topAssets.map((e) => /* @__PURE__ */ b("div", {
|
|
142
|
-
className: "flex items-center justify-between text-xs",
|
|
143
|
-
children: [/* @__PURE__ */ y("span", {
|
|
144
|
-
className: "truncate flex-1",
|
|
145
|
-
children: e.name
|
|
146
|
-
}), /* @__PURE__ */ b("span", {
|
|
147
|
-
className: "font-medium ml-2",
|
|
148
|
-
children: ["$", e.currentValue.toLocaleString()]
|
|
45
|
+
children: [
|
|
46
|
+
/* @__PURE__ */ S("div", {
|
|
47
|
+
className: "flex items-center justify-between",
|
|
48
|
+
children: [/* @__PURE__ */ S("div", { children: [/* @__PURE__ */ x("h1", {
|
|
49
|
+
className: "text-2xl font-bold",
|
|
50
|
+
children: /* @__PURE__ */ x(_, { children: "Asset Categories" })
|
|
51
|
+
}), /* @__PURE__ */ S("p", {
|
|
52
|
+
className: "text-sm text-text-secondary",
|
|
53
|
+
children: [
|
|
54
|
+
Object.keys(i).length,
|
|
55
|
+
" categories · ",
|
|
56
|
+
o,
|
|
57
|
+
" total assets · $",
|
|
58
|
+
s.toLocaleString(),
|
|
59
|
+
" total value"
|
|
60
|
+
]
|
|
61
|
+
})] }), /* @__PURE__ */ S(d, {
|
|
62
|
+
size: "sm",
|
|
63
|
+
children: [/* @__PURE__ */ x(a, { className: "mr-2 h-4 w-4" }), "Add Category"]
|
|
64
|
+
})]
|
|
65
|
+
}),
|
|
66
|
+
/* @__PURE__ */ x(y, { children: "Group and compare your assets by category to see where value and risk are concentrated. Each card rolls up how many assets you have in a category, their current value, depreciation, status mix and top items — so you can plan procurement and replacements by category, not one asset at a time." }),
|
|
67
|
+
Object.keys(i).length === 0 ? /* @__PURE__ */ x(v, {
|
|
68
|
+
illustration: "empty-data",
|
|
69
|
+
title: "No categories yet",
|
|
70
|
+
description: "Add assets and they will be grouped into categories here automatically."
|
|
71
|
+
}) : /* @__PURE__ */ x("div", {
|
|
72
|
+
className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3",
|
|
73
|
+
children: Object.entries(i).map(([e, t], r) => {
|
|
74
|
+
let i = o > 0 ? Math.round(t.count / o * 100) : 0, a = t.totalValue - t.currentValue;
|
|
75
|
+
return /* @__PURE__ */ S(g, {
|
|
76
|
+
treatment: r === 0 ? "glass" : "plain",
|
|
77
|
+
glow: r === 0,
|
|
78
|
+
className: "border-border-seam",
|
|
79
|
+
children: [/* @__PURE__ */ S(m, {
|
|
80
|
+
className: "pb-3",
|
|
81
|
+
children: [
|
|
82
|
+
/* @__PURE__ */ S("div", {
|
|
83
|
+
className: "flex items-center justify-between",
|
|
84
|
+
children: [/* @__PURE__ */ x("div", {
|
|
85
|
+
className: `p-2 rounded-lg ${w[e] || "bg-bg-sunken"}`,
|
|
86
|
+
children: C[e] || /* @__PURE__ */ x(n, { className: "h-5 w-5" })
|
|
87
|
+
}), /* @__PURE__ */ S(u, {
|
|
88
|
+
variant: "outline",
|
|
89
|
+
children: [i, "%"]
|
|
149
90
|
})]
|
|
150
|
-
},
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
91
|
+
}),
|
|
92
|
+
/* @__PURE__ */ x(h, {
|
|
93
|
+
className: "capitalize mt-3",
|
|
94
|
+
children: e.replace("_", " ")
|
|
95
|
+
}),
|
|
96
|
+
/* @__PURE__ */ S(p, { children: [t.count, " assets"] })
|
|
97
|
+
]
|
|
98
|
+
}), /* @__PURE__ */ x(f, { children: /* @__PURE__ */ S("div", {
|
|
99
|
+
className: "space-y-3",
|
|
100
|
+
children: [
|
|
101
|
+
/* @__PURE__ */ S("div", {
|
|
102
|
+
className: "flex justify-between text-sm",
|
|
103
|
+
children: [/* @__PURE__ */ x("span", {
|
|
104
|
+
className: "text-text-secondary",
|
|
105
|
+
children: "Current Value"
|
|
106
|
+
}), /* @__PURE__ */ S("span", {
|
|
107
|
+
className: "font-medium",
|
|
108
|
+
children: ["$", t.currentValue.toLocaleString()]
|
|
109
|
+
})]
|
|
110
|
+
}),
|
|
111
|
+
/* @__PURE__ */ S("div", {
|
|
112
|
+
className: "flex justify-between text-sm",
|
|
113
|
+
children: [/* @__PURE__ */ x("span", {
|
|
114
|
+
className: "text-text-secondary",
|
|
115
|
+
children: "Depreciation"
|
|
116
|
+
}), /* @__PURE__ */ S("span", {
|
|
117
|
+
className: "text-status-error-text",
|
|
118
|
+
children: ["-$", a.toLocaleString()]
|
|
119
|
+
})]
|
|
120
|
+
}),
|
|
121
|
+
/* @__PURE__ */ x("div", {
|
|
122
|
+
className: "h-2 rounded-full bg-bg-sunken overflow-hidden",
|
|
123
|
+
children: /* @__PURE__ */ x("div", {
|
|
124
|
+
className: "h-full rounded-full bg-action-primary-bg",
|
|
125
|
+
style: { width: `${i}%` }
|
|
126
|
+
})
|
|
127
|
+
}),
|
|
128
|
+
/* @__PURE__ */ x(b, {}),
|
|
129
|
+
/* @__PURE__ */ S("div", { children: [/* @__PURE__ */ x("p", {
|
|
130
|
+
className: "text-xs font-medium text-text-secondary mb-2",
|
|
131
|
+
children: "Status breakdown"
|
|
132
|
+
}), /* @__PURE__ */ x("div", {
|
|
133
|
+
className: "flex flex-wrap gap-1",
|
|
134
|
+
children: Object.entries(t.statuses).map(([e, t]) => /* @__PURE__ */ S(u, {
|
|
135
|
+
variant: "secondary",
|
|
136
|
+
className: "text-[10px]",
|
|
137
|
+
children: [
|
|
138
|
+
e.replace("_", " "),
|
|
139
|
+
": ",
|
|
140
|
+
t
|
|
141
|
+
]
|
|
142
|
+
}, e))
|
|
143
|
+
})] }),
|
|
144
|
+
/* @__PURE__ */ x(b, {}),
|
|
145
|
+
/* @__PURE__ */ S("div", { children: [/* @__PURE__ */ x("p", {
|
|
146
|
+
className: "text-xs font-medium text-text-secondary mb-2",
|
|
147
|
+
children: "Top Assets"
|
|
148
|
+
}), /* @__PURE__ */ x("div", {
|
|
149
|
+
className: "space-y-1.5",
|
|
150
|
+
children: t.topAssets.map((e) => /* @__PURE__ */ S("div", {
|
|
151
|
+
className: "flex items-center justify-between text-xs",
|
|
152
|
+
children: [/* @__PURE__ */ x("span", {
|
|
153
|
+
className: "truncate flex-1",
|
|
154
|
+
children: e.name
|
|
155
|
+
}), /* @__PURE__ */ S("span", {
|
|
156
|
+
className: "font-medium ml-2",
|
|
157
|
+
children: ["$", e.currentValue.toLocaleString()]
|
|
158
|
+
})]
|
|
159
|
+
}, e.id))
|
|
160
|
+
})] })
|
|
161
|
+
]
|
|
162
|
+
}) })]
|
|
163
|
+
}, e);
|
|
164
|
+
})
|
|
155
165
|
})
|
|
156
|
-
|
|
166
|
+
]
|
|
157
167
|
});
|
|
158
168
|
}
|
|
159
169
|
//#endregion
|
|
160
|
-
export {
|
|
170
|
+
export { T as AssetsAssetCategoriesPage };
|
|
161
171
|
|
|
162
172
|
//# sourceMappingURL=AssetsAssetCategoriesPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssetsAssetCategoriesPage.js","names":[],"sources":["../../../src/assethandler/pages/AssetsAssetCategoriesPage.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n Separator,\n GradientText,\n} from '@burdenoff/fe-libs/ui';\nimport { Box, Monitor, Server, Wifi, Truck, Wrench, Code, Plus } from 'lucide-react';\nimport { useAssetHandlerStore, type Asset } from '../store/assethandlerStore';\n\nconst categoryIcons: Record<string, React.ReactNode> = {\n electronics: <Monitor className=\"h-5 w-5\" />,\n it_hardware: <Monitor className=\"h-5 w-5\" />,\n furniture: <Box className=\"h-5 w-5\" />,\n vehicles: <Truck className=\"h-5 w-5\" />,\n equipment: <Wrench className=\"h-5 w-5\" />,\n software: <Code className=\"h-5 w-5\" />,\n networking: <Wifi className=\"h-5 w-5\" />,\n servers: <Server className=\"h-5 w-5\" />,\n};\n\nconst categoryColors: Record<string, string> = {\n electronics: 'bg-status-info-bg-subtle text-status-info-text',\n it_hardware: 'bg-status-info-bg-subtle text-status-info-text',\n furniture: 'bg-status-warning-bg-subtle text-status-warning-text',\n vehicles: 'bg-status-success-bg-subtle text-status-success-text',\n equipment: 'bg-status-warning-bg-subtle text-status-warning-text',\n software: 'bg-action-primary-bg/10 text-action-primary-bg',\n networking: 'bg-status-info-bg-subtle text-status-info-text',\n servers: 'bg-status-error-bg-subtle text-status-error-text',\n};\n\nexport function AssetsAssetCategoriesPage() {\n const { assets } = useAssetHandlerStore();\n\n const categories = useMemo(() => {\n const catMap: Record<\n string,\n {\n count: number;\n totalValue: number;\n currentValue: number;\n statuses: Record<string, number>;\n topAssets: Asset[];\n }\n > = {};\n for (const asset of assets) {\n if (!catMap[asset.category])\n catMap[asset.category] = {\n count: 0,\n totalValue: 0,\n currentValue: 0,\n statuses: {},\n topAssets: [],\n };\n const cat = catMap[asset.category];\n cat.count++;\n cat.totalValue += asset.value;\n cat.currentValue += asset.currentValue;\n cat.statuses[asset.status] = (cat.statuses[asset.status] || 0) + 1;\n cat.topAssets.push(asset);\n }\n for (const cat of Object.values(catMap)) {\n cat.topAssets.sort((a, b) => b.currentValue - a.currentValue);\n cat.topAssets = cat.topAssets.slice(0, 3);\n }\n return catMap;\n }, [assets]);\n\n const totalAssets = assets.length;\n const totalValue = assets.reduce((s, a) => s + a.currentValue, 0);\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-bold\">\n <GradientText>Asset Categories</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n {Object.keys(categories).length} categories · {totalAssets} total assets ·\n ${totalValue.toLocaleString()} total value\n </p>\n </div>\n <Button size=\"sm\">\n <Plus className=\"mr-2 h-4 w-4\" />\n Add Category\n </Button>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-3\">\n {Object.entries(categories).map(([key, data]) => {\n const pct = totalAssets > 0 ? Math.round((data.count / totalAssets) * 100) : 0;\n const depreciation = data.totalValue - data.currentValue;\n return (\n <Card key={key} className=\"hover:shadow-md transition-shadow cursor-pointer\">\n <CardHeader className=\"pb-3\">\n <div className=\"flex items-center justify-between\">\n <div className={`p-2 rounded-lg ${categoryColors[key] || 'bg-bg-sunken'}`}>\n {categoryIcons[key] || <Box className=\"h-5 w-5\" />}\n </div>\n <Badge variant=\"outline\">{pct}%</Badge>\n </div>\n <CardTitle className=\"capitalize mt-3\">{key.replace('_', ' ')}</CardTitle>\n <CardDescription>{data.count} assets</CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"space-y-3\">\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-secondary\">Current Value</span>\n <span className=\"font-medium\">${data.currentValue.toLocaleString()}</span>\n </div>\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-secondary\">Depreciation</span>\n <span className=\"text-status-error-text\">\n -${depreciation.toLocaleString()}\n </span>\n </div>\n <div className=\"h-2 rounded-full bg-bg-sunken overflow-hidden\">\n <div\n className=\"h-full rounded-full bg-action-primary-bg\"\n style={{ width: `${pct}%` }}\n />\n </div>\n <Separator />\n <div>\n <p className=\"text-xs font-medium text-text-secondary mb-2\">Status breakdown</p>\n <div className=\"flex flex-wrap gap-1\">\n {Object.entries(data.statuses).map(([status, count]) => (\n <Badge key={status} variant=\"secondary\" className=\"text-[10px]\">\n {status.replace('_', ' ')}: {count}\n </Badge>\n ))}\n </div>\n </div>\n <Separator />\n <div>\n <p className=\"text-xs font-medium text-text-secondary mb-2\">Top Assets</p>\n <div className=\"space-y-1.5\">\n {data.topAssets.map((a) => (\n <div key={a.id} className=\"flex items-center justify-between text-xs\">\n <span className=\"truncate flex-1\">{a.name}</span>\n <span className=\"font-medium ml-2\">\n ${a.currentValue.toLocaleString()}\n </span>\n </div>\n ))}\n </div>\n </div>\n </div>\n </CardContent>\n </Card>\n );\n })}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;AAeA,IAAM,IAAiD;CACrD,aAAa,kBAAC,GAAD,EAAS,WAAU,WAAY,CAAA;CAC5C,aAAa,kBAAC,GAAD,EAAS,WAAU,WAAY,CAAA;CAC5C,WAAW,kBAAC,GAAD,EAAK,WAAU,WAAY,CAAA;CACtC,UAAU,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;CACvC,WAAW,kBAAC,GAAD,EAAQ,WAAU,WAAY,CAAA;CACzC,UAAU,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA;CACtC,YAAY,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA;CACxC,SAAS,kBAAC,GAAD,EAAQ,WAAU,WAAY,CAAA;CACxC,EAEK,IAAyC;CAC7C,aAAa;CACb,aAAa;CACb,WAAW;CACX,UAAU;CACV,WAAW;CACX,UAAU;CACV,YAAY;CACZ,SAAS;CACV;AAED,SAAgB,IAA4B;CAC1C,IAAM,EAAE,cAAW,GAAsB,EAEnC,IAAa,QAAc;EAC/B,IAAM,IASF,EAAE;AACN,OAAK,IAAM,KAAS,GAAQ;AAC1B,GAAK,EAAO,EAAM,cAChB,EAAO,EAAM,YAAY;IACvB,OAAO;IACP,YAAY;IACZ,cAAc;IACd,UAAU,EAAE;IACZ,WAAW,EAAE;IACd;GACH,IAAM,IAAM,EAAO,EAAM;AAKzB,GAJA,EAAI,SACJ,EAAI,cAAc,EAAM,OACxB,EAAI,gBAAgB,EAAM,cAC1B,EAAI,SAAS,EAAM,WAAW,EAAI,SAAS,EAAM,WAAW,KAAK,GACjE,EAAI,UAAU,KAAK,EAAM;;AAE3B,OAAK,IAAM,KAAO,OAAO,OAAO,EAAO,CAErC,CADA,EAAI,UAAU,MAAM,GAAG,MAAM,EAAE,eAAe,EAAE,aAAa,EAC7D,EAAI,YAAY,EAAI,UAAU,MAAM,GAAG,EAAE;AAE3C,SAAO;IACN,CAAC,EAAO,CAAC,EAEN,IAAc,EAAO,QACrB,IAAa,EAAO,QAAQ,GAAG,MAAM,IAAI,EAAE,cAAc,EAAE;AAEjE,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;IAAI,WAAU;cACZ,kBAAC,GAAD,EAAA,UAAc,oBAA+B,CAAA;IAC1C,CAAA,EACL,kBAAC,KAAD;IAAG,WAAU;cAAb;KACG,OAAO,KAAK,EAAW,CAAC;KAAO;KAAsB;KAAY;KAChE,EAAW,gBAAgB;KAAC;KAC5B;MACA,EAAA,CAAA,EACN,kBAAC,GAAD;IAAQ,MAAK;cAAb,CACE,kBAAC,GAAD,EAAM,WAAU,gBAAiB,CAAA,EAAA,eAE1B;MACL;MAEN,kBAAC,OAAD;GAAK,WAAU;aACZ,OAAO,QAAQ,EAAW,CAAC,KAAK,CAAC,GAAK,OAAU;IAC/C,IAAM,IAAM,IAAc,IAAI,KAAK,MAAO,EAAK,QAAQ,IAAe,IAAI,GAAG,GACvE,IAAe,EAAK,aAAa,EAAK;AAC5C,WACE,kBAAC,GAAD;KAAgB,WAAU;eAA1B,CACE,kBAAC,GAAD;MAAY,WAAU;gBAAtB;OACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD;SAAK,WAAW,kBAAkB,EAAe,MAAQ;mBACtD,EAAc,MAAQ,kBAAC,GAAD,EAAK,WAAU,WAAY,CAAA;SAC9C,CAAA,EACN,kBAAC,GAAD;SAAO,SAAQ;mBAAf,CAA0B,GAAI,IAAS;WACnC;;OACN,kBAAC,GAAD;QAAW,WAAU;kBAAmB,EAAI,QAAQ,KAAK,IAAI;QAAa,CAAA;OAC1E,kBAAC,GAAD,EAAA,UAAA,CAAkB,EAAK,OAAM,UAAyB,EAAA,CAAA;OAC3C;SACb,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAAsB;SAAoB,CAAA,EAC1D,kBAAC,QAAD;SAAM,WAAU;mBAAhB,CAA8B,KAAE,EAAK,aAAa,gBAAgB,CAAQ;WACtE;;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAAsB;SAAmB,CAAA,EACzD,kBAAC,QAAD;SAAM,WAAU;mBAAhB,CAAyC,MACpC,EAAa,gBAAgB,CAC3B;WACH;;OACN,kBAAC,OAAD;QAAK,WAAU;kBACb,kBAAC,OAAD;SACE,WAAU;SACV,OAAO,EAAE,OAAO,GAAG,EAAI,IAAI;SAC3B,CAAA;QACE,CAAA;OACN,kBAAC,GAAD,EAAa,CAAA;OACb,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;QAAG,WAAU;kBAA+C;QAAoB,CAAA,EAChF,kBAAC,OAAD;QAAK,WAAU;kBACZ,OAAO,QAAQ,EAAK,SAAS,CAAC,KAAK,CAAC,GAAQ,OAC3C,kBAAC,GAAD;SAAoB,SAAQ;SAAY,WAAU;mBAAlD;UACG,EAAO,QAAQ,KAAK,IAAI;UAAC;UAAG;UACvB;WAFI,EAEJ,CACR;QACE,CAAA,CACF,EAAA,CAAA;OACN,kBAAC,GAAD,EAAa,CAAA;OACb,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;QAAG,WAAU;kBAA+C;QAAc,CAAA,EAC1E,kBAAC,OAAD;QAAK,WAAU;kBACZ,EAAK,UAAU,KAAK,MACnB,kBAAC,OAAD;SAAgB,WAAU;mBAA1B,CACE,kBAAC,QAAD;UAAM,WAAU;oBAAmB,EAAE;UAAY,CAAA,EACjD,kBAAC,QAAD;UAAM,WAAU;oBAAhB,CAAmC,KAC/B,EAAE,aAAa,gBAAgB,CAC5B;YACH;WALI,EAAE,GAKN,CACN;QACE,CAAA,CACF,EAAA,CAAA;OACF;SACM,CAAA,CACT;OAxDI,EAwDJ;KAET;GACE,CAAA,CACF"}
|
|
1
|
+
{"version":3,"file":"AssetsAssetCategoriesPage.js","names":[],"sources":["../../../src/assethandler/pages/AssetsAssetCategoriesPage.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport {\n Badge,\n Button,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n Separator,\n GradientText,\n GlassCard,\n PagePurpose,\n IllustratedEmptyState,\n} from '@burdenoff/fe-libs/ui';\nimport { Box, Monitor, Server, Wifi, Truck, Wrench, Code, Plus } from 'lucide-react';\nimport { useAssetHandlerStore, type Asset } from '../store/assethandlerStore';\n\nconst categoryIcons: Record<string, React.ReactNode> = {\n electronics: <Monitor className=\"h-5 w-5\" />,\n it_hardware: <Monitor className=\"h-5 w-5\" />,\n furniture: <Box className=\"h-5 w-5\" />,\n vehicles: <Truck className=\"h-5 w-5\" />,\n equipment: <Wrench className=\"h-5 w-5\" />,\n software: <Code className=\"h-5 w-5\" />,\n networking: <Wifi className=\"h-5 w-5\" />,\n servers: <Server className=\"h-5 w-5\" />,\n};\n\nconst categoryColors: Record<string, string> = {\n electronics: 'bg-status-info-bg-subtle text-status-info-text',\n it_hardware: 'bg-status-info-bg-subtle text-status-info-text',\n furniture: 'bg-status-warning-bg-subtle text-status-warning-text',\n vehicles: 'bg-status-success-bg-subtle text-status-success-text',\n equipment: 'bg-status-warning-bg-subtle text-status-warning-text',\n software: 'bg-action-primary-bg/10 text-action-primary-bg',\n networking: 'bg-status-info-bg-subtle text-status-info-text',\n servers: 'bg-status-error-bg-subtle text-status-error-text',\n};\n\nexport function AssetsAssetCategoriesPage() {\n const { assets } = useAssetHandlerStore();\n\n const categories = useMemo(() => {\n const catMap: Record<\n string,\n {\n count: number;\n totalValue: number;\n currentValue: number;\n statuses: Record<string, number>;\n topAssets: Asset[];\n }\n > = {};\n for (const asset of assets) {\n if (!catMap[asset.category])\n catMap[asset.category] = {\n count: 0,\n totalValue: 0,\n currentValue: 0,\n statuses: {},\n topAssets: [],\n };\n const cat = catMap[asset.category];\n cat.count++;\n cat.totalValue += asset.value;\n cat.currentValue += asset.currentValue;\n cat.statuses[asset.status] = (cat.statuses[asset.status] || 0) + 1;\n cat.topAssets.push(asset);\n }\n for (const cat of Object.values(catMap)) {\n cat.topAssets.sort((a, b) => b.currentValue - a.currentValue);\n cat.topAssets = cat.topAssets.slice(0, 3);\n }\n return catMap;\n }, [assets]);\n\n const totalAssets = assets.length;\n const totalValue = assets.reduce((s, a) => s + a.currentValue, 0);\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-bold\">\n <GradientText>Asset Categories</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n {Object.keys(categories).length} categories · {totalAssets} total assets ·\n ${totalValue.toLocaleString()} total value\n </p>\n </div>\n <Button size=\"sm\">\n <Plus className=\"mr-2 h-4 w-4\" />\n Add Category\n </Button>\n </div>\n\n <PagePurpose>\n Group and compare your assets by category to see where value and risk are concentrated.\n Each card rolls up how many assets you have in a category, their current value,\n depreciation, status mix and top items — so you can plan procurement and replacements by\n category, not one asset at a time.\n </PagePurpose>\n\n {Object.keys(categories).length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No categories yet\"\n description=\"Add assets and they will be grouped into categories here automatically.\"\n />\n ) : (\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-3\">\n {Object.entries(categories).map(([key, data], idx) => {\n const pct = totalAssets > 0 ? Math.round((data.count / totalAssets) * 100) : 0;\n const depreciation = data.totalValue - data.currentValue;\n return (\n <GlassCard\n key={key}\n treatment={idx === 0 ? 'glass' : 'plain'}\n glow={idx === 0}\n className=\"border-border-seam\"\n >\n <CardHeader className=\"pb-3\">\n <div className=\"flex items-center justify-between\">\n <div className={`p-2 rounded-lg ${categoryColors[key] || 'bg-bg-sunken'}`}>\n {categoryIcons[key] || <Box className=\"h-5 w-5\" />}\n </div>\n <Badge variant=\"outline\">{pct}%</Badge>\n </div>\n <CardTitle className=\"capitalize mt-3\">{key.replace('_', ' ')}</CardTitle>\n <CardDescription>{data.count} assets</CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"space-y-3\">\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-secondary\">Current Value</span>\n <span className=\"font-medium\">${data.currentValue.toLocaleString()}</span>\n </div>\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-secondary\">Depreciation</span>\n <span className=\"text-status-error-text\">\n -${depreciation.toLocaleString()}\n </span>\n </div>\n <div className=\"h-2 rounded-full bg-bg-sunken overflow-hidden\">\n <div\n className=\"h-full rounded-full bg-action-primary-bg\"\n style={{ width: `${pct}%` }}\n />\n </div>\n <Separator />\n <div>\n <p className=\"text-xs font-medium text-text-secondary mb-2\">Status breakdown</p>\n <div className=\"flex flex-wrap gap-1\">\n {Object.entries(data.statuses).map(([status, count]) => (\n <Badge key={status} variant=\"secondary\" className=\"text-[10px]\">\n {status.replace('_', ' ')}: {count}\n </Badge>\n ))}\n </div>\n </div>\n <Separator />\n <div>\n <p className=\"text-xs font-medium text-text-secondary mb-2\">Top Assets</p>\n <div className=\"space-y-1.5\">\n {data.topAssets.map((a) => (\n <div key={a.id} className=\"flex items-center justify-between text-xs\">\n <span className=\"truncate flex-1\">{a.name}</span>\n <span className=\"font-medium ml-2\">\n ${a.currentValue.toLocaleString()}\n </span>\n </div>\n ))}\n </div>\n </div>\n </div>\n </CardContent>\n </GlassCard>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|