import { isValidDate } from '../../domain/schemas'; import { centsToInput, parseAmountToCents } from '../../domain/money'; import type { Settlement, SettlementBody } from '../../domain/types'; import type { BuildResult, SettlementField, SettlementFormValues } from '../../forms/types'; import { str } from './form-utils'; export type { SettlementField, SettlementFormValues }; export function readSettlementForm(form: FormData): SettlementFormValues { return { from: str(form, 'from'), to: str(form, 'to'), amount: str(form, 'amount').trim(), date: str(form, 'date').trim(), note: str(form, 'note').trim() }; } export function settlementToFormValues(s: Settlement): SettlementFormValues { return { from: s.from, to: s.to, amount: centsToInput(s.amountCents), date: s.date, note: s.note ?? '' }; } /** Prefill from `/balances` "Settle up" links: ?from=&to=&amount=. */ export function settlementFormFromQuery(q: URLSearchParams, viewerId: string, today: string): SettlementFormValues { const clip = (v: string): string => v.trim().slice(0, 64); return { from: clip(q.get('from') ?? viewerId), to: clip(q.get('to') ?? ''), amount: clip(q.get('amount') ?? ''), date: today, note: '' }; } export function buildSettlementBody(v: SettlementFormValues, activeMemberIds: string[]): BuildResult { const errors: Partial> = {}; const active = new Set(activeMemberIds); if (!active.has(v.from)) errors.from = 'Choose who paid'; if (!active.has(v.to)) errors.to = 'Choose who received the money'; else if (v.to === v.from) errors.to = 'Payer and receiver must differ'; const amountCents = parseAmountToCents(v.amount); if (amountCents === null) errors.amount = 'Enter a positive amount with at most 2 decimals'; if (!isValidDate(v.date)) errors.date = 'Enter a valid date'; if (v.note.length > 2000) errors.form = 'Note is too long'; if (Object.keys(errors).length > 0 || amountCents === null) return { ok: false, errors }; const body: SettlementBody = { from: v.from, to: v.to, amountCents, date: v.date }; if (v.note.length > 0) body.note = v.note; return { ok: true, body }; }