splitwise / src /lib /server /forms /settlement-form.ts
assafvayner's picture
assafvayner HF Staff
fix(photos,forms): own-property content types, dimension bounds, VP8L signature, trimmed inputs
fa363c5
Raw
History Blame Contribute Delete
2.15 kB
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<SettlementBody, SettlementField> {
const errors: Partial<Record<SettlementField, string>> = {};
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 };
}