File size: 2,154 Bytes
0545b15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fa363c5
 
0545b15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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 };
}