'use client' import { useTranslations } from 'next-intl' import { X } from 'lucide-react' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select' import { formatCurrency } from '@/lib/utils' import { computeInstallmentAmounts, countCalendarMonths, } from '@/lib/bookkeeping/accruals/compute' import type { AccrualDirection } from '@/types' export interface AccrualFormValue { start: string end: string balanceAccount: string } // The statutory BAS interim accounts per direction — a fixed list reads // better than a full account combobox and mirrors the DB CHECK (17xx/29xx). const BALANCE_ACCOUNT_OPTIONS: Record> = { expense: [ { value: '1710', label: '1710 Förutbetalda hyreskostnader' }, { value: '1720', label: '1720 Förutbetalda leasingavgifter' }, { value: '1730', label: '1730 Förutbetalda försäkringspremier' }, { value: '1740', label: '1740 Förutbetalda räntekostnader' }, { value: '1790', label: '1790 Övriga förutbetalda kostnader' }, ], revenue: [ { value: '2970', label: '2970 Förutbetalda intäkter' }, { value: '2971', label: '2971 Förutbetalda hyresintäkter' }, { value: '2972', label: '2972 Förutbetalda medlemsavgifter' }, { value: '2979', label: '2979 Övriga förutbetalda intäkter' }, ], } /** * Per-line periodisering panel for the invoice editors: service period + * interim balance account + a live "N månader × X kr" preview. The parent * owns the toggle; this renders only while periodisering is active on the * line. VAT is never affected — only the net amount is deferred. */ export default function AccrualPeriodControl({ direction, amount, value, onChange, onRemove, idPrefix, }: { direction: AccrualDirection /** Net line amount (ex VAT) — drives the preview and the K2 hint. */ amount: number value: AccrualFormValue onChange: (next: AccrualFormValue) => void onRemove: () => void idPrefix: string }) { const t = useTranslations('accruals') let preview: string | null = null let previewInvalid: string | null = null if (value.start && value.end) { if (value.end < value.start) { previewInvalid = t('preview_invalid_period') } else { try { const months = countCalendarMonths(value.start, value.end) if (months < 2) { previewInvalid = t('preview_min_months') } else if (amount > 0) { const amounts = computeInstallmentAmounts(amount, months) preview = t('preview', { months, amount: formatCurrency(amounts[0]), }) } } catch { previewInvalid = t('preview_invalid_period') } } } const showK2Hint = amount > 0 && amount < 5000 return (
{t('panel_title')}
onChange({ ...value, start: e.target.value })} />
onChange({ ...value, end: e.target.value })} />
{(preview || previewInvalid) && (

{previewInvalid ?? preview}

)} {showK2Hint && (

{t('k2_hint')}

)}
) }