@burdenoff/microfe-assethandler 2026.713.2 → 2026.714.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.
Files changed (34) hide show
  1. package/dist/assethandler/components/AttachmentsPanel.d.ts.map +1 -1
  2. package/dist/assethandler/components/AttachmentsPanel.js.map +1 -1
  3. package/dist/assethandler/hooks/useCopy.d.ts +28 -0
  4. package/dist/assethandler/hooks/useCopy.d.ts.map +1 -0
  5. package/dist/assethandler/hooks/useCopy.js +33 -0
  6. package/dist/assethandler/hooks/useCopy.js.map +1 -0
  7. package/dist/assethandler/index.d.ts +1 -1
  8. package/dist/assethandler/index.d.ts.map +1 -1
  9. package/dist/assethandler/pages/AnalyticsPage.d.ts.map +1 -1
  10. package/dist/assethandler/pages/AnalyticsPage.js +259 -258
  11. package/dist/assethandler/pages/AnalyticsPage.js.map +1 -1
  12. package/dist/assethandler/pages/AssetsAssetCategoriesPage.d.ts.map +1 -1
  13. package/dist/assethandler/pages/AssetsAssetCategoriesPage.js +1 -2
  14. package/dist/assethandler/pages/AssetsAssetCategoriesPage.js.map +1 -1
  15. package/dist/assethandler/pages/AssetsAssetDetailPage.d.ts.map +1 -1
  16. package/dist/assethandler/pages/AssetsAssetDetailPage.js +376 -365
  17. package/dist/assethandler/pages/AssetsAssetDetailPage.js.map +1 -1
  18. package/dist/assethandler/pages/AssetsAssetListPage.d.ts.map +1 -1
  19. package/dist/assethandler/pages/AssetsAssetListPage.js +47 -48
  20. package/dist/assethandler/pages/AssetsAssetListPage.js.map +1 -1
  21. package/dist/assethandler/pages/DashboardPage.d.ts.map +1 -1
  22. package/dist/assethandler/pages/DashboardPage.js +236 -236
  23. package/dist/assethandler/pages/DashboardPage.js.map +1 -1
  24. package/dist/assethandler/pages/PortfolioPortfolioOverviewPage.d.ts.map +1 -1
  25. package/dist/assethandler/pages/PortfolioPortfolioOverviewPage.js +126 -125
  26. package/dist/assethandler/pages/PortfolioPortfolioOverviewPage.js.map +1 -1
  27. package/dist/assethandler/pages/TransactionsTransactionListPage.js +127 -127
  28. package/dist/assethandler/pages/TransactionsTransactionListPage.js.map +1 -1
  29. package/dist/assethandler/store/assethandlerStore.d.ts.map +1 -1
  30. package/dist/assethandler/store/assethandlerStore.js.map +1 -1
  31. package/dist/assethandler/types/index.d.ts +20 -0
  32. package/dist/assethandler/types/index.d.ts.map +1 -1
  33. package/dist/types/assistant.d.ts.map +1 -1
  34. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"AssetsAssetDetailPage.js","names":[],"sources":["../../../src/assethandler/pages/AssetsAssetDetailPage.tsx"],"sourcesContent":["import { useAssetHandlerNavigate } from '../hooks/useAssetHandlerNavigate';\nimport type React from 'react';\nimport { useState } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n GradientText,\n EmphasisPanel,\n PagePurpose,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n Input,\n Label,\n Textarea,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n GlassCard,\n} from '@burdenoff/fe-libs/ui';\nimport {\n ArrowLeft,\n MapPin,\n Calendar,\n Tag,\n User,\n Wrench,\n Pencil,\n Trash2,\n Archive,\n DollarSign,\n TrendingDown,\n Hash,\n Building2,\n Truck,\n ShieldCheck,\n Layers,\n} from 'lucide-react';\nimport { useParams } from 'react-router-dom';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport { useAssetHandlerStore } from '../store/assethandlerStore';\nimport { notify } from '../utils/toast';\nimport { AttachmentsPanel, CommentsPanel, ActivityTimeline, NotFoundState } from '../components';\nimport {\n StatTile,\n ChartCard,\n TrendChart,\n BarsChart,\n DonutChart,\n formatCurrencyCompact,\n} from '../components';\n\nconst ASSET_QUERY = gql`\n query AssetHandlerAsset($id: ID!) {\n asset(id: $id) {\n id\n assetNumber\n name\n description\n category\n status\n condition\n serialNumber\n locationName\n assignedTo\n tags\n createdAt\n updatedAt\n purchaseValue\n purchaseDate\n usefulLifeMonths\n salvageValue\n depreciationMethod\n department\n warrantyExpiry\n supplier\n disposalDate\n disposalMethod\n disposalNotes\n currentValue\n accumulatedDepreciation\n totalCostOfOwnership\n }\n }\n`;\n\ninterface AssetRecord {\n id: string;\n assetNumber: string;\n name: string;\n description?: string | null;\n category: string;\n status: string;\n condition: string;\n serialNumber?: string | null;\n locationName?: string | null;\n assignedTo?: string | null;\n tags: string[];\n createdAt: string;\n updatedAt: string;\n purchaseValue?: number | null;\n purchaseDate?: string | null;\n usefulLifeMonths?: number | null;\n salvageValue?: number | null;\n depreciationMethod?: string | null;\n department?: string | null;\n warrantyExpiry?: string | null;\n supplier?: string | null;\n disposalDate?: string | null;\n disposalMethod?: string | null;\n disposalNotes?: string | null;\n currentValue?: number | null;\n accumulatedDepreciation?: number | null;\n totalCostOfOwnership?: number | null;\n}\n\ninterface AssetQueryResult {\n asset: AssetRecord | null;\n}\n\nconst UPDATE_ASSET_MUTATION = gql`\n mutation AssetHandlerUpdateAsset($id: ID!, $input: UpdateAssetInput!) {\n updateAsset(id: $id, input: $input) {\n id\n }\n }\n`;\n\nconst DISPOSE_ASSET_MUTATION = gql`\n mutation AssetHandlerDisposeAsset($id: ID!, $input: DisposeAssetInput!) {\n disposeAsset(id: $id, input: $input) {\n id\n status\n }\n }\n`;\n\nconst DELETE_ASSET_MUTATION = gql`\n mutation AssetHandlerDeleteAsset($id: ID!) {\n deleteAsset(id: $id)\n }\n`;\n\nconst conditionColors: Record<string, string> = {\n excellent: 'text-status-success-text bg-status-success-bg-subtle',\n good: 'text-status-info-text bg-status-info-bg-subtle',\n fair: 'text-status-warning-text bg-status-warning-bg-subtle',\n poor: 'text-status-warning-text bg-status-warning-bg-subtle',\n damaged: 'text-status-error-text bg-status-error-bg-subtle',\n};\n\nconst money = (value: number | null | undefined): string =>\n value == null ? '—' : `$${Number(value).toLocaleString(undefined, { maximumFractionDigits: 2 })}`;\n\nconst depreciationLabels: Record<string, string> = {\n STRAIGHT_LINE: 'Straight line',\n REDUCING_BALANCE: 'Reducing balance',\n NONE: 'None',\n};\n\n// Soft, semantic status pill — matches the mock's soft pills.\nconst statusPill: Record<string, string> = {\n active: 'bg-status-success-bg-subtle text-status-success-text',\n maintenance: 'bg-status-warning-bg-subtle text-status-warning-text',\n inactive: 'bg-bg-sunken text-text-secondary',\n retired: 'bg-bg-sunken text-text-secondary',\n disposed: 'bg-status-error-bg-subtle text-status-error-text',\n};\n\n// Pure book-value schedule from real backend fields — empty when inputs missing.\nfunction buildDepreciationSeries(input: {\n purchaseValue?: number | null;\n salvageValue?: number | null;\n usefulLifeMonths?: number | null;\n method?: string | null;\n}): { year: number; bookValue: number }[] {\n const pv = input.purchaseValue;\n const life = input.usefulLifeMonths;\n if (!pv || pv <= 0 || !life || life <= 0) return [];\n const salvage = Math.max(0, Math.min(input.salvageValue ?? 0, pv));\n const method = (input.method ?? 'straight_line').toLowerCase();\n const years = Math.max(1, Math.round(life / 12));\n const points: { year: number; bookValue: number }[] = [];\n for (let y = 0; y <= years; y += 1) {\n let bv: number;\n if (method === 'reducing_balance') {\n const rate = salvage > 0 ? 1 - Math.pow(salvage / pv, 1 / years) : Math.min(0.9, 2 / years);\n bv = Math.max(pv * Math.pow(1 - rate, y), salvage);\n } else if (method === 'none') {\n bv = pv;\n } else {\n bv = Math.max(pv - (pv - salvage) * (y / years), salvage);\n }\n points.push({ year: y, bookValue: Math.round(bv) });\n }\n return points;\n}\n\ninterface EditForm {\n name: string;\n description: string;\n category: string;\n status: string;\n condition: string;\n serialNumber: string;\n locationName: string;\n assignedTo: string;\n department: string;\n supplier: string;\n purchaseValue: string;\n salvageValue: string;\n usefulLifeMonths: string;\n depreciationMethod: string;\n}\n\nfunction toEditForm(asset: AssetRecord): EditForm {\n return {\n name: asset.name,\n description: asset.description ?? '',\n category: asset.category,\n status: asset.status.toUpperCase(),\n condition: asset.condition.toUpperCase(),\n serialNumber: asset.serialNumber ?? '',\n locationName: asset.locationName ?? '',\n assignedTo: asset.assignedTo ?? '',\n department: asset.department ?? '',\n supplier: asset.supplier ?? '',\n purchaseValue: asset.purchaseValue != null ? String(asset.purchaseValue) : '',\n salvageValue: asset.salvageValue != null ? String(asset.salvageValue) : '',\n usefulLifeMonths: asset.usefulLifeMonths != null ? String(asset.usefulLifeMonths) : '',\n depreciationMethod: (asset.depreciationMethod ?? 'STRAIGHT_LINE').toUpperCase(),\n };\n}\n\nexport function AssetsAssetDetailPage() {\n const navigate = useAssetHandlerNavigate();\n const { assetId } = useParams<{ assetId: string }>();\n const { maintenanceRecords } = useAssetHandlerStore();\n\n const { data, loading, refetch } = useQuery<AssetQueryResult>(ASSET_QUERY, {\n variables: { id: assetId ?? '' },\n skip: !assetId,\n fetchPolicy: 'cache-and-network',\n });\n\n const [showEdit, setShowEdit] = useState(false);\n const [showDispose, setShowDispose] = useState(false);\n const [showDelete, setShowDelete] = useState(false);\n const [editForm, setEditForm] = useState<EditForm | null>(null);\n const [disposeForm, setDisposeForm] = useState({ disposalDate: '', method: '', notes: '' });\n\n const [updateAsset, { loading: updating }] = useMutation(UPDATE_ASSET_MUTATION, {\n refetchQueries: ['AssetHandlerBootstrap'],\n onCompleted: () => {\n notify.success('Asset updated', 'Your changes have been saved.');\n setShowEdit(false);\n void refetch();\n },\n onError: (error) => notify.error('Could not update asset', error.message),\n });\n\n const [disposeAsset, { loading: disposing }] = useMutation(DISPOSE_ASSET_MUTATION, {\n refetchQueries: ['AssetHandlerBootstrap'],\n onCompleted: () => {\n notify.success('Asset disposed', 'The asset has been marked as disposed.');\n setShowDispose(false);\n void refetch();\n },\n onError: (error) => notify.error('Could not dispose asset', error.message),\n });\n\n const [deleteAsset, { loading: deleting }] = useMutation(DELETE_ASSET_MUTATION, {\n refetchQueries: ['AssetHandlerBootstrap'],\n onCompleted: () => {\n notify.success('Asset deleted', 'The asset has been removed from the inventory.');\n navigate('/assets/asset-list');\n },\n onError: (error) => notify.error('Could not delete asset', error.message),\n });\n\n if (loading && !data) {\n return (\n <div className=\"space-y-3 p-6\">\n {Array.from({ length: 6 }).map((_, i) => (\n <div key={i} className=\"h-10 rounded-md bg-bg-sunken motion-safe:animate-vc-shimmer\" />\n ))}\n </div>\n );\n }\n\n const raw = data?.asset;\n if (!raw) {\n return (\n <NotFoundState\n entityLabel=\"Asset\"\n description=\"This asset may have been disposed or removed. Return to the inventory to find it.\"\n backLabel=\"Back to inventory\"\n onBack={() => navigate('/assets/asset-list')}\n />\n );\n }\n\n const asset = {\n ...raw,\n status: raw.status.toLowerCase(),\n condition: raw.condition.toLowerCase(),\n category: raw.category.toLowerCase(),\n };\n const assetMaintenance = maintenanceRecords.filter((m) => m.assetId === asset.id);\n const openMaintenance = assetMaintenance.filter(\n (m) => m.status !== 'completed' && m.status !== 'cancelled'\n );\n const isDisposed = asset.status === 'disposed';\n\n // Real derived depreciation schedule (empty if the asset lacks financial inputs).\n const depreciationSeries = buildDepreciationSeries({\n purchaseValue: asset.purchaseValue,\n salvageValue: asset.salvageValue,\n usefulLifeMonths: asset.usefulLifeMonths,\n method: asset.depreciationMethod,\n });\n const bookValueSpark = depreciationSeries.map((p) => p.bookValue);\n\n // Real maintenance cost history for this asset (per record, over scheduled date).\n const maintenanceCostData = assetMaintenance\n .filter((m) => (m.actualCost ?? m.estimatedCost) != null)\n .map((m) => ({\n label: m.scheduledDate\n ? new Date(m.scheduledDate).toLocaleDateString(undefined, {\n month: 'short',\n year: '2-digit',\n })\n : m.title.slice(0, 12),\n cost: m.actualCost ?? m.estimatedCost ?? 0,\n }));\n const maintenanceSpend = assetMaintenance.reduce(\n (sum, m) => sum + (m.actualCost ?? m.estimatedCost ?? 0),\n 0\n );\n // TCO composition — only when we have a real purchase value + some maintenance spend.\n const tcoSlices =\n asset.purchaseValue != null && maintenanceSpend > 0\n ? [\n {\n name: 'Purchase',\n value: asset.purchaseValue,\n color: 'var(--color-accent-primary)',\n },\n { name: 'Maintenance', value: maintenanceSpend, color: 'var(--color-status-info-bg)' },\n ]\n : [];\n\n const openEdit = () => {\n setEditForm(toEditForm(raw));\n setShowEdit(true);\n };\n\n const submitEdit = (event: React.FormEvent) => {\n event.preventDefault();\n if (!editForm) return;\n if (!editForm.name.trim()) {\n notify.warning('Name required', 'An asset must have a name.');\n return;\n }\n const optionalNumber = (value: string): number | null => {\n const trimmed = value.trim();\n if (trimmed === '') return null;\n const parsed = Number(trimmed);\n return Number.isNaN(parsed) ? null : parsed;\n };\n void updateAsset({\n variables: {\n id: asset.id,\n input: {\n name: editForm.name.trim(),\n description: editForm.description.trim() || null,\n category: editForm.category.trim(),\n status: editForm.status,\n condition: editForm.condition,\n serialNumber: editForm.serialNumber.trim() || null,\n locationName: editForm.locationName.trim() || null,\n assignedTo: editForm.assignedTo.trim() || null,\n department: editForm.department.trim() || null,\n supplier: editForm.supplier.trim() || null,\n purchaseValue: optionalNumber(editForm.purchaseValue),\n salvageValue: optionalNumber(editForm.salvageValue),\n usefulLifeMonths: optionalNumber(editForm.usefulLifeMonths),\n depreciationMethod: editForm.depreciationMethod,\n },\n },\n });\n };\n\n const submitDispose = (event: React.FormEvent) => {\n event.preventDefault();\n void disposeAsset({\n variables: {\n id: asset.id,\n input: {\n disposalDate: disposeForm.disposalDate\n ? new Date(disposeForm.disposalDate).toISOString()\n : new Date().toISOString(),\n method: disposeForm.method.trim() || null,\n notes: disposeForm.notes.trim() || null,\n },\n },\n });\n };\n\n const setEdit = (field: keyof EditForm, value: string) =>\n setEditForm((prev) => (prev ? { ...prev, [field]: value } : prev));\n\n return (\n <div className=\"space-y-6 p-6\">\n {/* Header */}\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <div className=\"flex items-center gap-4\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label=\"Go back\"\n onClick={() => navigate('/assets/asset-list')}\n >\n <ArrowLeft className=\"h-4 w-4\" />\n </Button>\n <div>\n <div className=\"flex items-center gap-3\">\n <h1 className=\"text-2xl font-bold\">\n <GradientText>{asset.name}</GradientText>\n </h1>\n <span\n className={`rounded-full px-2.5 py-0.5 text-xs font-medium capitalize ${statusPill[asset.status] ?? 'bg-bg-sunken text-text-secondary'}`}\n >\n {asset.status.replace(/_/g, ' ')}\n </span>\n <span\n className={`rounded-full px-2.5 py-0.5 text-xs font-medium capitalize ${conditionColors[asset.condition] ?? ''}`}\n >\n {asset.condition}\n </span>\n </div>\n <p className=\"text-sm text-text-secondary mt-1\">\n {asset.assetNumber}\n {asset.serialNumber ? <> &middot; SN: {asset.serialNumber}</> : null}\n </p>\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n <Button size=\"sm\" variant=\"outline\" onClick={openEdit}>\n <Pencil className=\"mr-2 h-4 w-4\" />\n Edit\n </Button>\n {!isDisposed ? (\n <Button size=\"sm\" variant=\"outline\" onClick={() => setShowDispose(true)}>\n <Archive className=\"mr-2 h-4 w-4\" />\n Dispose\n </Button>\n ) : null}\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"text-status-error-text\"\n onClick={() => setShowDelete(true)}\n >\n <Trash2 className=\"mr-2 h-4 w-4\" />\n Delete\n </Button>\n </div>\n </div>\n\n <PagePurpose>\n The complete profile of a single asset — its identity, condition, location, assignment,\n financials and maintenance history. Use this page as the asset&apos;s home base: edit its\n details, track its book value, and dispose of it when it reaches end of life.\n </PagePurpose>\n\n {isDisposed ? (\n <EmphasisPanel>\n <div className=\"flex items-center gap-2 text-sm font-medium\">\n <Archive className=\"h-4 w-4\" />\n This asset was disposed\n {asset.disposalDate ? ` on ${new Date(asset.disposalDate).toLocaleDateString()}` : ''}\n </div>\n {asset.disposalMethod ? (\n <p className=\"mt-1 text-sm text-text-secondary\">Method: {asset.disposalMethod}</p>\n ) : null}\n {asset.disposalNotes ? (\n <p className=\"mt-1 text-sm text-text-secondary\">{asset.disposalNotes}</p>\n ) : null}\n </EmphasisPanel>\n ) : null}\n\n {/* Quick Stats */}\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n <StatTile\n hero\n label=\"Current value\"\n value={money(asset.currentValue)}\n delta={asset.purchaseValue != null ? `of ${money(asset.purchaseValue)}` : undefined}\n deltaDirection=\"neutral\"\n spark={bookValueSpark.length > 1 ? bookValueSpark : undefined}\n icon={DollarSign}\n />\n <StatTile\n label=\"Maintenance records\"\n value={assetMaintenance.length}\n delta={openMaintenance.length > 0 ? `${openMaintenance.length} open` : undefined}\n deltaTone=\"neutral\"\n deltaDirection=\"neutral\"\n icon={Wrench}\n />\n <StatTile\n label=\"Registered\"\n value={asset.createdAt ? new Date(asset.createdAt).toLocaleDateString() : '—'}\n icon={Calendar}\n />\n <StatTile label=\"Location\" value={asset.locationName || '—'} icon={MapPin} />\n </div>\n\n <div className=\"grid gap-6 lg:grid-cols-3\">\n <div className=\"min-w-0 lg:col-span-2\">\n <Tabs defaultValue=\"details\">\n <TabsList className=\"max-w-full justify-start overflow-x-auto\">\n <TabsTrigger value=\"details\">Details</TabsTrigger>\n <TabsTrigger value=\"financial\">Financial</TabsTrigger>\n <TabsTrigger value=\"maintenance\">Maintenance</TabsTrigger>\n <TabsTrigger value=\"discussion\">Discussion</TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"details\" className=\"mt-4 space-y-4\">\n {asset.description ? (\n <FieldTile label=\"Description\" value={asset.description} full />\n ) : null}\n <div className=\"grid gap-3 sm:grid-cols-2 xl:grid-cols-3\">\n <FieldTile label=\"Asset Tag\" value={asset.assetNumber} icon={Hash} mono />\n <FieldTile\n label=\"Serial Number\"\n value={asset.serialNumber || '—'}\n icon={Hash}\n mono\n />\n <FieldTile\n label=\"Category\"\n value={asset.category.replace(/_/g, ' ')}\n icon={Layers}\n capitalize\n />\n <FieldTile label=\"Condition\" icon={ShieldCheck}>\n <span\n className={`inline-flex rounded-full px-2.5 py-0.5 text-xs font-medium capitalize ${conditionColors[asset.condition] ?? ''}`}\n >\n {asset.condition}\n </span>\n </FieldTile>\n <FieldTile label=\"Assigned To\" value={asset.assignedTo || '—'} icon={User} />\n <FieldTile label=\"Department\" value={asset.department || '—'} icon={Building2} />\n <FieldTile label=\"Location\" value={asset.locationName || '—'} icon={MapPin} />\n <FieldTile label=\"Supplier\" value={asset.supplier || '—'} icon={Truck} />\n <FieldTile\n label=\"Warranty Expiry\"\n value={\n asset.warrantyExpiry ? new Date(asset.warrantyExpiry).toLocaleDateString() : '—'\n }\n icon={Calendar}\n />\n </div>\n <AttachmentsPanel entityType=\"assethandler-asset\" entityId={asset.id} />\n </TabsContent>\n\n <TabsContent value=\"financial\" className=\"mt-4 space-y-6\">\n <div className=\"grid gap-4 sm:grid-cols-2 xl:grid-cols-4\">\n <StatTile label=\"Purchase Value\" value={money(asset.purchaseValue)} />\n <StatTile hero label=\"Current Book Value\" value={money(asset.currentValue)} />\n <StatTile\n label=\"Accum. Depreciation\"\n value={money(asset.accumulatedDepreciation)}\n />\n <StatTile\n label=\"Total Cost of Ownership\"\n value={money(asset.totalCostOfOwnership)}\n />\n </div>\n\n <div className=\"grid gap-4 lg:grid-cols-2\">\n <ChartCard\n title=\"Depreciation & book value\"\n subtitle=\"Projected book value over the useful life\"\n icon={TrendingDown}\n >\n {depreciationSeries.length > 0 ? (\n <TrendChart\n data={depreciationSeries}\n xKey=\"year\"\n height={260}\n valueFormat={formatCurrencyCompact('USD')}\n xTickFormat={(v) => `${v}y`}\n series={[{ key: 'bookValue', label: 'Book value' }]}\n />\n ) : (\n <div className=\"py-12 text-center text-sm text-text-secondary\">\n Add purchase value, useful life and salvage value to see the depreciation\n schedule.\n </div>\n )}\n </ChartCard>\n\n <ChartCard title=\"Key facts\" subtitle=\"Purchase & depreciation terms\">\n <dl className=\"overflow-hidden rounded-lg border border-border-seam text-sm\">\n <LedgerRow\n label=\"Purchase Date\"\n value={\n asset.purchaseDate ? new Date(asset.purchaseDate).toLocaleDateString() : '—'\n }\n striped\n />\n <LedgerRow\n label=\"Useful Life\"\n value={asset.usefulLifeMonths ? `${asset.usefulLifeMonths} months` : '—'}\n />\n <LedgerRow label=\"Salvage Value\" value={money(asset.salvageValue)} striped />\n <LedgerRow\n label=\"Depreciation Method\"\n value={\n asset.depreciationMethod\n ? (depreciationLabels[asset.depreciationMethod.toUpperCase()] ??\n asset.depreciationMethod)\n : '—'\n }\n />\n <LedgerRow label=\"Supplier\" value={asset.supplier || '—'} striped />\n <LedgerRow\n label=\"Warranty Expiry\"\n value={\n asset.warrantyExpiry\n ? new Date(asset.warrantyExpiry).toLocaleDateString()\n : '—'\n }\n />\n </dl>\n </ChartCard>\n </div>\n\n {tcoSlices.length > 0 ? (\n <ChartCard\n title=\"Total cost of ownership\"\n subtitle=\"What drives lifetime cost\"\n icon={DollarSign}\n >\n <DonutChart\n data={tcoSlices}\n centerLabel=\"TCO\"\n centerValue={tcoSlices.reduce((s, x) => s + x.value, 0)}\n valueFormat={formatCurrencyCompact('USD')}\n height={220}\n />\n </ChartCard>\n ) : null}\n </TabsContent>\n\n <TabsContent value=\"maintenance\" className=\"mt-4 space-y-4\">\n {maintenanceCostData.length > 0 ? (\n <ChartCard\n title=\"Maintenance cost history\"\n subtitle=\"Recorded cost per maintenance event\"\n icon={Wrench}\n >\n <BarsChart\n data={maintenanceCostData}\n xKey=\"label\"\n height={220}\n valueFormat={formatCurrencyCompact('USD')}\n series={[{ key: 'cost', label: 'Cost' }]}\n />\n </ChartCard>\n ) : null}\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <Wrench className=\"h-4 w-4\" />\n Maintenance History\n </CardTitle>\n <CardDescription>{assetMaintenance.length} records found</CardDescription>\n </CardHeader>\n <CardContent>\n {assetMaintenance.length === 0 ? (\n <p className=\"py-8 text-center text-text-secondary\">\n No maintenance records for this asset.\n </p>\n ) : (\n <div className=\"space-y-3\">\n {assetMaintenance.map((m) => (\n <div key={m.id} className=\"flex items-start gap-4 rounded-lg border p-4\">\n <div className=\"flex-1\">\n <div className=\"flex items-center gap-2\">\n <Badge variant=\"outline\" className=\"capitalize\">\n {m.type}\n </Badge>\n <span\n className={`rounded-full px-2.5 py-0.5 text-xs font-medium capitalize ${\n m.status === 'completed'\n ? 'bg-status-success-bg-subtle text-status-success-text'\n : 'bg-status-warning-bg-subtle text-status-warning-text'\n }`}\n >\n {m.status.replace(/_/g, ' ')}\n </span>\n </div>\n <p className=\"mt-1 font-medium\">{m.title}</p>\n <p className=\"text-sm text-text-secondary\">{m.description}</p>\n <div className=\"mt-2 flex gap-4 text-xs text-text-secondary\">\n <span>\n Scheduled:{' '}\n {m.scheduledDate\n ? new Date(m.scheduledDate).toLocaleDateString()\n : '—'}\n </span>\n {m.actualCost != null || m.estimatedCost != null ? (\n <span>Cost: {money(m.actualCost ?? m.estimatedCost)}</span>\n ) : null}\n </div>\n </div>\n </div>\n ))}\n </div>\n )}\n </CardContent>\n </Card>\n </TabsContent>\n\n <TabsContent value=\"discussion\" className=\"mt-4\">\n <CommentsPanel entityType=\"assethandler-asset\" entityId={asset.id} />\n </TabsContent>\n </Tabs>\n </div>\n\n {/* Persistent right rail — Tags + Activity (mirrors the mock) */}\n <aside className=\"space-y-6\">\n <GlassCard treatment=\"glass\" className=\"border-border-seam\">\n <div className=\"space-y-3 p-5\">\n <h3 className=\"flex items-center gap-2 text-sm font-semibold\">\n <Tag className=\"h-4 w-4 text-text-secondary\" />\n Tags\n </h3>\n {asset.tags.length === 0 ? (\n <p className=\"text-xs text-text-secondary\">No tags yet</p>\n ) : (\n <div className=\"flex flex-wrap gap-1.5\">\n {asset.tags.map((tag) => (\n <span\n key={tag}\n className=\"rounded-full bg-action-primary-bg/10 px-2.5 py-0.5 text-xs font-medium text-action-primary-bg\"\n >\n {tag}\n </span>\n ))}\n </div>\n )}\n </div>\n </GlassCard>\n\n <ActivityTimeline resourceId={asset.id} />\n </aside>\n </div>\n\n {/* Edit dialog */}\n <ResponsiveDialog open={showEdit} onOpenChange={setShowEdit}>\n <ResponsiveDialogContent className=\"max-h-[85vh] overflow-y-auto sm:max-w-2xl\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Edit asset</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Update this asset&apos;s details and financials.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n {editForm ? (\n <form className=\"space-y-4\" onSubmit={submitEdit}>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Name</Label>\n <Input value={editForm.name} onChange={(e) => setEdit('name', e.target.value)} />\n </div>\n <div className=\"space-y-2\">\n <Label>Category</Label>\n <Input\n value={editForm.category}\n onChange={(e) => setEdit('category', e.target.value)}\n />\n </div>\n </div>\n <div className=\"space-y-2\">\n <Label>Description</Label>\n <Textarea\n value={editForm.description}\n onChange={(e) => setEdit('description', e.target.value)}\n rows={2}\n />\n </div>\n <div className=\"grid gap-4 md:grid-cols-3\">\n <div className=\"space-y-2\">\n <Label>Status</Label>\n <Select value={editForm.status} onValueChange={(v) => setEdit('status', v)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"ACTIVE\">Active</SelectItem>\n <SelectItem value=\"INACTIVE\">Inactive</SelectItem>\n <SelectItem value=\"MAINTENANCE\">Maintenance</SelectItem>\n <SelectItem value=\"RETIRED\">Retired</SelectItem>\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-2\">\n <Label>Condition</Label>\n <Select value={editForm.condition} onValueChange={(v) => setEdit('condition', v)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"EXCELLENT\">Excellent</SelectItem>\n <SelectItem value=\"GOOD\">Good</SelectItem>\n <SelectItem value=\"FAIR\">Fair</SelectItem>\n <SelectItem value=\"POOR\">Poor</SelectItem>\n <SelectItem value=\"DAMAGED\">Damaged</SelectItem>\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-2\">\n <Label>Department</Label>\n <Input\n value={editForm.department}\n onChange={(e) => setEdit('department', e.target.value)}\n />\n </div>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Serial Number</Label>\n <Input\n value={editForm.serialNumber}\n onChange={(e) => setEdit('serialNumber', e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Assigned To</Label>\n <Input\n value={editForm.assignedTo}\n onChange={(e) => setEdit('assignedTo', e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Location</Label>\n <Input\n value={editForm.locationName}\n onChange={(e) => setEdit('locationName', e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Supplier</Label>\n <Input\n value={editForm.supplier}\n onChange={(e) => setEdit('supplier', e.target.value)}\n />\n </div>\n </div>\n <div className=\"grid gap-4 md:grid-cols-4\">\n <div className=\"space-y-2\">\n <Label>Purchase Value</Label>\n <Input\n type=\"number\"\n min=\"0\"\n step=\"0.01\"\n value={editForm.purchaseValue}\n onChange={(e) => setEdit('purchaseValue', e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Salvage Value</Label>\n <Input\n type=\"number\"\n min=\"0\"\n step=\"0.01\"\n value={editForm.salvageValue}\n onChange={(e) => setEdit('salvageValue', e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Useful Life (mo)</Label>\n <Input\n type=\"number\"\n min=\"0\"\n step=\"1\"\n value={editForm.usefulLifeMonths}\n onChange={(e) => setEdit('usefulLifeMonths', e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Depreciation</Label>\n <Select\n value={editForm.depreciationMethod}\n onValueChange={(v) => setEdit('depreciationMethod', v)}\n >\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"STRAIGHT_LINE\">Straight line</SelectItem>\n <SelectItem value=\"REDUCING_BALANCE\">Reducing balance</SelectItem>\n <SelectItem value=\"NONE\">None</SelectItem>\n </SelectContent>\n </Select>\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => setShowEdit(false)}\n disabled={updating}\n >\n Cancel\n </Button>\n <Button type=\"submit\" disabled={updating}>\n {updating ? 'Saving…' : 'Save changes'}\n </Button>\n </ResponsiveDialogFooter>\n </form>\n ) : null}\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n\n {/* Dispose dialog */}\n <ResponsiveDialog open={showDispose} onOpenChange={setShowDispose}>\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Dispose asset</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Record the disposal of this asset. It will be marked as disposed and removed from\n active inventory.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <form className=\"space-y-4\" onSubmit={submitDispose}>\n <div className=\"space-y-2\">\n <Label>Disposal Date</Label>\n <Input\n type=\"date\"\n value={disposeForm.disposalDate}\n onChange={(e) =>\n setDisposeForm((prev) => ({ ...prev, disposalDate: e.target.value }))\n }\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Method</Label>\n <Input\n placeholder=\"e.g., Sold, Recycled, Scrapped\"\n value={disposeForm.method}\n onChange={(e) => setDisposeForm((prev) => ({ ...prev, method: e.target.value }))}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Notes</Label>\n <Textarea\n placeholder=\"Optional details about the disposal\"\n value={disposeForm.notes}\n onChange={(e) => setDisposeForm((prev) => ({ ...prev, notes: e.target.value }))}\n rows={2}\n />\n </div>\n <ResponsiveDialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => setShowDispose(false)}\n disabled={disposing}\n >\n Cancel\n </Button>\n <Button type=\"submit\" disabled={disposing}>\n {disposing ? 'Disposing…' : 'Confirm disposal'}\n </Button>\n </ResponsiveDialogFooter>\n </form>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n\n {/* Delete dialog */}\n <ResponsiveDialog open={showDelete} onOpenChange={setShowDelete}>\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Delete asset</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n This removes <span className=\"font-medium\">{asset.name}</span> from the inventory.\n This action cannot be undone.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => setShowDelete(false)} disabled={deleting}>\n Cancel\n </Button>\n <Button\n variant=\"destructive\"\n onClick={() => void deleteAsset({ variables: { id: asset.id } })}\n disabled={deleting}\n >\n {deleting ? 'Deleting…' : 'Delete asset'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </div>\n );\n}\n\n// A single labelled field rendered as its own clean card (mock's field grid).\n// Machine values (serial, tags, supplier) render verbatim — no blanket capitalize.\nfunction FieldTile({\n label,\n value,\n icon: Icon,\n mono,\n capitalize,\n full,\n children,\n}: {\n label: string;\n value?: string;\n icon?: React.ComponentType<{ className?: string }>;\n mono?: boolean;\n capitalize?: boolean;\n full?: boolean;\n children?: React.ReactNode;\n}) {\n return (\n <div\n className={`rounded-lg border border-border-seam bg-bg-surface p-3.5 ${full ? 'sm:col-span-2 xl:col-span-3' : ''}`}\n >\n <p className=\"flex items-center gap-1.5 text-xs text-text-secondary\">\n {Icon ? <Icon className=\"h-3.5 w-3.5\" /> : null}\n {label}\n </p>\n {children ? (\n <div className=\"mt-1.5\">{children}</div>\n ) : (\n <p\n className={`mt-1 break-words font-medium ${mono ? 'font-mono text-sm' : ''} ${capitalize ? 'capitalize' : ''}`}\n >\n {value}\n </p>\n )}\n </div>\n );\n}\n\n// A striped ledger row for the financial key-facts panel.\nfunction LedgerRow({ label, value, striped }: { label: string; value: string; striped?: boolean }) {\n return (\n <div\n className={`flex items-center justify-between gap-4 px-3.5 py-2.5 ${striped ? 'bg-bg-sunken/40' : ''}`}\n >\n <dt className=\"shrink-0 text-text-secondary\">{label}</dt>\n <dd className=\"truncate text-right font-medium\">{value}</dd>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"AssetsAssetDetailPage.js","names":[],"sources":["../../../src/assethandler/pages/AssetsAssetDetailPage.tsx"],"sourcesContent":["import { useAssetHandlerNavigate } from '../hooks/useAssetHandlerNavigate';\nimport type React from 'react';\nimport { useState } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n GradientText,\n EmphasisPanel,\n PagePurpose,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n Input,\n Label,\n Textarea,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n GlassCard,\n} from '@burdenoff/fe-libs/ui';\nimport {\n ArrowLeft,\n MapPin,\n Calendar,\n Tag,\n User,\n Wrench,\n Pencil,\n Trash2,\n Archive,\n DollarSign,\n TrendingDown,\n Hash,\n Building2,\n Truck,\n ShieldCheck,\n Layers,\n} from 'lucide-react';\nimport { useParams } from 'react-router-dom';\nimport { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport { useAssetHandlerStore } from '../store/assethandlerStore';\nimport { useCopy } from '../hooks/useCopy';\nimport { notify } from '../utils/toast';\nimport { AttachmentsPanel, CommentsPanel, ActivityTimeline, NotFoundState } from '../components';\nimport {\n StatTile,\n ChartCard,\n TrendChart,\n BarsChart,\n DonutChart,\n formatCurrencyCompact,\n} from '../components';\n\nconst ASSET_QUERY = gql`\n query AssetHandlerAsset($id: ID!) {\n asset(id: $id) {\n id\n assetNumber\n name\n description\n category\n status\n condition\n serialNumber\n locationName\n assignedTo\n tags\n createdAt\n updatedAt\n purchaseValue\n purchaseDate\n usefulLifeMonths\n salvageValue\n depreciationMethod\n department\n warrantyExpiry\n supplier\n disposalDate\n disposalMethod\n disposalNotes\n currentValue\n accumulatedDepreciation\n totalCostOfOwnership\n }\n }\n`;\n\ninterface AssetRecord {\n id: string;\n assetNumber: string;\n name: string;\n description?: string | null;\n category: string;\n status: string;\n condition: string;\n serialNumber?: string | null;\n locationName?: string | null;\n assignedTo?: string | null;\n tags: string[];\n createdAt: string;\n updatedAt: string;\n purchaseValue?: number | null;\n purchaseDate?: string | null;\n usefulLifeMonths?: number | null;\n salvageValue?: number | null;\n depreciationMethod?: string | null;\n department?: string | null;\n warrantyExpiry?: string | null;\n supplier?: string | null;\n disposalDate?: string | null;\n disposalMethod?: string | null;\n disposalNotes?: string | null;\n currentValue?: number | null;\n accumulatedDepreciation?: number | null;\n totalCostOfOwnership?: number | null;\n}\n\ninterface AssetQueryResult {\n asset: AssetRecord | null;\n}\n\nconst UPDATE_ASSET_MUTATION = gql`\n mutation AssetHandlerUpdateAsset($id: ID!, $input: UpdateAssetInput!) {\n updateAsset(id: $id, input: $input) {\n id\n }\n }\n`;\n\nconst DISPOSE_ASSET_MUTATION = gql`\n mutation AssetHandlerDisposeAsset($id: ID!, $input: DisposeAssetInput!) {\n disposeAsset(id: $id, input: $input) {\n id\n status\n }\n }\n`;\n\nconst DELETE_ASSET_MUTATION = gql`\n mutation AssetHandlerDeleteAsset($id: ID!) {\n deleteAsset(id: $id)\n }\n`;\n\nconst conditionColors: Record<string, string> = {\n excellent: 'text-status-success-text bg-status-success-bg-subtle',\n good: 'text-status-info-text bg-status-info-bg-subtle',\n fair: 'text-status-warning-text bg-status-warning-bg-subtle',\n poor: 'text-status-warning-text bg-status-warning-bg-subtle',\n damaged: 'text-status-error-text bg-status-error-bg-subtle',\n};\n\nconst money = (value: number | null | undefined): string =>\n value == null ? '—' : `$${Number(value).toLocaleString(undefined, { maximumFractionDigits: 2 })}`;\n\n// Soonest future scheduled date among the given (already status-filtered) records.\n// Records with no / past / unparseable dates are ignored; returns undefined when none.\nfunction nextServiceDate(records: { scheduledDate?: string }[]): string | undefined {\n const now = Date.now();\n return records\n .map((record) => record.scheduledDate)\n .filter((date): date is string => date != null && new Date(date).getTime() >= now)\n .sort((a, b) => new Date(a).getTime() - new Date(b).getTime())[0];\n}\n\nconst depreciationLabels: Record<string, string> = {\n STRAIGHT_LINE: 'Straight line',\n REDUCING_BALANCE: 'Reducing balance',\n NONE: 'None',\n};\n\n// Soft, semantic status pill — matches the mock's soft pills.\nconst statusPill: Record<string, string> = {\n active: 'bg-status-success-bg-subtle text-status-success-text',\n maintenance: 'bg-status-warning-bg-subtle text-status-warning-text',\n inactive: 'bg-bg-sunken text-text-secondary',\n retired: 'bg-bg-sunken text-text-secondary',\n disposed: 'bg-status-error-bg-subtle text-status-error-text',\n};\n\n// Pure book-value schedule from real backend fields — empty when inputs missing.\nfunction buildDepreciationSeries(input: {\n purchaseValue?: number | null;\n salvageValue?: number | null;\n usefulLifeMonths?: number | null;\n method?: string | null;\n}): { year: number; bookValue: number }[] {\n const pv = input.purchaseValue;\n const life = input.usefulLifeMonths;\n if (!pv || pv <= 0 || !life || life <= 0) return [];\n const salvage = Math.max(0, Math.min(input.salvageValue ?? 0, pv));\n const method = (input.method ?? 'straight_line').toLowerCase();\n const years = Math.max(1, Math.round(life / 12));\n const points: { year: number; bookValue: number }[] = [];\n for (let y = 0; y <= years; y += 1) {\n let bv: number;\n if (method === 'reducing_balance') {\n const rate = salvage > 0 ? 1 - Math.pow(salvage / pv, 1 / years) : Math.min(0.9, 2 / years);\n bv = Math.max(pv * Math.pow(1 - rate, y), salvage);\n } else if (method === 'none') {\n bv = pv;\n } else {\n bv = Math.max(pv - (pv - salvage) * (y / years), salvage);\n }\n points.push({ year: y, bookValue: Math.round(bv) });\n }\n return points;\n}\n\ninterface EditForm {\n name: string;\n description: string;\n category: string;\n status: string;\n condition: string;\n serialNumber: string;\n locationName: string;\n assignedTo: string;\n department: string;\n supplier: string;\n purchaseValue: string;\n salvageValue: string;\n usefulLifeMonths: string;\n depreciationMethod: string;\n}\n\nfunction toEditForm(asset: AssetRecord): EditForm {\n return {\n name: asset.name,\n description: asset.description ?? '',\n category: asset.category,\n status: asset.status.toUpperCase(),\n condition: asset.condition.toUpperCase(),\n serialNumber: asset.serialNumber ?? '',\n locationName: asset.locationName ?? '',\n assignedTo: asset.assignedTo ?? '',\n department: asset.department ?? '',\n supplier: asset.supplier ?? '',\n purchaseValue: asset.purchaseValue != null ? String(asset.purchaseValue) : '',\n salvageValue: asset.salvageValue != null ? String(asset.salvageValue) : '',\n usefulLifeMonths: asset.usefulLifeMonths != null ? String(asset.usefulLifeMonths) : '',\n depreciationMethod: (asset.depreciationMethod ?? 'STRAIGHT_LINE').toUpperCase(),\n };\n}\n\nexport function AssetsAssetDetailPage() {\n const navigate = useAssetHandlerNavigate();\n const { assetId } = useParams<{ assetId: string }>();\n const { maintenanceRecords } = useAssetHandlerStore();\n const tc = useCopy();\n\n const { data, loading, refetch } = useQuery<AssetQueryResult>(ASSET_QUERY, {\n variables: { id: assetId ?? '' },\n skip: !assetId,\n fetchPolicy: 'cache-and-network',\n });\n\n const [showEdit, setShowEdit] = useState(false);\n const [showDispose, setShowDispose] = useState(false);\n const [showDelete, setShowDelete] = useState(false);\n const [editForm, setEditForm] = useState<EditForm | null>(null);\n const [disposeForm, setDisposeForm] = useState({ disposalDate: '', method: '', notes: '' });\n\n const [updateAsset, { loading: updating }] = useMutation(UPDATE_ASSET_MUTATION, {\n refetchQueries: ['AssetHandlerBootstrap'],\n onCompleted: () => {\n notify.success('Asset updated', 'Your changes have been saved.');\n setShowEdit(false);\n void refetch();\n },\n onError: (error) => notify.error('Could not update asset', error.message),\n });\n\n const [disposeAsset, { loading: disposing }] = useMutation(DISPOSE_ASSET_MUTATION, {\n refetchQueries: ['AssetHandlerBootstrap'],\n onCompleted: () => {\n notify.success('Asset disposed', 'The asset has been marked as disposed.');\n setShowDispose(false);\n void refetch();\n },\n onError: (error) => notify.error('Could not dispose asset', error.message),\n });\n\n const [deleteAsset, { loading: deleting }] = useMutation(DELETE_ASSET_MUTATION, {\n refetchQueries: ['AssetHandlerBootstrap'],\n onCompleted: () => {\n notify.success('Asset deleted', 'The asset has been removed from the inventory.');\n navigate('/assets/asset-list');\n },\n onError: (error) => notify.error('Could not delete asset', error.message),\n });\n\n if (loading && !data) {\n return (\n <div className=\"space-y-3 p-6\">\n {Array.from({ length: 6 }).map((_, i) => (\n <div key={i} className=\"h-10 rounded-md bg-bg-sunken motion-safe:animate-vc-shimmer\" />\n ))}\n </div>\n );\n }\n\n const raw = data?.asset;\n if (!raw) {\n return (\n <NotFoundState\n entityLabel=\"Asset\"\n description=\"This asset may have been disposed or removed. Return to the inventory to find it.\"\n backLabel=\"Back to inventory\"\n onBack={() => navigate('/assets/asset-list')}\n />\n );\n }\n\n const asset = {\n ...raw,\n status: raw.status.toLowerCase(),\n condition: raw.condition.toLowerCase(),\n category: raw.category.toLowerCase(),\n };\n const assetMaintenance = maintenanceRecords.filter((m) => m.assetId === asset.id);\n const openMaintenance = assetMaintenance.filter(\n (m) => m.status !== 'completed' && m.status !== 'cancelled'\n );\n // Soonest upcoming (future) scheduled service among the open records, if any.\n const nextServiceAt = nextServiceDate(openMaintenance);\n const isDisposed = asset.status === 'disposed';\n\n // Real derived depreciation schedule (empty if the asset lacks financial inputs).\n const depreciationSeries = buildDepreciationSeries({\n purchaseValue: asset.purchaseValue,\n salvageValue: asset.salvageValue,\n usefulLifeMonths: asset.usefulLifeMonths,\n method: asset.depreciationMethod,\n });\n const bookValueSpark = depreciationSeries.map((p) => p.bookValue);\n\n // Real maintenance cost history for this asset (per record, over scheduled date).\n const maintenanceCostData = assetMaintenance\n .filter((m) => (m.actualCost ?? m.estimatedCost) != null)\n .map((m) => ({\n label: m.scheduledDate\n ? new Date(m.scheduledDate).toLocaleDateString(undefined, {\n month: 'short',\n year: '2-digit',\n })\n : m.title.slice(0, 12),\n cost: m.actualCost ?? m.estimatedCost ?? 0,\n }));\n const maintenanceSpend = assetMaintenance.reduce(\n (sum, m) => sum + (m.actualCost ?? m.estimatedCost ?? 0),\n 0\n );\n // TCO composition — only when we have a real purchase value + some maintenance spend.\n const tcoSlices =\n asset.purchaseValue != null && maintenanceSpend > 0\n ? [\n {\n name: 'Purchase',\n value: asset.purchaseValue,\n color: 'var(--color-accent-primary)',\n },\n { name: 'Maintenance', value: maintenanceSpend, color: 'var(--color-status-info-bg)' },\n ]\n : [];\n\n const openEdit = () => {\n setEditForm(toEditForm(raw));\n setShowEdit(true);\n };\n\n const submitEdit = (event: React.FormEvent) => {\n event.preventDefault();\n if (!editForm) return;\n if (!editForm.name.trim()) {\n notify.warning('Name required', 'An asset must have a name.');\n return;\n }\n const optionalNumber = (value: string): number | null => {\n const trimmed = value.trim();\n if (trimmed === '') return null;\n const parsed = Number(trimmed);\n return Number.isNaN(parsed) ? null : parsed;\n };\n void updateAsset({\n variables: {\n id: asset.id,\n input: {\n name: editForm.name.trim(),\n description: editForm.description.trim() || null,\n category: editForm.category.trim(),\n status: editForm.status,\n condition: editForm.condition,\n serialNumber: editForm.serialNumber.trim() || null,\n locationName: editForm.locationName.trim() || null,\n assignedTo: editForm.assignedTo.trim() || null,\n department: editForm.department.trim() || null,\n supplier: editForm.supplier.trim() || null,\n purchaseValue: optionalNumber(editForm.purchaseValue),\n salvageValue: optionalNumber(editForm.salvageValue),\n usefulLifeMonths: optionalNumber(editForm.usefulLifeMonths),\n depreciationMethod: editForm.depreciationMethod,\n },\n },\n });\n };\n\n const submitDispose = (event: React.FormEvent) => {\n event.preventDefault();\n void disposeAsset({\n variables: {\n id: asset.id,\n input: {\n disposalDate: disposeForm.disposalDate\n ? new Date(disposeForm.disposalDate).toISOString()\n : new Date().toISOString(),\n method: disposeForm.method.trim() || null,\n notes: disposeForm.notes.trim() || null,\n },\n },\n });\n };\n\n const setEdit = (field: keyof EditForm, value: string) =>\n setEditForm((prev) => (prev ? { ...prev, [field]: value } : prev));\n\n return (\n <div className=\"space-y-6 p-6\">\n {/* Header */}\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <div className=\"flex items-center gap-4\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label=\"Go back\"\n onClick={() => navigate('/assets/asset-list')}\n >\n <ArrowLeft className=\"h-4 w-4\" />\n </Button>\n <div>\n <div className=\"flex items-center gap-3\">\n <h1 className=\"text-2xl font-bold\">\n <GradientText>{asset.name}</GradientText>\n </h1>\n <span\n className={`rounded-full px-2.5 py-0.5 text-xs font-medium capitalize ${statusPill[asset.status] ?? 'bg-bg-sunken text-text-secondary'}`}\n >\n {asset.status.replace(/_/g, ' ')}\n </span>\n <span\n className={`rounded-full px-2.5 py-0.5 text-xs font-medium capitalize ${conditionColors[asset.condition] ?? ''}`}\n >\n {asset.condition}\n </span>\n </div>\n <p className=\"text-sm text-text-secondary mt-1\">\n {asset.assetNumber}\n {asset.serialNumber ? <> &middot; SN: {asset.serialNumber}</> : null}\n </p>\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n <Button size=\"sm\" variant=\"outline\" onClick={openEdit}>\n <Pencil className=\"mr-2 h-4 w-4\" />\n Edit\n </Button>\n {!isDisposed ? (\n <Button size=\"sm\" variant=\"outline\" onClick={() => setShowDispose(true)}>\n <Archive className=\"mr-2 h-4 w-4\" />\n Dispose\n </Button>\n ) : null}\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"text-status-error-text\"\n onClick={() => setShowDelete(true)}\n >\n <Trash2 className=\"mr-2 h-4 w-4\" />\n Delete\n </Button>\n </div>\n </div>\n\n <PagePurpose>\n The complete profile of a single asset — its identity, condition, location, assignment,\n financials and maintenance history. Use this page as the asset&apos;s home base: edit its\n details, track its book value, and dispose of it when it reaches end of life.\n </PagePurpose>\n\n {isDisposed ? (\n <EmphasisPanel>\n <div className=\"flex items-center gap-2 text-sm font-medium\">\n <Archive className=\"h-4 w-4\" />\n This asset was disposed\n {asset.disposalDate ? ` on ${new Date(asset.disposalDate).toLocaleDateString()}` : ''}\n </div>\n {asset.disposalMethod ? (\n <p className=\"mt-1 text-sm text-text-secondary\">Method: {asset.disposalMethod}</p>\n ) : null}\n {asset.disposalNotes ? (\n <p className=\"mt-1 text-sm text-text-secondary\">{asset.disposalNotes}</p>\n ) : null}\n </EmphasisPanel>\n ) : null}\n\n {/* Quick Stats */}\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n <StatTile\n hero\n label=\"Current value\"\n value={money(asset.currentValue)}\n delta={asset.purchaseValue != null ? `of ${money(asset.purchaseValue)}` : undefined}\n deltaDirection=\"neutral\"\n spark={bookValueSpark.length > 1 ? bookValueSpark : undefined}\n icon={DollarSign}\n />\n <StatTile\n label=\"Maintenance records\"\n value={assetMaintenance.length}\n delta={openMaintenance.length > 0 ? `${openMaintenance.length} open` : undefined}\n deltaTone=\"neutral\"\n deltaDirection=\"neutral\"\n icon={Wrench}\n />\n <StatTile\n label=\"Registered\"\n value={asset.createdAt ? new Date(asset.createdAt).toLocaleDateString() : '—'}\n icon={Calendar}\n />\n <StatTile label=\"Location\" value={asset.locationName || '—'} icon={MapPin} />\n </div>\n\n <div className=\"grid gap-6 lg:grid-cols-3\">\n <div className=\"min-w-0 lg:col-span-2\">\n <Tabs defaultValue=\"details\">\n <TabsList className=\"max-w-full justify-start overflow-x-auto\">\n <TabsTrigger value=\"details\">Details</TabsTrigger>\n <TabsTrigger value=\"financial\">Financial</TabsTrigger>\n <TabsTrigger value=\"maintenance\">Maintenance</TabsTrigger>\n <TabsTrigger value=\"discussion\">Discussion</TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"details\" className=\"mt-4 space-y-4\">\n {asset.description ? (\n <FieldTile label=\"Description\" value={asset.description} full />\n ) : null}\n <div className=\"grid gap-3 sm:grid-cols-2 xl:grid-cols-3\">\n <FieldTile label=\"Asset Tag\" value={asset.assetNumber} icon={Hash} mono />\n <FieldTile\n label=\"Serial Number\"\n value={asset.serialNumber || '—'}\n icon={Hash}\n mono\n />\n <FieldTile\n label=\"Category\"\n value={asset.category.replace(/_/g, ' ')}\n icon={Layers}\n capitalize\n />\n <FieldTile label=\"Condition\" icon={ShieldCheck}>\n <span\n className={`inline-flex rounded-full px-2.5 py-0.5 text-xs font-medium capitalize ${conditionColors[asset.condition] ?? ''}`}\n >\n {asset.condition}\n </span>\n </FieldTile>\n <FieldTile label=\"Assigned To\" value={asset.assignedTo || '—'} icon={User} />\n <FieldTile\n label={tc('assethandler.asset.detail.nextService', 'Next Service')}\n value={nextServiceAt ? new Date(nextServiceAt).toLocaleDateString() : '—'}\n icon={Wrench}\n />\n <FieldTile label=\"Department\" value={asset.department || '—'} icon={Building2} />\n <FieldTile label=\"Location\" value={asset.locationName || '—'} icon={MapPin} />\n <FieldTile label=\"Supplier\" value={asset.supplier || '—'} icon={Truck} />\n <FieldTile\n label=\"Warranty Expiry\"\n value={\n asset.warrantyExpiry ? new Date(asset.warrantyExpiry).toLocaleDateString() : '—'\n }\n icon={Calendar}\n />\n </div>\n <AttachmentsPanel entityType=\"assethandler-asset\" entityId={asset.id} />\n </TabsContent>\n\n <TabsContent value=\"financial\" className=\"mt-4 space-y-6\">\n <div className=\"grid gap-4 sm:grid-cols-2 xl:grid-cols-4\">\n <StatTile label=\"Purchase Value\" value={money(asset.purchaseValue)} />\n <StatTile hero label=\"Current Book Value\" value={money(asset.currentValue)} />\n <StatTile\n label=\"Accum. Depreciation\"\n value={money(asset.accumulatedDepreciation)}\n />\n <StatTile\n label=\"Total Cost of Ownership\"\n value={money(asset.totalCostOfOwnership)}\n />\n </div>\n\n <div className=\"grid gap-4 lg:grid-cols-2\">\n <ChartCard\n title=\"Depreciation & book value\"\n subtitle=\"Projected book value over the useful life\"\n icon={TrendingDown}\n >\n {depreciationSeries.length > 0 ? (\n <TrendChart\n data={depreciationSeries}\n xKey=\"year\"\n height={260}\n valueFormat={formatCurrencyCompact('USD')}\n xTickFormat={(v) => `${v}y`}\n series={[{ key: 'bookValue', label: 'Book value' }]}\n />\n ) : (\n <div className=\"py-12 text-center text-sm text-text-secondary\">\n Add purchase value, useful life and salvage value to see the depreciation\n schedule.\n </div>\n )}\n </ChartCard>\n\n <ChartCard title=\"Key facts\" subtitle=\"Purchase & depreciation terms\">\n <dl className=\"overflow-hidden rounded-lg border border-border-seam text-sm\">\n <LedgerRow\n label=\"Purchase Date\"\n value={\n asset.purchaseDate ? new Date(asset.purchaseDate).toLocaleDateString() : '—'\n }\n striped\n />\n <LedgerRow\n label=\"Useful Life\"\n value={asset.usefulLifeMonths ? `${asset.usefulLifeMonths} months` : '—'}\n />\n <LedgerRow label=\"Salvage Value\" value={money(asset.salvageValue)} striped />\n <LedgerRow\n label=\"Depreciation Method\"\n value={\n asset.depreciationMethod\n ? (depreciationLabels[asset.depreciationMethod.toUpperCase()] ??\n asset.depreciationMethod)\n : '—'\n }\n />\n <LedgerRow label=\"Supplier\" value={asset.supplier || '—'} striped />\n <LedgerRow\n label=\"Warranty Expiry\"\n value={\n asset.warrantyExpiry\n ? new Date(asset.warrantyExpiry).toLocaleDateString()\n : '—'\n }\n />\n </dl>\n </ChartCard>\n </div>\n\n {tcoSlices.length > 0 ? (\n <ChartCard\n title=\"Total cost of ownership\"\n subtitle=\"What drives lifetime cost\"\n icon={DollarSign}\n >\n <DonutChart\n data={tcoSlices}\n centerLabel=\"TCO\"\n centerValue={tcoSlices.reduce((s, x) => s + x.value, 0)}\n valueFormat={formatCurrencyCompact('USD')}\n height={220}\n />\n </ChartCard>\n ) : null}\n </TabsContent>\n\n <TabsContent value=\"maintenance\" className=\"mt-4 space-y-4\">\n {maintenanceCostData.length > 0 ? (\n <ChartCard\n title=\"Maintenance cost history\"\n subtitle=\"Recorded cost per maintenance event\"\n icon={Wrench}\n >\n <BarsChart\n data={maintenanceCostData}\n xKey=\"label\"\n height={220}\n valueFormat={formatCurrencyCompact('USD')}\n series={[{ key: 'cost', label: 'Cost' }]}\n />\n </ChartCard>\n ) : null}\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <Wrench className=\"h-4 w-4\" />\n Maintenance History\n </CardTitle>\n <CardDescription>{assetMaintenance.length} records found</CardDescription>\n </CardHeader>\n <CardContent>\n {assetMaintenance.length === 0 ? (\n <p className=\"py-8 text-center text-text-secondary\">\n No maintenance records for this asset.\n </p>\n ) : (\n <div className=\"space-y-3\">\n {assetMaintenance.map((m) => (\n <div key={m.id} className=\"flex items-start gap-4 rounded-lg border p-4\">\n <div className=\"flex-1\">\n <div className=\"flex items-center gap-2\">\n <Badge variant=\"outline\" className=\"capitalize\">\n {m.type}\n </Badge>\n <span\n className={`rounded-full px-2.5 py-0.5 text-xs font-medium capitalize ${\n m.status === 'completed'\n ? 'bg-status-success-bg-subtle text-status-success-text'\n : 'bg-status-warning-bg-subtle text-status-warning-text'\n }`}\n >\n {m.status.replace(/_/g, ' ')}\n </span>\n </div>\n <p className=\"mt-1 font-medium\">{m.title}</p>\n <p className=\"text-sm text-text-secondary\">{m.description}</p>\n <div className=\"mt-2 flex gap-4 text-xs text-text-secondary\">\n <span>\n Scheduled:{' '}\n {m.scheduledDate\n ? new Date(m.scheduledDate).toLocaleDateString()\n : '—'}\n </span>\n {m.actualCost != null || m.estimatedCost != null ? (\n <span>Cost: {money(m.actualCost ?? m.estimatedCost)}</span>\n ) : null}\n </div>\n </div>\n </div>\n ))}\n </div>\n )}\n </CardContent>\n </Card>\n </TabsContent>\n\n <TabsContent value=\"discussion\" className=\"mt-4\">\n <CommentsPanel entityType=\"assethandler-asset\" entityId={asset.id} />\n </TabsContent>\n </Tabs>\n </div>\n\n {/* Persistent right rail — Tags + Activity (mirrors the mock) */}\n <aside className=\"space-y-6\">\n <GlassCard treatment=\"glass\" className=\"border-border-seam\">\n <div className=\"space-y-3 p-5\">\n <h3 className=\"flex items-center gap-2 text-sm font-semibold\">\n <Tag className=\"h-4 w-4 text-text-secondary\" />\n Tags\n </h3>\n {asset.tags.length === 0 ? (\n <p className=\"text-xs text-text-secondary\">No tags yet</p>\n ) : (\n <div className=\"flex flex-wrap gap-1.5\">\n {asset.tags.map((tag) => (\n <span\n key={tag}\n className=\"rounded-full bg-action-primary-bg/10 px-2.5 py-0.5 text-xs font-medium text-action-primary-bg\"\n >\n {tag}\n </span>\n ))}\n </div>\n )}\n </div>\n </GlassCard>\n\n <ActivityTimeline resourceId={asset.id} />\n </aside>\n </div>\n\n {/* Edit dialog */}\n <ResponsiveDialog open={showEdit} onOpenChange={setShowEdit}>\n <ResponsiveDialogContent className=\"max-h-[85vh] overflow-y-auto sm:max-w-2xl\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Edit asset</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Update this asset&apos;s details and financials.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n {editForm ? (\n <form className=\"space-y-4\" onSubmit={submitEdit}>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Name</Label>\n <Input value={editForm.name} onChange={(e) => setEdit('name', e.target.value)} />\n </div>\n <div className=\"space-y-2\">\n <Label>Category</Label>\n <Input\n value={editForm.category}\n onChange={(e) => setEdit('category', e.target.value)}\n />\n </div>\n </div>\n <div className=\"space-y-2\">\n <Label>Description</Label>\n <Textarea\n value={editForm.description}\n onChange={(e) => setEdit('description', e.target.value)}\n rows={2}\n />\n </div>\n <div className=\"grid gap-4 md:grid-cols-3\">\n <div className=\"space-y-2\">\n <Label>Status</Label>\n <Select value={editForm.status} onValueChange={(v) => setEdit('status', v)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"ACTIVE\">Active</SelectItem>\n <SelectItem value=\"INACTIVE\">Inactive</SelectItem>\n <SelectItem value=\"MAINTENANCE\">Maintenance</SelectItem>\n <SelectItem value=\"RETIRED\">Retired</SelectItem>\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-2\">\n <Label>Condition</Label>\n <Select value={editForm.condition} onValueChange={(v) => setEdit('condition', v)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"EXCELLENT\">Excellent</SelectItem>\n <SelectItem value=\"GOOD\">Good</SelectItem>\n <SelectItem value=\"FAIR\">Fair</SelectItem>\n <SelectItem value=\"POOR\">Poor</SelectItem>\n <SelectItem value=\"DAMAGED\">Damaged</SelectItem>\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-2\">\n <Label>Department</Label>\n <Input\n value={editForm.department}\n onChange={(e) => setEdit('department', e.target.value)}\n />\n </div>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Serial Number</Label>\n <Input\n value={editForm.serialNumber}\n onChange={(e) => setEdit('serialNumber', e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Assigned To</Label>\n <Input\n value={editForm.assignedTo}\n onChange={(e) => setEdit('assignedTo', e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Location</Label>\n <Input\n value={editForm.locationName}\n onChange={(e) => setEdit('locationName', e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Supplier</Label>\n <Input\n value={editForm.supplier}\n onChange={(e) => setEdit('supplier', e.target.value)}\n />\n </div>\n </div>\n <div className=\"grid gap-4 md:grid-cols-4\">\n <div className=\"space-y-2\">\n <Label>Purchase Value</Label>\n <Input\n type=\"number\"\n min=\"0\"\n step=\"0.01\"\n value={editForm.purchaseValue}\n onChange={(e) => setEdit('purchaseValue', e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Salvage Value</Label>\n <Input\n type=\"number\"\n min=\"0\"\n step=\"0.01\"\n value={editForm.salvageValue}\n onChange={(e) => setEdit('salvageValue', e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Useful Life (mo)</Label>\n <Input\n type=\"number\"\n min=\"0\"\n step=\"1\"\n value={editForm.usefulLifeMonths}\n onChange={(e) => setEdit('usefulLifeMonths', e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Depreciation</Label>\n <Select\n value={editForm.depreciationMethod}\n onValueChange={(v) => setEdit('depreciationMethod', v)}\n >\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"STRAIGHT_LINE\">Straight line</SelectItem>\n <SelectItem value=\"REDUCING_BALANCE\">Reducing balance</SelectItem>\n <SelectItem value=\"NONE\">None</SelectItem>\n </SelectContent>\n </Select>\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => setShowEdit(false)}\n disabled={updating}\n >\n Cancel\n </Button>\n <Button type=\"submit\" disabled={updating}>\n {updating ? 'Saving…' : 'Save changes'}\n </Button>\n </ResponsiveDialogFooter>\n </form>\n ) : null}\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n\n {/* Dispose dialog */}\n <ResponsiveDialog open={showDispose} onOpenChange={setShowDispose}>\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Dispose asset</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Record the disposal of this asset. It will be marked as disposed and removed from\n active inventory.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <form className=\"space-y-4\" onSubmit={submitDispose}>\n <div className=\"space-y-2\">\n <Label>Disposal Date</Label>\n <Input\n type=\"date\"\n value={disposeForm.disposalDate}\n onChange={(e) =>\n setDisposeForm((prev) => ({ ...prev, disposalDate: e.target.value }))\n }\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Method</Label>\n <Input\n placeholder=\"e.g., Sold, Recycled, Scrapped\"\n value={disposeForm.method}\n onChange={(e) => setDisposeForm((prev) => ({ ...prev, method: e.target.value }))}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Notes</Label>\n <Textarea\n placeholder=\"Optional details about the disposal\"\n value={disposeForm.notes}\n onChange={(e) => setDisposeForm((prev) => ({ ...prev, notes: e.target.value }))}\n rows={2}\n />\n </div>\n <ResponsiveDialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => setShowDispose(false)}\n disabled={disposing}\n >\n Cancel\n </Button>\n <Button type=\"submit\" disabled={disposing}>\n {disposing ? 'Disposing…' : 'Confirm disposal'}\n </Button>\n </ResponsiveDialogFooter>\n </form>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n\n {/* Delete dialog */}\n <ResponsiveDialog open={showDelete} onOpenChange={setShowDelete}>\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Delete asset</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n This removes <span className=\"font-medium\">{asset.name}</span> from the inventory.\n This action cannot be undone.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => setShowDelete(false)} disabled={deleting}>\n Cancel\n </Button>\n <Button\n variant=\"destructive\"\n onClick={() => void deleteAsset({ variables: { id: asset.id } })}\n disabled={deleting}\n >\n {deleting ? 'Deleting…' : 'Delete asset'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </div>\n );\n}\n\n// A single labelled field rendered as its own clean card (mock's field grid).\n// Machine values (serial, tags, supplier) render verbatim — no blanket capitalize.\nfunction FieldTile({\n label,\n value,\n icon: Icon,\n mono,\n capitalize,\n full,\n children,\n}: {\n label: string;\n value?: string;\n icon?: React.ComponentType<{ className?: string }>;\n mono?: boolean;\n capitalize?: boolean;\n full?: boolean;\n children?: React.ReactNode;\n}) {\n return (\n <div\n className={`rounded-lg border border-border-seam bg-bg-surface p-3.5 ${full ? 'sm:col-span-2 xl:col-span-3' : ''}`}\n >\n <p className=\"flex items-center gap-1.5 text-xs text-text-secondary\">\n {Icon ? <Icon className=\"h-3.5 w-3.5\" /> : null}\n {label}\n </p>\n {children ? (\n <div className=\"mt-1.5\">{children}</div>\n ) : (\n <p\n className={`mt-1 break-words font-medium ${mono ? 'font-mono text-sm' : ''} ${capitalize ? 'capitalize' : ''}`}\n >\n {value}\n </p>\n )}\n </div>\n );\n}\n\n// A striped ledger row for the financial key-facts panel.\nfunction LedgerRow({ label, value, striped }: { label: string; value: string; striped?: boolean }) {\n return (\n <div\n className={`flex items-center justify-between gap-4 px-3.5 py-2.5 ${striped ? 'bg-bg-sunken/40' : ''}`}\n >\n <dt className=\"shrink-0 text-text-secondary\">{label}</dt>\n <dd className=\"truncate text-right font-medium\">{value}</dd>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"AssetsAssetListPage.d.ts","sourceRoot":"","sources":["../../../src/assethandler/pages/AssetsAssetListPage.tsx"],"names":[],"mappings":"AAkJA,wBAAgB,mBAAmB,gCA2gBlC"}
1
+ {"version":3,"file":"AssetsAssetListPage.d.ts","sourceRoot":"","sources":["../../../src/assethandler/pages/AssetsAssetListPage.tsx"],"names":[],"mappings":"AAiJA,wBAAgB,mBAAmB,gCA4flC"}
@@ -1,7 +1,7 @@
1
1
  import { useAssetHandlerStore as e } from "../store/assethandlerStore.js";
2
2
  import { useHiddenCategoryIds as t } from "../providers/AssetHandlerProvider.js";
3
3
  import { useAssetHandlerNavigate as n } from "../hooks/useAssetHandlerNavigate.js";
4
- import { tWithFallback as r } from "../utils/i18n.js";
4
+ import { useCopy as r } from "../hooks/useCopy.js";
5
5
  import { notify as i } from "../utils/toast.js";
6
6
  import { formatCompact as a } from "../components/charts/chartTheme.js";
7
7
  import { BarsChart as ee } from "../components/charts/BarsChart.js";
@@ -14,7 +14,6 @@ import { useMemo as c, useState as l, useSyncExternalStore as u } from "react";
14
14
  import { ArrowDown as ie, ArrowUp as ae, Box as d, Boxes as oe, CheckCircle2 as se, ChevronsUpDown as ce, Code as f, Copy as p, Eye as m, Grid3x3 as le, List as ue, Monitor as h, MoreHorizontal as g, Plus as _, Search as v, Server as y, Table as de, Truck as b, Wifi as x, Wrench as S } from "lucide-react";
15
15
  import { Fragment as C, jsx as w, jsxs as T } from "react/jsx-runtime";
16
16
  import { Button as E, Card as D, CardContent as O, CardHeader as fe, CardTitle as pe, DropdownMenu as k, DropdownMenuContent as A, DropdownMenuItem as j, DropdownMenuTrigger as M, GradientText as me, IllustratedEmptyState as he, Input as ge, PagePurpose as _e, Select as N, SelectContent as P, SelectItem as F, SelectTrigger as I, SelectValue as L } from "@burdenoff/fe-libs/ui";
17
- import { useI18n as ve } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
18
17
  //#region src/assethandler/pages/AssetsAssetListPage.tsx
19
18
  var R = {
20
19
  active: "bg-status-success-bg-subtle text-status-success-text",
@@ -28,7 +27,7 @@ var R = {
28
27
  fair: "text-status-warning-text bg-status-warning-bg-subtle",
29
28
  poor: "text-status-warning-text bg-status-warning-bg-subtle",
30
29
  damaged: "text-status-error-text bg-status-error-bg-subtle"
31
- }, ye = {
30
+ }, ve = {
32
31
  active: "var(--color-status-success-bg)",
33
32
  maintenance: "var(--color-status-warning-bg)",
34
33
  inactive: "var(--color-status-info-bg)",
@@ -66,7 +65,7 @@ function U({ status: e }) {
66
65
  children: e.replace(/_/g, " ")
67
66
  });
68
67
  }
69
- function be() {
68
+ function ye() {
70
69
  return u((e) => {
71
70
  if (typeof window > "u" || !window.matchMedia) return () => {};
72
71
  let t = window.matchMedia("(max-width: 767px)");
@@ -74,7 +73,7 @@ function be() {
74
73
  }, () => typeof window < "u" && window.matchMedia ? window.matchMedia("(max-width: 767px)").matches : !1, () => !1);
75
74
  }
76
75
  function W() {
77
- let { t: u } = ve(), f = n(), p = t(), { assets: m, hydrated: h } = e(), g = be(), [y, b] = l(""), [x, S] = l("all"), [k, A] = l("all"), [j, M] = l("table"), [R, B] = l(!1), [V, W] = l("name"), [G, K] = l("asc"), q = !R && g && j === "table" ? "list" : j, J = (e) => {
76
+ let u = r(), f = n(), p = t(), { assets: m, hydrated: h } = e(), g = ye(), [y, b] = l(""), [x, S] = l("all"), [k, A] = l("all"), [j, M] = l("table"), [R, B] = l(!1), [V, W] = l("name"), [G, K] = l("asc"), q = !R && g && j === "table" ? "list" : j, J = (e) => {
78
77
  B(!0), M(e);
79
78
  }, Y = c(() => [...new Set(m.map((e) => e.category).filter(Boolean))].filter((e) => !p.has(e)).sort(), [m, p]), X = c(() => m.filter((e) => {
80
79
  if (p.has(e.category)) return !1;
@@ -86,7 +85,7 @@ function W() {
86
85
  x,
87
86
  k,
88
87
  p
89
- ]), Se = c(() => {
88
+ ]), xe = c(() => {
90
89
  let e = G === "asc" ? 1 : -1;
91
90
  return [...X].sort((t, n) => {
92
91
  let r = (t[V] ?? "").toString().toLowerCase(), i = (n[V] ?? "").toString().toLowerCase();
@@ -96,35 +95,35 @@ function W() {
96
95
  X,
97
96
  V,
98
97
  G
99
- ]), Z = m.filter((e) => e.status === "active").length, Ce = c(() => {
98
+ ]), Z = m.filter((e) => e.status === "active").length, Se = c(() => {
100
99
  let e = {};
101
100
  for (let t of m) e[t.status] = (e[t.status] || 0) + 1;
102
101
  return Object.entries(e).map(([e, t]) => ({
103
102
  name: e.charAt(0).toUpperCase() + e.slice(1),
104
103
  value: t,
105
- color: ye[e]
104
+ color: ve[e]
106
105
  }));
107
- }, [m]), we = c(() => {
106
+ }, [m]), Ce = c(() => {
108
107
  let e = {};
109
108
  for (let t of m) e[t.category] = (e[t.category] || 0) + 1;
110
109
  return Object.entries(e).sort((e, t) => t[1] - e[1]).slice(0, 8).map(([e, t]) => ({
111
110
  category: e.replace(/_/g, " "),
112
111
  count: t
113
112
  }));
114
- }, [m]), Q = re(Se, {
113
+ }, [m]), Q = re(xe, {
115
114
  pageSize: 12,
116
115
  resetKey: `${y}|${x}|${k}|${V}|${G}`
117
- }), Te = (e) => {
116
+ }), we = (e) => {
118
117
  V === e ? K((e) => e === "asc" ? "desc" : "asc") : (W(e), K("asc"));
119
118
  }, $ = (e, t) => /* @__PURE__ */ w("th", {
120
119
  className: "p-3 text-left font-medium",
121
120
  children: /* @__PURE__ */ T("button", {
122
121
  type: "button",
123
- onClick: () => Te(t),
122
+ onClick: () => we(t),
124
123
  className: "inline-flex items-center gap-1 hover:text-text-primary",
125
124
  children: [e, V === t ? w(G === "asc" ? ae : ie, { className: "h-3 w-3 text-action-primary-bg" }) : /* @__PURE__ */ w(ce, { className: "h-3 w-3 text-text-muted" })]
126
125
  })
127
- }), Ee = (e) => {
126
+ }), Te = (e) => {
128
127
  navigator.clipboard?.writeText(e), i.success("Asset tag copied", `${e} copied to clipboard.`);
129
128
  };
130
129
  return /* @__PURE__ */ T("div", {
@@ -134,27 +133,27 @@ function W() {
134
133
  className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",
135
134
  children: [/* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("h1", {
136
135
  className: "text-2xl font-bold",
137
- children: /* @__PURE__ */ w(me, { children: r(u, "assethandler.assets.list.title", "Asset Inventory") })
136
+ children: /* @__PURE__ */ w(me, { children: u("assethandler.assets.list.title", "{{asset}} Inventory") })
138
137
  }), /* @__PURE__ */ T("p", {
139
138
  className: "text-sm text-text-secondary",
140
139
  children: [
141
140
  m.length,
142
141
  " ",
143
- r(u, "assethandler.assets.list.subtitle.totalAssets", "total assets"),
142
+ u("assethandler.assets.list.subtitle.totalAssets", "total {{assetsLower}}"),
143
+ " ·",
144
144
  " ",
145
- "· ",
146
145
  Z,
147
146
  " ",
148
- r(u, "assethandler.assets.list.subtitle.active", "active")
147
+ u("assethandler.assets.list.subtitle.active", "active")
149
148
  ]
150
149
  })] }), /* @__PURE__ */ T(E, {
151
150
  className: "w-full sm:w-auto",
152
151
  size: "sm",
153
152
  onClick: () => f("/assets/asset-create"),
154
- children: [/* @__PURE__ */ w(_, { className: "mr-2 h-4 w-4" }), r(u, "assethandler.assets.list.actions.addAsset", "Add Asset")]
153
+ children: [/* @__PURE__ */ w(_, { className: "mr-2 h-4 w-4" }), u("assethandler.assets.list.actions.addAsset", "Add {{asset}}")]
155
154
  })]
156
155
  }),
157
- /* @__PURE__ */ w(_e, { children: r(u, "assethandler.assets.list.purpose", "The single source of truth for every asset you own or manage. Search, filter and group by category, status or condition to find any item fast, review its assignment, then drill in to update, check it in/out or schedule maintenance.") }),
156
+ /* @__PURE__ */ w(_e, { children: u("assethandler.assets.list.purpose", "The single source of truth for every {{assetLower}} you own or manage. Search, filter and group by category, status or condition to find any item fast, review its assignment, then drill in to update, check it in/out or schedule maintenance.") }),
158
157
  m.length > 0 ? /* @__PURE__ */ T(C, { children: [/* @__PURE__ */ T("div", {
159
158
  className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-4",
160
159
  children: [
@@ -190,7 +189,7 @@ function W() {
190
189
  title: "Status mix",
191
190
  subtitle: "Assets by lifecycle status",
192
191
  children: /* @__PURE__ */ w(te, {
193
- data: Ce,
192
+ data: Se,
194
193
  centerLabel: "Total",
195
194
  centerValue: m.length,
196
195
  height: 220
@@ -199,7 +198,7 @@ function W() {
199
198
  title: "By category",
200
199
  subtitle: "Top categories by asset count",
201
200
  children: /* @__PURE__ */ w(ee, {
202
- data: we,
201
+ data: Ce,
203
202
  xKey: "category",
204
203
  orientation: "horizontal",
205
204
  height: 220,
@@ -207,7 +206,7 @@ function W() {
207
206
  valueFormat: a,
208
207
  series: [{
209
208
  key: "count",
210
- label: "Assets"
209
+ label: u("assethandler.assets.list.chart.series", "{{assets}}")
211
210
  }]
212
211
  })
213
212
  })]
@@ -220,7 +219,7 @@ function W() {
220
219
  /* @__PURE__ */ T("div", {
221
220
  className: "relative min-w-0 flex-1",
222
221
  children: [/* @__PURE__ */ w(v, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary" }), /* @__PURE__ */ w(ge, {
223
- placeholder: r(u, "assethandler.assets.list.search.placeholder", "Search by name, asset tag, serial number..."),
222
+ placeholder: u("assethandler.assets.list.search.placeholder", "Search by name, {{assetLower}} tag, serial number..."),
224
223
  value: y,
225
224
  onChange: (e) => b(e.target.value),
226
225
  className: "pl-9"
@@ -231,10 +230,10 @@ function W() {
231
230
  onValueChange: S,
232
231
  children: [/* @__PURE__ */ w(I, {
233
232
  className: "w-full sm:w-[180px]",
234
- children: /* @__PURE__ */ w(L, { placeholder: r(u, "assethandler.assets.list.filters.category.placeholder", "Category") })
233
+ children: /* @__PURE__ */ w(L, { placeholder: u("assethandler.assets.list.filters.category.placeholder", "Category") })
235
234
  }), /* @__PURE__ */ T(P, { children: [/* @__PURE__ */ w(F, {
236
235
  value: "all",
237
- children: r(u, "assethandler.assets.list.filters.category.all", "All Categories")
236
+ children: u("assethandler.assets.list.filters.category.all", "All Categories")
238
237
  }), Y.map((e) => /* @__PURE__ */ w(F, {
239
238
  value: e,
240
239
  className: "capitalize",
@@ -246,31 +245,31 @@ function W() {
246
245
  onValueChange: A,
247
246
  children: [/* @__PURE__ */ w(I, {
248
247
  className: "w-full sm:w-[160px]",
249
- children: /* @__PURE__ */ w(L, { placeholder: r(u, "assethandler.assets.list.filters.status.placeholder", "Status") })
248
+ children: /* @__PURE__ */ w(L, { placeholder: u("assethandler.assets.list.filters.status.placeholder", "Status") })
250
249
  }), /* @__PURE__ */ T(P, { children: [
251
250
  /* @__PURE__ */ w(F, {
252
251
  value: "all",
253
- children: r(u, "assethandler.assets.list.filters.status.all", "All Statuses")
252
+ children: u("assethandler.assets.list.filters.status.all", "All Statuses")
254
253
  }),
255
254
  /* @__PURE__ */ w(F, {
256
255
  value: "active",
257
- children: r(u, "assethandler.assets.list.filters.status.active", "Active")
256
+ children: u("assethandler.assets.list.filters.status.active", "Active")
258
257
  }),
259
258
  /* @__PURE__ */ w(F, {
260
259
  value: "inactive",
261
- children: r(u, "assethandler.assets.list.filters.status.inactive", "Inactive")
260
+ children: u("assethandler.assets.list.filters.status.inactive", "Inactive")
262
261
  }),
263
262
  /* @__PURE__ */ w(F, {
264
263
  value: "maintenance",
265
- children: r(u, "assethandler.assets.list.filters.status.maintenance", "Maintenance")
264
+ children: u("assethandler.assets.list.filters.status.maintenance", "Maintenance")
266
265
  }),
267
266
  /* @__PURE__ */ w(F, {
268
267
  value: "retired",
269
- children: r(u, "assethandler.assets.list.filters.status.retired", "Retired")
268
+ children: u("assethandler.assets.list.filters.status.retired", "Retired")
270
269
  }),
271
270
  /* @__PURE__ */ w(F, {
272
271
  value: "disposed",
273
- children: r(u, "assethandler.assets.list.filters.status.disposed", "Disposed")
272
+ children: u("assethandler.assets.list.filters.status.disposed", "Disposed")
274
273
  })
275
274
  ] })]
276
275
  }),
@@ -328,16 +327,16 @@ function W() {
328
327
  children: [/* @__PURE__ */ w("thead", { children: /* @__PURE__ */ T("tr", {
329
328
  className: "border-b bg-bg-sunken/50 text-text-secondary",
330
329
  children: [
331
- $(r(u, "assethandler.assets.list.table.assetTag", "Asset Tag"), "assetTag"),
332
- $(r(u, "assethandler.assets.list.table.name", "Name"), "name"),
333
- $(r(u, "assethandler.assets.list.table.category", "Category"), "category"),
334
- $(r(u, "assethandler.assets.list.table.status", "Status"), "status"),
335
- $(r(u, "assethandler.assets.list.table.condition", "Condition"), "condition"),
330
+ $(u("assethandler.assets.list.table.assetTag", "{{asset}} Tag"), "assetTag"),
331
+ $(u("assethandler.assets.list.table.name", "Name"), "name"),
332
+ $(u("assethandler.assets.list.table.category", "Category"), "category"),
333
+ $(u("assethandler.assets.list.table.status", "Status"), "status"),
334
+ $(u("assethandler.assets.list.table.condition", "Condition"), "condition"),
336
335
  /* @__PURE__ */ w("th", {
337
336
  className: "p-3 text-left font-medium",
338
- children: r(u, "assethandler.assets.list.table.location", "Location")
337
+ children: u("assethandler.assets.list.table.location", "Location")
339
338
  }),
340
- $(r(u, "assethandler.assets.list.table.assignedTo", "Assigned To"), "assignedTo"),
339
+ $(u("assethandler.assets.list.table.assignedTo", "Assigned To"), "assignedTo"),
341
340
  /* @__PURE__ */ w("th", { className: "w-10 p-3" })
342
341
  ]
343
342
  }) }), /* @__PURE__ */ w("tbody", { children: Q.pageItems.map((e) => /* @__PURE__ */ T("tr", {
@@ -390,9 +389,9 @@ function W() {
390
389
  /* @__PURE__ */ w("td", {
391
390
  className: "p-3",
392
391
  onClick: (e) => e.stopPropagation(),
393
- children: /* @__PURE__ */ w(xe, {
392
+ children: /* @__PURE__ */ w(be, {
394
393
  onView: () => f(`/assets/${e.id}`),
395
- onCopy: () => Ee(e.assetTag)
394
+ onCopy: () => Te(e.assetTag)
396
395
  })
397
396
  })
398
397
  ]
@@ -427,7 +426,7 @@ function W() {
427
426
  className: "flex justify-between",
428
427
  children: [/* @__PURE__ */ w("span", {
429
428
  className: "text-text-secondary",
430
- children: r(u, "assethandler.assets.list.grid.category", "Category")
429
+ children: u("assethandler.assets.list.grid.category", "Category")
431
430
  }), /* @__PURE__ */ w("span", {
432
431
  className: "capitalize",
433
432
  children: e.category.replace(/_/g, " ")
@@ -437,7 +436,7 @@ function W() {
437
436
  className: "flex justify-between",
438
437
  children: [/* @__PURE__ */ w("span", {
439
438
  className: "text-text-secondary",
440
- children: r(u, "assethandler.assets.list.grid.condition", "Condition")
439
+ children: u("assethandler.assets.list.grid.condition", "Condition")
441
440
  }), /* @__PURE__ */ w("span", {
442
441
  className: `rounded-md px-2 py-0.5 text-xs font-medium capitalize ${z[e.condition] || ""}`,
443
442
  children: e.condition
@@ -447,7 +446,7 @@ function W() {
447
446
  className: "flex justify-between",
448
447
  children: [/* @__PURE__ */ w("span", {
449
448
  className: "text-text-secondary",
450
- children: r(u, "assethandler.assets.list.grid.assignedTo", "Assigned To")
449
+ children: u("assethandler.assets.list.grid.assignedTo", "Assigned To")
451
450
  }), /* @__PURE__ */ w("span", {
452
451
  className: "text-xs",
453
452
  children: e.assignedTo || "—"
@@ -501,18 +500,18 @@ function W() {
501
500
  }),
502
501
  h && X.length === 0 && /* @__PURE__ */ w(he, {
503
502
  illustration: y || x !== "all" || k !== "all" ? "empty-search" : "empty-data",
504
- title: r(u, "assethandler.assets.list.empty.title", "No assets found"),
505
- description: r(u, "assethandler.assets.list.empty.description", "Try adjusting your filters or add a new asset to get started."),
503
+ title: u("assethandler.assets.list.empty.title", "No {{assetsLower}} found"),
504
+ description: u("assethandler.assets.list.empty.description", "Try adjusting your filters or add a new {{assetLower}} to get started."),
506
505
  action: /* @__PURE__ */ T(E, {
507
506
  size: "sm",
508
507
  onClick: () => f("/assets/asset-create"),
509
- children: [/* @__PURE__ */ w(_, { className: "mr-2 h-4 w-4" }), r(u, "assethandler.assets.list.actions.addAsset", "Add Asset")]
508
+ children: [/* @__PURE__ */ w(_, { className: "mr-2 h-4 w-4" }), u("assethandler.assets.list.actions.addAsset", "Add {{asset}}")]
510
509
  })
511
510
  })
512
511
  ]
513
512
  });
514
513
  }
515
- function xe({ onView: e, onCopy: t }) {
514
+ function be({ onView: e, onCopy: t }) {
516
515
  return /* @__PURE__ */ T(k, { children: [/* @__PURE__ */ w(M, {
517
516
  asChild: !0,
518
517
  children: /* @__PURE__ */ w(E, {