ultisuite-client/lib/stores/scheduled-store.ts
R3D347HR4Y c87670e90f
Some checks failed
E2E / Playwright e2e (push) Has been cancelled
feat(api): offline-first mail sync w/ TanStack Query
Move mail, compose, contacts, and accounts off mocks onto REST + WS.
Add client, auth store, IDB-backed query cache, offline queue, and
sync bar; hybrid Zustand for UI-only state. Settings still local until
backend has preferences API.
2026-05-23 00:04:28 +02:00

95 lines
2.7 KiB
TypeScript

"use client"
import { create } from "zustand"
import { persist } from "zustand/middleware"
import { debouncedPersistJSONStorage } from "@/lib/stores/debounced-json-storage"
import type { Email } from "@/lib/email-data"
export interface OutboxEntry {
id: string
account_id: string
status: "queued" | "scheduled" | "sending" | "sent" | "failed" | "cancelled"
subject: string
to: { name: string; address: string }[]
scheduled_at?: string
created_at: string
}
type ScheduledStoreState = {
scheduledEmails: OutboxEntry[]
snoozedEmails: Email[]
}
type ScheduledStoreActions = {
addScheduledEmail: (entry: OutboxEntry) => void
updateScheduledStatus: (id: string, status: OutboxEntry["status"]) => void
removeScheduled: (id: string) => void
snoozeMailboxEmail: (row: Email) => void
restoreSnoozedToInbox: (row: Email) => void
}
export const useScheduledStore = create<ScheduledStoreState & ScheduledStoreActions>()(
persist(
(set) => ({
scheduledEmails: [],
snoozedEmails: [],
addScheduledEmail: (entry) =>
set((s) => ({
scheduledEmails: [entry, ...s.scheduledEmails.filter((e) => e.id !== entry.id)],
})),
updateScheduledStatus: (id, status) =>
set((s) => ({
scheduledEmails: s.scheduledEmails.map((e) =>
e.id === id ? { ...e, status } : e
),
})),
removeScheduled: (id) =>
set((s) => ({
scheduledEmails: s.scheduledEmails.filter((e) => e.id !== id),
})),
snoozeMailboxEmail: (row) =>
set((s) => {
const persistedId = row.id.startsWith("snz-") ? row.id : `snz-${row.id}`
const wake = new Date(Date.now() + 24 * 60 * 60 * 1000)
const wakeIso = wake.toISOString()
const copy: Email = {
...row,
id: persistedId,
labels: ["snoozed"],
snoozeWakeAt: wakeIso,
scheduledSendAt: undefined,
scheduledToName: undefined,
read: true,
}
return {
snoozedEmails: [
copy,
...s.snoozedEmails.filter((e) => e.id !== persistedId),
],
}
}),
restoreSnoozedToInbox: (row) =>
set((s) => ({
snoozedEmails: s.snoozedEmails.filter((e) => e.id !== row.id),
})),
}),
{
name: "ultimail-scheduled-state",
storage: debouncedPersistJSONStorage,
version: 2,
migrate: (persisted) => {
const state = persisted as Record<string, unknown>
return {
scheduledEmails: [],
snoozedEmails: Array.isArray(state.snoozedEmails) ? state.snoozedEmails : [],
}
},
}
)
)