Files
Investidor-V2/resources/js/lib/desk-field-values.ts
T

62 lines
1.9 KiB
TypeScript

export type DeskValueField = { type: string; options?: Record<string, string> };
export type DeskAnswer = string | number | boolean | string[] | null;
export function deskScalar(value: unknown): string {
if (typeof value === 'string' || typeof value === 'number')
return String(value);
if (typeof value === 'boolean') return value ? '1' : '';
return '';
}
export function deskChoices(value: unknown): string[] {
return Array.isArray(value) && value.every((v) => typeof v === 'string')
? value
: [];
}
export function deskEmpty(value: unknown): boolean {
return (
value === null ||
value === undefined ||
(typeof value === 'string' && value.trim() === '') ||
(Array.isArray(value) && value.length === 0)
);
}
/** Preserve typed answers and refusals; a master/profile can never supply a consent declaration. */
export function mergeDeskPrefill(
current: Record<string, DeskAnswer>,
patch: Record<string, unknown>,
fields: Record<string, DeskValueField>,
replace = false,
): Record<string, DeskAnswer> {
const next = { ...current };
for (const [key, value] of Object.entries(patch)) {
const field = fields[key];
if (
field?.type === 'consent' ||
field?.type === 'attachment' ||
(!replace && !deskEmpty(current[key]))
)
continue;
if (field?.type === 'multiselect') {
if (
Array.isArray(value) &&
value.every(
(v) =>
typeof v === 'string' &&
Object.hasOwn(field.options ?? {}, v),
)
)
next[key] = [...value];
} else if (
value === null ||
typeof value === 'string' ||
typeof value === 'number' ||
typeof value === 'boolean'
)
next[key] = value;
}
return next;
}