ultisuite-client/lib/mail-date.ts
R3D347HR4Y efaaf16f60
Some checks are pending
E2E / Playwright e2e (push) Waiting to run
feat: update metadata and layout for new product pages
- Refactored metadata for contacts, administration, and Ulticards pages to utilize dynamic app names and descriptions.
- Introduced new product pages for Ultiai, Ultical, Ulticards, Ultidrive, Ultimail, and Ultimeet with appropriate metadata.
- Enhanced layout components to ensure consistent styling and functionality across new product sections.
- Updated various components to replace hardcoded labels with dynamic references to improve maintainability and consistency.
2026-06-19 22:11:42 +02:00

133 lines
3.7 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" | "previewShort" | "detail"
const TWO_WEEKS_MS = 14 * 24 * 60 * 60 * 1000
function formatMailPreviewRelative(d: Dayjs, now: Dayjs): string | null {
if (d.isAfter(now)) return null
const msAgo = now.valueOf() - d.valueOf()
const withinTwoWeeks = msAgo >= 0 && msAgo < TWO_WEEKS_MS
if (d.isSame(now, "day") || withinTwoWeeks) {
return `(${d.fromNow()})`
}
return null
}
function relativeSuffix(d: Dayjs, now: Dayjs): string {
const relative = formatMailPreviewRelative(d, now)
return relative ? ` ${relative}` : ""
}
/** 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")
}
/** Date seule pour len-tête / aperçu (sans relatif). */
export function formatMailPreviewDatePrimary(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
}
const datePart = d.format("ddd D MMM")
if (d.isSame(now, "year")) {
return `${datePart} ${time}`
}
return `${d.format("ddd D MMM YYYY")} ${time}`
}
/** Relatif « (il y a …) » pour laperçu, ou null si absent. */
export function formatMailPreviewDateRelative(
iso: string,
now: Dayjs = dayjs()
): string | null {
ensureMailDateLocale()
const d = parseMailDate(iso)
if (!d) return null
return formatMailPreviewRelative(d, now)
}
/** 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 "—"
return `${formatMailPreviewDatePrimary(iso, now)}${relativeSuffix(d, now)}`
}
/** 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":
case "previewShort":
return formatMailListDate(iso)
case "preview":
return formatMailPreviewDate(iso)
case "detail":
return formatMailDetailDate(iso)
}
}