diff --git a/frontend/src/store/mailStore.ts b/frontend/src/store/mailStore.ts new file mode 100644 index 00000000..2ff3294f --- /dev/null +++ b/frontend/src/store/mailStore.ts @@ -0,0 +1,75 @@ +import { create } from 'zustand' +import { persist } from 'zustand/middleware' + +export interface Folder { name: string; display: string; unread: number; total: number } +export interface MailSummary { + uid: string; subject: string; sender: string; sender_addr: string + date: string; is_read: boolean; has_attachment: boolean; size: number; preview: string +} +export interface MailDetail extends MailSummary { + to: string; cc: string; body_text: string; body_html: string + attachments: { part_id: string; filename: string; content_type: string; size: number }[] +} + +interface MailStore { + token: string | null + username: string + displayName: string + folders: Folder[] + currentFolder: string + messages: MailSummary[] + totalMessages: number + currentPage: number + selectedMail: MailDetail | null + loading: boolean + searchQuery: string + composeOpen: boolean + replyTo: MailDetail | null + + setToken: (token: string, username: string, displayName: string) => void + logout: () => void + setFolders: (f: Folder[]) => void + setCurrentFolder: (f: string) => void + setMessages: (m: MailSummary[], total: number, page: number) => void + setSelectedMail: (m: MailDetail | null) => void + setLoading: (v: boolean) => void + setSearchQuery: (q: string) => void + openCompose: (replyTo?: MailDetail | null) => void + closeCompose: () => void + markRead: (uid: string) => void + removeMessage: (uid: string) => void +} + +export const useMailStore = create()( + persist( + (set) => ({ + token: null, username: '', displayName: '', + folders: [], currentFolder: 'INBOX', + messages: [], totalMessages: 0, currentPage: 1, + selectedMail: null, loading: false, + searchQuery: '', composeOpen: false, replyTo: null, + + setToken: (token, username, displayName) => set({ token, username, displayName }), + logout: () => set({ token: null, username: '', displayName: '', messages: [], selectedMail: null }), + setFolders: (folders) => set({ folders }), + setCurrentFolder: (currentFolder) => set({ currentFolder, messages: [], selectedMail: null, currentPage: 1 }), + setMessages: (messages, totalMessages, currentPage) => set({ messages, totalMessages, currentPage }), + setSelectedMail: (selectedMail) => set({ selectedMail }), + setLoading: (loading) => set({ loading }), + setSearchQuery: (searchQuery) => set({ searchQuery }), + openCompose: (replyTo = null) => set({ composeOpen: true, replyTo }), + closeCompose: () => set({ composeOpen: false, replyTo: null }), + markRead: (uid) => set(s => ({ + messages: s.messages.map(m => m.uid === uid ? { ...m, is_read: true } : m), + folders: s.folders.map(f => + f.name === s.currentFolder ? { ...f, unread: Math.max(0, f.unread - 1) } : f + ), + })), + removeMessage: (uid) => set(s => ({ + messages: s.messages.filter(m => m.uid !== uid), + selectedMail: s.selectedMail?.uid === uid ? null : s.selectedMail, + })), + }), + { name: 'zioinfo-mail', partialize: s => ({ token: s.token, username: s.username, displayName: s.displayName }) } + ) +)