"use client"
import { create } from "zustand"
import { persist } from "zustand/middleware"
import type { Email } from "@/lib/email-data"
export type ScheduleSendPayload = {
sendAtIso: string
to: { name: string; email: string }[]
subject: string
previewText: string
bodyHtml: string
}
type ScheduledStoreState = {
scheduledEmails: Email[]
snoozedEmails: Email[]
sentPlaceholderEmails: Email[]
}
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, email }] : [],
subject: row.subject,
previewText: row.preview,
bodyHtml: row.body ?? `
`,
}
}
type ScheduledStoreActions = {
createScheduledSend: (payload: ScheduleSendPayload) => { id: string }
deleteScheduledSend: (id: string) => void
archiveScheduledSend: (id: string) => void
snoozeScheduledSend: (id: string) => void
rescheduleScheduledSend: (id: string, sendAtIso: string) => void
markScheduledReadState: (id: string, read: boolean) => void
getScheduledEditPayload: (id: string) => ScheduleSendPayload | null
updateScheduledSend: (id: string, payload: ScheduleSendPayload) => void
sendScheduledNow: (id: string) => void
removeScheduledLocal: (id: string) => void
}
export const useScheduledStore = create()(
persist(
(set, get) => ({
scheduledEmails: [],
snoozedEmails: [],
sentPlaceholderEmails: [],
createScheduledSend: (payload) => {
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,
}
set((s) => ({
scheduledEmails: [row, ...s.scheduledEmails.filter((e) => e.id !== id)],
}))
return { id }
},
deleteScheduledSend: (id) =>
set((s) => ({
scheduledEmails: s.scheduledEmails.filter((e) => e.id !== id),
})),
archiveScheduledSend: (id) =>
set((s) => ({
scheduledEmails: s.scheduledEmails.filter((e) => e.id !== id),
})),
snoozeScheduledSend: (id) =>
set((s) => {
const row = s.scheduledEmails.find((e) => e.id === id)
if (!row) return s
const wake = new Date(Date.now() + 24 * 60 * 60 * 1000)
return {
scheduledEmails: s.scheduledEmails.filter((e) => e.id !== id),
snoozedEmails: [
{
...row,
labels: ["snoozed"],
scheduledSendAt: undefined,
scheduledToName: undefined,
snoozeWakeAt: wake.toISOString(),
sender: row.scheduledToName ?? row.sender,
date: wake.toLocaleString("fr-FR", { dateStyle: "medium", timeStyle: "short" }),
read: true,
},
...s.snoozedEmails,
],
}
}),
rescheduleScheduledSend: (id, sendAtIso) =>
set((s) => ({
scheduledEmails: s.scheduledEmails.map((e) =>
e.id === id ? { ...e, scheduledSendAt: sendAtIso } : e
),
})),
markScheduledReadState: (id, read) =>
set((s) => ({
scheduledEmails: s.scheduledEmails.map((e) =>
e.id === id ? { ...e, read } : e
),
})),
getScheduledEditPayload: (id) => {
const row = get().scheduledEmails.find((e) => e.id === id)
if (!row) return null
return rowToSchedulePayload(row)
},
updateScheduledSend: (id, payload) =>
set((s) => {
const first = payload.to[0]
const toName = first?.name?.trim() || first?.email || "Destinataire"
return {
scheduledEmails: s.scheduledEmails.map((e) =>
e.id === id
? {
...e,
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,
}
: e
),
}
}),
sendScheduledNow: (id) =>
set((s) => {
const row = s.scheduledEmails.find((e) => e.id === id)
if (!row) return s
const now = new Date()
return {
scheduledEmails: s.scheduledEmails.filter((e) => e.id !== id),
sentPlaceholderEmails: [
{
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"],
},
...s.sentPlaceholderEmails,
],
}
}),
removeScheduledLocal: (id) =>
set((s) => ({
scheduledEmails: s.scheduledEmails.filter((e) => e.id !== id),
})),
}),
{
name: "ultimail-scheduled-state",
version: 1,
}
)
)