mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-09-30 20:53:12 +00:00
Some checks are pending
* feat(locations): derive site areas from state * chore(locations): keep ticket keys out of source comments --------- Co-authored-by: Codex Review Integration <codex-review@local.invalid>
170 lines
4.1 KiB
TypeScript
170 lines
4.1 KiB
TypeScript
/**
|
|
* Canonical source of truth for US states and their Seahaven area zone
|
|
* mapping. Exactly the 50 states — no DC and no territories.
|
|
* Area is always derived from the state code and never persisted.
|
|
*/
|
|
export const AREA_ZONES = ["East", "Central", "West", "California"] as const;
|
|
|
|
export type AreaZone = (typeof AREA_ZONES)[number];
|
|
|
|
export const AREA_ZONE_STATE_CODES = {
|
|
East: [
|
|
"CT",
|
|
"DE",
|
|
"GA",
|
|
"MA",
|
|
"MD",
|
|
"ME",
|
|
"NC",
|
|
"NH",
|
|
"NJ",
|
|
"NY",
|
|
"PA",
|
|
"RI",
|
|
"SC",
|
|
"VA",
|
|
"VT",
|
|
"WV",
|
|
],
|
|
Central: [
|
|
"AL",
|
|
"AR",
|
|
"FL",
|
|
"IA",
|
|
"IL",
|
|
"IN",
|
|
"KS",
|
|
"KY",
|
|
"LA",
|
|
"MI",
|
|
"MN",
|
|
"MO",
|
|
"MS",
|
|
"ND",
|
|
"NE",
|
|
"OH",
|
|
"OK",
|
|
"SD",
|
|
"TN",
|
|
"WI",
|
|
],
|
|
West: ["AK", "AZ", "CO", "HI", "ID", "MT", "NM", "NV", "OR", "TX", "UT", "WA", "WY"],
|
|
California: ["CA"],
|
|
} as const satisfies Record<AreaZone, readonly string[]>;
|
|
|
|
export type StateCode = (typeof AREA_ZONE_STATE_CODES)[AreaZone][number];
|
|
|
|
/** All 50 state codes in canonical order: East, Central, West, California. */
|
|
export const US_STATE_CODES = [
|
|
...AREA_ZONE_STATE_CODES.East,
|
|
...AREA_ZONE_STATE_CODES.Central,
|
|
...AREA_ZONE_STATE_CODES.West,
|
|
...AREA_ZONE_STATE_CODES.California,
|
|
] as [StateCode, ...StateCode[]];
|
|
|
|
const STATE_NAMES = {
|
|
AL: "Alabama",
|
|
AK: "Alaska",
|
|
AZ: "Arizona",
|
|
AR: "Arkansas",
|
|
CA: "California",
|
|
CO: "Colorado",
|
|
CT: "Connecticut",
|
|
DE: "Delaware",
|
|
FL: "Florida",
|
|
GA: "Georgia",
|
|
HI: "Hawaii",
|
|
ID: "Idaho",
|
|
IL: "Illinois",
|
|
IN: "Indiana",
|
|
IA: "Iowa",
|
|
KS: "Kansas",
|
|
KY: "Kentucky",
|
|
LA: "Louisiana",
|
|
ME: "Maine",
|
|
MD: "Maryland",
|
|
MA: "Massachusetts",
|
|
MI: "Michigan",
|
|
MN: "Minnesota",
|
|
MS: "Mississippi",
|
|
MO: "Missouri",
|
|
MT: "Montana",
|
|
NE: "Nebraska",
|
|
NV: "Nevada",
|
|
NH: "New Hampshire",
|
|
NJ: "New Jersey",
|
|
NM: "New Mexico",
|
|
NY: "New York",
|
|
NC: "North Carolina",
|
|
ND: "North Dakota",
|
|
OH: "Ohio",
|
|
OK: "Oklahoma",
|
|
OR: "Oregon",
|
|
PA: "Pennsylvania",
|
|
RI: "Rhode Island",
|
|
SC: "South Carolina",
|
|
SD: "South Dakota",
|
|
TN: "Tennessee",
|
|
TX: "Texas",
|
|
UT: "Utah",
|
|
VT: "Vermont",
|
|
VA: "Virginia",
|
|
WA: "Washington",
|
|
WV: "West Virginia",
|
|
WI: "Wisconsin",
|
|
WY: "Wyoming",
|
|
} as const satisfies Record<StateCode, string>;
|
|
|
|
export interface StateAreaEntry {
|
|
code: StateCode;
|
|
name: string;
|
|
zone: AreaZone;
|
|
}
|
|
|
|
/** All 50 states with postal code, full name, and their single area zone. */
|
|
export const STATE_AREA_ENTRIES: readonly StateAreaEntry[] = AREA_ZONES.flatMap((zone) =>
|
|
AREA_ZONE_STATE_CODES[zone].map((code) => ({ code, name: STATE_NAMES[code], zone })),
|
|
);
|
|
|
|
const STATE_CODE_SET = new Set<string>(US_STATE_CODES);
|
|
|
|
const STATE_NAME_TO_CODE = new Map<string, StateCode>(
|
|
STATE_AREA_ENTRIES.map((entry) => [entry.name.toLowerCase(), entry.code]),
|
|
);
|
|
|
|
const STATE_ZONE_BY_CODE = Object.fromEntries(
|
|
STATE_AREA_ENTRIES.map((entry) => [entry.code, entry.zone]),
|
|
) as Record<StateCode, AreaZone>;
|
|
|
|
/** Autocomplete option label: `Texas (TX)`. */
|
|
export function formatStateOptionLabel(code: StateCode): string {
|
|
return `${STATE_NAMES[code]} (${code})`;
|
|
}
|
|
|
|
/**
|
|
* Normalizes legacy API state values to the canonical two-letter code.
|
|
* Accepts codes in any case and full state names (any case); otherwise null.
|
|
*/
|
|
export function normalizeStateCode(value: string | null | undefined): StateCode | null {
|
|
const trimmed = value?.trim() ?? "";
|
|
if (trimmed === "") {
|
|
return null;
|
|
}
|
|
const upper = trimmed.toUpperCase();
|
|
if (STATE_CODE_SET.has(upper)) {
|
|
return upper as StateCode;
|
|
}
|
|
return STATE_NAME_TO_CODE.get(trimmed.toLowerCase()) ?? null;
|
|
}
|
|
|
|
/** Derives the area zone for a state code or legacy full-name value. */
|
|
export function getAreaForState(value: string | null | undefined): AreaZone | null {
|
|
const code = normalizeStateCode(value);
|
|
return code === null ? null : STATE_ZONE_BY_CODE[code];
|
|
}
|
|
|
|
/** Expands selected area zones to their state codes in canonical order. */
|
|
export function expandAreasToStateCodes(areas: readonly AreaZone[]): StateCode[] {
|
|
const selected = new Set<AreaZone>(areas);
|
|
return US_STATE_CODES.filter((code) => selected.has(STATE_ZONE_BY_CODE[code]));
|
|
}
|