/** Données navigation dossiers / libellés (partagées sidebar + filtre mails). */ import { buildEmailLabelToSidebarFolderId, buildFolderIdToLabelRecord, type FolderTreeNode, type LabelRowItem, } from "@/lib/sidebar-nav-maps" export type { FolderTreeNode, LabelRowItem } from "@/lib/sidebar-nav-maps" export const folderTree: FolderTreeNode[] = [ { id: "folder-travail", label: "Travail", color: "bg-blue-500", count: 24, children: [ { id: "folder-travail-clients", label: "Clients", color: "bg-blue-400", count: 11 }, { id: "folder-travail-projets", label: "Projets", color: "bg-blue-400", count: 8, children: [ { id: "folder-travail-projets-q1", label: "Q1 2026", color: "bg-sky-400", count: 3 }, { id: "folder-travail-projets-archive", label: "Archives projets", color: "bg-slate-400", count: 5 }, ], }, { id: "folder-travail-rh", label: "RH", color: "bg-blue-400", count: 5 }, ], }, { id: "folder-perso", label: "Personnel", color: "bg-emerald-500", count: 18, children: [ { id: "folder-perso-voyages", label: "Voyages", color: "bg-emerald-400", count: 6 }, { id: "folder-perso-famille", label: "Famille", color: "bg-emerald-400", count: 12 }, ], }, { id: "folder-factures", label: "Factures", color: "bg-amber-500", count: 42 }, ] export function normalizeLabelRow(row: LabelRowItem): LabelRowItem { return { ...row, tabbed: row.tabbed ?? false, favorite: row.favorite ?? false, excludeFromPrincipal: row.excludeFromPrincipal ?? false, showInMessageList: row.showInMessageList ?? true, enabled: row.enabled ?? true, } } /** Libellés navigation système (onglets + catégories) — ids stables proches du titre. */ export const SYSTEM_NAV_LABEL_DEFAULTS: readonly LabelRowItem[] = [ { id: "promotions", label: "Promotions", color: "bg-[#1e8e3e]", icon: "mdi:tag", tabbed: true, favorite: true, excludeFromPrincipal: true, showInMessageList: false, enabled: true, }, { id: "reseaux-sociaux", label: "Réseaux sociaux", color: "bg-[#0b57d0]", icon: "mdi:account-group", tabbed: true, favorite: true, excludeFromPrincipal: true, showInMessageList: false, enabled: true, }, { id: "newsletters", label: "Newsletters", color: "bg-[#e8710a]", icon: "mdi:email-newsletter", tabbed: true, favorite: true, excludeFromPrincipal: true, showInMessageList: false, enabled: true, }, { id: "mises-a-jour", label: "Mises à jour", color: "bg-[#c5221f]", icon: "mdi:update", tabbed: true, favorite: true, excludeFromPrincipal: true, showInMessageList: false, enabled: true, }, { id: "forums", label: "Forums", color: "bg-[#9334e6]", icon: "mdi:forum", tabbed: true, favorite: true, excludeFromPrincipal: true, showInMessageList: false, enabled: true, }, { id: "achats", label: "Achats", color: "bg-amber-600", icon: "mdi:cart-outline", tabbed: false, favorite: false, excludeFromPrincipal: false, showInMessageList: true, enabled: true, }, { id: "deplacements", label: "Déplacements", color: "bg-teal-600", icon: "mdi:map-marker", tabbed: false, favorite: false, excludeFromPrincipal: false, showInMessageList: true, enabled: true, }, { id: "finance", label: "Finance", color: "bg-indigo-600", icon: "mdi:credit-card-outline", tabbed: false, favorite: false, excludeFromPrincipal: false, showInMessageList: true, enabled: true, }, ] as const export const SYSTEM_NAV_LABEL_ID_SET = new Set(SYSTEM_NAV_LABEL_DEFAULTS.map((r) => r.id)) const DEMO_IMAP_LABEL_ROWS: readonly LabelRowItem[] = [ { id: "imap-sent", label: "[Imap]/Sent", color: "bg-gray-500" }, { id: "imap-trash", label: "[Imap]/Trash", color: "bg-red-400", count: 4 }, { id: "browser-alerts", label: "BrowserAlerts", color: "bg-red-400", count: 1 }, { id: "cctv", label: "CCTV", color: "bg-red-400" }, { id: "cm-security", label: "CMSecurity Alerts", color: "bg-red-400", count: 14 }, { id: "twitch", label: "Twitch", color: "bg-purple-500", count: 137 }, ] /** Tous les libellés par défaut (système + démo IMAP) — ordre stable. */ export const DEFAULT_NAV_LABEL_ROWS: LabelRowItem[] = [ ...SYSTEM_NAV_LABEL_DEFAULTS.map((r) => normalizeLabelRow({ ...r })), ...DEMO_IMAP_LABEL_ROWS.map((r) => normalizeLabelRow({ ...r })), ] /** Snapshot pour filtres quand aucun contexte nav (tests, défaut). */ export const defaultNavLabelRowsSnapshot: LabelRowItem[] = DEFAULT_NAV_LABEL_ROWS.map((r) => ({ ...r })) export function isSystemNavLabelId(id: string): boolean { return SYSTEM_NAV_LABEL_ID_SET.has(id) } /** Libellés visibles en onglets boîte de réception (hors Principale). */ export function tabbedInboxLabelRows(rows: readonly LabelRowItem[]): LabelRowItem[] { return rows.filter((r) => r.enabled !== false && r.tabbed === true) } export function favoriteNavLabelRows(rows: readonly LabelRowItem[]): LabelRowItem[] { return rows.filter((r) => r.enabled !== false && r.favorite === true) } export function nonTabbedNavLabelRows(rows: readonly LabelRowItem[]): LabelRowItem[] { return rows.filter((r) => r.enabled !== false && r.tabbed !== true && SYSTEM_NAV_LABEL_ID_SET.has(r.id)) } export function labelRowById( rows: readonly LabelRowItem[], id: string ): LabelRowItem | undefined { return rows.find((r) => r.id === id) } /** id de ligne sidebar (dossier hiérarchique ou libellé) → libellé pour matcher `email.labels`. */ export const sidebarNavFolderIdToLabel: Readonly> = buildFolderIdToLabelRecord(folderTree, defaultNavLabelRowsSnapshot) /** Libellé Gmail (comme dans `email.labels`) → id de ligne sidebar correspondant. */ export const emailLabelToSidebarFolderId: Readonly> = buildEmailLabelToSidebarFolderId(sidebarNavFolderIdToLabel) /** Libellés navigation dossiers système — hors libellés définis dans `labelRows`. */ const STATIC_NAV_FOLDER_LABELS: Record = { inbox: "Boîte de réception", starred: "Messages suivis", snoozed: "En attente", important: "Important", sent: "Messages envoyés", drafts: "Brouillons", scheduled: "Planifié", spam: "Indésirables", trash: "Corbeille", } /** Libellé lisible pour id de ligne (liste vide, messages d’état). Dossiers / libellés IMAP viennent de l’arbre. */ export function getMailNavFolderLabel( folderId: string, dynamicFolderIdToLabel?: Record ): string { const fromStatic = STATIC_NAV_FOLDER_LABELS[folderId] if (fromStatic) return fromStatic const mapped = dynamicFolderIdToLabel?.[folderId] ?? sidebarNavFolderIdToLabel[folderId] if (mapped && mapped !== "scheduled") return mapped return folderId } export function inboxTabDisplayLabel( inboxTab: string, labelRows: readonly LabelRowItem[], folderIdToLabel: Record ): string { if (inboxTab === "primary") return "Principale" if (inboxTab === "all") return "Tous les messages" const row = labelRowById(labelRows, inboxTab) if (row && row.enabled !== false) return row.label return getMailNavFolderLabel(inboxTab, folderIdToLabel) } export function cloneDefaultFolderTree(): FolderTreeNode[] { return structuredClone(folderTree) } export function cloneDefaultLabelRows(): LabelRowItem[] { return DEFAULT_NAV_LABEL_ROWS.map((r) => ({ ...r })) } const LEGACY_LABEL_ROW_ID_MAP: Record = { purchases: "achats", travel: "deplacements", social: "reseaux-sociaux", updates: "mises-a-jour", notifications: "newsletters", } /** Fusionne la persistance avec les défauts (ids système + nouveaux champs). */ export function reconcileLabelRowsFromPersisted(persisted: LabelRowItem[] | undefined): LabelRowItem[] { const defaults = cloneDefaultLabelRows() const defaultIds = new Set(defaults.map((r) => r.id)) const persistByResolvedId = new Map() for (const p of persisted ?? []) { const resolvedId = LEGACY_LABEL_ROW_ID_MAP[p.id] ?? p.id persistByResolvedId.set(resolvedId, { ...p, id: resolvedId }) } const merged = defaults.map((d) => { const p = persistByResolvedId.get(d.id) if (!p) return { ...d } const row = normalizeLabelRow({ ...d, ...p, id: d.id }) if (SYSTEM_NAV_LABEL_ID_SET.has(d.id)) { return { ...row, icon: d.icon, color: d.color } } return row }) const mergedIds = new Set(merged.map((r) => r.id)) const extras: LabelRowItem[] = [] for (const p of persisted ?? []) { const resolvedId = LEGACY_LABEL_ROW_ID_MAP[p.id] ?? p.id if (!mergedIds.has(resolvedId)) { extras.push(normalizeLabelRow({ ...p, id: resolvedId })) mergedIds.add(resolvedId) } } return [...merged, ...extras] }