mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-05 16:32:06 +00:00
Document the backend #66 producer, drop incomplete extras from persist, and show the same required-field errors on POC 2+.
102 lines
2.6 KiB
TypeScript
102 lines
2.6 KiB
TypeScript
import type { WorkOrderAdditionalContact } from "@/domain/work-orders/types/work-order-additional-contact";
|
|
|
|
function asRecord(raw: unknown): Record<string, unknown> {
|
|
return typeof raw === "object" && raw !== null ? (raw as Record<string, unknown>) : {};
|
|
}
|
|
|
|
function readString(record: Record<string, unknown>, ...keys: string[]): string {
|
|
for (const key of keys) {
|
|
const value = record[key];
|
|
if (typeof value === "string") {
|
|
return value;
|
|
}
|
|
if (typeof value === "number") {
|
|
return String(value);
|
|
}
|
|
}
|
|
return "";
|
|
}
|
|
|
|
function mapContactItem(raw: unknown): WorkOrderAdditionalContact | null {
|
|
const item = asRecord(raw);
|
|
const name = readString(item, "name", "Name");
|
|
const phone = readString(item, "phone", "Phone");
|
|
const notes = readString(item, "notes", "Notes");
|
|
|
|
if (!name.trim() && !phone.trim()) {
|
|
return null;
|
|
}
|
|
|
|
const contact: WorkOrderAdditionalContact = {
|
|
name,
|
|
phone,
|
|
};
|
|
|
|
if (notes.trim()) {
|
|
contact.notes = notes;
|
|
}
|
|
|
|
return contact;
|
|
}
|
|
|
|
/** Reads additional POCs from board/detail payloads; missing field yields []. */
|
|
export function readAdditionalContacts(
|
|
record: Record<string, unknown>,
|
|
): WorkOrderAdditionalContact[] {
|
|
for (const key of ["additionalContacts", "AdditionalContacts"]) {
|
|
const value = record[key];
|
|
if (!Array.isArray(value)) {
|
|
continue;
|
|
}
|
|
|
|
return value
|
|
.map(mapContactItem)
|
|
.filter((contact): contact is WorkOrderAdditionalContact => contact !== null);
|
|
}
|
|
|
|
return [];
|
|
}
|
|
|
|
/** True when exactly one of name/phone is filled (not persistable). */
|
|
export function isIncompleteAdditionalContact(contact: WorkOrderAdditionalContact): boolean {
|
|
const hasName = Boolean(contact.name.trim());
|
|
const hasPhone = Boolean(contact.phone.trim());
|
|
return hasName !== hasPhone;
|
|
}
|
|
|
|
/** Drops empty and incomplete rows; returns undefined when nothing to persist. */
|
|
export function normalizeAdditionalContacts(
|
|
contacts: WorkOrderAdditionalContact[],
|
|
): WorkOrderAdditionalContact[] | undefined {
|
|
const out: WorkOrderAdditionalContact[] = [];
|
|
|
|
for (const raw of contacts) {
|
|
const name = raw.name.trim();
|
|
const phone = raw.phone.trim();
|
|
const notes = raw.notes?.trim();
|
|
|
|
if (!name && !phone) {
|
|
continue;
|
|
}
|
|
|
|
if (!name || !phone) {
|
|
continue;
|
|
}
|
|
|
|
const contact: WorkOrderAdditionalContact = { name, phone };
|
|
|
|
if (notes) {
|
|
contact.notes = notes;
|
|
}
|
|
|
|
out.push(contact);
|
|
}
|
|
|
|
return out.length > 0 ? out : undefined;
|
|
}
|
|
|
|
export function serializeAdditionalContactsForPatch(
|
|
contacts: WorkOrderAdditionalContact[],
|
|
): string {
|
|
return JSON.stringify(normalizeAdditionalContacts(contacts) ?? []);
|
|
}
|