import type { Location, LocationContact, LocationListItem, LocationSite, } from "@/domain/locations/types/location"; function readString(record: Record, ...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 readId(record: Record): string | number { const value = record.id ?? record.Id; if (typeof value === "string" || typeof value === "number") { return value; } return ""; } function readOptionalId(record: Record): string | number { const value = record.accountId ?? record.AccountId; if (typeof value === "string" || typeof value === "number") { return value; } return ""; } export function formatLocationSiteLabel( site: Pick, ): string { const place = [site.city, site.state].filter(Boolean).join(", "); if (site.code && place) { return `${site.code} ยท ${place}`; } return site.code || place || ""; } /** Table cell label: `BK5 . Dallas, TX` (period separator). */ export function formatSiteTableLabel(params: { code?: string; city?: string; state?: string; fallbackLocation?: string; }): string { const code = params.code?.trim() ?? ""; const place = [params.city, params.state].filter(Boolean).join(", ") || (params.fallbackLocation?.trim() ?? ""); if (code && place) { return `${code} . ${place}`; } return code || place || ""; } export function formatSitePlace(city?: string, state?: string, fallbackLocation = ""): string { return [city, state].filter(Boolean).join(", ") || fallbackLocation.trim() || ""; } /** Wizard preview: `3811 Distribution Dr, Dallas, TX 70068` */ export function formatLocationAddressPreview( location: Pick, ): string { const street = location.address?.trim() ?? ""; const city = location.city?.trim() ?? ""; const stateZip = [location.state?.trim(), location.zipCode?.trim()].filter(Boolean).join(" "); const cityStateZip = [city, stateZip].filter(Boolean).join(", "); if (street && cityStateZip) { return `${street}, ${cityStateZip}`; } return street || cityStateZip || ""; } export function mapLocationSite(raw: unknown): LocationSite { const item = (typeof raw === "object" && raw !== null ? raw : {}) as Record; return { id: readId(item), code: readString(item, "code", "Code", "siteCode", "SiteCode"), city: readString(item, "city", "City"), state: readString(item, "state", "State"), }; } export function mapLocationSites(rawItems: unknown[]): LocationSite[] { return rawItems.map(mapLocationSite); } /** Reads the additive contacts array; returns [] when absent or malformed. */ export function mapLocationContacts(raw: unknown): LocationContact[] { if (!Array.isArray(raw)) { return []; } return raw.map((entry) => { const item = (typeof entry === "object" && entry !== null ? entry : {}) as Record< string, unknown >; const id = item.id ?? item.Id; return { ...(typeof id === "number" && Number.isInteger(id) && id > 0 ? { id } : {}), name: readString(item, "name", "Name", "contact", "Contact"), phone: readString(item, "phone", "Phone"), }; }); } export function mapLocationListItem(raw: unknown): LocationListItem { const item = (typeof raw === "object" && raw !== null ? raw : {}) as Record; const contacts = mapLocationContacts(item.contacts ?? item.Contacts); const mainContact = contacts[0]; return { id: readId(item), name: readString(item, "name", "Name"), clientName: readString(item, "clientName", "ClientName", "accountName", "AccountName"), sitePhone: readString(item, "phone", "Phone"), address: readString(item, "address", "Address"), city: readString(item, "city", "City"), state: readString(item, "state", "State"), zipCode: readString(item, "zipCode", "ZipCode", "Zip"), phone: mainContact ? mainContact.phone : readString(item, "phone", "Phone"), contact: mainContact ? mainContact.name : readString(item, "contact", "Contact", "contactPerson", "ContactPerson"), contactEmail: readString(item, "contactEmail", "ContactEmail"), status: readString(item, "status", "Status"), accountId: readOptionalId(item), contacts: contacts.length > 0 ? contacts : undefined, }; } export function mapLocationListItems(rawItems: unknown[]): LocationListItem[] { return rawItems.map(mapLocationListItem); } export function mapLocation(raw: unknown): Location { const item = (typeof raw === "object" && raw !== null ? raw : {}) as Record; const address = readString(item, "address", "Address") || [readString(item, "address1", "Address1"), readString(item, "address2", "Address2")] .filter(Boolean) .join(", ") || undefined; const contacts = mapLocationContacts(item.contacts ?? item.Contacts); const mainContact = contacts[0]; const legacyPhone = readString(item, "phone", "Phone") || undefined; const legacyContact = readString(item, "contact", "Contact", "contactPerson", "ContactPerson") || undefined; return { id: readId(item) || undefined, name: readString(item, "name", "Name") || undefined, title: readString(item, "title", "Title") || undefined, clientName: readString(item, "clientName", "ClientName", "accountName", "AccountName") || undefined, sitePhone: legacyPhone, notes: readString(item, "notes", "Notes") || undefined, address: address || undefined, city: readString(item, "city", "City") || undefined, state: readString(item, "state", "State") || undefined, zipCode: readString(item, "zipCode", "ZipCode", "Zip") || undefined, phone: mainContact ? mainContact.phone : legacyPhone, contact: mainContact ? mainContact.name : legacyContact, contactEmail: readString(item, "contactEmail", "ContactEmail") || undefined, status: readString(item, "status", "Status") || undefined, accountId: readOptionalId(item) || undefined, contacts: contacts.length > 0 ? contacts : undefined, }; } /** Request payload contacts: trimmed, in displayed order. */ export function mapContactsToBackend(raw: unknown): LocationContact[] { if (!Array.isArray(raw)) { return []; } return raw .map((entry) => { const item = (typeof entry === "object" && entry !== null ? entry : {}) as Record< string, unknown >; return { ...(typeof item.id === "number" && Number.isInteger(item.id) && item.id > 0 ? { id: item.id } : {}), name: readString(item, "name", "Name", "contact", "Contact").trim(), phone: readString(item, "phone", "Phone").trim(), }; }) .filter((contact) => contact.name !== "" || contact.phone !== ""); } /** * Create/update payload. `phone` is the Site Phone (independent of the contacts); `status`, * `title` and `notes` are sent only when present so an update keeps the stored values. */ export function mapLocationToBackend(location: unknown): Record { const item = (typeof location === "object" && location !== null ? location : {}) as Record< string, unknown >; const contacts = mapContactsToBackend(item.contacts ?? item.Contacts); const mainContact = contacts[0]; const payload: Record = { name: typeof item.name === "string" ? item.name.trim() : "", address: item.address ?? "", city: item.city ?? "", state: item.state ?? "", zipCode: item.zipCode ?? "", phone: typeof item.sitePhone === "string" ? item.sitePhone.trim() : "", contact: mainContact ? mainContact.name : "", contactEmail: typeof item.contactEmail === "string" ? item.contactEmail.trim() : "", accountId: item.accountId ?? "", contacts, }; for (const key of ["status", "title", "notes"] as const) { if (typeof item[key] === "string") { payload[key] = item[key]; } } const id = item.id ?? item.Id; if (typeof id === "string" || typeof id === "number") { payload.id = id; } return payload; }