ultisuite-client/lib/contacts/contacts-store.ts
R3D347HR4Y ae54fa29e4 Hehe
2026-05-18 17:47:32 +02:00

143 lines
3.9 KiB
TypeScript

"use client"
import { create } from "zustand"
import { persist } from "zustand/middleware"
import { debouncedPersistJSONStorage } from "@/lib/stores/debounced-json-storage"
import { MOCK_FULL_CONTACTS } from "./mock-data"
import type { FullContact } from "./types"
type ContactsView = "list" | "view" | "create" | "edit"
/** Prefill for "Nouveau contact" opened from hover card / elsewhere. */
export type ContactCreateDraft = {
firstName?: string
lastName?: string
emails?: { value: string; label: string }[]
}
interface ContactsState {
contacts: FullContact[]
panelOpen: boolean
view: ContactsView
activeContactId: string | null
searchQuery: string
searchMode: boolean
createDraft: ContactCreateDraft | null
}
interface ContactsActions {
togglePanel: () => void
openPanel: () => void
closePanel: () => void
openContactDetail: (contactId: string) => void
openCreateContact: (draft?: ContactCreateDraft | null) => void
clearCreateDraft: () => void
setView: (view: ContactsView, activeContactId?: string | null) => void
setSearchQuery: (q: string) => void
setSearchMode: (active: boolean) => void
addContact: (
contact: Omit<FullContact, "id" | "createdAt" | "updatedAt">
) => string
updateContact: (id: string, patch: Partial<FullContact>) => void
deleteContact: (id: string) => void
}
export type ContactsStore = ContactsState & ContactsActions
export const useContactsStore = create<ContactsStore>()(
persist(
(set) => ({
contacts: MOCK_FULL_CONTACTS,
panelOpen: false,
view: "list",
activeContactId: null,
searchQuery: "",
searchMode: false,
createDraft: null,
togglePanel: () =>
set((s) =>
s.panelOpen
? {
panelOpen: false,
view: "list",
activeContactId: null,
searchQuery: "",
searchMode: false,
createDraft: null,
}
: { panelOpen: true }
),
openPanel: () => set({ panelOpen: true }),
closePanel: () =>
set({
panelOpen: false,
view: "list",
activeContactId: null,
searchQuery: "",
searchMode: false,
createDraft: null,
}),
openContactDetail: (contactId) =>
set({
panelOpen: true,
view: "view",
activeContactId: contactId,
searchQuery: "",
searchMode: false,
createDraft: null,
}),
openCreateContact: (draft = null) =>
set({
panelOpen: true,
view: "create",
activeContactId: null,
searchQuery: "",
searchMode: false,
createDraft: draft,
}),
clearCreateDraft: () => set({ createDraft: null }),
setView: (view, activeContactId = null) =>
set({ view, activeContactId, createDraft: null }),
setSearchQuery: (searchQuery) => set({ searchQuery }),
setSearchMode: (searchMode) =>
set(searchMode ? { searchMode } : { searchMode, searchQuery: "" }),
addContact: (contact) => {
const id = `contact-${crypto.randomUUID()}`
const now = Date.now()
const full: FullContact = { ...contact, id, createdAt: now, updatedAt: now }
set((s) => ({ contacts: [...s.contacts, full] }))
return id
},
updateContact: (id, patch) =>
set((s) => ({
contacts: s.contacts.map((c) =>
c.id === id ? { ...c, ...patch, updatedAt: Date.now() } : c
),
})),
deleteContact: (id) =>
set((s) => ({
contacts: s.contacts.filter((c) => c.id !== id),
activeContactId: s.activeContactId === id ? null : s.activeContactId,
view: s.activeContactId === id ? "list" : s.view,
})),
}),
{
name: "contacts-store",
storage: debouncedPersistJSONStorage,
partialize: (state) => ({ contacts: state.contacts }),
}
)
)