mirror of
https://github.com/Sea-Haven-Industries/seahaven-ap.git
synced 2026-10-01 23:13:21 +00:00
* feat(web): fix shell chrome, logo home, and live nav badges Refs: AP-42 * feat(web): add invoice grid lines and bold headers Refs: AP-44 * feat(web): support auto row height for multi-line invoice cells Refs: AP-44 * feat(web): expand mock invoice fields for Stampli column catalog Refs: AP-47 * feat(web): add multi-line Stampli invoice cell renderers Refs: AP-47 * fix(web): address review feedback * ci: remove the pr policy caller * fix(web): keep mock catalog dates and updates in sync * fix(web): derive mock action labels from invoice status * fix(ci): drop the unused catalog refresh index * fix(ci): format invoice mock helpers
56 lines
1.5 KiB
TypeScript
56 lines
1.5 KiB
TypeScript
function startOfLocalDay(date: Date): Date {
|
|
return new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
|
}
|
|
|
|
function formatUnit(count: number, unit: "day" | "month" | "year", future: boolean): string {
|
|
const noun = count === 1 ? unit : `${unit}s`;
|
|
return future ? `in ${count} ${noun}` : `${count} ${noun} ago`;
|
|
}
|
|
|
|
export function formatSlashDate(value: string | null | undefined): string {
|
|
if (!value) {
|
|
return "—";
|
|
}
|
|
const parsed = new Date(`${value.slice(0, 10)}T00:00:00`);
|
|
if (Number.isNaN(parsed.getTime())) {
|
|
return value;
|
|
}
|
|
return new Intl.DateTimeFormat("en-US", {
|
|
year: "numeric",
|
|
month: "2-digit",
|
|
day: "2-digit",
|
|
}).format(parsed);
|
|
}
|
|
|
|
export function formatRelativeFromIsoDate(
|
|
value: string | null | undefined,
|
|
now: Date = new Date(),
|
|
): string {
|
|
if (!value) {
|
|
return "";
|
|
}
|
|
const parsed = new Date(`${value.slice(0, 10)}T00:00:00`);
|
|
if (Number.isNaN(parsed.getTime())) {
|
|
return "";
|
|
}
|
|
|
|
const dayMs = 24 * 60 * 60 * 1000;
|
|
const days = Math.round(
|
|
(startOfLocalDay(now).getTime() - startOfLocalDay(parsed).getTime()) / dayMs,
|
|
);
|
|
if (days === 0) {
|
|
return "today";
|
|
}
|
|
|
|
const future = days < 0;
|
|
const absDays = Math.abs(days);
|
|
if (absDays < 30) {
|
|
return formatUnit(absDays, "day", future);
|
|
}
|
|
const months = Math.floor(absDays / 30);
|
|
if (months < 12) {
|
|
return formatUnit(months, "month", future);
|
|
}
|
|
const years = Math.floor(months / 12);
|
|
return formatUnit(years, "year", future);
|
|
}
|