export type Confirmation = { actorId: number | null; actorName: string | null; date: string | null; reason: string | null; }; export const agreementParties = ['proponent', 'candidate'] as const; export function agreementObject( value: unknown, ): value is Record { return value !== null && typeof value === 'object' && !Array.isArray(value); } const text = (value: unknown) => (typeof value === 'string' ? value : null); export function readAgreement(value: unknown) { const record = agreementObject(value) ? value : null; const map = record && agreementObject(record.confirmations) ? record.confirmations : record && Array.isArray(record.confirmations) && record.confirmations.length === 0 ? {} : null; const confirmations: Partial< Record<(typeof agreementParties)[number], Confirmation> > = {}; for (const party of agreementParties) { if (!map || !Object.hasOwn(map, party)) continue; const stamp = agreementObject(map[party]) ? map[party] : {}; const id = stamp.actor_id; confirmations[party] = { actorId: typeof id === 'number' && Number.isSafeInteger(id) && id > 0 ? id : null, actorName: text(stamp.actor_name), date: text(stamp.date), reason: text(stamp.reason), }; } return { kind: value == null ? ('absent' as const) : record ? ('recorded' as const) : ('malformed' as const), title: text(record?.title), terms: text(record?.terms), confirmationsState: map ? ('recorded' as const) : record?.confirmations == null ? ('absent' as const) : ('malformed' as const), confirmations, extraConfirmations: !!map && Object.keys(map).some( (key) => !agreementParties.some((party) => party === key), ), legalStatus: text(record?.legal_signature_status), }; }