@burdenoff/microfe-assethandler 2026.813.1 → 2026.813.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/components/charts/BarsChart.js +25 -25
- package/dist/assethandler/components/charts/ChartParts.js +27 -27
- package/dist/assethandler/components/charts/DonutChart.js +17 -17
- package/dist/assethandler/components/charts/ProgressMeter.js +5 -5
- package/dist/assethandler/components/charts/RadialGauge.js +13 -13
- package/dist/assethandler/components/charts/Sparkline.js +27 -27
- package/dist/assethandler/components/charts/TrendChart.js +47 -47
- package/dist/assethandler/components/index.js +1 -1
- package/dist/assethandler/pages/AiPredictionsPage.js +20 -20
- package/dist/assethandler/pages/AnalyticsPage.d.ts.map +1 -1
- package/dist/assethandler/pages/AnalyticsPage.js +133 -133
- package/dist/assethandler/pages/AnalyticsPage.js.map +1 -1
- package/dist/assethandler/pages/AssetsAssetCategoriesPage.d.ts.map +1 -1
- package/dist/assethandler/pages/AssetsAssetCategoriesPage.js +55 -55
- package/dist/assethandler/pages/AssetsAssetCategoriesPage.js.map +1 -1
- package/dist/assethandler/pages/AssetsAssetCreatePage.d.ts.map +1 -1
- package/dist/assethandler/pages/AssetsAssetCreatePage.js +77 -78
- package/dist/assethandler/pages/AssetsAssetCreatePage.js.map +1 -1
- package/dist/assethandler/pages/AssetsAssetDetailPage.d.ts.map +1 -1
- package/dist/assethandler/pages/AssetsAssetDetailPage.js +140 -141
- package/dist/assethandler/pages/AssetsAssetDetailPage.js.map +1 -1
- package/dist/assethandler/pages/AssetsAssetListPage.js +249 -249
- package/dist/assethandler/pages/AssetsAssetListPage.js.map +1 -1
- package/dist/assethandler/pages/AssetsAssetTrackingPage.js +8 -8
- package/dist/assethandler/pages/CmdbBrowserPage.js +34 -34
- package/dist/assethandler/pages/DashboardPage.d.ts.map +1 -1
- package/dist/assethandler/pages/DashboardPage.js +256 -255
- package/dist/assethandler/pages/DashboardPage.js.map +1 -1
- package/dist/assethandler/pages/DiscoveryJobsPage.js +27 -27
- package/dist/assethandler/pages/EsgDashboardPage.js +53 -53
- package/dist/assethandler/pages/FinanceBudgetDetailPage.d.ts.map +1 -1
- package/dist/assethandler/pages/FinanceBudgetDetailPage.js +156 -155
- package/dist/assethandler/pages/FinanceBudgetDetailPage.js.map +1 -1
- package/dist/assethandler/pages/FinanceFinanceHubPage.d.ts.map +1 -1
- package/dist/assethandler/pages/FinanceFinanceHubPage.js +475 -475
- package/dist/assethandler/pages/FinanceFinanceHubPage.js.map +1 -1
- package/dist/assethandler/pages/FinanceInvoiceDetailPage.d.ts.map +1 -1
- package/dist/assethandler/pages/FinanceInvoiceDetailPage.js +141 -140
- package/dist/assethandler/pages/FinanceInvoiceDetailPage.js.map +1 -1
- package/dist/assethandler/pages/ItilChangeManagementPage.js +21 -21
- package/dist/assethandler/pages/ItilIncidentManagementPage.js +34 -34
- package/dist/assethandler/pages/ItilProblemManagementPage.js +17 -17
- package/dist/assethandler/pages/KnowledgeBasePage.js +39 -39
- package/dist/assethandler/pages/MaintenanceMaintenanceSchedulerPage.d.ts.map +1 -1
- package/dist/assethandler/pages/MaintenanceMaintenanceSchedulerPage.js +114 -114
- package/dist/assethandler/pages/MaintenanceMaintenanceSchedulerPage.js.map +1 -1
- package/dist/assethandler/pages/OperationsMaintenanceDetailPage.d.ts.map +1 -1
- package/dist/assethandler/pages/OperationsMaintenanceDetailPage.js +158 -157
- package/dist/assethandler/pages/OperationsMaintenanceDetailPage.js.map +1 -1
- package/dist/assethandler/pages/OperationsOperationsHubPage.d.ts.map +1 -1
- package/dist/assethandler/pages/OperationsOperationsHubPage.js +253 -252
- package/dist/assethandler/pages/OperationsOperationsHubPage.js.map +1 -1
- package/dist/assethandler/pages/PortfolioPortfolioOverviewPage.d.ts.map +1 -1
- package/dist/assethandler/pages/PortfolioPortfolioOverviewPage.js +96 -95
- package/dist/assethandler/pages/PortfolioPortfolioOverviewPage.js.map +1 -1
- package/dist/assethandler/pages/ProvenancePage.js +21 -21
- package/dist/assethandler/pages/ReportsDashboardPage.d.ts.map +1 -1
- package/dist/assethandler/pages/ReportsDashboardPage.js +301 -301
- package/dist/assethandler/pages/ReportsDashboardPage.js.map +1 -1
- package/dist/assethandler/pages/SecuritySecurityHubPage.js +126 -126
- package/dist/assethandler/pages/SecuritySecurityHubPage.js.map +1 -1
- package/dist/assethandler/pages/TransactionsTransactionDetailPage.d.ts.map +1 -1
- package/dist/assethandler/pages/TransactionsTransactionDetailPage.js +112 -113
- package/dist/assethandler/pages/TransactionsTransactionDetailPage.js.map +1 -1
- package/dist/assethandler/pages/TransactionsTransactionListPage.d.ts.map +1 -1
- package/dist/assethandler/pages/TransactionsTransactionListPage.js +136 -137
- package/dist/assethandler/pages/TransactionsTransactionListPage.js.map +1 -1
- package/dist/assethandler/providers/AssetHandlerProvider.d.ts +14 -0
- package/dist/assethandler/providers/AssetHandlerProvider.d.ts.map +1 -1
- package/dist/assethandler/providers/AssetHandlerProvider.js +44 -34
- package/dist/assethandler/providers/AssetHandlerProvider.js.map +1 -1
- package/dist/assethandler/types/index.d.ts +10 -0
- package/dist/assethandler/types/index.d.ts.map +1 -1
- package/dist/assethandler/utils/money.d.ts +34 -0
- package/dist/assethandler/utils/money.d.ts.map +1 -0
- package/dist/assethandler/utils/money.js +27 -0
- package/dist/assethandler/utils/money.js.map +1 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssetsAssetCategoriesPage.js","names":[],"sources":["../../../src/assethandler/pages/AssetsAssetCategoriesPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Badge,\n GradientText,\n GlassCard,\n PagePurpose,\n IllustratedEmptyState,\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport {\n Box,\n Monitor,\n Server,\n Wifi,\n Truck,\n Wrench,\n Code,\n MoreHorizontal,\n Copy,\n ExternalLink,\n ArrowUpDown,\n Layers,\n} from 'lucide-react';\nimport { useAssetHandlerNavigate } from '../hooks/useAssetHandlerNavigate';\nimport {\n formatAssetCategory,\n useAssetCategoryPresentation,\n useAssetTerminology,\n useHiddenCategoryIds,\n} from '../providers/AssetHandlerProvider';\nimport { useAssetHandlerStore, type AssetStatus } from '../store/assethandlerStore';\nimport { notify } from '../utils/toast';\nimport {\n ChartCard,\n StatTile,\n BarsChart,\n formatCompact,\n formatCurrencyCompact,\n} from '../components';\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\n// Stable fallback tint for any category outside the known slug map — hashes the\n// key into the semantic palette so every real category is visually differentiated.\nconst FALLBACK_TINTS = [\n 'bg-status-info-bg-subtle text-status-info-text',\n 'bg-status-success-bg-subtle text-status-success-text',\n 'bg-status-warning-bg-subtle text-status-warning-text',\n 'bg-status-error-bg-subtle text-status-error-text',\n 'bg-action-primary-bg/10 text-action-primary-bg',\n];\nfunction tintFor(key: string): string {\n if (categoryColors[key]) return categoryColors[key];\n let hash = 0;\n for (let i = 0; i < key.length; i += 1) hash = (hash * 31 + key.charCodeAt(i)) >>> 0;\n return FALLBACK_TINTS[hash % FALLBACK_TINTS.length];\n}\n\n// Proportional status-bar segments — semantic tokens (CSS vars), theme-aware.\nconst STATUS_SEGMENTS: { key: AssetStatus; label: string; varName: string }[] = [\n { key: 'active', label: 'Active', varName: 'var(--color-status-success-bg)' },\n { key: 'maintenance', label: 'Maintenance', varName: 'var(--color-status-warning-bg)' },\n { key: 'retired', label: 'Retired', varName: 'var(--color-status-error-bg)' },\n { key: 'inactive', label: 'Inactive', varName: 'var(--color-status-info-bg)' },\n { key: 'disposed', label: 'Disposed', varName: 'var(--color-text-muted)' },\n];\n\nconst CONDITION_SCORE: Record<string, number> = {\n excellent: 5,\n good: 4,\n fair: 3,\n poor: 2,\n damaged: 1,\n};\n\ninterface CategoryAggregate {\n key: string;\n count: number;\n totalValue: number;\n statuses: Record<string, number>;\n conditions: Record<string, number>;\n avgCondition: number;\n}\n\nconst money = (value: number): string => `$${value.toLocaleString()}`;\n\nexport function AssetsAssetCategoriesPage() {\n const navigate = useAssetHandlerNavigate();\n const term = useAssetTerminology();\n const hiddenCategories = useHiddenCategoryIds();\n const { labels: categoryLabels } = useAssetCategoryPresentation();\n const { assets: allAssets } = useAssetHandlerStore();\n const assets = useMemo(\n () => allAssets.filter((a) => !hiddenCategories.has(a.category)),\n [allAssets, hiddenCategories]\n );\n const [chartMetric, setChartMetric] = useState<'count' | 'value'>('count');\n const [sortKey, setSortKey] = useState<'count' | 'value'>('count');\n\n const aggregates = useMemo<CategoryAggregate[]>(() => {\n const map: Record<string, CategoryAggregate> = {};\n for (const asset of assets) {\n if (!map[asset.category]) {\n map[asset.category] = {\n key: asset.category,\n count: 0,\n totalValue: 0,\n statuses: {},\n conditions: {},\n avgCondition: 0,\n };\n }\n const cat = map[asset.category];\n cat.count += 1;\n cat.totalValue += asset.currentValue ?? asset.purchaseValue ?? 0;\n cat.statuses[asset.status] = (cat.statuses[asset.status] || 0) + 1;\n cat.conditions[asset.condition] = (cat.conditions[asset.condition] || 0) + 1;\n }\n for (const cat of Object.values(map)) {\n let scoreSum = 0;\n let scoreN = 0;\n for (const [cond, n] of Object.entries(cat.conditions)) {\n const score = CONDITION_SCORE[cond];\n if (score) {\n scoreSum += score * n;\n scoreN += n;\n }\n }\n cat.avgCondition = scoreN > 0 ? scoreSum / scoreN : 0;\n }\n return Object.values(map).sort((a, b) => b.count - a.count);\n }, [assets]);\n\n const totalAssets = assets.length;\n const totalValue = useMemo(\n () => assets.reduce((sum, a) => sum + (a.currentValue ?? a.purchaseValue ?? 0), 0),\n [assets]\n );\n\n const chartData = useMemo(\n () =>\n aggregates.map((cat) => ({\n category: formatAssetCategory(cat.key, categoryLabels),\n count: cat.count,\n value: cat.totalValue,\n })),\n [aggregates, categoryLabels]\n );\n\n const sortedRows = useMemo(\n () =>\n [...aggregates].sort((a, b) =>\n sortKey === 'count' ? b.count - a.count : b.totalValue - a.totalValue\n ),\n [aggregates, sortKey]\n );\n\n const copyId = (key: string) => {\n void navigator.clipboard?.writeText(key);\n notify.success(\n 'Category copied',\n `\"${formatAssetCategory(key, categoryLabels)}\" copied to clipboard.`\n );\n };\n\n return (\n <div className=\"space-y-6 p-4 sm:p-6\">\n <div>\n <h1 className=\"text-2xl font-bold\">\n <GradientText>{term.asset} Categories</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n {aggregates.length} categories · {totalAssets} total {term.assets.toLowerCase()}\n </p>\n </div>\n\n <PagePurpose>\n Group and compare your assets by category to see where value and volume are concentrated.\n Each card rolls up how many assets you hold, their total book value and a proportional\n status mix — so you can plan procurement and replacements by category, not one asset at a\n time.\n </PagePurpose>\n\n {aggregates.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No categories yet\"\n description={`Add ${term.assets.toLowerCase()} and they will be grouped into categories here automatically.`}\n />\n ) : (\n <>\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n <StatTile\n label=\"Categories\"\n value={aggregates.length}\n format={formatCompact}\n icon={Layers}\n hero\n />\n <StatTile\n label={`${term.assets} tracked`}\n value={totalAssets}\n format={formatCompact}\n icon={Box}\n />\n <StatTile\n label=\"Total book value\"\n value={totalValue}\n format={formatCurrencyCompact('USD')}\n icon={Box}\n />\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-3\">\n {aggregates.map((cat, idx) => {\n const pct = totalAssets > 0 ? Math.round((cat.count / totalAssets) * 100) : 0;\n const segments = STATUS_SEGMENTS.filter((s) => (cat.statuses[s.key] || 0) > 0);\n return (\n <GlassCard\n key={cat.key}\n treatment={idx === 0 ? 'glass' : 'plain'}\n glow={idx === 0}\n className=\"border-border-seam\"\n >\n <div className=\"space-y-4 p-5\">\n {/* Header: icon + title + overflow */}\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"flex min-w-0 items-center gap-3\">\n <div className={`shrink-0 rounded-lg p-2 ${tintFor(cat.key)}`}>\n {categoryIcons[cat.key] || <Box className=\"h-5 w-5\" />}\n </div>\n <div className=\"min-w-0\">\n <p className=\"truncate text-base font-semibold capitalize\">\n {formatAssetCategory(cat.key, categoryLabels)}\n </p>\n <Badge variant=\"outline\" className=\"mt-0.5 text-xs\">\n {pct}% of estate\n </Badge>\n </div>\n </div>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-8 w-8 shrink-0\"\n aria-label={`Actions for ${formatAssetCategory(cat.key, categoryLabels)}`}\n >\n <MoreHorizontal className=\"h-4 w-4\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem onClick={() => navigate('/assets/asset-list')}>\n <ExternalLink className=\"mr-2 h-4 w-4\" />\n View {term.assets.toLowerCase()}\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => copyId(cat.key)}>\n <Copy className=\"mr-2 h-4 w-4\" />\n Copy category ID\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n\n {/* Dual metric row */}\n <div className=\"flex flex-wrap items-end justify-between gap-3\">\n <div>\n <p className=\"text-xs text-text-secondary\">{term.asset} count</p>\n <p className=\"text-2xl font-bold tabular-nums\">{cat.count}</p>\n </div>\n <div className=\"text-right\">\n <p className=\"text-xs text-text-secondary\">Total value</p>\n <p className=\"text-2xl font-bold tabular-nums\">\n {formatCurrencyCompact('USD')(cat.totalValue)}\n </p>\n </div>\n </div>\n\n {/* Proportional status bar */}\n <div>\n <div\n className=\"flex h-2.5 w-full overflow-hidden rounded-full bg-bg-sunken\"\n role=\"img\"\n aria-label={segments\n .map((s) => `${s.label}: ${cat.statuses[s.key]}`)\n .join(', ')}\n >\n {segments.map((s) => (\n <div\n key={s.key}\n style={{\n width: `${((cat.statuses[s.key] || 0) / cat.count) * 100}%`,\n backgroundColor: s.varName,\n }}\n />\n ))}\n </div>\n <div className=\"mt-2 flex flex-wrap gap-x-3 gap-y-1\">\n {segments.map((s) => (\n <span\n key={s.key}\n className=\"inline-flex items-center gap-1.5 text-xs text-text-secondary\"\n >\n <span\n className=\"h-2.5 w-2.5 rounded-[3px]\"\n style={{ backgroundColor: s.varName }}\n />\n {s.label}\n <span className=\"tabular-nums text-text-muted\">\n {cat.statuses[s.key]}\n </span>\n </span>\n ))}\n </div>\n </div>\n\n {/* Avg condition */}\n <div className=\"flex items-center justify-between border-t border-border-seam pt-3 text-sm\">\n <span className=\"text-text-secondary\">Avg. condition</span>\n <span className=\"font-semibold tabular-nums\">\n {cat.avgCondition > 0 ? cat.avgCondition.toFixed(1) : '—'}\n <span className=\"text-xs font-normal text-text-muted\"> / 5</span>\n </span>\n </div>\n </div>\n </GlassCard>\n );\n })}\n </div>\n\n {/* Cross-category comparison chart */}\n <ChartCard\n title=\"Category comparison\"\n subtitle={\n chartMetric === 'count' ? `${term.assets} per category` : 'Book value per category'\n }\n actions={\n <div className=\"flex gap-1 rounded-md border border-border-seam p-0.5\">\n <Button\n variant={chartMetric === 'count' ? 'default' : 'ghost'}\n size=\"sm\"\n className=\"h-7 px-2 text-xs\"\n onClick={() => setChartMetric('count')}\n >\n Count\n </Button>\n <Button\n variant={chartMetric === 'value' ? 'default' : 'ghost'}\n size=\"sm\"\n className=\"h-7 px-2 text-xs\"\n onClick={() => setChartMetric('value')}\n >\n Value\n </Button>\n </div>\n }\n >\n <BarsChart\n data={chartData}\n xKey=\"category\"\n orientation=\"horizontal\"\n height={Math.max(200, chartData.length * 44)}\n categoryWidth={120}\n valueFormat={chartMetric === 'value' ? formatCurrencyCompact('USD') : formatCompact}\n series={[\n {\n key: chartMetric,\n label: chartMetric === 'count' ? term.assets : 'Book value',\n },\n ]}\n />\n </ChartCard>\n\n {/* Summary comparison table */}\n <ChartCard\n title=\"Category summary\"\n subtitle=\"Sortable roll-up across every category\"\n icon={Layers}\n >\n <div className=\"overflow-x-auto\">\n <table className=\"w-full min-w-[520px] text-sm\">\n <thead>\n <tr className=\"border-b border-border-seam text-left text-text-secondary\">\n <th className=\"py-2 pr-4 font-medium\">Category</th>\n <th className=\"py-2 pr-4 font-medium\">\n <button\n type=\"button\"\n className=\"inline-flex items-center gap-1 hover:text-text-primary\"\n onClick={() => setSortKey('count')}\n >\n Count\n <ArrowUpDown\n className={`h-3 w-3 ${sortKey === 'count' ? 'text-action-primary-bg' : ''}`}\n />\n </button>\n </th>\n <th className=\"py-2 pr-4 font-medium\">\n <button\n type=\"button\"\n className=\"inline-flex items-center gap-1 hover:text-text-primary\"\n onClick={() => setSortKey('value')}\n >\n Value\n <ArrowUpDown\n className={`h-3 w-3 ${sortKey === 'value' ? 'text-action-primary-bg' : ''}`}\n />\n </button>\n </th>\n <th className=\"py-2 font-medium\">Avg. condition</th>\n </tr>\n </thead>\n <tbody>\n {sortedRows.map((cat) => (\n <tr key={cat.key} className=\"border-b border-border-seam/60 last:border-0\">\n <td className=\"py-2.5 pr-4 font-medium capitalize\">\n {formatAssetCategory(cat.key, categoryLabels)}\n </td>\n <td className=\"py-2.5 pr-4 tabular-nums\">{cat.count}</td>\n <td className=\"py-2.5 pr-4 tabular-nums\">{money(cat.totalValue)}</td>\n <td className=\"py-2.5 tabular-nums\">\n {cat.avgCondition > 0 ? cat.avgCondition.toFixed(1) : '—'}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </ChartCard>\n </>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AssetsAssetCategoriesPage.js","names":[],"sources":["../../../src/assethandler/pages/AssetsAssetCategoriesPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Badge,\n GradientText,\n GlassCard,\n PagePurpose,\n IllustratedEmptyState,\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport {\n Box,\n Monitor,\n Server,\n Wifi,\n Truck,\n Wrench,\n Code,\n MoreHorizontal,\n Copy,\n ExternalLink,\n ArrowUpDown,\n Layers,\n} from 'lucide-react';\nimport { useAssetHandlerNavigate } from '../hooks/useAssetHandlerNavigate';\nimport {\n formatAssetCategory,\n useAssetCategoryPresentation,\n useAssetMoney,\n useAssetTerminology,\n useHiddenCategoryIds,\n} from '../providers/AssetHandlerProvider';\nimport { useAssetHandlerStore, type AssetStatus } from '../store/assethandlerStore';\nimport { notify } from '../utils/toast';\nimport { ChartCard, StatTile, BarsChart, formatCompact } from '../components';\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\n// Stable fallback tint for any category outside the known slug map — hashes the\n// key into the semantic palette so every real category is visually differentiated.\nconst FALLBACK_TINTS = [\n 'bg-status-info-bg-subtle text-status-info-text',\n 'bg-status-success-bg-subtle text-status-success-text',\n 'bg-status-warning-bg-subtle text-status-warning-text',\n 'bg-status-error-bg-subtle text-status-error-text',\n 'bg-action-primary-bg/10 text-action-primary-bg',\n];\nfunction tintFor(key: string): string {\n if (categoryColors[key]) return categoryColors[key];\n let hash = 0;\n for (let i = 0; i < key.length; i += 1) hash = (hash * 31 + key.charCodeAt(i)) >>> 0;\n return FALLBACK_TINTS[hash % FALLBACK_TINTS.length];\n}\n\n// Proportional status-bar segments — semantic tokens (CSS vars), theme-aware.\nconst STATUS_SEGMENTS: { key: AssetStatus; label: string; varName: string }[] = [\n { key: 'active', label: 'Active', varName: 'var(--color-status-success-bg)' },\n { key: 'maintenance', label: 'Maintenance', varName: 'var(--color-status-warning-bg)' },\n { key: 'retired', label: 'Retired', varName: 'var(--color-status-error-bg)' },\n { key: 'inactive', label: 'Inactive', varName: 'var(--color-status-info-bg)' },\n { key: 'disposed', label: 'Disposed', varName: 'var(--color-text-muted)' },\n];\n\nconst CONDITION_SCORE: Record<string, number> = {\n excellent: 5,\n good: 4,\n fair: 3,\n poor: 2,\n damaged: 1,\n};\n\ninterface CategoryAggregate {\n key: string;\n count: number;\n totalValue: number;\n statuses: Record<string, number>;\n conditions: Record<string, number>;\n avgCondition: number;\n}\n\nexport function AssetsAssetCategoriesPage() {\n const { format: money, compact: moneyCompact } = useAssetMoney();\n const navigate = useAssetHandlerNavigate();\n const term = useAssetTerminology();\n const hiddenCategories = useHiddenCategoryIds();\n const { labels: categoryLabels } = useAssetCategoryPresentation();\n const { assets: allAssets } = useAssetHandlerStore();\n const assets = useMemo(\n () => allAssets.filter((a) => !hiddenCategories.has(a.category)),\n [allAssets, hiddenCategories]\n );\n const [chartMetric, setChartMetric] = useState<'count' | 'value'>('count');\n const [sortKey, setSortKey] = useState<'count' | 'value'>('count');\n\n const aggregates = useMemo<CategoryAggregate[]>(() => {\n const map: Record<string, CategoryAggregate> = {};\n for (const asset of assets) {\n if (!map[asset.category]) {\n map[asset.category] = {\n key: asset.category,\n count: 0,\n totalValue: 0,\n statuses: {},\n conditions: {},\n avgCondition: 0,\n };\n }\n const cat = map[asset.category];\n cat.count += 1;\n cat.totalValue += asset.currentValue ?? asset.purchaseValue ?? 0;\n cat.statuses[asset.status] = (cat.statuses[asset.status] || 0) + 1;\n cat.conditions[asset.condition] = (cat.conditions[asset.condition] || 0) + 1;\n }\n for (const cat of Object.values(map)) {\n let scoreSum = 0;\n let scoreN = 0;\n for (const [cond, n] of Object.entries(cat.conditions)) {\n const score = CONDITION_SCORE[cond];\n if (score) {\n scoreSum += score * n;\n scoreN += n;\n }\n }\n cat.avgCondition = scoreN > 0 ? scoreSum / scoreN : 0;\n }\n return Object.values(map).sort((a, b) => b.count - a.count);\n }, [assets]);\n\n const totalAssets = assets.length;\n const totalValue = useMemo(\n () => assets.reduce((sum, a) => sum + (a.currentValue ?? a.purchaseValue ?? 0), 0),\n [assets]\n );\n\n const chartData = useMemo(\n () =>\n aggregates.map((cat) => ({\n category: formatAssetCategory(cat.key, categoryLabels),\n count: cat.count,\n value: cat.totalValue,\n })),\n [aggregates, categoryLabels]\n );\n\n const sortedRows = useMemo(\n () =>\n [...aggregates].sort((a, b) =>\n sortKey === 'count' ? b.count - a.count : b.totalValue - a.totalValue\n ),\n [aggregates, sortKey]\n );\n\n const copyId = (key: string) => {\n void navigator.clipboard?.writeText(key);\n notify.success(\n 'Category copied',\n `\"${formatAssetCategory(key, categoryLabels)}\" copied to clipboard.`\n );\n };\n\n return (\n <div className=\"space-y-6 p-4 sm:p-6\">\n <div>\n <h1 className=\"text-2xl font-bold\">\n <GradientText>{term.asset} Categories</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n {aggregates.length} categories · {totalAssets} total {term.assets.toLowerCase()}\n </p>\n </div>\n\n <PagePurpose>\n Group and compare your assets by category to see where value and volume are concentrated.\n Each card rolls up how many assets you hold, their total book value and a proportional\n status mix — so you can plan procurement and replacements by category, not one asset at a\n time.\n </PagePurpose>\n\n {aggregates.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No categories yet\"\n description={`Add ${term.assets.toLowerCase()} and they will be grouped into categories here automatically.`}\n />\n ) : (\n <>\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n <StatTile\n label=\"Categories\"\n value={aggregates.length}\n format={formatCompact}\n icon={Layers}\n hero\n />\n <StatTile\n label={`${term.assets} tracked`}\n value={totalAssets}\n format={formatCompact}\n icon={Box}\n />\n <StatTile\n label=\"Total book value\"\n value={totalValue}\n format={moneyCompact}\n icon={Box}\n />\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-3\">\n {aggregates.map((cat, idx) => {\n const pct = totalAssets > 0 ? Math.round((cat.count / totalAssets) * 100) : 0;\n const segments = STATUS_SEGMENTS.filter((s) => (cat.statuses[s.key] || 0) > 0);\n return (\n <GlassCard\n key={cat.key}\n treatment={idx === 0 ? 'glass' : 'plain'}\n glow={idx === 0}\n className=\"border-border-seam\"\n >\n <div className=\"space-y-4 p-5\">\n {/* Header: icon + title + overflow */}\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"flex min-w-0 items-center gap-3\">\n <div className={`shrink-0 rounded-lg p-2 ${tintFor(cat.key)}`}>\n {categoryIcons[cat.key] || <Box className=\"h-5 w-5\" />}\n </div>\n <div className=\"min-w-0\">\n <p className=\"truncate text-base font-semibold capitalize\">\n {formatAssetCategory(cat.key, categoryLabels)}\n </p>\n <Badge variant=\"outline\" className=\"mt-0.5 text-xs\">\n {pct}% of estate\n </Badge>\n </div>\n </div>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-8 w-8 shrink-0\"\n aria-label={`Actions for ${formatAssetCategory(cat.key, categoryLabels)}`}\n >\n <MoreHorizontal className=\"h-4 w-4\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem onClick={() => navigate('/assets/asset-list')}>\n <ExternalLink className=\"mr-2 h-4 w-4\" />\n View {term.assets.toLowerCase()}\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => copyId(cat.key)}>\n <Copy className=\"mr-2 h-4 w-4\" />\n Copy category ID\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n\n {/* Dual metric row */}\n <div className=\"flex flex-wrap items-end justify-between gap-3\">\n <div>\n <p className=\"text-xs text-text-secondary\">{term.asset} count</p>\n <p className=\"text-2xl font-bold tabular-nums\">{cat.count}</p>\n </div>\n <div className=\"text-right\">\n <p className=\"text-xs text-text-secondary\">Total value</p>\n <p className=\"text-2xl font-bold tabular-nums\">\n {moneyCompact(cat.totalValue)}\n </p>\n </div>\n </div>\n\n {/* Proportional status bar */}\n <div>\n <div\n className=\"flex h-2.5 w-full overflow-hidden rounded-full bg-bg-sunken\"\n role=\"img\"\n aria-label={segments\n .map((s) => `${s.label}: ${cat.statuses[s.key]}`)\n .join(', ')}\n >\n {segments.map((s) => (\n <div\n key={s.key}\n style={{\n width: `${((cat.statuses[s.key] || 0) / cat.count) * 100}%`,\n backgroundColor: s.varName,\n }}\n />\n ))}\n </div>\n <div className=\"mt-2 flex flex-wrap gap-x-3 gap-y-1\">\n {segments.map((s) => (\n <span\n key={s.key}\n className=\"inline-flex items-center gap-1.5 text-xs text-text-secondary\"\n >\n <span\n className=\"h-2.5 w-2.5 rounded-[3px]\"\n style={{ backgroundColor: s.varName }}\n />\n {s.label}\n <span className=\"tabular-nums text-text-muted\">\n {cat.statuses[s.key]}\n </span>\n </span>\n ))}\n </div>\n </div>\n\n {/* Avg condition */}\n <div className=\"flex items-center justify-between border-t border-border-seam pt-3 text-sm\">\n <span className=\"text-text-secondary\">Avg. condition</span>\n <span className=\"font-semibold tabular-nums\">\n {cat.avgCondition > 0 ? cat.avgCondition.toFixed(1) : '—'}\n <span className=\"text-xs font-normal text-text-muted\"> / 5</span>\n </span>\n </div>\n </div>\n </GlassCard>\n );\n })}\n </div>\n\n {/* Cross-category comparison chart */}\n <ChartCard\n title=\"Category comparison\"\n subtitle={\n chartMetric === 'count' ? `${term.assets} per category` : 'Book value per category'\n }\n actions={\n <div className=\"flex gap-1 rounded-md border border-border-seam p-0.5\">\n <Button\n variant={chartMetric === 'count' ? 'default' : 'ghost'}\n size=\"sm\"\n className=\"h-7 px-2 text-xs\"\n onClick={() => setChartMetric('count')}\n >\n Count\n </Button>\n <Button\n variant={chartMetric === 'value' ? 'default' : 'ghost'}\n size=\"sm\"\n className=\"h-7 px-2 text-xs\"\n onClick={() => setChartMetric('value')}\n >\n Value\n </Button>\n </div>\n }\n >\n <BarsChart\n data={chartData}\n xKey=\"category\"\n orientation=\"horizontal\"\n height={Math.max(200, chartData.length * 44)}\n categoryWidth={120}\n valueFormat={chartMetric === 'value' ? moneyCompact : formatCompact}\n series={[\n {\n key: chartMetric,\n label: chartMetric === 'count' ? term.assets : 'Book value',\n },\n ]}\n />\n </ChartCard>\n\n {/* Summary comparison table */}\n <ChartCard\n title=\"Category summary\"\n subtitle=\"Sortable roll-up across every category\"\n icon={Layers}\n >\n <div className=\"overflow-x-auto\">\n <table className=\"w-full min-w-[520px] text-sm\">\n <thead>\n <tr className=\"border-b border-border-seam text-left text-text-secondary\">\n <th className=\"py-2 pr-4 font-medium\">Category</th>\n <th className=\"py-2 pr-4 font-medium\">\n <button\n type=\"button\"\n className=\"inline-flex items-center gap-1 hover:text-text-primary\"\n onClick={() => setSortKey('count')}\n >\n Count\n <ArrowUpDown\n className={`h-3 w-3 ${sortKey === 'count' ? 'text-action-primary-bg' : ''}`}\n />\n </button>\n </th>\n <th className=\"py-2 pr-4 font-medium\">\n <button\n type=\"button\"\n className=\"inline-flex items-center gap-1 hover:text-text-primary\"\n onClick={() => setSortKey('value')}\n >\n Value\n <ArrowUpDown\n className={`h-3 w-3 ${sortKey === 'value' ? 'text-action-primary-bg' : ''}`}\n />\n </button>\n </th>\n <th className=\"py-2 font-medium\">Avg. condition</th>\n </tr>\n </thead>\n <tbody>\n {sortedRows.map((cat) => (\n <tr key={cat.key} className=\"border-b border-border-seam/60 last:border-0\">\n <td className=\"py-2.5 pr-4 font-medium capitalize\">\n {formatAssetCategory(cat.key, categoryLabels)}\n </td>\n <td className=\"py-2.5 pr-4 tabular-nums\">{cat.count}</td>\n <td className=\"py-2.5 pr-4 tabular-nums\">{money(cat.totalValue)}</td>\n <td className=\"py-2.5 tabular-nums\">\n {cat.avgCondition > 0 ? cat.avgCondition.toFixed(1) : '—'}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </ChartCard>\n </>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssetsAssetCreatePage.d.ts","sourceRoot":"","sources":["../../../src/assethandler/pages/AssetsAssetCreatePage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AssetsAssetCreatePage.d.ts","sourceRoot":"","sources":["../../../src/assethandler/pages/AssetsAssetCreatePage.tsx"],"names":[],"mappings":"AAkLA,wBAAgB,qBAAqB,gCA8jBpC"}
|
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
import { useAssetHandlerStore as e } from "../store/assethandlerStore.js";
|
|
2
2
|
import { formatAssetCategory as t } from "../utils/categoryPresentation.js";
|
|
3
|
-
import { useAssetCategoryPresentation as n,
|
|
4
|
-
import { useAssetHandlerNavigate as
|
|
5
|
-
import { useCopy as
|
|
6
|
-
import { notify as
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { ChartCard as s } from "../components/ChartCard.js";
|
|
3
|
+
import { useAssetCategoryPresentation as n, useAssetMoney as r, useHiddenCategoryIds as i } from "../providers/AssetHandlerProvider.js";
|
|
4
|
+
import { useAssetHandlerNavigate as a } from "../hooks/useAssetHandlerNavigate.js";
|
|
5
|
+
import { useCopy as o } from "../hooks/useCopy.js";
|
|
6
|
+
import { notify as s } from "../utils/toast.js";
|
|
7
|
+
import { TrendChart as c } from "../components/charts/TrendChart.js";
|
|
8
|
+
import { ChartCard as ee } from "../components/ChartCard.js";
|
|
10
9
|
import "../components/index.js";
|
|
11
|
-
import { useMemo as
|
|
12
|
-
import { ArrowLeft as
|
|
13
|
-
import { gql as
|
|
14
|
-
import { useMutation as
|
|
10
|
+
import { useMemo as l, useRef as u, useState as d } from "react";
|
|
11
|
+
import { ArrowLeft as te, Info as ne, Loader2 as f, Save as p, TrendingDown as re, X as m } from "lucide-react";
|
|
12
|
+
import { gql as h } from "@apollo/client";
|
|
13
|
+
import { useMutation as ie } from "@apollo/client/react";
|
|
15
14
|
import { jsx as g, jsxs as _ } from "react/jsx-runtime";
|
|
16
|
-
import { Badge as v, Button as y, GlassCard as b, GradientText as ae, Input as x, Label as S, PagePurpose as
|
|
15
|
+
import { Badge as v, Button as y, GlassCard as b, GradientText as ae, Input as x, Label as S, PagePurpose as C, Select as w, SelectContent as T, SelectItem as E, SelectTrigger as D, SelectValue as O, Textarea as k } from "@burdenoff/fe-libs/ui";
|
|
17
16
|
//#region src/assethandler/pages/AssetsAssetCreatePage.tsx
|
|
18
|
-
var
|
|
17
|
+
var oe = h`
|
|
19
18
|
mutation AssetHandlerCreateAsset($input: CreateAssetInput!) {
|
|
20
19
|
createAsset(input: $input) {
|
|
21
20
|
id
|
|
@@ -23,7 +22,7 @@ var k = m`
|
|
|
23
22
|
name
|
|
24
23
|
}
|
|
25
24
|
}
|
|
26
|
-
`,
|
|
25
|
+
`, se = [
|
|
27
26
|
"electronics",
|
|
28
27
|
"it_hardware",
|
|
29
28
|
"furniture",
|
|
@@ -32,7 +31,7 @@ var k = m`
|
|
|
32
31
|
"software",
|
|
33
32
|
"networking",
|
|
34
33
|
"servers"
|
|
35
|
-
],
|
|
34
|
+
], A = {
|
|
36
35
|
name: "",
|
|
37
36
|
description: "",
|
|
38
37
|
category: "it_hardware",
|
|
@@ -53,7 +52,7 @@ var k = m`
|
|
|
53
52
|
supplier: "",
|
|
54
53
|
department: ""
|
|
55
54
|
};
|
|
56
|
-
function
|
|
55
|
+
function j(e) {
|
|
57
56
|
let t = e.purchaseValue, n = e.usefulLifeMonths;
|
|
58
57
|
if (!t || t <= 0 || !n || n <= 0) return [];
|
|
59
58
|
let r = Math.max(0, Math.min(e.salvageValue ?? 0, t)), i = e.method.toLowerCase(), a = Math.max(1, Math.round(n / 12));
|
|
@@ -89,7 +88,7 @@ function M(e) {
|
|
|
89
88
|
}
|
|
90
89
|
return o;
|
|
91
90
|
}
|
|
92
|
-
var
|
|
91
|
+
var M = ({ title: e, description: t, children: n, glow: r }) => /* @__PURE__ */ g(b, {
|
|
93
92
|
treatment: "glass",
|
|
94
93
|
glow: r,
|
|
95
94
|
className: "border-border-seam",
|
|
@@ -104,25 +103,25 @@ var N = ({ title: e, description: t, children: n, glow: r }) => /* @__PURE__ */
|
|
|
104
103
|
}) : null] }), n]
|
|
105
104
|
})
|
|
106
105
|
});
|
|
107
|
-
function
|
|
108
|
-
let
|
|
109
|
-
let e = new Set(I?.map((e) => e.id) ??
|
|
106
|
+
function N() {
|
|
107
|
+
let h = o(), b = a(), { symbol: N, compact: ce } = r(), P = i(), { labels: F, options: I } = n(), { assets: L } = e(), [R, z] = d(A), [B, V] = d([]), [H, U] = d(""), [W, G] = d({}), [K, q] = d(null), J = u(!1), le = l(() => {
|
|
108
|
+
let e = new Set(I?.map((e) => e.id) ?? se);
|
|
110
109
|
if (!I) for (let t of L) t.category && e.add(t.category);
|
|
111
110
|
return [...e].filter((e) => !P.has(e)).sort();
|
|
112
111
|
}, [
|
|
113
112
|
L,
|
|
114
113
|
I,
|
|
115
114
|
P
|
|
116
|
-
]), [
|
|
115
|
+
]), [ue, { loading: Y }] = ie(oe, {
|
|
117
116
|
refetchQueries: ["AssetHandlerBootstrap"],
|
|
118
117
|
onCompleted: (e) => {
|
|
119
|
-
|
|
118
|
+
s.success(h("assethandler.assets.create.toast.title", "{{asset}} created"), h("assethandler.assets.create.toast.body", "{{name}} was registered in the inventory.", { name: e.createAsset.name })), q(null), J.current ? (J.current = !1, z(A), V([]), U(""), G({}), typeof window < "u" && window.scrollTo({
|
|
120
119
|
top: 0,
|
|
121
120
|
behavior: "smooth"
|
|
122
121
|
})) : b(`/assets/${e.createAsset.id}`);
|
|
123
122
|
},
|
|
124
123
|
onError: (e) => {
|
|
125
|
-
q(null),
|
|
124
|
+
q(null), s.error("Could not create asset", e.message);
|
|
126
125
|
}
|
|
127
126
|
}), X = (e, t) => {
|
|
128
127
|
z((n) => ({
|
|
@@ -136,9 +135,9 @@ function P() {
|
|
|
136
135
|
}, Z = () => {
|
|
137
136
|
let e = H.trim().replace(/,$/, "").trim();
|
|
138
137
|
e && !B.includes(e) && V((t) => [...t, e]), U("");
|
|
139
|
-
},
|
|
138
|
+
}, de = (e) => {
|
|
140
139
|
e.key === "Enter" || e.key === "," ? (e.preventDefault(), Z()) : e.key === "Backspace" && H === "" && B.length > 0 && V((e) => e.slice(0, -1));
|
|
141
|
-
}, Q =
|
|
140
|
+
}, Q = l(() => j({
|
|
142
141
|
purchaseValue: R.purchaseValue.trim() ? Number(R.purchaseValue) : null,
|
|
143
142
|
salvageValue: R.salvageValue.trim() ? Number(R.salvageValue) : null,
|
|
144
143
|
usefulLifeMonths: R.usefulLifeMonths.trim() ? Number(R.usefulLifeMonths) : null,
|
|
@@ -161,7 +160,7 @@ function P() {
|
|
|
161
160
|
(Number.isNaN(i) || i < 0) && (t[r] = `${n} must be a positive number`);
|
|
162
161
|
};
|
|
163
162
|
if (n(R.purchaseValue, "Purchase value", "purchaseValue"), n(R.salvageValue, "Salvage value", "salvageValue"), n(R.usefulLifeMonths, "Useful life", "usefulLifeMonths"), G(t), Object.keys(t).length > 0) {
|
|
164
|
-
|
|
163
|
+
s.warning("Missing required fields", "Fill in the highlighted fields and try again.");
|
|
165
164
|
return;
|
|
166
165
|
}
|
|
167
166
|
let r = (e) => {
|
|
@@ -170,7 +169,7 @@ function P() {
|
|
|
170
169
|
let n = Number(t);
|
|
171
170
|
return Number.isNaN(n) ? null : n;
|
|
172
171
|
}, i = (e) => e.trim() === "" ? null : new Date(e).toISOString();
|
|
173
|
-
J.current = e, q(e ? "add" : "create"),
|
|
172
|
+
J.current = e, q(e ? "add" : "create"), ue({ variables: { input: {
|
|
174
173
|
name: R.name.trim(),
|
|
175
174
|
assetNumber: R.assetNumber.trim(),
|
|
176
175
|
category: R.category,
|
|
@@ -204,14 +203,14 @@ function P() {
|
|
|
204
203
|
"aria-label": "Go back",
|
|
205
204
|
className: "w-fit",
|
|
206
205
|
onClick: () => b("/assets/asset-list"),
|
|
207
|
-
children: /* @__PURE__ */ g(
|
|
206
|
+
children: /* @__PURE__ */ g(te, { className: "h-4 w-4" })
|
|
208
207
|
}), /* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("h1", {
|
|
209
208
|
className: "text-2xl font-bold",
|
|
210
|
-
children: /* @__PURE__ */ g(ae, { children:
|
|
209
|
+
children: /* @__PURE__ */ g(ae, { children: h("assethandler.assets.create.title", "Create New {{asset}}") })
|
|
211
210
|
}), /* @__PURE__ */ _("p", {
|
|
212
211
|
className: "text-sm text-text-secondary",
|
|
213
212
|
children: [
|
|
214
|
-
|
|
213
|
+
h("assethandler.assets.create.subtitle", "Register a new {{assetLower}} in the inventory"),
|
|
215
214
|
" ",
|
|
216
215
|
"· ",
|
|
217
216
|
/* @__PURE__ */ g("span", {
|
|
@@ -222,10 +221,10 @@ function P() {
|
|
|
222
221
|
]
|
|
223
222
|
})] })]
|
|
224
223
|
}),
|
|
225
|
-
/* @__PURE__ */ g(
|
|
226
|
-
/* @__PURE__ */ _(
|
|
224
|
+
/* @__PURE__ */ g(C, { children: h("assethandler.assets.create.purpose", "Register a new {{assetLower}} so it can be tracked, maintained and assigned from day one. Capture its identity, category and condition, then its financials and location — the more you fill in now, the better your reports and audits later.") }),
|
|
225
|
+
/* @__PURE__ */ _(M, {
|
|
227
226
|
title: "General Information",
|
|
228
|
-
description:
|
|
227
|
+
description: h("assethandler.assets.create.general.description", "Basic {{assetLower}} details and identification"),
|
|
229
228
|
glow: !0,
|
|
230
229
|
children: [
|
|
231
230
|
/* @__PURE__ */ _("div", {
|
|
@@ -234,7 +233,7 @@ function P() {
|
|
|
234
233
|
className: "space-y-2",
|
|
235
234
|
children: [
|
|
236
235
|
/* @__PURE__ */ _(S, { children: [
|
|
237
|
-
|
|
236
|
+
h("assethandler.assets.create.field.name", "{{asset}} Name"),
|
|
238
237
|
" ",
|
|
239
238
|
/* @__PURE__ */ g("span", {
|
|
240
239
|
className: "text-status-error-text",
|
|
@@ -242,7 +241,7 @@ function P() {
|
|
|
242
241
|
})
|
|
243
242
|
] }),
|
|
244
243
|
/* @__PURE__ */ g(x, {
|
|
245
|
-
placeholder:
|
|
244
|
+
placeholder: h("assethandler.assets.create.field.namePlaceholder", "e.g., Dell OptiPlex 7090"),
|
|
246
245
|
value: R.name,
|
|
247
246
|
onChange: (e) => X("name", e.target.value),
|
|
248
247
|
"aria-invalid": !!W.name
|
|
@@ -256,7 +255,7 @@ function P() {
|
|
|
256
255
|
className: "space-y-2",
|
|
257
256
|
children: [
|
|
258
257
|
/* @__PURE__ */ _(S, { children: [
|
|
259
|
-
|
|
258
|
+
h("assethandler.assets.create.field.tag", "{{asset}} Tag"),
|
|
260
259
|
" ",
|
|
261
260
|
/* @__PURE__ */ g("span", {
|
|
262
261
|
className: "text-status-error-text",
|
|
@@ -264,7 +263,7 @@ function P() {
|
|
|
264
263
|
})
|
|
265
264
|
] }),
|
|
266
265
|
/* @__PURE__ */ g(x, {
|
|
267
|
-
placeholder:
|
|
266
|
+
placeholder: h("assethandler.assets.create.field.tagPlaceholder", "e.g., IT-HW-001"),
|
|
268
267
|
value: R.assetNumber,
|
|
269
268
|
onChange: (e) => X("assetNumber", e.target.value),
|
|
270
269
|
"aria-invalid": !!W.assetNumber
|
|
@@ -278,8 +277,8 @@ function P() {
|
|
|
278
277
|
}),
|
|
279
278
|
/* @__PURE__ */ _("div", {
|
|
280
279
|
className: "space-y-2",
|
|
281
|
-
children: [/* @__PURE__ */ g(S, { children: "Description" }), /* @__PURE__ */ g(
|
|
282
|
-
placeholder:
|
|
280
|
+
children: [/* @__PURE__ */ g(S, { children: "Description" }), /* @__PURE__ */ g(k, {
|
|
281
|
+
placeholder: h("assethandler.assets.create.field.descriptionPlaceholder", "Brief description of the {{assetLower}}..."),
|
|
283
282
|
value: R.description,
|
|
284
283
|
onChange: (e) => X("description", e.target.value),
|
|
285
284
|
rows: 3
|
|
@@ -293,10 +292,10 @@ function P() {
|
|
|
293
292
|
children: [/* @__PURE__ */ _(S, { children: ["Category ", /* @__PURE__ */ g("span", {
|
|
294
293
|
className: "text-status-error-text",
|
|
295
294
|
children: "*"
|
|
296
|
-
})] }), /* @__PURE__ */ _(
|
|
295
|
+
})] }), /* @__PURE__ */ _(w, {
|
|
297
296
|
value: R.category,
|
|
298
297
|
onValueChange: (e) => X("category", e),
|
|
299
|
-
children: [/* @__PURE__ */ g(
|
|
298
|
+
children: [/* @__PURE__ */ g(D, { children: /* @__PURE__ */ g(O, {}) }), /* @__PURE__ */ g(T, { children: le.map((e) => /* @__PURE__ */ g(E, {
|
|
300
299
|
value: e,
|
|
301
300
|
className: "capitalize",
|
|
302
301
|
children: I?.find((t) => t.id === e)?.label ?? t(e, F)
|
|
@@ -305,23 +304,23 @@ function P() {
|
|
|
305
304
|
}),
|
|
306
305
|
/* @__PURE__ */ _("div", {
|
|
307
306
|
className: "space-y-2",
|
|
308
|
-
children: [/* @__PURE__ */ g(S, { children: "Status" }), /* @__PURE__ */ _(
|
|
307
|
+
children: [/* @__PURE__ */ g(S, { children: "Status" }), /* @__PURE__ */ _(w, {
|
|
309
308
|
value: R.status,
|
|
310
309
|
onValueChange: (e) => X("status", e),
|
|
311
|
-
children: [/* @__PURE__ */ g(
|
|
312
|
-
/* @__PURE__ */ g(
|
|
310
|
+
children: [/* @__PURE__ */ g(D, { children: /* @__PURE__ */ g(O, {}) }), /* @__PURE__ */ _(T, { children: [
|
|
311
|
+
/* @__PURE__ */ g(E, {
|
|
313
312
|
value: "ACTIVE",
|
|
314
313
|
children: "Active"
|
|
315
314
|
}),
|
|
316
|
-
/* @__PURE__ */ g(
|
|
315
|
+
/* @__PURE__ */ g(E, {
|
|
317
316
|
value: "INACTIVE",
|
|
318
317
|
children: "Inactive"
|
|
319
318
|
}),
|
|
320
|
-
/* @__PURE__ */ g(
|
|
319
|
+
/* @__PURE__ */ g(E, {
|
|
321
320
|
value: "MAINTENANCE",
|
|
322
321
|
children: "Maintenance"
|
|
323
322
|
}),
|
|
324
|
-
/* @__PURE__ */ g(
|
|
323
|
+
/* @__PURE__ */ g(E, {
|
|
325
324
|
value: "RETIRED",
|
|
326
325
|
children: "Retired"
|
|
327
326
|
})
|
|
@@ -330,27 +329,27 @@ function P() {
|
|
|
330
329
|
}),
|
|
331
330
|
/* @__PURE__ */ _("div", {
|
|
332
331
|
className: "space-y-2",
|
|
333
|
-
children: [/* @__PURE__ */ g(S, { children: "Condition" }), /* @__PURE__ */ _(
|
|
332
|
+
children: [/* @__PURE__ */ g(S, { children: "Condition" }), /* @__PURE__ */ _(w, {
|
|
334
333
|
value: R.condition,
|
|
335
334
|
onValueChange: (e) => X("condition", e),
|
|
336
|
-
children: [/* @__PURE__ */ g(
|
|
337
|
-
/* @__PURE__ */ g(
|
|
335
|
+
children: [/* @__PURE__ */ g(D, { children: /* @__PURE__ */ g(O, {}) }), /* @__PURE__ */ _(T, { children: [
|
|
336
|
+
/* @__PURE__ */ g(E, {
|
|
338
337
|
value: "EXCELLENT",
|
|
339
338
|
children: "Excellent"
|
|
340
339
|
}),
|
|
341
|
-
/* @__PURE__ */ g(
|
|
340
|
+
/* @__PURE__ */ g(E, {
|
|
342
341
|
value: "GOOD",
|
|
343
342
|
children: "Good"
|
|
344
343
|
}),
|
|
345
|
-
/* @__PURE__ */ g(
|
|
344
|
+
/* @__PURE__ */ g(E, {
|
|
346
345
|
value: "FAIR",
|
|
347
346
|
children: "Fair"
|
|
348
347
|
}),
|
|
349
|
-
/* @__PURE__ */ g(
|
|
348
|
+
/* @__PURE__ */ g(E, {
|
|
350
349
|
value: "POOR",
|
|
351
350
|
children: "Poor"
|
|
352
351
|
}),
|
|
353
|
-
/* @__PURE__ */ g(
|
|
352
|
+
/* @__PURE__ */ g(E, {
|
|
354
353
|
value: "DAMAGED",
|
|
355
354
|
children: "Damaged"
|
|
356
355
|
})
|
|
@@ -369,7 +368,7 @@ function P() {
|
|
|
369
368
|
})
|
|
370
369
|
]
|
|
371
370
|
}),
|
|
372
|
-
/* @__PURE__ */ _(
|
|
371
|
+
/* @__PURE__ */ _(M, {
|
|
373
372
|
title: "Financial Details",
|
|
374
373
|
description: "Purchase and depreciation data powers book value, TCO and finance reports",
|
|
375
374
|
children: [
|
|
@@ -384,7 +383,7 @@ function P() {
|
|
|
384
383
|
className: "relative",
|
|
385
384
|
children: [/* @__PURE__ */ g("span", {
|
|
386
385
|
className: "pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-sm text-text-secondary",
|
|
387
|
-
children:
|
|
386
|
+
children: N
|
|
388
387
|
}), /* @__PURE__ */ g(x, {
|
|
389
388
|
type: "number",
|
|
390
389
|
min: "0",
|
|
@@ -457,7 +456,7 @@ function P() {
|
|
|
457
456
|
className: "relative",
|
|
458
457
|
children: [/* @__PURE__ */ g("span", {
|
|
459
458
|
className: "pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-sm text-text-secondary",
|
|
460
|
-
children:
|
|
459
|
+
children: N
|
|
461
460
|
}), /* @__PURE__ */ g(x, {
|
|
462
461
|
type: "number",
|
|
463
462
|
min: "0",
|
|
@@ -477,31 +476,31 @@ function P() {
|
|
|
477
476
|
}),
|
|
478
477
|
/* @__PURE__ */ _("div", {
|
|
479
478
|
className: "space-y-2",
|
|
480
|
-
children: [/* @__PURE__ */ g(S, { children: "Depreciation Method" }), /* @__PURE__ */ _(
|
|
479
|
+
children: [/* @__PURE__ */ g(S, { children: "Depreciation Method" }), /* @__PURE__ */ _(w, {
|
|
481
480
|
value: R.depreciationMethod,
|
|
482
481
|
onValueChange: (e) => X("depreciationMethod", e),
|
|
483
|
-
children: [/* @__PURE__ */ g(
|
|
484
|
-
/* @__PURE__ */ g(
|
|
482
|
+
children: [/* @__PURE__ */ g(D, { children: /* @__PURE__ */ g(O, {}) }), /* @__PURE__ */ _(T, { children: [
|
|
483
|
+
/* @__PURE__ */ g(E, {
|
|
485
484
|
value: "STRAIGHT_LINE",
|
|
486
485
|
children: "Straight line"
|
|
487
486
|
}),
|
|
488
|
-
/* @__PURE__ */ g(
|
|
487
|
+
/* @__PURE__ */ g(E, {
|
|
489
488
|
value: "REDUCING_BALANCE",
|
|
490
489
|
children: "Reducing balance (200%)"
|
|
491
490
|
}),
|
|
492
|
-
/* @__PURE__ */ g(
|
|
491
|
+
/* @__PURE__ */ g(E, {
|
|
493
492
|
value: "DECLINING_BALANCE",
|
|
494
493
|
children: "Declining balance (150%)"
|
|
495
494
|
}),
|
|
496
|
-
/* @__PURE__ */ g(
|
|
495
|
+
/* @__PURE__ */ g(E, {
|
|
497
496
|
value: "SUM_OF_YEARS_DIGITS",
|
|
498
497
|
children: "Sum of years' digits"
|
|
499
498
|
}),
|
|
500
|
-
/* @__PURE__ */ g(
|
|
499
|
+
/* @__PURE__ */ g(E, {
|
|
501
500
|
value: "UNITS_OF_PRODUCTION",
|
|
502
501
|
children: "Units of production"
|
|
503
502
|
}),
|
|
504
|
-
/* @__PURE__ */ g(
|
|
503
|
+
/* @__PURE__ */ g(E, {
|
|
505
504
|
value: "NONE",
|
|
506
505
|
children: "None"
|
|
507
506
|
})
|
|
@@ -542,15 +541,15 @@ function P() {
|
|
|
542
541
|
onChange: (e) => X("warrantyExpiry", e.target.value)
|
|
543
542
|
})]
|
|
544
543
|
}),
|
|
545
|
-
/* @__PURE__ */ g(
|
|
544
|
+
/* @__PURE__ */ g(ee, {
|
|
546
545
|
title: "Depreciation preview",
|
|
547
|
-
subtitle:
|
|
548
|
-
icon:
|
|
549
|
-
children: Q.length > 0 ? /* @__PURE__ */ g(
|
|
546
|
+
subtitle: h("assethandler.assets.create.depreciation.subtitle", "Projected book value over the {{assetLower}}'s useful life"),
|
|
547
|
+
icon: re,
|
|
548
|
+
children: Q.length > 0 ? /* @__PURE__ */ g(c, {
|
|
550
549
|
data: Q,
|
|
551
550
|
xKey: "year",
|
|
552
551
|
height: 240,
|
|
553
|
-
valueFormat:
|
|
552
|
+
valueFormat: ce,
|
|
554
553
|
xTickFormat: (e) => `${e}y`,
|
|
555
554
|
series: [{
|
|
556
555
|
key: "bookValue",
|
|
@@ -558,12 +557,12 @@ function P() {
|
|
|
558
557
|
}]
|
|
559
558
|
}) : /* @__PURE__ */ _("div", {
|
|
560
559
|
className: "flex flex-col items-center gap-2 py-10 text-center text-sm text-text-secondary",
|
|
561
|
-
children: [/* @__PURE__ */ g(
|
|
560
|
+
children: [/* @__PURE__ */ g(ne, { className: "h-5 w-5 text-text-muted" }), "Enter a purchase value and useful life to preview the depreciation schedule."]
|
|
562
561
|
})
|
|
563
562
|
})
|
|
564
563
|
]
|
|
565
564
|
}),
|
|
566
|
-
/* @__PURE__ */ g(
|
|
565
|
+
/* @__PURE__ */ g(M, {
|
|
567
566
|
title: "Assignment & Location",
|
|
568
567
|
description: "Who holds it and where it lives",
|
|
569
568
|
children: /* @__PURE__ */ _("div", {
|
|
@@ -605,12 +604,12 @@ function P() {
|
|
|
605
604
|
"aria-label": `Remove ${e}`,
|
|
606
605
|
onClick: () => V((t) => t.filter((t) => t !== e)),
|
|
607
606
|
className: "text-text-secondary hover:text-text-primary",
|
|
608
|
-
children: /* @__PURE__ */ g(
|
|
607
|
+
children: /* @__PURE__ */ g(m, { className: "h-3 w-3" })
|
|
609
608
|
})]
|
|
610
609
|
}, e)), /* @__PURE__ */ g("input", {
|
|
611
610
|
value: H,
|
|
612
611
|
onChange: (e) => U(e.target.value),
|
|
613
|
-
onKeyDown:
|
|
612
|
+
onKeyDown: de,
|
|
614
613
|
onBlur: Z,
|
|
615
614
|
placeholder: B.length === 0 ? "Type a tag and press Enter" : "",
|
|
616
615
|
className: "min-w-[8rem] flex-1 border-0 bg-transparent text-sm outline-none placeholder:text-text-secondary"
|
|
@@ -630,20 +629,20 @@ function P() {
|
|
|
630
629
|
className: "w-full sm:w-auto",
|
|
631
630
|
onClick: () => b("/assets/asset-list"),
|
|
632
631
|
disabled: Y,
|
|
633
|
-
children: [/* @__PURE__ */ g(
|
|
632
|
+
children: [/* @__PURE__ */ g(m, { className: "mr-2 h-4 w-4" }), "Cancel"]
|
|
634
633
|
}),
|
|
635
634
|
/* @__PURE__ */ _(y, {
|
|
636
635
|
variant: "outline",
|
|
637
636
|
className: "w-full sm:w-auto",
|
|
638
637
|
onClick: () => $(!0),
|
|
639
638
|
disabled: Y,
|
|
640
|
-
children: [Y && K === "add" ? /* @__PURE__ */ g(
|
|
639
|
+
children: [Y && K === "add" ? /* @__PURE__ */ g(f, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ g(p, { className: "mr-2 h-4 w-4" }), "Save & add another"]
|
|
641
640
|
}),
|
|
642
641
|
/* @__PURE__ */ _(y, {
|
|
643
642
|
className: "w-full sm:w-auto",
|
|
644
643
|
onClick: () => $(!1),
|
|
645
644
|
disabled: Y,
|
|
646
|
-
children: [Y && K === "create" ? /* @__PURE__ */ g(
|
|
645
|
+
children: [Y && K === "create" ? /* @__PURE__ */ g(f, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ g(p, { className: "mr-2 h-4 w-4" }), Y ? "Creating..." : "Create Asset"]
|
|
647
646
|
})
|
|
648
647
|
]
|
|
649
648
|
})
|
|
@@ -652,6 +651,6 @@ function P() {
|
|
|
652
651
|
});
|
|
653
652
|
}
|
|
654
653
|
//#endregion
|
|
655
|
-
export {
|
|
654
|
+
export { N as AssetsAssetCreatePage };
|
|
656
655
|
|
|
657
656
|
//# sourceMappingURL=AssetsAssetCreatePage.js.map
|