@burdenoff/microfe-assethandler 2026.714.1 → 2026.716.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assethandler/pages/AssetsAssetDetailPage.d.ts.map +1 -1
- package/dist/assethandler/pages/AssetsAssetDetailPage.js +376 -365
- package/dist/assethandler/pages/AssetsAssetDetailPage.js.map +1 -1
- package/dist/stories/ListEmptyState.stories.d.ts +10 -0
- package/dist/stories/ListEmptyState.stories.d.ts.map +1 -0
- package/dist/stories/SectionHeader.stories.d.ts +10 -0
- package/dist/stories/SectionHeader.stories.d.ts.map +1 -0
- package/dist/stories/StatTile.stories.d.ts +10 -0
- package/dist/stories/StatTile.stories.d.ts.map +1 -0
- package/package.json +13 -2
|
@@ -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 ? <> · 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'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'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 ? <> · 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'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'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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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { ListEmptyState } from '../assethandler/components/ListEmptyState';
|
|
3
|
+
|
|
4
|
+
declare const meta: Meta<typeof ListEmptyState>;
|
|
5
|
+
export default meta;
|
|
6
|
+
type Story = StoryObj<typeof meta>;
|
|
7
|
+
export declare const Default: Story;
|
|
8
|
+
export declare const WithAction: Story;
|
|
9
|
+
export declare const CustomDescription: Story;
|
|
10
|
+
//# sourceMappingURL=ListEmptyState.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ListEmptyState.stories.d.ts","sourceRoot":"","sources":["../../src/stories/ListEmptyState.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAGvD,OAAO,EAAE,cAAc,EAAE,MAAM,2CAA2C,CAAC;AAE3E,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,cAAc,CAMrC,CAAC;AAEF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,OAAO,EAAE,KAIrB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAUxB,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,KAM/B,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { SectionHeader } from '../assethandler/components/SectionHeader';
|
|
3
|
+
|
|
4
|
+
declare const meta: Meta<typeof SectionHeader>;
|
|
5
|
+
export default meta;
|
|
6
|
+
type Story = StoryObj<typeof meta>;
|
|
7
|
+
export declare const Default: Story;
|
|
8
|
+
export declare const WithIconAndActions: Story;
|
|
9
|
+
export declare const Hero: Story;
|
|
10
|
+
//# sourceMappingURL=SectionHeader.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SectionHeader.stories.d.ts","sourceRoot":"","sources":["../../src/stories/SectionHeader.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAGvD,OAAO,EAAE,aAAa,EAAE,MAAM,0CAA0C,CAAC;AAEzE,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,aAAa,CAMpC,CAAC;AAEF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,OAAO,EAAE,KAKrB,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,KAYhC,CAAC;AAEF,eAAO,MAAM,IAAI,EAAE,KAMlB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { StatTile } from '../assethandler/components/StatTile';
|
|
3
|
+
|
|
4
|
+
declare const meta: Meta<typeof StatTile>;
|
|
5
|
+
export default meta;
|
|
6
|
+
type Story = StoryObj<typeof meta>;
|
|
7
|
+
export declare const Default: Story;
|
|
8
|
+
export declare const WithTrend: Story;
|
|
9
|
+
export declare const HeroWithSpark: Story;
|
|
10
|
+
//# sourceMappingURL=StatTile.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StatTile.stories.d.ts","sourceRoot":"","sources":["../../src/stories/StatTile.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,QAAQ,EAAE,MAAM,qCAAqC,CAAC;AAE/D,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,QAAQ,CAM/B,CAAC;AAEF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,OAAO,EAAE,KAMrB,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,KAQvB,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KAW3B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@burdenoff/microfe-assethandler",
|
|
3
|
-
"version": "2026.
|
|
3
|
+
"version": "2026.716.1",
|
|
4
4
|
"description": "Burdenoff AssetHandler Microfrontend",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -40,7 +40,10 @@
|
|
|
40
40
|
"switch:local": "bun scripts/deps-mode.ts local",
|
|
41
41
|
"switch:check": "bun scripts/deps-mode.ts check",
|
|
42
42
|
"prepare": "lefthook install || true",
|
|
43
|
-
"format:check": "prettier --check \"src/**/*.{ts,tsx}\""
|
|
43
|
+
"format:check": "prettier --check \"src/**/*.{ts,tsx}\"",
|
|
44
|
+
"storybook": "storybook dev -p 6006",
|
|
45
|
+
"build-storybook": "storybook build",
|
|
46
|
+
"test:storybook": "test-storybook"
|
|
44
47
|
},
|
|
45
48
|
"dependencies": {
|
|
46
49
|
"@apollo/client": "^4.0.11",
|
|
@@ -69,6 +72,13 @@
|
|
|
69
72
|
"@graphql-inspector/cli": "^6.0.7",
|
|
70
73
|
"@types/react": "^19.0.2",
|
|
71
74
|
"@types/react-dom": "^19.0.2",
|
|
75
|
+
"@storybook/addon-essentials": "^8.6.0",
|
|
76
|
+
"@storybook/addon-interactions": "^8.6.0",
|
|
77
|
+
"@storybook/react": "^8.6.0",
|
|
78
|
+
"@storybook/react-vite": "^8.6.0",
|
|
79
|
+
"@storybook/test": "^8.6.0",
|
|
80
|
+
"@storybook/test-runner": "0.24.4",
|
|
81
|
+
"@tailwindcss/vite": "^4.3.2",
|
|
72
82
|
"@vitejs/plugin-react": "^4.3.4",
|
|
73
83
|
"autoprefixer": "^10.4.20",
|
|
74
84
|
"eslint": "^9.18.0",
|
|
@@ -78,6 +88,7 @@
|
|
|
78
88
|
"lefthook": "^2.1.1",
|
|
79
89
|
"postcss": "^8.4.49",
|
|
80
90
|
"prettier": "^3.4.2",
|
|
91
|
+
"storybook": "^8.6.0",
|
|
81
92
|
"tailwindcss": "^4.0.0",
|
|
82
93
|
"typescript": "^5.9.0",
|
|
83
94
|
"typescript-eslint": "^8.54.0",
|