214 lines
6.5 KiB
TypeScript
214 lines
6.5 KiB
TypeScript
/**
|
||
* API envois planifiés / attente / envoi immédiat — placeholders jusqu’au branchement serveur.
|
||
* Remplacer par fetch() vers vos routes (ex. POST /api/mail/scheduled, …).
|
||
*/
|
||
|
||
import type { Email } from "@/lib/email-data"
|
||
|
||
export type ScheduleSendPayload = {
|
||
sendAtIso: string
|
||
to: { name: string; email: string }[]
|
||
subject: string
|
||
previewText: string
|
||
bodyHtml: string
|
||
}
|
||
|
||
let scheduledStore: Email[] = []
|
||
let snoozedStore: Email[] = []
|
||
let sentPlaceholderStore: Email[] = []
|
||
|
||
export function __resetScheduledMailPlaceholderStoreForTests() {
|
||
scheduledStore = []
|
||
snoozedStore = []
|
||
sentPlaceholderStore = []
|
||
}
|
||
|
||
export async function listScheduledSends(): Promise<Email[]> {
|
||
// TODO: fetch GET /api/mail/scheduled
|
||
await Promise.resolve()
|
||
return [...scheduledStore]
|
||
}
|
||
|
||
export async function listSnoozedSends(): Promise<Email[]> {
|
||
// TODO: fetch GET /api/mail/snoozed
|
||
await Promise.resolve()
|
||
return [...snoozedStore]
|
||
}
|
||
|
||
export async function listSentPlaceholder(): Promise<Email[]> {
|
||
// TODO: fusion avec réponse serveur « Envoyés »
|
||
await Promise.resolve()
|
||
return [...sentPlaceholderStore]
|
||
}
|
||
|
||
export async function createScheduledSend(
|
||
payload: ScheduleSendPayload
|
||
): Promise<{ id: string }> {
|
||
// TODO: POST /api/mail/scheduled
|
||
await Promise.resolve()
|
||
const id = `sched-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`
|
||
const first = payload.to[0]
|
||
const toName = first?.name?.trim() || first?.email || "Destinataire"
|
||
const row: Email = {
|
||
id,
|
||
sender: toName,
|
||
senderEmail: first?.email,
|
||
subject: payload.subject.trim() || "(Sans objet)",
|
||
preview: payload.previewText.slice(0, 200),
|
||
body: payload.bodyHtml,
|
||
date: "",
|
||
read: true,
|
||
starred: false,
|
||
important: false,
|
||
category: "primary",
|
||
labels: ["scheduled"],
|
||
scheduledSendAt: payload.sendAtIso,
|
||
scheduledToName: toName,
|
||
}
|
||
scheduledStore = [row, ...scheduledStore.filter((e) => e.id !== id)]
|
||
return { id }
|
||
}
|
||
|
||
export async function deleteScheduledSend(id: string): Promise<void> {
|
||
// TODO: DELETE /api/mail/scheduled/:id
|
||
await Promise.resolve()
|
||
scheduledStore = scheduledStore.filter((e) => e.id !== id)
|
||
}
|
||
|
||
export async function archiveScheduledSend(id: string): Promise<void> {
|
||
// TODO: POST /api/mail/scheduled/:id/archive
|
||
await Promise.resolve()
|
||
scheduledStore = scheduledStore.filter((e) => e.id !== id)
|
||
}
|
||
|
||
/** Retire de « planifié » et place dans « En attente » (snooze). */
|
||
export async function snoozeScheduledSend(id: string): Promise<void> {
|
||
// TODO: POST /api/mail/scheduled/:id/snooze
|
||
await Promise.resolve()
|
||
const i = scheduledStore.findIndex((e) => e.id === id)
|
||
if (i === -1) return
|
||
const row = scheduledStore[i]!
|
||
scheduledStore = scheduledStore.filter((e) => e.id !== id)
|
||
const wake = new Date(Date.now() + 24 * 60 * 60 * 1000)
|
||
const wakeIso = wake.toISOString()
|
||
snoozedStore.unshift({
|
||
...row,
|
||
labels: ["snoozed"],
|
||
scheduledSendAt: undefined,
|
||
scheduledToName: undefined,
|
||
snoozeWakeAt: wakeIso,
|
||
sender: row.scheduledToName ?? row.sender,
|
||
date: wake.toLocaleString("fr-FR", { dateStyle: "medium", timeStyle: "short" }),
|
||
read: true,
|
||
})
|
||
}
|
||
|
||
export async function rescheduleScheduledSend(
|
||
id: string,
|
||
sendAtIso: string
|
||
): Promise<void> {
|
||
// TODO: PATCH /api/mail/scheduled/:id { sendAt }
|
||
await Promise.resolve()
|
||
const idx = scheduledStore.findIndex((e) => e.id === id)
|
||
if (idx === -1) return
|
||
scheduledStore[idx] = {
|
||
...scheduledStore[idx]!,
|
||
scheduledSendAt: sendAtIso,
|
||
}
|
||
}
|
||
|
||
function rowToSchedulePayload(row: Email): ScheduleSendPayload {
|
||
const email = row.senderEmail?.trim() ?? ""
|
||
const name = row.scheduledToName ?? row.sender
|
||
return {
|
||
sendAtIso: row.scheduledSendAt ?? new Date().toISOString(),
|
||
to: email ? [{ name: name, email }] : [],
|
||
subject: row.subject,
|
||
previewText: row.preview,
|
||
bodyHtml: row.body ?? `<p></p>`,
|
||
}
|
||
}
|
||
|
||
/** Lecture seule pour ouvrir le compose sans retirer de la liste « Planifié ». */
|
||
export async function getScheduledSendPayloadForEdit(
|
||
id: string
|
||
): Promise<ScheduleSendPayload | null> {
|
||
// TODO: GET /api/mail/scheduled/:id/edit
|
||
await Promise.resolve()
|
||
const row = scheduledStore.find((e) => e.id === id)
|
||
if (!row) return null
|
||
return rowToSchedulePayload(row)
|
||
}
|
||
|
||
/** Met à jour contenu + date d’envoi pour un id planifié existant. */
|
||
export async function updateScheduledSend(
|
||
id: string,
|
||
payload: ScheduleSendPayload
|
||
): Promise<void> {
|
||
// TODO: PUT /api/mail/scheduled/:id
|
||
await Promise.resolve()
|
||
const idx = scheduledStore.findIndex((e) => e.id === id)
|
||
if (idx === -1) return
|
||
const row = scheduledStore[idx]!
|
||
const first = payload.to[0]
|
||
const toName = first?.name?.trim() || first?.email || "Destinataire"
|
||
scheduledStore[idx] = {
|
||
...row,
|
||
sender: toName,
|
||
senderEmail: first?.email,
|
||
subject: payload.subject.trim() || "(Sans objet)",
|
||
preview: payload.previewText.slice(0, 200),
|
||
body: payload.bodyHtml,
|
||
scheduledSendAt: payload.sendAtIso,
|
||
scheduledToName: toName,
|
||
}
|
||
}
|
||
|
||
/** Retire le planifié et renvoie le contenu (ex. flux legacy). */
|
||
export async function popScheduledSendForEdit(
|
||
id: string
|
||
): Promise<ScheduleSendPayload | null> {
|
||
// TODO: POST /api/mail/scheduled/:id/edit-session
|
||
await Promise.resolve()
|
||
const i = scheduledStore.findIndex((e) => e.id === id)
|
||
if (i === -1) return null
|
||
const row = scheduledStore[i]!
|
||
scheduledStore = scheduledStore.filter((e) => e.id !== id)
|
||
return rowToSchedulePayload(row)
|
||
}
|
||
|
||
export async function sendScheduledNow(id: string): Promise<void> {
|
||
// TODO: POST /api/mail/scheduled/:id/send-now
|
||
await Promise.resolve()
|
||
const i = scheduledStore.findIndex((e) => e.id === id)
|
||
if (i === -1) return
|
||
const row = scheduledStore[i]!
|
||
scheduledStore = scheduledStore.filter((e) => e.id !== id)
|
||
const now = new Date()
|
||
sentPlaceholderStore.unshift({
|
||
id: `sent-now-${Date.now()}-${Math.random().toString(36).slice(2, 5)}`,
|
||
sender: row.scheduledToName ?? row.sender,
|
||
senderEmail: row.senderEmail,
|
||
subject: row.subject,
|
||
preview: row.preview,
|
||
body: row.body,
|
||
date: now.toLocaleString("fr-FR", { dateStyle: "short", timeStyle: "short" }),
|
||
read: true,
|
||
starred: false,
|
||
important: false,
|
||
category: "primary",
|
||
labels: ["sent"],
|
||
})
|
||
}
|
||
|
||
export async function markScheduledSendReadState(
|
||
id: string,
|
||
read: boolean
|
||
): Promise<void> {
|
||
// TODO: PATCH
|
||
await Promise.resolve()
|
||
const i = scheduledStore.findIndex((e) => e.id === id)
|
||
if (i === -1) return
|
||
scheduledStore[i] = { ...scheduledStore[i]!, read }
|
||
}
|