@burdenoff/microfe-assethandler 2026.826.12 → 2026.826.13

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.
@@ -1 +1 @@
1
- {"version":3,"file":"FinanceFinanceHubPage.d.ts","sourceRoot":"","sources":["../../../src/assethandler/pages/FinanceFinanceHubPage.tsx"],"names":[],"mappings":"AAwsBA,wBAAgB,qBAAqB,gCAmuBpC"}
1
+ {"version":3,"file":"FinanceFinanceHubPage.d.ts","sourceRoot":"","sources":["../../../src/assethandler/pages/FinanceFinanceHubPage.tsx"],"names":[],"mappings":"AAwsBA,wBAAgB,qBAAqB,gCAquBpC"}
@@ -105,7 +105,7 @@ function Te({ open: e, onOpenChange: n }) {
105
105
  open: e,
106
106
  onOpenChange: n,
107
107
  children: /* @__PURE__ */ D(N, { children: [
108
- /* @__PURE__ */ D(I, { children: [/* @__PURE__ */ E(ce, { children: "New Transaction" }), /* @__PURE__ */ E(P, { children: "Record a financial movement against your assets." })] }),
108
+ /* @__PURE__ */ D(I, { children: [/* @__PURE__ */ E(ce, { children: "New Transaction" }), /* @__PURE__ */ E(P, { children: "Record a workspace financial movement for the asset estate." })] }),
109
109
  /* @__PURE__ */ D("div", {
110
110
  className: "space-y-4",
111
111
  children: [
@@ -349,7 +349,7 @@ function De({ open: e, onOpenChange: n }) {
349
349
  open: e,
350
350
  onOpenChange: n,
351
351
  children: /* @__PURE__ */ D(N, { children: [
352
- /* @__PURE__ */ D(I, { children: [/* @__PURE__ */ E(ce, { children: "New Invoice" }), /* @__PURE__ */ E(P, { children: "Log a vendor invoice for an asset purchase or service." })] }),
352
+ /* @__PURE__ */ D(I, { children: [/* @__PURE__ */ E(ce, { children: "New Invoice" }), /* @__PURE__ */ E(P, { children: "Log a workspace vendor invoice for an asset purchase or service." })] }),
353
353
  /* @__PURE__ */ D("div", {
354
354
  className: "space-y-4",
355
355
  children: [
@@ -577,7 +577,7 @@ function ke() {
577
577
  children: /* @__PURE__ */ E(ie, { children: "Finance Hub" })
578
578
  }), /* @__PURE__ */ E("p", {
579
579
  className: "mt-1 text-sm text-text-secondary",
580
- children: "Financial management for IT assets"
580
+ children: "Workspace budgets, transactions, and supplier invoices"
581
581
  })] }), /* @__PURE__ */ E(re, {
582
582
  primary: {
583
583
  label: "New Transaction",
@@ -687,7 +687,7 @@ function ke() {
687
687
  open: ce,
688
688
  onOpenChange: pe
689
689
  }),
690
- /* @__PURE__ */ E(se, { children: "The money side of your asset estate: track spend, keep departmental budgets on course, and stay on top of vendor invoices. Use this hub to spot over-budget areas and overdue invoices early — so asset costs stay predictable and nothing slips past its due date." }),
690
+ /* @__PURE__ */ E(se, { children: "The workspace money view for your asset estate: record transactions, maintain departmental budget totals, and stay on top of vendor invoices. Transactions do not automatically update budgets, and these records are not yet allocated to an individual asset." }),
691
691
  /* @__PURE__ */ E(oe, {
692
692
  storageKey: "assethandler-finance-hub",
693
693
  steps: [
@@ -705,8 +705,8 @@ function ke() {
705
705
  },
706
706
  {
707
707
  id: "reports",
708
- label: "Build a finance report",
709
- description: "Turn spend and budget data into a shareable report.",
708
+ label: "Open financial summaries",
709
+ description: "Review the fixed live financial summary and CSV-ready registers.",
710
710
  onClick: () => w("/reports/reports-dashboard")
711
711
  }
712
712
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"FinanceFinanceHubPage.js","names":[],"sources":["../../../src/assethandler/pages/FinanceFinanceHubPage.tsx"],"sourcesContent":["import { useMemo, useState, type ReactNode } from 'react';\nimport { useAssetMoney } from '../providers/AssetHandlerProvider';\nimport { useAssetHandlerNavigate } from '../hooks/useAssetHandlerNavigate';\nimport {\n Button,\n GlassCard,\n Input,\n Label,\n Textarea,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n GradientText,\n CTAOverflowMenu,\n PagePurpose,\n NextSteps,\n IllustratedEmptyState,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport {\n DollarSign,\n TrendingDown,\n Receipt,\n Wallet,\n Download,\n Loader2,\n Check,\n X,\n Search,\n BarChart3,\n PieChart as PieChartIcon,\n} from 'lucide-react';\nimport { gql } from '@apollo/client';\nimport { useMutation } from '@apollo/client/react';\nimport { useAssetHandlerStore } from '../store/assethandlerStore';\nimport type { Budget, FinanceTransaction, Invoice } from '../store/assethandlerStore';\nimport { notify } from '../utils/toast';\nimport { cn } from '../utils/cn';\nimport { downloadCsv } from '../utils/csv';\nimport {\n StatTile,\n ChartCard,\n BarsChart,\n DonutChart,\n ProgressMeter,\n Pagination,\n usePagination,\n type DonutSlice,\n} from '../components';\n\n// ─── Mutations ────────────────────────────────────────────────────────────────\nconst CREATE_TRANSACTION_MUTATION = gql`\n mutation AssetHandlerCreateTransaction($input: CreateTransactionInput!) {\n createTransaction(input: $input) {\n id\n description\n }\n }\n`;\n\nconst CREATE_BUDGET_MUTATION = gql`\n mutation AssetHandlerCreateBudget($input: AssetHandlerCreateBudgetInput!) {\n createBudget(input: $input) {\n id\n name\n }\n }\n`;\n\nconst CREATE_INVOICE_MUTATION = gql`\n mutation AssetHandlerCreateInvoice($input: AssetHandlerCreateInvoiceInput!) {\n createInvoice(input: $input) {\n id\n number\n }\n }\n`;\n\nconst APPROVE_TRANSACTION_MUTATION = gql`\n mutation AssetHandlerHubApproveTransaction($id: ID!) {\n approveTransaction(id: $id) {\n id\n status\n }\n }\n`;\n\nconst REJECT_TRANSACTION_MUTATION = gql`\n mutation AssetHandlerHubRejectTransaction($id: ID!, $reason: String) {\n rejectTransaction(id: $id, reason: $reason) {\n id\n status\n }\n }\n`;\n\ninterface CreateTransactionResult {\n createTransaction: { id: string; description: string };\n}\ninterface CreateBudgetResult {\n createBudget: { id: string; name: string };\n}\ninterface CreateInvoiceResult {\n createInvoice: { id: string; number: string };\n}\ninterface ApproveTransactionResult {\n approveTransaction: { id: string; status: string };\n}\ninterface RejectTransactionResult {\n rejectTransaction: { id: string; status: string };\n}\n\nconst TRANSACTION_TYPES = ['PURCHASE', 'LEASE', 'DISPOSAL', 'TRANSFER', 'MAINTENANCE'] as const;\nconst TRANSACTION_STATUSES = ['PENDING', 'APPROVED', 'COMPLETED', 'REJECTED'] as const;\nconst BUDGET_STATUSES = ['ON_TRACK', 'OVER_BUDGET', 'UNDER_BUDGET'] as const;\nconst INVOICE_STATUSES = ['DRAFT', 'SENT', 'PAID', 'OVERDUE', 'CANCELLED'] as const;\n\nconst humanize = (value: string) =>\n value\n .toLowerCase()\n .replace(/_/g, ' ')\n .replace(/^\\w/, (c) => c.toUpperCase());\n\n// ─── Presentation helpers ───────────────────────────────────────────────────\ntype Tone = 'success' | 'warning' | 'error' | 'info' | 'neutral';\n\nconst PILL_TONE: Record<Tone, string> = {\n success: 'bg-status-success-subtle text-status-success-text',\n warning: 'bg-status-warning-subtle text-status-warning-text',\n error: 'bg-status-error-subtle text-status-error-text',\n info: 'bg-status-info-subtle text-status-info-text',\n neutral: 'bg-bg-sunken text-text-secondary',\n};\n\nfunction StatusPill({ tone, children }: { tone: Tone; children: ReactNode }) {\n return (\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium capitalize',\n PILL_TONE[tone]\n )}\n >\n {children}\n </span>\n );\n}\n\nconst txnStatusTone = (status: string): Tone =>\n status === 'approved' || status === 'completed'\n ? 'success'\n : status === 'rejected'\n ? 'error'\n : status === 'pending'\n ? 'warning'\n : 'neutral';\n\nconst txnTypeTone = (type: string): Tone =>\n type === 'purchase' || type === 'lease'\n ? 'info'\n : type === 'disposal'\n ? 'error'\n : type === 'maintenance'\n ? 'warning'\n : 'neutral';\n\nconst budgetStatusTone = (status: string): Tone =>\n status === 'over_budget' ? 'error' : status === 'under_budget' ? 'success' : 'info';\n\nconst invoiceStatusTone = (status: string): Tone =>\n status === 'paid'\n ? 'success'\n : status === 'overdue'\n ? 'error'\n : status === 'sent'\n ? 'warning'\n : 'neutral';\n\nconst formatDate = (value: string): string => {\n const parsed = new Date(value);\n return Number.isNaN(parsed.getTime()) ? value : parsed.toLocaleDateString();\n};\n\n// ─── New Transaction dialog ───────────────────────────────────────────────────\nfunction NewTransactionDialog({\n open,\n onOpenChange,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}) {\n const [type, setType] = useState<(typeof TRANSACTION_TYPES)[number]>('PURCHASE');\n const [status, setStatus] = useState<(typeof TRANSACTION_STATUSES)[number]>('PENDING');\n const [amount, setAmount] = useState('');\n const { currency: moduleCurrency } = useAssetMoney();\n const [currency, setCurrency] = useState(moduleCurrency);\n const [category, setCategory] = useState('');\n const [description, setDescription] = useState('');\n const [vendor, setVendor] = useState('');\n const [department, setDepartment] = useState('');\n\n const reset = () => {\n setType('PURCHASE');\n setStatus('PENDING');\n setAmount('');\n setCurrency(moduleCurrency);\n setCategory('');\n setDescription('');\n setVendor('');\n setDepartment('');\n };\n\n const [createTransaction, { loading }] = useMutation<CreateTransactionResult>(\n CREATE_TRANSACTION_MUTATION,\n {\n refetchQueries: ['AssetHandlerBootstrap'],\n onCompleted: (data) => {\n notify.success(\n 'Transaction created',\n `${data.createTransaction.description} was recorded.`\n );\n reset();\n onOpenChange(false);\n },\n onError: (error) => notify.error('Could not create transaction', error.message),\n }\n );\n\n const handleSubmit = () => {\n const parsedAmount = Number(amount);\n if (!Number.isFinite(parsedAmount) || amount.trim() === '') {\n notify.warning('Invalid amount', 'Enter a numeric amount for the transaction.');\n return;\n }\n if (!category.trim() || !description.trim()) {\n notify.warning('Missing details', 'Category and description are required.');\n return;\n }\n void createTransaction({\n variables: {\n input: {\n amount: parsedAmount,\n category: category.trim(),\n currency: currency.trim() || moduleCurrency,\n description: description.trim(),\n type,\n status,\n vendor: vendor.trim() || null,\n department: department.trim() || null,\n },\n },\n });\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>New Transaction</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Record a financial movement against your assets.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-4\">\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Type</Label>\n <Select value={type} onValueChange={(v) => setType(v as typeof type)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {TRANSACTION_TYPES.map((t) => (\n <SelectItem key={t} value={t}>\n {humanize(t)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-2\">\n <Label>Status</Label>\n <Select value={status} onValueChange={(v) => setStatus(v as typeof status)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {TRANSACTION_STATUSES.map((s) => (\n <SelectItem key={s} value={s}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Amount *</Label>\n <Input\n type=\"number\"\n placeholder=\"e.g., 1500\"\n value={amount}\n onChange={(e) => setAmount(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Currency</Label>\n <Input value={currency} onChange={(e) => setCurrency(e.target.value)} />\n </div>\n </div>\n <div className=\"space-y-2\">\n <Label>Category *</Label>\n <Input\n placeholder=\"e.g., it_hardware\"\n value={category}\n onChange={(e) => setCategory(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Description *</Label>\n <Textarea\n placeholder=\"What is this transaction for?\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n rows={2}\n />\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Vendor</Label>\n <Input value={vendor} onChange={(e) => setVendor(e.target.value)} />\n </div>\n <div className=\"space-y-2\">\n <Label>Department</Label>\n <Input value={department} onChange={(e) => setDepartment(e.target.value)} />\n </div>\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => onOpenChange(false)} disabled={loading}>\n Cancel\n </Button>\n <Button onClick={handleSubmit} disabled={loading}>\n {loading ? <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" /> : null}\n {loading ? 'Creating…' : 'Create Transaction'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n\n// ─── New Budget dialog ────────────────────────────────────────────────────────\nfunction NewBudgetDialog({\n open,\n onOpenChange,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}) {\n const [name, setName] = useState('');\n const [category, setCategory] = useState('');\n const [department, setDepartment] = useState('');\n const [period, setPeriod] = useState('');\n const [allocated, setAllocated] = useState('');\n const [spent, setSpent] = useState('0');\n const [status, setStatus] = useState<(typeof BUDGET_STATUSES)[number]>('ON_TRACK');\n\n const reset = () => {\n setName('');\n setCategory('');\n setDepartment('');\n setPeriod('');\n setAllocated('');\n setSpent('0');\n setStatus('ON_TRACK');\n };\n\n const [createBudget, { loading }] = useMutation<CreateBudgetResult>(CREATE_BUDGET_MUTATION, {\n refetchQueries: ['AssetHandlerBootstrap'],\n onCompleted: (data) => {\n notify.success('Budget created', `${data.createBudget.name} is now being tracked.`);\n reset();\n onOpenChange(false);\n },\n onError: (error) => notify.error('Could not create budget', error.message),\n });\n\n const handleSubmit = () => {\n const parsedAllocated = Number(allocated);\n const parsedSpent = Number(spent);\n if (!name.trim() || !category.trim() || !department.trim() || !period.trim()) {\n notify.warning('Missing details', 'Name, category, department and period are required.');\n return;\n }\n if (!Number.isFinite(parsedAllocated) || allocated.trim() === '') {\n notify.warning('Invalid allocation', 'Enter a numeric allocated amount.');\n return;\n }\n void createBudget({\n variables: {\n input: {\n allocated: parsedAllocated,\n category: category.trim(),\n department: department.trim(),\n name: name.trim(),\n period: period.trim(),\n spent: Number.isFinite(parsedSpent) ? parsedSpent : 0,\n status,\n },\n },\n });\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>New Budget</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Set an allocation to track departmental asset spend.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Label>Name *</Label>\n <Input\n placeholder=\"e.g., IT Hardware Q1\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n />\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Category *</Label>\n <Input value={category} onChange={(e) => setCategory(e.target.value)} />\n </div>\n <div className=\"space-y-2\">\n <Label>Department *</Label>\n <Input value={department} onChange={(e) => setDepartment(e.target.value)} />\n </div>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Period *</Label>\n <Input\n placeholder=\"e.g., Q1 2026\"\n value={period}\n onChange={(e) => setPeriod(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Status</Label>\n <Select value={status} onValueChange={(v) => setStatus(v as typeof status)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {BUDGET_STATUSES.map((s) => (\n <SelectItem key={s} value={s}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Allocated *</Label>\n <Input\n type=\"number\"\n placeholder=\"e.g., 50000\"\n value={allocated}\n onChange={(e) => setAllocated(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Spent</Label>\n <Input type=\"number\" value={spent} onChange={(e) => setSpent(e.target.value)} />\n </div>\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => onOpenChange(false)} disabled={loading}>\n Cancel\n </Button>\n <Button onClick={handleSubmit} disabled={loading}>\n {loading ? <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" /> : null}\n {loading ? 'Creating…' : 'Create Budget'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n\n// ─── New Invoice dialog ───────────────────────────────────────────────────────\nfunction NewInvoiceDialog({\n open,\n onOpenChange,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}) {\n const [number, setNumber] = useState('');\n const [vendor, setVendor] = useState('');\n const [amount, setAmount] = useState('');\n const { currency: moduleCurrency } = useAssetMoney();\n const [currency, setCurrency] = useState(moduleCurrency);\n const [issueDate, setIssueDate] = useState('');\n const [dueDate, setDueDate] = useState('');\n const [relatedPO, setRelatedPO] = useState('');\n const [status, setStatus] = useState<(typeof INVOICE_STATUSES)[number]>('DRAFT');\n\n const reset = () => {\n setNumber('');\n setVendor('');\n setAmount('');\n setCurrency(moduleCurrency);\n setIssueDate('');\n setDueDate('');\n setRelatedPO('');\n setStatus('DRAFT');\n };\n\n const [createInvoice, { loading }] = useMutation<CreateInvoiceResult>(CREATE_INVOICE_MUTATION, {\n refetchQueries: ['AssetHandlerBootstrap'],\n onCompleted: (data) => {\n notify.success('Invoice created', `Invoice ${data.createInvoice.number} was added.`);\n reset();\n onOpenChange(false);\n },\n onError: (error) => notify.error('Could not create invoice', error.message),\n });\n\n const handleSubmit = () => {\n const parsedAmount = Number(amount);\n if (!number.trim() || !vendor.trim()) {\n notify.warning('Missing details', 'Invoice number and vendor are required.');\n return;\n }\n if (!Number.isFinite(parsedAmount) || amount.trim() === '') {\n notify.warning('Invalid amount', 'Enter a numeric invoice amount.');\n return;\n }\n if (!issueDate || !dueDate) {\n notify.warning('Missing dates', 'Issue date and due date are required.');\n return;\n }\n void createInvoice({\n variables: {\n input: {\n amount: parsedAmount,\n currency: currency.trim() || moduleCurrency,\n dueDate: new Date(dueDate).toISOString(),\n issueDate: new Date(issueDate).toISOString(),\n number: number.trim(),\n relatedPO: relatedPO.trim() || null,\n status,\n vendor: vendor.trim(),\n },\n },\n });\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>New Invoice</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Log a vendor invoice for an asset purchase or service.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-4\">\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Invoice Number *</Label>\n <Input\n placeholder=\"e.g., INV-2026-001\"\n value={number}\n onChange={(e) => setNumber(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Vendor *</Label>\n <Input value={vendor} onChange={(e) => setVendor(e.target.value)} />\n </div>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Amount *</Label>\n <Input\n type=\"number\"\n placeholder=\"e.g., 12000\"\n value={amount}\n onChange={(e) => setAmount(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Currency</Label>\n <Input value={currency} onChange={(e) => setCurrency(e.target.value)} />\n </div>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Issue Date *</Label>\n <Input type=\"date\" value={issueDate} onChange={(e) => setIssueDate(e.target.value)} />\n </div>\n <div className=\"space-y-2\">\n <Label>Due Date *</Label>\n <Input type=\"date\" value={dueDate} onChange={(e) => setDueDate(e.target.value)} />\n </div>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Related PO</Label>\n <Input value={relatedPO} onChange={(e) => setRelatedPO(e.target.value)} />\n </div>\n <div className=\"space-y-2\">\n <Label>Status</Label>\n <Select value={status} onValueChange={(v) => setStatus(v as typeof status)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {INVOICE_STATUSES.map((s) => (\n <SelectItem key={s} value={s}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => onOpenChange(false)} disabled={loading}>\n Cancel\n </Button>\n <Button onClick={handleSubmit} disabled={loading}>\n {loading ? <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" /> : null}\n {loading ? 'Creating…' : 'Create Invoice'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n\n// ─── Transaction row action buttons (approve / reject pending) ────────────────\nfunction TransactionActions({\n txn,\n actingId,\n onApprove,\n onReject,\n}: {\n txn: FinanceTransaction;\n actingId: string | null;\n onApprove: (id: string) => void;\n onReject: (id: string) => void;\n}) {\n if (txn.status !== 'pending') return null;\n const busy = actingId === txn.id;\n return (\n <div className=\"flex items-center gap-1.5\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7 gap-1 border-status-success-subtle px-2 text-status-success-text\"\n disabled={busy}\n onClick={(e) => {\n e.stopPropagation();\n onApprove(txn.id);\n }}\n >\n {busy ? (\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />\n ) : (\n <Check className=\"h-3.5 w-3.5\" />\n )}\n Approve\n </Button>\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7 gap-1 border-status-error-subtle px-2 text-status-error-text\"\n disabled={busy}\n onClick={(e) => {\n e.stopPropagation();\n onReject(txn.id);\n }}\n >\n <X className=\"h-3.5 w-3.5\" />\n Reject\n </Button>\n </div>\n );\n}\n\nexport function FinanceFinanceHubPage() {\n const { currency: moduleCurrency, compact: compactUsd } = useAssetMoney();\n // A record's own currency wins; the module currency is the fallback for rows\n // that never carried one.\n const fmtMoney = (value: number, currency?: string | null): string => {\n try {\n return new Intl.NumberFormat(undefined, {\n style: 'currency',\n currency: currency || moduleCurrency,\n maximumFractionDigits: 2,\n }).format(value);\n } catch {\n // An unknown/invalid ISO code: show the code rather than a wrong symbol.\n return `${currency || moduleCurrency} ${value.toLocaleString()}`;\n }\n };\n\n const navigate = useAssetHandlerNavigate();\n const { transactions, budgets, invoices } = useAssetHandlerStore();\n\n const [txnDialogOpen, setTxnDialogOpen] = useState(false);\n const [budgetDialogOpen, setBudgetDialogOpen] = useState(false);\n const [invoiceDialogOpen, setInvoiceDialogOpen] = useState(false);\n\n const [activeTab, setActiveTab] = useState<'transactions' | 'budgets' | 'invoices'>(\n 'transactions'\n );\n\n const [txnStatusFilter, setTxnStatusFilter] = useState<string>('all');\n const [txnTypeFilter, setTxnTypeFilter] = useState<string>('all');\n const [txnSearch, setTxnSearch] = useState('');\n const [invStatusFilter, setInvStatusFilter] = useState<string>('all');\n const [invSearch, setInvSearch] = useState('');\n\n const [actingId, setActingId] = useState<string | null>(null);\n\n // ─── Headline finance figures (money-forward, real store data) ───\n const totalSpend = transactions.filter((t) => t.amount > 0).reduce((s, t) => s + t.amount, 0);\n const pendingTxns = transactions.filter((t) => t.status === 'pending');\n const overBudget = budgets.filter((b) => b.status === 'over_budget');\n const overdueInvoices = invoices.filter((i) => i.status === 'overdue');\n const budgetAllocated = budgets.reduce((s, b) => s + b.allocated, 0);\n const budgetSpent = budgets.reduce((s, b) => s + b.spent, 0);\n const invoicesOutstanding = invoices\n .filter((i) => i.status !== 'paid' && i.status !== 'cancelled')\n .reduce((s, i) => s + i.amount, 0);\n const outstandingCount = invoices.filter(\n (i) => i.status !== 'paid' && i.status !== 'cancelled'\n ).length;\n\n // ─── Chart aggregations (real data only) ───\n const budgetByDept = useMemo(() => {\n const map = new Map<string, { allocated: number; spent: number }>();\n for (const b of budgets) {\n const key = b.department || 'Unassigned';\n const cur = map.get(key) ?? { allocated: 0, spent: 0 };\n cur.allocated += b.allocated;\n cur.spent += b.spent;\n map.set(key, cur);\n }\n return Array.from(map, ([department, v]) => ({ department, ...v })).sort(\n (a, b) => b.allocated - a.allocated\n );\n }, [budgets]);\n\n const spendByCategory = useMemo<DonutSlice[]>(() => {\n const map = new Map<string, number>();\n for (const t of transactions) {\n if (t.amount > 0) map.set(t.category, (map.get(t.category) ?? 0) + t.amount);\n }\n return Array.from(map, ([name, value]) => ({ name: humanize(name), value })).sort(\n (a, b) => b.value - a.value\n );\n }, [transactions]);\n\n const hasCharts = budgetByDept.length > 0 || spendByCategory.length > 0;\n\n // ─── Filtered lists ───\n const filteredTxns = useMemo(() => {\n const q = txnSearch.trim().toLowerCase();\n return transactions.filter((t) => {\n if (txnStatusFilter !== 'all' && t.status !== txnStatusFilter) return false;\n if (txnTypeFilter !== 'all' && t.type !== txnTypeFilter) return false;\n if (\n q &&\n !`${t.description} ${t.department} ${t.vendor ?? ''} ${t.id}`.toLowerCase().includes(q)\n )\n return false;\n return true;\n });\n }, [transactions, txnStatusFilter, txnTypeFilter, txnSearch]);\n\n const filteredInvoices = useMemo(() => {\n const q = invSearch.trim().toLowerCase();\n return invoices.filter((i) => {\n if (invStatusFilter !== 'all' && i.status !== invStatusFilter) return false;\n if (q && !`${i.number} ${i.vendor}`.toLowerCase().includes(q)) return false;\n return true;\n });\n }, [invoices, invStatusFilter, invSearch]);\n\n const txnPage = usePagination(filteredTxns, {\n pageSize: 10,\n resetKey: `${txnStatusFilter}|${txnTypeFilter}|${txnSearch}`,\n });\n const invPage = usePagination(filteredInvoices, {\n pageSize: 10,\n resetKey: `${invStatusFilter}|${invSearch}`,\n });\n\n // ─── Approve / reject ───\n const [approveTransaction] = useMutation<ApproveTransactionResult>(APPROVE_TRANSACTION_MUTATION, {\n refetchQueries: ['AssetHandlerBootstrap'],\n onCompleted: () => {\n notify.success('Transaction approved', 'The transaction has been approved.');\n setActingId(null);\n },\n onError: (error) => {\n notify.error('Could not approve transaction', error.message);\n setActingId(null);\n },\n });\n const [rejectTransaction] = useMutation<RejectTransactionResult>(REJECT_TRANSACTION_MUTATION, {\n refetchQueries: ['AssetHandlerBootstrap'],\n onCompleted: () => {\n notify.success('Transaction rejected', 'The transaction has been rejected.');\n setActingId(null);\n },\n onError: (error) => {\n notify.error('Could not reject transaction', error.message);\n setActingId(null);\n },\n });\n\n const handleApprove = (id: string) => {\n setActingId(id);\n void approveTransaction({ variables: { id } });\n };\n const handleReject = (id: string) => {\n setActingId(id);\n void rejectTransaction({ variables: { id, reason: null } });\n };\n\n // ─── Export the active tab ───\n const handleExport = () => {\n const stamp = new Date().toISOString().slice(0, 10);\n if (activeTab === 'budgets') {\n if (budgets.length === 0) {\n notify.warning('Nothing to export', 'There are no budgets to export yet.');\n return;\n }\n downloadCsv(\n `budgets-${stamp}`,\n ['Name', 'Department', 'Category', 'Period', 'Allocated', 'Spent', 'Remaining', 'Status'],\n budgets.map((b) => [\n b.name,\n b.department,\n b.category,\n b.period,\n b.allocated,\n b.spent,\n b.remaining,\n b.status,\n ])\n );\n return;\n }\n if (activeTab === 'invoices') {\n if (invoices.length === 0) {\n notify.warning('Nothing to export', 'There are no invoices to export yet.');\n return;\n }\n downloadCsv(\n `invoices-${stamp}`,\n ['Invoice #', 'Vendor', 'Amount', 'Currency', 'Issue Date', 'Due Date', 'Status'],\n invoices.map((i) => [\n i.number,\n i.vendor,\n i.amount,\n i.currency,\n i.issueDate,\n i.dueDate,\n i.status,\n ])\n );\n return;\n }\n if (transactions.length === 0) {\n notify.warning('Nothing to export', 'There are no transactions to export yet.');\n return;\n }\n downloadCsv(\n `transactions-${stamp}`,\n ['ID', 'Type', 'Description', 'Department', 'Amount', 'Currency', 'Status', 'Date'],\n transactions.map((t) => [\n t.id,\n t.type,\n t.description,\n t.department,\n t.amount,\n t.currency,\n t.status,\n t.date,\n ])\n );\n };\n\n return (\n <div className=\"space-y-6 p-4 sm:p-6\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between\">\n <div>\n <h1 className=\"text-2xl font-bold sm:text-3xl\">\n <GradientText>Finance Hub</GradientText>\n </h1>\n <p className=\"mt-1 text-sm text-text-secondary\">Financial management for IT assets</p>\n </div>\n <CTAOverflowMenu\n primary={{ label: 'New Transaction', onSelect: () => setTxnDialogOpen(true) }}\n actions={[\n { label: 'New Budget', onSelect: () => setBudgetDialogOpen(true) },\n { label: 'New Invoice', onSelect: () => setInvoiceDialogOpen(true) },\n { label: 'Export', onSelect: handleExport, icon: <Download className=\"h-4 w-4\" /> },\n ]}\n />\n </div>\n\n <NewTransactionDialog open={txnDialogOpen} onOpenChange={setTxnDialogOpen} />\n <NewBudgetDialog open={budgetDialogOpen} onOpenChange={setBudgetDialogOpen} />\n <NewInvoiceDialog open={invoiceDialogOpen} onOpenChange={setInvoiceDialogOpen} />\n\n <PagePurpose>\n The money side of your asset estate: track spend, keep departmental budgets on course, and\n stay on top of vendor invoices. Use this hub to spot over-budget areas and overdue invoices\n early — so asset costs stay predictable and nothing slips past its due date.\n </PagePurpose>\n\n <NextSteps\n storageKey=\"assethandler-finance-hub\"\n steps={[\n {\n id: 'transactions',\n label: 'Review recent transactions',\n description: 'Check spend and approve anything still pending.',\n onClick: () => navigate('/transactions/transaction-list'),\n },\n {\n id: 'budgets',\n label: 'Review reporting dashboard',\n description: 'See budget health and spend trends across departments.',\n onClick: () => navigate('/reports/reports-dashboard'),\n },\n {\n id: 'reports',\n label: 'Build a finance report',\n description: 'Turn spend and budget data into a shareable report.',\n onClick: () => navigate('/reports/reports-dashboard'),\n },\n ]}\n />\n\n {/* ─── Money-forward KPI row ─── */}\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n <StatTile\n label=\"Total Spend\"\n value={totalSpend}\n format={(v) => fmtMoney(v)}\n icon={DollarSign}\n hero\n delta={`${pendingTxns.length} pending`}\n deltaTone=\"neutral\"\n />\n <StatTile\n label=\"Budget Allocated\"\n value={budgetAllocated}\n format={(v) => fmtMoney(v)}\n icon={Wallet}\n />\n <StatTile\n label=\"Budget Spent\"\n value={budgetSpent}\n format={(v) => fmtMoney(v)}\n icon={TrendingDown}\n delta={overBudget.length > 0 ? `${overBudget.length} over` : undefined}\n deltaTone=\"negative\"\n deltaDirection={overBudget.length > 0 ? 'up' : 'neutral'}\n />\n <StatTile\n label=\"Invoices Outstanding\"\n value={invoicesOutstanding}\n format={(v) => fmtMoney(v)}\n icon={Receipt}\n delta={\n overdueInvoices.length > 0\n ? `${overdueInvoices.length} overdue`\n : outstandingCount > 0\n ? `${outstandingCount} open`\n : undefined\n }\n deltaTone={overdueInvoices.length > 0 ? 'negative' : 'neutral'}\n deltaDirection=\"neutral\"\n />\n </div>\n\n {/* ─── Insights charts ─── */}\n {hasCharts ? (\n <div className=\"grid gap-4 lg:grid-cols-2\">\n {budgetByDept.length > 0 ? (\n <ChartCard\n title=\"Budget vs spend\"\n subtitle=\"Allocated against actual spend by department\"\n icon={BarChart3}\n >\n <BarsChart\n data={budgetByDept}\n xKey=\"department\"\n series={[\n { key: 'allocated', label: 'Allocated' },\n { key: 'spent', label: 'Spent' },\n ]}\n height={260}\n valueFormat={compactUsd}\n ariaLabel=\"Budget allocated versus spent by department\"\n />\n </ChartCard>\n ) : null}\n {spendByCategory.length > 0 ? (\n <ChartCard\n title=\"Spend by category\"\n subtitle=\"Recorded transaction spend, grouped by category\"\n icon={PieChartIcon}\n >\n <DonutChart\n data={spendByCategory}\n centerLabel=\"Total spend\"\n centerValue={totalSpend}\n valueFormat={(v) => fmtMoney(v)}\n height={260}\n ariaLabel=\"Transaction spend by category\"\n />\n </ChartCard>\n ) : null}\n </div>\n ) : null}\n\n <Tabs\n value={activeTab}\n onValueChange={(v) => setActiveTab(v as typeof activeTab)}\n className=\"space-y-4\"\n >\n <TabsList>\n <TabsTrigger value=\"transactions\">Transactions</TabsTrigger>\n <TabsTrigger value=\"budgets\">Budgets</TabsTrigger>\n <TabsTrigger value=\"invoices\">Invoices</TabsTrigger>\n </TabsList>\n\n {/* ─── Transactions ─── */}\n <TabsContent value=\"transactions\" className=\"space-y-4\">\n {transactions.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No transactions yet\"\n description=\"Asset-related spend and reimbursements will appear here as they are recorded.\"\n />\n ) : (\n <>\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center\">\n <div className=\"relative flex-1\">\n <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-muted\" />\n <Input\n value={txnSearch}\n onChange={(e) => setTxnSearch(e.target.value)}\n placeholder=\"Search description, vendor or department\"\n className=\"pl-9\"\n />\n </div>\n <Select value={txnStatusFilter} onValueChange={setTxnStatusFilter}>\n <SelectTrigger className=\"w-full sm:w-40\">\n <SelectValue placeholder=\"Status\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">All statuses</SelectItem>\n {TRANSACTION_STATUSES.map((s) => (\n <SelectItem key={s} value={s.toLowerCase()}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Select value={txnTypeFilter} onValueChange={setTxnTypeFilter}>\n <SelectTrigger className=\"w-full sm:w-40\">\n <SelectValue placeholder=\"Type\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">All types</SelectItem>\n {TRANSACTION_TYPES.map((t) => (\n <SelectItem key={t} value={t.toLowerCase()}>\n {humanize(t)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {filteredTxns.length === 0 ? (\n <GlassCard treatment=\"glass\" className=\"border-border-seam\">\n <p className=\"p-8 text-center text-sm text-text-secondary\">\n No transactions match your filters.\n </p>\n </GlassCard>\n ) : (\n <GlassCard treatment=\"glass\" className=\"overflow-hidden border-border-seam\">\n {/* Desktop table */}\n <div className=\"hidden overflow-x-auto md:block\">\n <table className=\"w-full min-w-[820px] text-sm\">\n <thead>\n <tr className=\"border-b border-border-seam bg-bg-sunken/40 text-left\">\n <th className=\"p-3 font-medium\">Type</th>\n <th className=\"p-3 font-medium\">Description</th>\n <th className=\"p-3 font-medium\">Department</th>\n <th className=\"p-3 text-right font-medium\">Amount</th>\n <th className=\"p-3 font-medium\">Status</th>\n <th className=\"p-3 font-medium\">Date</th>\n <th className=\"p-3 text-right font-medium\">Actions</th>\n </tr>\n </thead>\n <tbody>\n {txnPage.pageItems.map((txn) => (\n <tr\n key={txn.id}\n className=\"cursor-pointer border-b border-border-seam/60 last:border-0 hover:bg-bg-sunken/40\"\n onClick={() => navigate('/transactions/' + txn.id)}\n >\n <td className=\"p-3\">\n <StatusPill tone={txnTypeTone(txn.type)}>{txn.type}</StatusPill>\n </td>\n <td className=\"max-w-xs truncate p-3\" title={txn.description}>\n {txn.description}\n </td>\n <td className=\"p-3 text-xs text-text-secondary\">{txn.department}</td>\n <td\n className={cn(\n 'p-3 text-right font-medium tabular-nums',\n txn.amount < 0 && 'text-status-error-text'\n )}\n >\n {fmtMoney(Math.abs(txn.amount), txn.currency)}\n </td>\n <td className=\"p-3\">\n <StatusPill tone={txnStatusTone(txn.status)}>{txn.status}</StatusPill>\n </td>\n <td className=\"p-3 text-xs text-text-secondary\">\n {formatDate(txn.date)}\n </td>\n <td className=\"p-3\">\n <div className=\"flex justify-end\">\n <TransactionActions\n txn={txn}\n actingId={actingId}\n onApprove={handleApprove}\n onReject={handleReject}\n />\n </div>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n\n {/* Mobile cards */}\n <div className=\"divide-y divide-border-seam/60 md:hidden\">\n {txnPage.pageItems.map((txn) => (\n <button\n key={txn.id}\n type=\"button\"\n className=\"block w-full p-4 text-left hover:bg-bg-sunken/40\"\n onClick={() => navigate('/transactions/' + txn.id)}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <p className=\"min-w-0 flex-1 truncate font-medium\">{txn.description}</p>\n <span\n className={cn(\n 'shrink-0 font-semibold tabular-nums',\n txn.amount < 0 && 'text-status-error-text'\n )}\n >\n {fmtMoney(Math.abs(txn.amount), txn.currency)}\n </span>\n </div>\n <div className=\"mt-2 flex flex-wrap items-center gap-2\">\n <StatusPill tone={txnTypeTone(txn.type)}>{txn.type}</StatusPill>\n <StatusPill tone={txnStatusTone(txn.status)}>{txn.status}</StatusPill>\n <span className=\"text-xs text-text-secondary\">\n {txn.department} · {formatDate(txn.date)}\n </span>\n </div>\n {txn.status === 'pending' ? (\n <div className=\"mt-3\">\n <TransactionActions\n txn={txn}\n actingId={actingId}\n onApprove={handleApprove}\n onReject={handleReject}\n />\n </div>\n ) : null}\n </button>\n ))}\n </div>\n\n <div className=\"px-3\">\n <Pagination\n page={txnPage.page}\n pageCount={txnPage.pageCount}\n rangeStart={txnPage.rangeStart}\n rangeEnd={txnPage.rangeEnd}\n totalItems={txnPage.totalItems}\n canPrev={txnPage.canPrev}\n canNext={txnPage.canNext}\n onPrev={txnPage.prevPage}\n onNext={txnPage.nextPage}\n itemLabel=\"transactions\"\n />\n </div>\n </GlassCard>\n )}\n </>\n )}\n </TabsContent>\n\n {/* ─── Budgets ─── */}\n <TabsContent value=\"budgets\" className=\"space-y-4\">\n {budgets.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-generic\"\n title=\"No budgets defined\"\n description=\"Create departmental budgets to track allocated vs. actual asset spend.\"\n />\n ) : (\n <div className=\"grid gap-4 md:grid-cols-2\">\n {budgets.map((budget: Budget) => (\n <GlassCard\n key={budget.id}\n treatment=\"glass\"\n className=\"cursor-pointer border-border-seam\"\n >\n <div\n className=\"p-5\"\n role=\"button\"\n tabIndex={0}\n onClick={() => navigate('/finance/budgets/' + budget.id)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ')\n navigate('/finance/budgets/' + budget.id);\n }}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <h3 className=\"truncate font-semibold text-text-primary\">{budget.name}</h3>\n <p className=\"mt-0.5 text-xs text-text-secondary\">\n {budget.department} · {budget.period}\n </p>\n </div>\n <StatusPill tone={budgetStatusTone(budget.status)}>\n {budget.status.replace(/_/g, ' ')}\n </StatusPill>\n </div>\n <div className=\"mt-4 space-y-3\">\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-secondary\">Allocated</span>\n <span className=\"font-medium tabular-nums\">\n {fmtMoney(budget.allocated)}\n </span>\n </div>\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-secondary\">Remaining</span>\n <span\n className={cn(\n 'font-medium tabular-nums',\n budget.remaining < 0\n ? 'text-status-error-text'\n : 'text-status-success-text'\n )}\n >\n {fmtMoney(budget.remaining)}\n </span>\n </div>\n <ProgressMeter\n value={budget.spent}\n max={budget.allocated}\n label=\"Spent\"\n format={(v) => fmtMoney(v)}\n thresholds={{ warning: 0.8, danger: 1 }}\n />\n </div>\n </div>\n </GlassCard>\n ))}\n </div>\n )}\n </TabsContent>\n\n {/* ─── Invoices ─── */}\n <TabsContent value=\"invoices\" className=\"space-y-4\">\n {invoices.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-files\"\n title=\"No invoices\"\n description=\"Vendor invoices for asset purchases and services will be listed here.\"\n />\n ) : (\n <>\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center\">\n <div className=\"relative flex-1\">\n <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-muted\" />\n <Input\n value={invSearch}\n onChange={(e) => setInvSearch(e.target.value)}\n placeholder=\"Search invoice number or vendor\"\n className=\"pl-9\"\n />\n </div>\n <Select value={invStatusFilter} onValueChange={setInvStatusFilter}>\n <SelectTrigger className=\"w-full sm:w-40\">\n <SelectValue placeholder=\"Status\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">All statuses</SelectItem>\n {INVOICE_STATUSES.map((s) => (\n <SelectItem key={s} value={s.toLowerCase()}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {filteredInvoices.length === 0 ? (\n <GlassCard treatment=\"glass\" className=\"border-border-seam\">\n <p className=\"p-8 text-center text-sm text-text-secondary\">\n No invoices match your filters.\n </p>\n </GlassCard>\n ) : (\n <GlassCard treatment=\"glass\" className=\"overflow-hidden border-border-seam\">\n {/* Desktop table */}\n <div className=\"hidden overflow-x-auto md:block\">\n <table className=\"w-full min-w-[720px] text-sm\">\n <thead>\n <tr className=\"border-b border-border-seam bg-bg-sunken/40 text-left\">\n <th className=\"p-3 font-medium\">Invoice #</th>\n <th className=\"p-3 font-medium\">Vendor</th>\n <th className=\"p-3 text-right font-medium\">Amount</th>\n <th className=\"p-3 font-medium\">Issue Date</th>\n <th className=\"p-3 font-medium\">Due Date</th>\n <th className=\"p-3 font-medium\">Status</th>\n </tr>\n </thead>\n <tbody>\n {invPage.pageItems.map((inv: Invoice) => (\n <tr\n key={inv.id}\n className=\"cursor-pointer border-b border-border-seam/60 last:border-0 hover:bg-bg-sunken/40\"\n onClick={() => navigate('/finance/invoices/' + inv.id)}\n >\n <td className=\"p-3 font-mono text-xs\">{inv.number}</td>\n <td className=\"p-3\">{inv.vendor}</td>\n <td className=\"p-3 text-right font-medium tabular-nums\">\n {fmtMoney(inv.amount, inv.currency)}\n </td>\n <td className=\"p-3 text-xs text-text-secondary\">\n {formatDate(inv.issueDate)}\n </td>\n <td className=\"p-3 text-xs text-text-secondary\">\n {formatDate(inv.dueDate)}\n </td>\n <td className=\"p-3\">\n <StatusPill tone={invoiceStatusTone(inv.status)}>\n {inv.status}\n </StatusPill>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n\n {/* Mobile cards */}\n <div className=\"divide-y divide-border-seam/60 md:hidden\">\n {invPage.pageItems.map((inv: Invoice) => (\n <button\n key={inv.id}\n type=\"button\"\n className=\"block w-full p-4 text-left hover:bg-bg-sunken/40\"\n onClick={() => navigate('/finance/invoices/' + inv.id)}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <p className=\"truncate font-mono text-xs text-text-secondary\">\n {inv.number}\n </p>\n <p className=\"truncate font-medium\">{inv.vendor}</p>\n </div>\n <span className=\"shrink-0 font-semibold tabular-nums\">\n {fmtMoney(inv.amount, inv.currency)}\n </span>\n </div>\n <div className=\"mt-2 flex flex-wrap items-center gap-2\">\n <StatusPill tone={invoiceStatusTone(inv.status)}>{inv.status}</StatusPill>\n <span className=\"text-xs text-text-secondary\">\n Due {formatDate(inv.dueDate)}\n </span>\n </div>\n </button>\n ))}\n </div>\n\n <div className=\"px-3\">\n <Pagination\n page={invPage.page}\n pageCount={invPage.pageCount}\n rangeStart={invPage.rangeStart}\n rangeEnd={invPage.rangeEnd}\n totalItems={invPage.totalItems}\n canPrev={invPage.canPrev}\n canNext={invPage.canNext}\n onPrev={invPage.prevPage}\n onNext={invPage.nextPage}\n itemLabel=\"invoices\"\n />\n </div>\n </GlassCard>\n )}\n </>\n )}\n </TabsContent>\n </Tabs>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"FinanceFinanceHubPage.js","names":[],"sources":["../../../src/assethandler/pages/FinanceFinanceHubPage.tsx"],"sourcesContent":["import { useMemo, useState, type ReactNode } from 'react';\nimport { useAssetMoney } from '../providers/AssetHandlerProvider';\nimport { useAssetHandlerNavigate } from '../hooks/useAssetHandlerNavigate';\nimport {\n Button,\n GlassCard,\n Input,\n Label,\n Textarea,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n GradientText,\n CTAOverflowMenu,\n PagePurpose,\n NextSteps,\n IllustratedEmptyState,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport {\n DollarSign,\n TrendingDown,\n Receipt,\n Wallet,\n Download,\n Loader2,\n Check,\n X,\n Search,\n BarChart3,\n PieChart as PieChartIcon,\n} from 'lucide-react';\nimport { gql } from '@apollo/client';\nimport { useMutation } from '@apollo/client/react';\nimport { useAssetHandlerStore } from '../store/assethandlerStore';\nimport type { Budget, FinanceTransaction, Invoice } from '../store/assethandlerStore';\nimport { notify } from '../utils/toast';\nimport { cn } from '../utils/cn';\nimport { downloadCsv } from '../utils/csv';\nimport {\n StatTile,\n ChartCard,\n BarsChart,\n DonutChart,\n ProgressMeter,\n Pagination,\n usePagination,\n type DonutSlice,\n} from '../components';\n\n// ─── Mutations ────────────────────────────────────────────────────────────────\nconst CREATE_TRANSACTION_MUTATION = gql`\n mutation AssetHandlerCreateTransaction($input: CreateTransactionInput!) {\n createTransaction(input: $input) {\n id\n description\n }\n }\n`;\n\nconst CREATE_BUDGET_MUTATION = gql`\n mutation AssetHandlerCreateBudget($input: AssetHandlerCreateBudgetInput!) {\n createBudget(input: $input) {\n id\n name\n }\n }\n`;\n\nconst CREATE_INVOICE_MUTATION = gql`\n mutation AssetHandlerCreateInvoice($input: AssetHandlerCreateInvoiceInput!) {\n createInvoice(input: $input) {\n id\n number\n }\n }\n`;\n\nconst APPROVE_TRANSACTION_MUTATION = gql`\n mutation AssetHandlerHubApproveTransaction($id: ID!) {\n approveTransaction(id: $id) {\n id\n status\n }\n }\n`;\n\nconst REJECT_TRANSACTION_MUTATION = gql`\n mutation AssetHandlerHubRejectTransaction($id: ID!, $reason: String) {\n rejectTransaction(id: $id, reason: $reason) {\n id\n status\n }\n }\n`;\n\ninterface CreateTransactionResult {\n createTransaction: { id: string; description: string };\n}\ninterface CreateBudgetResult {\n createBudget: { id: string; name: string };\n}\ninterface CreateInvoiceResult {\n createInvoice: { id: string; number: string };\n}\ninterface ApproveTransactionResult {\n approveTransaction: { id: string; status: string };\n}\ninterface RejectTransactionResult {\n rejectTransaction: { id: string; status: string };\n}\n\nconst TRANSACTION_TYPES = ['PURCHASE', 'LEASE', 'DISPOSAL', 'TRANSFER', 'MAINTENANCE'] as const;\nconst TRANSACTION_STATUSES = ['PENDING', 'APPROVED', 'COMPLETED', 'REJECTED'] as const;\nconst BUDGET_STATUSES = ['ON_TRACK', 'OVER_BUDGET', 'UNDER_BUDGET'] as const;\nconst INVOICE_STATUSES = ['DRAFT', 'SENT', 'PAID', 'OVERDUE', 'CANCELLED'] as const;\n\nconst humanize = (value: string) =>\n value\n .toLowerCase()\n .replace(/_/g, ' ')\n .replace(/^\\w/, (c) => c.toUpperCase());\n\n// ─── Presentation helpers ───────────────────────────────────────────────────\ntype Tone = 'success' | 'warning' | 'error' | 'info' | 'neutral';\n\nconst PILL_TONE: Record<Tone, string> = {\n success: 'bg-status-success-subtle text-status-success-text',\n warning: 'bg-status-warning-subtle text-status-warning-text',\n error: 'bg-status-error-subtle text-status-error-text',\n info: 'bg-status-info-subtle text-status-info-text',\n neutral: 'bg-bg-sunken text-text-secondary',\n};\n\nfunction StatusPill({ tone, children }: { tone: Tone; children: ReactNode }) {\n return (\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium capitalize',\n PILL_TONE[tone]\n )}\n >\n {children}\n </span>\n );\n}\n\nconst txnStatusTone = (status: string): Tone =>\n status === 'approved' || status === 'completed'\n ? 'success'\n : status === 'rejected'\n ? 'error'\n : status === 'pending'\n ? 'warning'\n : 'neutral';\n\nconst txnTypeTone = (type: string): Tone =>\n type === 'purchase' || type === 'lease'\n ? 'info'\n : type === 'disposal'\n ? 'error'\n : type === 'maintenance'\n ? 'warning'\n : 'neutral';\n\nconst budgetStatusTone = (status: string): Tone =>\n status === 'over_budget' ? 'error' : status === 'under_budget' ? 'success' : 'info';\n\nconst invoiceStatusTone = (status: string): Tone =>\n status === 'paid'\n ? 'success'\n : status === 'overdue'\n ? 'error'\n : status === 'sent'\n ? 'warning'\n : 'neutral';\n\nconst formatDate = (value: string): string => {\n const parsed = new Date(value);\n return Number.isNaN(parsed.getTime()) ? value : parsed.toLocaleDateString();\n};\n\n// ─── New Transaction dialog ───────────────────────────────────────────────────\nfunction NewTransactionDialog({\n open,\n onOpenChange,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}) {\n const [type, setType] = useState<(typeof TRANSACTION_TYPES)[number]>('PURCHASE');\n const [status, setStatus] = useState<(typeof TRANSACTION_STATUSES)[number]>('PENDING');\n const [amount, setAmount] = useState('');\n const { currency: moduleCurrency } = useAssetMoney();\n const [currency, setCurrency] = useState(moduleCurrency);\n const [category, setCategory] = useState('');\n const [description, setDescription] = useState('');\n const [vendor, setVendor] = useState('');\n const [department, setDepartment] = useState('');\n\n const reset = () => {\n setType('PURCHASE');\n setStatus('PENDING');\n setAmount('');\n setCurrency(moduleCurrency);\n setCategory('');\n setDescription('');\n setVendor('');\n setDepartment('');\n };\n\n const [createTransaction, { loading }] = useMutation<CreateTransactionResult>(\n CREATE_TRANSACTION_MUTATION,\n {\n refetchQueries: ['AssetHandlerBootstrap'],\n onCompleted: (data) => {\n notify.success(\n 'Transaction created',\n `${data.createTransaction.description} was recorded.`\n );\n reset();\n onOpenChange(false);\n },\n onError: (error) => notify.error('Could not create transaction', error.message),\n }\n );\n\n const handleSubmit = () => {\n const parsedAmount = Number(amount);\n if (!Number.isFinite(parsedAmount) || amount.trim() === '') {\n notify.warning('Invalid amount', 'Enter a numeric amount for the transaction.');\n return;\n }\n if (!category.trim() || !description.trim()) {\n notify.warning('Missing details', 'Category and description are required.');\n return;\n }\n void createTransaction({\n variables: {\n input: {\n amount: parsedAmount,\n category: category.trim(),\n currency: currency.trim() || moduleCurrency,\n description: description.trim(),\n type,\n status,\n vendor: vendor.trim() || null,\n department: department.trim() || null,\n },\n },\n });\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>New Transaction</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Record a workspace financial movement for the asset estate.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-4\">\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Type</Label>\n <Select value={type} onValueChange={(v) => setType(v as typeof type)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {TRANSACTION_TYPES.map((t) => (\n <SelectItem key={t} value={t}>\n {humanize(t)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-2\">\n <Label>Status</Label>\n <Select value={status} onValueChange={(v) => setStatus(v as typeof status)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {TRANSACTION_STATUSES.map((s) => (\n <SelectItem key={s} value={s}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Amount *</Label>\n <Input\n type=\"number\"\n placeholder=\"e.g., 1500\"\n value={amount}\n onChange={(e) => setAmount(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Currency</Label>\n <Input value={currency} onChange={(e) => setCurrency(e.target.value)} />\n </div>\n </div>\n <div className=\"space-y-2\">\n <Label>Category *</Label>\n <Input\n placeholder=\"e.g., it_hardware\"\n value={category}\n onChange={(e) => setCategory(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Description *</Label>\n <Textarea\n placeholder=\"What is this transaction for?\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n rows={2}\n />\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Vendor</Label>\n <Input value={vendor} onChange={(e) => setVendor(e.target.value)} />\n </div>\n <div className=\"space-y-2\">\n <Label>Department</Label>\n <Input value={department} onChange={(e) => setDepartment(e.target.value)} />\n </div>\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => onOpenChange(false)} disabled={loading}>\n Cancel\n </Button>\n <Button onClick={handleSubmit} disabled={loading}>\n {loading ? <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" /> : null}\n {loading ? 'Creating…' : 'Create Transaction'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n\n// ─── New Budget dialog ────────────────────────────────────────────────────────\nfunction NewBudgetDialog({\n open,\n onOpenChange,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}) {\n const [name, setName] = useState('');\n const [category, setCategory] = useState('');\n const [department, setDepartment] = useState('');\n const [period, setPeriod] = useState('');\n const [allocated, setAllocated] = useState('');\n const [spent, setSpent] = useState('0');\n const [status, setStatus] = useState<(typeof BUDGET_STATUSES)[number]>('ON_TRACK');\n\n const reset = () => {\n setName('');\n setCategory('');\n setDepartment('');\n setPeriod('');\n setAllocated('');\n setSpent('0');\n setStatus('ON_TRACK');\n };\n\n const [createBudget, { loading }] = useMutation<CreateBudgetResult>(CREATE_BUDGET_MUTATION, {\n refetchQueries: ['AssetHandlerBootstrap'],\n onCompleted: (data) => {\n notify.success('Budget created', `${data.createBudget.name} is now being tracked.`);\n reset();\n onOpenChange(false);\n },\n onError: (error) => notify.error('Could not create budget', error.message),\n });\n\n const handleSubmit = () => {\n const parsedAllocated = Number(allocated);\n const parsedSpent = Number(spent);\n if (!name.trim() || !category.trim() || !department.trim() || !period.trim()) {\n notify.warning('Missing details', 'Name, category, department and period are required.');\n return;\n }\n if (!Number.isFinite(parsedAllocated) || allocated.trim() === '') {\n notify.warning('Invalid allocation', 'Enter a numeric allocated amount.');\n return;\n }\n void createBudget({\n variables: {\n input: {\n allocated: parsedAllocated,\n category: category.trim(),\n department: department.trim(),\n name: name.trim(),\n period: period.trim(),\n spent: Number.isFinite(parsedSpent) ? parsedSpent : 0,\n status,\n },\n },\n });\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>New Budget</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Set an allocation to track departmental asset spend.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Label>Name *</Label>\n <Input\n placeholder=\"e.g., IT Hardware Q1\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n />\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Category *</Label>\n <Input value={category} onChange={(e) => setCategory(e.target.value)} />\n </div>\n <div className=\"space-y-2\">\n <Label>Department *</Label>\n <Input value={department} onChange={(e) => setDepartment(e.target.value)} />\n </div>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Period *</Label>\n <Input\n placeholder=\"e.g., Q1 2026\"\n value={period}\n onChange={(e) => setPeriod(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Status</Label>\n <Select value={status} onValueChange={(v) => setStatus(v as typeof status)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {BUDGET_STATUSES.map((s) => (\n <SelectItem key={s} value={s}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Allocated *</Label>\n <Input\n type=\"number\"\n placeholder=\"e.g., 50000\"\n value={allocated}\n onChange={(e) => setAllocated(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Spent</Label>\n <Input type=\"number\" value={spent} onChange={(e) => setSpent(e.target.value)} />\n </div>\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => onOpenChange(false)} disabled={loading}>\n Cancel\n </Button>\n <Button onClick={handleSubmit} disabled={loading}>\n {loading ? <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" /> : null}\n {loading ? 'Creating…' : 'Create Budget'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n\n// ─── New Invoice dialog ───────────────────────────────────────────────────────\nfunction NewInvoiceDialog({\n open,\n onOpenChange,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}) {\n const [number, setNumber] = useState('');\n const [vendor, setVendor] = useState('');\n const [amount, setAmount] = useState('');\n const { currency: moduleCurrency } = useAssetMoney();\n const [currency, setCurrency] = useState(moduleCurrency);\n const [issueDate, setIssueDate] = useState('');\n const [dueDate, setDueDate] = useState('');\n const [relatedPO, setRelatedPO] = useState('');\n const [status, setStatus] = useState<(typeof INVOICE_STATUSES)[number]>('DRAFT');\n\n const reset = () => {\n setNumber('');\n setVendor('');\n setAmount('');\n setCurrency(moduleCurrency);\n setIssueDate('');\n setDueDate('');\n setRelatedPO('');\n setStatus('DRAFT');\n };\n\n const [createInvoice, { loading }] = useMutation<CreateInvoiceResult>(CREATE_INVOICE_MUTATION, {\n refetchQueries: ['AssetHandlerBootstrap'],\n onCompleted: (data) => {\n notify.success('Invoice created', `Invoice ${data.createInvoice.number} was added.`);\n reset();\n onOpenChange(false);\n },\n onError: (error) => notify.error('Could not create invoice', error.message),\n });\n\n const handleSubmit = () => {\n const parsedAmount = Number(amount);\n if (!number.trim() || !vendor.trim()) {\n notify.warning('Missing details', 'Invoice number and vendor are required.');\n return;\n }\n if (!Number.isFinite(parsedAmount) || amount.trim() === '') {\n notify.warning('Invalid amount', 'Enter a numeric invoice amount.');\n return;\n }\n if (!issueDate || !dueDate) {\n notify.warning('Missing dates', 'Issue date and due date are required.');\n return;\n }\n void createInvoice({\n variables: {\n input: {\n amount: parsedAmount,\n currency: currency.trim() || moduleCurrency,\n dueDate: new Date(dueDate).toISOString(),\n issueDate: new Date(issueDate).toISOString(),\n number: number.trim(),\n relatedPO: relatedPO.trim() || null,\n status,\n vendor: vendor.trim(),\n },\n },\n });\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>New Invoice</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Log a workspace vendor invoice for an asset purchase or service.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-4\">\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Invoice Number *</Label>\n <Input\n placeholder=\"e.g., INV-2026-001\"\n value={number}\n onChange={(e) => setNumber(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Vendor *</Label>\n <Input value={vendor} onChange={(e) => setVendor(e.target.value)} />\n </div>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Amount *</Label>\n <Input\n type=\"number\"\n placeholder=\"e.g., 12000\"\n value={amount}\n onChange={(e) => setAmount(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Currency</Label>\n <Input value={currency} onChange={(e) => setCurrency(e.target.value)} />\n </div>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Issue Date *</Label>\n <Input type=\"date\" value={issueDate} onChange={(e) => setIssueDate(e.target.value)} />\n </div>\n <div className=\"space-y-2\">\n <Label>Due Date *</Label>\n <Input type=\"date\" value={dueDate} onChange={(e) => setDueDate(e.target.value)} />\n </div>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>Related PO</Label>\n <Input value={relatedPO} onChange={(e) => setRelatedPO(e.target.value)} />\n </div>\n <div className=\"space-y-2\">\n <Label>Status</Label>\n <Select value={status} onValueChange={(v) => setStatus(v as typeof status)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {INVOICE_STATUSES.map((s) => (\n <SelectItem key={s} value={s}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => onOpenChange(false)} disabled={loading}>\n Cancel\n </Button>\n <Button onClick={handleSubmit} disabled={loading}>\n {loading ? <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" /> : null}\n {loading ? 'Creating…' : 'Create Invoice'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n\n// ─── Transaction row action buttons (approve / reject pending) ────────────────\nfunction TransactionActions({\n txn,\n actingId,\n onApprove,\n onReject,\n}: {\n txn: FinanceTransaction;\n actingId: string | null;\n onApprove: (id: string) => void;\n onReject: (id: string) => void;\n}) {\n if (txn.status !== 'pending') return null;\n const busy = actingId === txn.id;\n return (\n <div className=\"flex items-center gap-1.5\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7 gap-1 border-status-success-subtle px-2 text-status-success-text\"\n disabled={busy}\n onClick={(e) => {\n e.stopPropagation();\n onApprove(txn.id);\n }}\n >\n {busy ? (\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />\n ) : (\n <Check className=\"h-3.5 w-3.5\" />\n )}\n Approve\n </Button>\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7 gap-1 border-status-error-subtle px-2 text-status-error-text\"\n disabled={busy}\n onClick={(e) => {\n e.stopPropagation();\n onReject(txn.id);\n }}\n >\n <X className=\"h-3.5 w-3.5\" />\n Reject\n </Button>\n </div>\n );\n}\n\nexport function FinanceFinanceHubPage() {\n const { currency: moduleCurrency, compact: compactUsd } = useAssetMoney();\n // A record's own currency wins; the module currency is the fallback for rows\n // that never carried one.\n const fmtMoney = (value: number, currency?: string | null): string => {\n try {\n return new Intl.NumberFormat(undefined, {\n style: 'currency',\n currency: currency || moduleCurrency,\n maximumFractionDigits: 2,\n }).format(value);\n } catch {\n // An unknown/invalid ISO code: show the code rather than a wrong symbol.\n return `${currency || moduleCurrency} ${value.toLocaleString()}`;\n }\n };\n\n const navigate = useAssetHandlerNavigate();\n const { transactions, budgets, invoices } = useAssetHandlerStore();\n\n const [txnDialogOpen, setTxnDialogOpen] = useState(false);\n const [budgetDialogOpen, setBudgetDialogOpen] = useState(false);\n const [invoiceDialogOpen, setInvoiceDialogOpen] = useState(false);\n\n const [activeTab, setActiveTab] = useState<'transactions' | 'budgets' | 'invoices'>(\n 'transactions'\n );\n\n const [txnStatusFilter, setTxnStatusFilter] = useState<string>('all');\n const [txnTypeFilter, setTxnTypeFilter] = useState<string>('all');\n const [txnSearch, setTxnSearch] = useState('');\n const [invStatusFilter, setInvStatusFilter] = useState<string>('all');\n const [invSearch, setInvSearch] = useState('');\n\n const [actingId, setActingId] = useState<string | null>(null);\n\n // ─── Headline finance figures (money-forward, real store data) ───\n const totalSpend = transactions.filter((t) => t.amount > 0).reduce((s, t) => s + t.amount, 0);\n const pendingTxns = transactions.filter((t) => t.status === 'pending');\n const overBudget = budgets.filter((b) => b.status === 'over_budget');\n const overdueInvoices = invoices.filter((i) => i.status === 'overdue');\n const budgetAllocated = budgets.reduce((s, b) => s + b.allocated, 0);\n const budgetSpent = budgets.reduce((s, b) => s + b.spent, 0);\n const invoicesOutstanding = invoices\n .filter((i) => i.status !== 'paid' && i.status !== 'cancelled')\n .reduce((s, i) => s + i.amount, 0);\n const outstandingCount = invoices.filter(\n (i) => i.status !== 'paid' && i.status !== 'cancelled'\n ).length;\n\n // ─── Chart aggregations (real data only) ───\n const budgetByDept = useMemo(() => {\n const map = new Map<string, { allocated: number; spent: number }>();\n for (const b of budgets) {\n const key = b.department || 'Unassigned';\n const cur = map.get(key) ?? { allocated: 0, spent: 0 };\n cur.allocated += b.allocated;\n cur.spent += b.spent;\n map.set(key, cur);\n }\n return Array.from(map, ([department, v]) => ({ department, ...v })).sort(\n (a, b) => b.allocated - a.allocated\n );\n }, [budgets]);\n\n const spendByCategory = useMemo<DonutSlice[]>(() => {\n const map = new Map<string, number>();\n for (const t of transactions) {\n if (t.amount > 0) map.set(t.category, (map.get(t.category) ?? 0) + t.amount);\n }\n return Array.from(map, ([name, value]) => ({ name: humanize(name), value })).sort(\n (a, b) => b.value - a.value\n );\n }, [transactions]);\n\n const hasCharts = budgetByDept.length > 0 || spendByCategory.length > 0;\n\n // ─── Filtered lists ───\n const filteredTxns = useMemo(() => {\n const q = txnSearch.trim().toLowerCase();\n return transactions.filter((t) => {\n if (txnStatusFilter !== 'all' && t.status !== txnStatusFilter) return false;\n if (txnTypeFilter !== 'all' && t.type !== txnTypeFilter) return false;\n if (\n q &&\n !`${t.description} ${t.department} ${t.vendor ?? ''} ${t.id}`.toLowerCase().includes(q)\n )\n return false;\n return true;\n });\n }, [transactions, txnStatusFilter, txnTypeFilter, txnSearch]);\n\n const filteredInvoices = useMemo(() => {\n const q = invSearch.trim().toLowerCase();\n return invoices.filter((i) => {\n if (invStatusFilter !== 'all' && i.status !== invStatusFilter) return false;\n if (q && !`${i.number} ${i.vendor}`.toLowerCase().includes(q)) return false;\n return true;\n });\n }, [invoices, invStatusFilter, invSearch]);\n\n const txnPage = usePagination(filteredTxns, {\n pageSize: 10,\n resetKey: `${txnStatusFilter}|${txnTypeFilter}|${txnSearch}`,\n });\n const invPage = usePagination(filteredInvoices, {\n pageSize: 10,\n resetKey: `${invStatusFilter}|${invSearch}`,\n });\n\n // ─── Approve / reject ───\n const [approveTransaction] = useMutation<ApproveTransactionResult>(APPROVE_TRANSACTION_MUTATION, {\n refetchQueries: ['AssetHandlerBootstrap'],\n onCompleted: () => {\n notify.success('Transaction approved', 'The transaction has been approved.');\n setActingId(null);\n },\n onError: (error) => {\n notify.error('Could not approve transaction', error.message);\n setActingId(null);\n },\n });\n const [rejectTransaction] = useMutation<RejectTransactionResult>(REJECT_TRANSACTION_MUTATION, {\n refetchQueries: ['AssetHandlerBootstrap'],\n onCompleted: () => {\n notify.success('Transaction rejected', 'The transaction has been rejected.');\n setActingId(null);\n },\n onError: (error) => {\n notify.error('Could not reject transaction', error.message);\n setActingId(null);\n },\n });\n\n const handleApprove = (id: string) => {\n setActingId(id);\n void approveTransaction({ variables: { id } });\n };\n const handleReject = (id: string) => {\n setActingId(id);\n void rejectTransaction({ variables: { id, reason: null } });\n };\n\n // ─── Export the active tab ───\n const handleExport = () => {\n const stamp = new Date().toISOString().slice(0, 10);\n if (activeTab === 'budgets') {\n if (budgets.length === 0) {\n notify.warning('Nothing to export', 'There are no budgets to export yet.');\n return;\n }\n downloadCsv(\n `budgets-${stamp}`,\n ['Name', 'Department', 'Category', 'Period', 'Allocated', 'Spent', 'Remaining', 'Status'],\n budgets.map((b) => [\n b.name,\n b.department,\n b.category,\n b.period,\n b.allocated,\n b.spent,\n b.remaining,\n b.status,\n ])\n );\n return;\n }\n if (activeTab === 'invoices') {\n if (invoices.length === 0) {\n notify.warning('Nothing to export', 'There are no invoices to export yet.');\n return;\n }\n downloadCsv(\n `invoices-${stamp}`,\n ['Invoice #', 'Vendor', 'Amount', 'Currency', 'Issue Date', 'Due Date', 'Status'],\n invoices.map((i) => [\n i.number,\n i.vendor,\n i.amount,\n i.currency,\n i.issueDate,\n i.dueDate,\n i.status,\n ])\n );\n return;\n }\n if (transactions.length === 0) {\n notify.warning('Nothing to export', 'There are no transactions to export yet.');\n return;\n }\n downloadCsv(\n `transactions-${stamp}`,\n ['ID', 'Type', 'Description', 'Department', 'Amount', 'Currency', 'Status', 'Date'],\n transactions.map((t) => [\n t.id,\n t.type,\n t.description,\n t.department,\n t.amount,\n t.currency,\n t.status,\n t.date,\n ])\n );\n };\n\n return (\n <div className=\"space-y-6 p-4 sm:p-6\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between\">\n <div>\n <h1 className=\"text-2xl font-bold sm:text-3xl\">\n <GradientText>Finance Hub</GradientText>\n </h1>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Workspace budgets, transactions, and supplier invoices\n </p>\n </div>\n <CTAOverflowMenu\n primary={{ label: 'New Transaction', onSelect: () => setTxnDialogOpen(true) }}\n actions={[\n { label: 'New Budget', onSelect: () => setBudgetDialogOpen(true) },\n { label: 'New Invoice', onSelect: () => setInvoiceDialogOpen(true) },\n { label: 'Export', onSelect: handleExport, icon: <Download className=\"h-4 w-4\" /> },\n ]}\n />\n </div>\n\n <NewTransactionDialog open={txnDialogOpen} onOpenChange={setTxnDialogOpen} />\n <NewBudgetDialog open={budgetDialogOpen} onOpenChange={setBudgetDialogOpen} />\n <NewInvoiceDialog open={invoiceDialogOpen} onOpenChange={setInvoiceDialogOpen} />\n\n <PagePurpose>\n The workspace money view for your asset estate: record transactions, maintain departmental\n budget totals, and stay on top of vendor invoices. Transactions do not automatically update\n budgets, and these records are not yet allocated to an individual asset.\n </PagePurpose>\n\n <NextSteps\n storageKey=\"assethandler-finance-hub\"\n steps={[\n {\n id: 'transactions',\n label: 'Review recent transactions',\n description: 'Check spend and approve anything still pending.',\n onClick: () => navigate('/transactions/transaction-list'),\n },\n {\n id: 'budgets',\n label: 'Review reporting dashboard',\n description: 'See budget health and spend trends across departments.',\n onClick: () => navigate('/reports/reports-dashboard'),\n },\n {\n id: 'reports',\n label: 'Open financial summaries',\n description: 'Review the fixed live financial summary and CSV-ready registers.',\n onClick: () => navigate('/reports/reports-dashboard'),\n },\n ]}\n />\n\n {/* ─── Money-forward KPI row ─── */}\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n <StatTile\n label=\"Total Spend\"\n value={totalSpend}\n format={(v) => fmtMoney(v)}\n icon={DollarSign}\n hero\n delta={`${pendingTxns.length} pending`}\n deltaTone=\"neutral\"\n />\n <StatTile\n label=\"Budget Allocated\"\n value={budgetAllocated}\n format={(v) => fmtMoney(v)}\n icon={Wallet}\n />\n <StatTile\n label=\"Budget Spent\"\n value={budgetSpent}\n format={(v) => fmtMoney(v)}\n icon={TrendingDown}\n delta={overBudget.length > 0 ? `${overBudget.length} over` : undefined}\n deltaTone=\"negative\"\n deltaDirection={overBudget.length > 0 ? 'up' : 'neutral'}\n />\n <StatTile\n label=\"Invoices Outstanding\"\n value={invoicesOutstanding}\n format={(v) => fmtMoney(v)}\n icon={Receipt}\n delta={\n overdueInvoices.length > 0\n ? `${overdueInvoices.length} overdue`\n : outstandingCount > 0\n ? `${outstandingCount} open`\n : undefined\n }\n deltaTone={overdueInvoices.length > 0 ? 'negative' : 'neutral'}\n deltaDirection=\"neutral\"\n />\n </div>\n\n {/* ─── Insights charts ─── */}\n {hasCharts ? (\n <div className=\"grid gap-4 lg:grid-cols-2\">\n {budgetByDept.length > 0 ? (\n <ChartCard\n title=\"Budget vs spend\"\n subtitle=\"Allocated against actual spend by department\"\n icon={BarChart3}\n >\n <BarsChart\n data={budgetByDept}\n xKey=\"department\"\n series={[\n { key: 'allocated', label: 'Allocated' },\n { key: 'spent', label: 'Spent' },\n ]}\n height={260}\n valueFormat={compactUsd}\n ariaLabel=\"Budget allocated versus spent by department\"\n />\n </ChartCard>\n ) : null}\n {spendByCategory.length > 0 ? (\n <ChartCard\n title=\"Spend by category\"\n subtitle=\"Recorded transaction spend, grouped by category\"\n icon={PieChartIcon}\n >\n <DonutChart\n data={spendByCategory}\n centerLabel=\"Total spend\"\n centerValue={totalSpend}\n valueFormat={(v) => fmtMoney(v)}\n height={260}\n ariaLabel=\"Transaction spend by category\"\n />\n </ChartCard>\n ) : null}\n </div>\n ) : null}\n\n <Tabs\n value={activeTab}\n onValueChange={(v) => setActiveTab(v as typeof activeTab)}\n className=\"space-y-4\"\n >\n <TabsList>\n <TabsTrigger value=\"transactions\">Transactions</TabsTrigger>\n <TabsTrigger value=\"budgets\">Budgets</TabsTrigger>\n <TabsTrigger value=\"invoices\">Invoices</TabsTrigger>\n </TabsList>\n\n {/* ─── Transactions ─── */}\n <TabsContent value=\"transactions\" className=\"space-y-4\">\n {transactions.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No transactions yet\"\n description=\"Asset-related spend and reimbursements will appear here as they are recorded.\"\n />\n ) : (\n <>\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center\">\n <div className=\"relative flex-1\">\n <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-muted\" />\n <Input\n value={txnSearch}\n onChange={(e) => setTxnSearch(e.target.value)}\n placeholder=\"Search description, vendor or department\"\n className=\"pl-9\"\n />\n </div>\n <Select value={txnStatusFilter} onValueChange={setTxnStatusFilter}>\n <SelectTrigger className=\"w-full sm:w-40\">\n <SelectValue placeholder=\"Status\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">All statuses</SelectItem>\n {TRANSACTION_STATUSES.map((s) => (\n <SelectItem key={s} value={s.toLowerCase()}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Select value={txnTypeFilter} onValueChange={setTxnTypeFilter}>\n <SelectTrigger className=\"w-full sm:w-40\">\n <SelectValue placeholder=\"Type\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">All types</SelectItem>\n {TRANSACTION_TYPES.map((t) => (\n <SelectItem key={t} value={t.toLowerCase()}>\n {humanize(t)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {filteredTxns.length === 0 ? (\n <GlassCard treatment=\"glass\" className=\"border-border-seam\">\n <p className=\"p-8 text-center text-sm text-text-secondary\">\n No transactions match your filters.\n </p>\n </GlassCard>\n ) : (\n <GlassCard treatment=\"glass\" className=\"overflow-hidden border-border-seam\">\n {/* Desktop table */}\n <div className=\"hidden overflow-x-auto md:block\">\n <table className=\"w-full min-w-[820px] text-sm\">\n <thead>\n <tr className=\"border-b border-border-seam bg-bg-sunken/40 text-left\">\n <th className=\"p-3 font-medium\">Type</th>\n <th className=\"p-3 font-medium\">Description</th>\n <th className=\"p-3 font-medium\">Department</th>\n <th className=\"p-3 text-right font-medium\">Amount</th>\n <th className=\"p-3 font-medium\">Status</th>\n <th className=\"p-3 font-medium\">Date</th>\n <th className=\"p-3 text-right font-medium\">Actions</th>\n </tr>\n </thead>\n <tbody>\n {txnPage.pageItems.map((txn) => (\n <tr\n key={txn.id}\n className=\"cursor-pointer border-b border-border-seam/60 last:border-0 hover:bg-bg-sunken/40\"\n onClick={() => navigate('/transactions/' + txn.id)}\n >\n <td className=\"p-3\">\n <StatusPill tone={txnTypeTone(txn.type)}>{txn.type}</StatusPill>\n </td>\n <td className=\"max-w-xs truncate p-3\" title={txn.description}>\n {txn.description}\n </td>\n <td className=\"p-3 text-xs text-text-secondary\">{txn.department}</td>\n <td\n className={cn(\n 'p-3 text-right font-medium tabular-nums',\n txn.amount < 0 && 'text-status-error-text'\n )}\n >\n {fmtMoney(Math.abs(txn.amount), txn.currency)}\n </td>\n <td className=\"p-3\">\n <StatusPill tone={txnStatusTone(txn.status)}>{txn.status}</StatusPill>\n </td>\n <td className=\"p-3 text-xs text-text-secondary\">\n {formatDate(txn.date)}\n </td>\n <td className=\"p-3\">\n <div className=\"flex justify-end\">\n <TransactionActions\n txn={txn}\n actingId={actingId}\n onApprove={handleApprove}\n onReject={handleReject}\n />\n </div>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n\n {/* Mobile cards */}\n <div className=\"divide-y divide-border-seam/60 md:hidden\">\n {txnPage.pageItems.map((txn) => (\n <button\n key={txn.id}\n type=\"button\"\n className=\"block w-full p-4 text-left hover:bg-bg-sunken/40\"\n onClick={() => navigate('/transactions/' + txn.id)}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <p className=\"min-w-0 flex-1 truncate font-medium\">{txn.description}</p>\n <span\n className={cn(\n 'shrink-0 font-semibold tabular-nums',\n txn.amount < 0 && 'text-status-error-text'\n )}\n >\n {fmtMoney(Math.abs(txn.amount), txn.currency)}\n </span>\n </div>\n <div className=\"mt-2 flex flex-wrap items-center gap-2\">\n <StatusPill tone={txnTypeTone(txn.type)}>{txn.type}</StatusPill>\n <StatusPill tone={txnStatusTone(txn.status)}>{txn.status}</StatusPill>\n <span className=\"text-xs text-text-secondary\">\n {txn.department} · {formatDate(txn.date)}\n </span>\n </div>\n {txn.status === 'pending' ? (\n <div className=\"mt-3\">\n <TransactionActions\n txn={txn}\n actingId={actingId}\n onApprove={handleApprove}\n onReject={handleReject}\n />\n </div>\n ) : null}\n </button>\n ))}\n </div>\n\n <div className=\"px-3\">\n <Pagination\n page={txnPage.page}\n pageCount={txnPage.pageCount}\n rangeStart={txnPage.rangeStart}\n rangeEnd={txnPage.rangeEnd}\n totalItems={txnPage.totalItems}\n canPrev={txnPage.canPrev}\n canNext={txnPage.canNext}\n onPrev={txnPage.prevPage}\n onNext={txnPage.nextPage}\n itemLabel=\"transactions\"\n />\n </div>\n </GlassCard>\n )}\n </>\n )}\n </TabsContent>\n\n {/* ─── Budgets ─── */}\n <TabsContent value=\"budgets\" className=\"space-y-4\">\n {budgets.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-generic\"\n title=\"No budgets defined\"\n description=\"Create departmental budgets to track allocated vs. actual asset spend.\"\n />\n ) : (\n <div className=\"grid gap-4 md:grid-cols-2\">\n {budgets.map((budget: Budget) => (\n <GlassCard\n key={budget.id}\n treatment=\"glass\"\n className=\"cursor-pointer border-border-seam\"\n >\n <div\n className=\"p-5\"\n role=\"button\"\n tabIndex={0}\n onClick={() => navigate('/finance/budgets/' + budget.id)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ')\n navigate('/finance/budgets/' + budget.id);\n }}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <h3 className=\"truncate font-semibold text-text-primary\">{budget.name}</h3>\n <p className=\"mt-0.5 text-xs text-text-secondary\">\n {budget.department} · {budget.period}\n </p>\n </div>\n <StatusPill tone={budgetStatusTone(budget.status)}>\n {budget.status.replace(/_/g, ' ')}\n </StatusPill>\n </div>\n <div className=\"mt-4 space-y-3\">\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-secondary\">Allocated</span>\n <span className=\"font-medium tabular-nums\">\n {fmtMoney(budget.allocated)}\n </span>\n </div>\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-secondary\">Remaining</span>\n <span\n className={cn(\n 'font-medium tabular-nums',\n budget.remaining < 0\n ? 'text-status-error-text'\n : 'text-status-success-text'\n )}\n >\n {fmtMoney(budget.remaining)}\n </span>\n </div>\n <ProgressMeter\n value={budget.spent}\n max={budget.allocated}\n label=\"Spent\"\n format={(v) => fmtMoney(v)}\n thresholds={{ warning: 0.8, danger: 1 }}\n />\n </div>\n </div>\n </GlassCard>\n ))}\n </div>\n )}\n </TabsContent>\n\n {/* ─── Invoices ─── */}\n <TabsContent value=\"invoices\" className=\"space-y-4\">\n {invoices.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-files\"\n title=\"No invoices\"\n description=\"Vendor invoices for asset purchases and services will be listed here.\"\n />\n ) : (\n <>\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center\">\n <div className=\"relative flex-1\">\n <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-muted\" />\n <Input\n value={invSearch}\n onChange={(e) => setInvSearch(e.target.value)}\n placeholder=\"Search invoice number or vendor\"\n className=\"pl-9\"\n />\n </div>\n <Select value={invStatusFilter} onValueChange={setInvStatusFilter}>\n <SelectTrigger className=\"w-full sm:w-40\">\n <SelectValue placeholder=\"Status\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">All statuses</SelectItem>\n {INVOICE_STATUSES.map((s) => (\n <SelectItem key={s} value={s.toLowerCase()}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {filteredInvoices.length === 0 ? (\n <GlassCard treatment=\"glass\" className=\"border-border-seam\">\n <p className=\"p-8 text-center text-sm text-text-secondary\">\n No invoices match your filters.\n </p>\n </GlassCard>\n ) : (\n <GlassCard treatment=\"glass\" className=\"overflow-hidden border-border-seam\">\n {/* Desktop table */}\n <div className=\"hidden overflow-x-auto md:block\">\n <table className=\"w-full min-w-[720px] text-sm\">\n <thead>\n <tr className=\"border-b border-border-seam bg-bg-sunken/40 text-left\">\n <th className=\"p-3 font-medium\">Invoice #</th>\n <th className=\"p-3 font-medium\">Vendor</th>\n <th className=\"p-3 text-right font-medium\">Amount</th>\n <th className=\"p-3 font-medium\">Issue Date</th>\n <th className=\"p-3 font-medium\">Due Date</th>\n <th className=\"p-3 font-medium\">Status</th>\n </tr>\n </thead>\n <tbody>\n {invPage.pageItems.map((inv: Invoice) => (\n <tr\n key={inv.id}\n className=\"cursor-pointer border-b border-border-seam/60 last:border-0 hover:bg-bg-sunken/40\"\n onClick={() => navigate('/finance/invoices/' + inv.id)}\n >\n <td className=\"p-3 font-mono text-xs\">{inv.number}</td>\n <td className=\"p-3\">{inv.vendor}</td>\n <td className=\"p-3 text-right font-medium tabular-nums\">\n {fmtMoney(inv.amount, inv.currency)}\n </td>\n <td className=\"p-3 text-xs text-text-secondary\">\n {formatDate(inv.issueDate)}\n </td>\n <td className=\"p-3 text-xs text-text-secondary\">\n {formatDate(inv.dueDate)}\n </td>\n <td className=\"p-3\">\n <StatusPill tone={invoiceStatusTone(inv.status)}>\n {inv.status}\n </StatusPill>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n\n {/* Mobile cards */}\n <div className=\"divide-y divide-border-seam/60 md:hidden\">\n {invPage.pageItems.map((inv: Invoice) => (\n <button\n key={inv.id}\n type=\"button\"\n className=\"block w-full p-4 text-left hover:bg-bg-sunken/40\"\n onClick={() => navigate('/finance/invoices/' + inv.id)}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <p className=\"truncate font-mono text-xs text-text-secondary\">\n {inv.number}\n </p>\n <p className=\"truncate font-medium\">{inv.vendor}</p>\n </div>\n <span className=\"shrink-0 font-semibold tabular-nums\">\n {fmtMoney(inv.amount, inv.currency)}\n </span>\n </div>\n <div className=\"mt-2 flex flex-wrap items-center gap-2\">\n <StatusPill tone={invoiceStatusTone(inv.status)}>{inv.status}</StatusPill>\n <span className=\"text-xs text-text-secondary\">\n Due {formatDate(inv.dueDate)}\n </span>\n </div>\n </button>\n ))}\n </div>\n\n <div className=\"px-3\">\n <Pagination\n page={invPage.page}\n pageCount={invPage.pageCount}\n rangeStart={invPage.rangeStart}\n rangeEnd={invPage.rangeEnd}\n totalItems={invPage.totalItems}\n canPrev={invPage.canPrev}\n canNext={invPage.canNext}\n onPrev={invPage.prevPage}\n onNext={invPage.nextPage}\n itemLabel=\"invoices\"\n />\n </div>\n </GlassCard>\n )}\n </>\n )}\n </TabsContent>\n </Tabs>\n </div>\n );\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-assethandler",
3
- "version": "2026.826.12",
3
+ "version": "2026.826.13",
4
4
  "description": "Burdenoff AssetHandler Microfrontend",
5
5
  "type": "module",
6
6
  "files": [