'use client' import { useId, useState } from 'react' import { ChevronDown, ChevronRight } from 'lucide-react' import { AccountNumber } from '@/components/ui/account-number' export interface DeclarationAccountLine { accountNumber: string accountName: string amount: number } /** * Default formatter: whole kronor, matching the filed SRU values. Truncation, * not rounding: SFL "öretal faller bort" and the NE/INK2 SRU generators drop * öre with Math.trunc, so the UI must agree with the filed figures. Callers * that need öre pass their own formatter. */ export function formatWholeKronor(n: number): string { // + 0 normalizes -0 (Math.trunc(-0.3) is -0, which sv-SE renders "−0"). return `${(Math.trunc(n) + 0).toLocaleString('sv-SE')} kr` } /** * One expandable declaration row (NE-bilaga, INK2): ruta code chip, label, * signed amount, and a per-account breakdown behind a keyboard-accessible * toggle. Replaces the copy-pasted rows that had no keyboard * path, no aria-expanded, and double-encoded signs. * * `amount` is the SIGNED display value: expense callers pass the negated * value instead of an isExpense flag, so a credit-balance expense renders * with its true sign. Composes inside the Table primitive's TableBody. */ export function DeclarationRutaRow({ code, label, amount, accounts = [], hideWhenZero = true, formatAmount = formatWholeKronor, }: { code: string label: string amount: number accounts?: DeclarationAccountLine[] hideWhenZero?: boolean formatAmount?: (n: number) => string }) { const [expanded, setExpanded] = useState(false) const panelId = useId() if (amount === 0 && accounts.length === 0 && hideWhenZero) return null const hasAccounts = accounts.length > 0 return ( <> hasAccounts && setExpanded((v) => !v)} > {hasAccounts && ( )} {code} {label} {hasAccounts && ( ({accounts.length} konton) )} {formatAmount(amount)} {expanded && hasAccounts && ( {accounts.map((acc) => ( ))}
{acc.accountName} {formatAmount(acc.amount)}
)} ) }