mirror of
https://github.com/Sea-Haven-Industries/seahaven-ap.git
synced 2026-09-30 03:23:16 +00:00
* feat(shared): add payment ladder and CSV domain package Introduce @seahaven-ap/shared via npm workspaces so FE and future API share payments-dashboard-compatible status ladders, pay-date helpers, and CSV headers. * fix(web): build shared package before vite dev Ensure fresh npm ci && npm run dev (and Playwright webServer) can resolve @seahaven-ap/shared dist exports that are gitignored.
53 lines
1.8 KiB
TypeScript
53 lines
1.8 KiB
TypeScript
/**
|
|
* Shared date parsing for Stampli M/D/YY and MM/DD/YYYY formats.
|
|
* Ported from payments-dashboard/src/dates.js — both formats must parse;
|
|
* anything else returns null (never pass through garbage).
|
|
*/
|
|
|
|
export type ParsedMDY = {
|
|
year: number;
|
|
month: number;
|
|
day: number;
|
|
};
|
|
|
|
/** Parse "M/D/YY" or "MM/DD/YYYY" into { year, month, day }, or null. */
|
|
export function parseMDY(value: string | null | undefined): ParsedMDY | null {
|
|
const match = /^(\d{1,2})\/(\d{1,2})\/(\d{2}|\d{4})$/.exec(String(value ?? "").trim());
|
|
if (!match) return null;
|
|
const month = Number.parseInt(match[1]!, 10);
|
|
const day = Number.parseInt(match[2]!, 10);
|
|
let year = Number.parseInt(match[3]!, 10);
|
|
if (match[3]!.length === 2) year += 2000;
|
|
const dt = new Date(year, month - 1, day);
|
|
if (dt.getFullYear() !== year || dt.getMonth() !== month - 1 || dt.getDate() !== day) {
|
|
return null;
|
|
}
|
|
return { year, month, day };
|
|
}
|
|
|
|
/** "YYYY-MM-DD" or null. */
|
|
export function toISODate(value: string | null | undefined): string | null {
|
|
const p = parseMDY(value);
|
|
if (!p) return null;
|
|
return `${p.year}-${String(p.month).padStart(2, "0")}-${String(p.day).padStart(2, "0")}`;
|
|
}
|
|
|
|
/** Canonical "MM/DD/YYYY" or null. Stored form for send_payment_on / CSV. */
|
|
export function toCanonicalMDY(value: string | null | undefined): string | null {
|
|
const p = parseMDY(value);
|
|
if (!p) return null;
|
|
return `${String(p.month).padStart(2, "0")}/${String(p.day).padStart(2, "0")}/${p.year}`;
|
|
}
|
|
|
|
/**
|
|
* Plausibility window for ingested send dates.
|
|
* Relative to the current year (7 years back, 2 years forward).
|
|
*/
|
|
export function isPlausibleSendYear(
|
|
value: string | null | undefined,
|
|
nowYear: number = new Date().getFullYear(),
|
|
): boolean {
|
|
const p = parseMDY(value);
|
|
if (p === null) return false;
|
|
return p.year >= nowYear - 7 && p.year <= nowYear + 2;
|
|
}
|