62 lines
1.9 KiB
TypeScript
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;
|
|
}
|