ultisuite-client/lib/mail-date.ts
2026-05-16 20:30:50 +02:00

107 lines
2.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import dayjs, { type Dayjs } from "dayjs"
import localizedFormat from "dayjs/plugin/localizedFormat"
import relativeTime from "dayjs/plugin/relativeTime"
import "dayjs/locale/fr"
import "dayjs/locale/en"
dayjs.extend(localizedFormat)
dayjs.extend(relativeTime)
const SUPPORTED_LOCALES = new Set(["fr", "en", "de", "es", "it", "pt", "nl", "pl", "ja", "zh"])
let activeLocale: string | null = null
/** Browser locale for dayjs (client); stable fallback on server. */
export function resolveMailDateLocale(): string {
if (typeof navigator === "undefined") return "fr"
const base = navigator.language.split("-")[0]?.toLowerCase() ?? "fr"
return SUPPORTED_LOCALES.has(base) ? base : "en"
}
export function ensureMailDateLocale(): void {
const next = resolveMailDateLocale()
if (activeLocale === next) return
dayjs.locale(next)
activeLocale = next
}
export function parseMailDate(iso: string): Dayjs | null {
if (!iso?.trim()) return null
const d = dayjs(iso)
return d.isValid() ? d : null
}
export type MailDateDisplayVariant = "list" | "preview" | "detail"
const TWO_WEEKS_MS = 14 * 24 * 60 * 60 * 1000
function relativeSuffix(d: Dayjs, now: Dayjs): string {
if (d.isAfter(now)) return ""
return ` (${d.fromNow()})`
}
/** Colonne date de la liste (fuseau navigateur). */
export function formatMailListDate(iso: string, now: Dayjs = dayjs()): string {
ensureMailDateLocale()
const d = parseMailDate(iso)
if (!d) return "—"
if (d.isSame(now, "day")) {
return d.format("LT")
}
if (d.isSame(now, "year")) {
return d.format("D MMM")
}
return d.format("L")
}
/** En-tête / aperçu dun message (fuseau navigateur). */
export function formatMailPreviewDate(iso: string, now: Dayjs = dayjs()): string {
ensureMailDateLocale()
const d = parseMailDate(iso)
if (!d) return "—"
const time = d.format("LT")
if (d.isSame(now, "day")) {
return `${time}${relativeSuffix(d, now)}`
}
const msAgo = now.valueOf() - d.valueOf()
const withinTwoWeeks = msAgo >= 0 && msAgo < TWO_WEEKS_MS
const datePart = d.format("ddd D MMM")
if (withinTwoWeeks) {
return `${datePart} ${time}${relativeSuffix(d, now)}`
}
if (d.isSame(now, "year")) {
return `${datePart} ${time}`
}
return `${d.format("ddd D MMM YYYY")} ${time}`
}
/** Citations, impression, panneau « détails » (sans relatif). */
export function formatMailDetailDate(iso: string, now: Dayjs = dayjs()): string {
ensureMailDateLocale()
const d = parseMailDate(iso)
if (!d) return "—"
const time = d.format("LT")
const datePart = d.format("ddd D MMM")
if (d.isSame(now, "year")) {
return `${datePart} ${time}`
}
return `${d.format("ddd D MMM YYYY")} ${time}`
}
export function formatMailDate(iso: string, variant: MailDateDisplayVariant): string {
switch (variant) {
case "list":
return formatMailListDate(iso)
case "preview":
return formatMailPreviewDate(iso)
case "detail":
return formatMailDetailDate(iso)
}
}