ultisuite-client/lib/demo/demo-contacts-store.ts
R3D347HR4Y ad1370ea7e
Some checks are pending
E2E / Playwright e2e (push) Waiting to run
feat: enhance configuration and add new demo layouts
- Introduced turbopack alias for canvas in next.config.mjs.
- Updated package.json scripts for development and branding tasks.
- Added new dependencies for Tiptap extensions.
- Implemented new demo layouts for agenda, contacts, drive, and mail applications.
- Enhanced globals.css for improved theming and splash screen animations.
- Added OAuth callback handling for drive mounts.
- Updated layout components to integrate new demo shells and improve structure.
2026-06-12 19:10:24 +02:00

109 lines
2.9 KiB
TypeScript

"use client"
import { create } from "zustand"
import { fullContactToApiContact } from "@/lib/api/adapters"
import type { ApiContact } from "@/lib/api/types"
import { DEMO_FULL_CONTACTS } from "@/components/demo/demo-contacts-data"
import type { FullContact } from "@/lib/contacts/types"
import { rankApiContacts } from "@/lib/contacts/contact-match-score"
const DEMO_BOOK_ID = "contacts"
function toDemoContact(full: FullContact): ApiContact {
const partial = fullContactToApiContact(full)
return {
uid: full.id,
full_name: partial.full_name ?? "Contact",
email: partial.email,
phone: partial.phone,
org: partial.org,
path: `books/${DEMO_BOOK_ID}/${full.id}.vcf`,
etag: `"demo-${full.id}"`,
raw_vcard: partial.raw_vcard,
}
}
function createInitialContacts(): ApiContact[] {
return DEMO_FULL_CONTACTS.map(toDemoContact)
}
type DemoContactsStoreState = {
active: boolean
contacts: ApiContact[]
version: number
}
type DemoContactsStoreActions = {
reset: () => void
bump: () => void
listBooks: () => { id: string; name: string }[]
listContacts: (bookId: string) => ApiContact[]
searchContacts: (query: string) => ApiContact[]
createContact: (bookId: string, contact: Partial<ApiContact>) => ApiContact
updateContact: (path: string, contact: Partial<ApiContact>) => void
deleteContact: (path: string) => void
}
export const useDemoContactsStore = create<
DemoContactsStoreState & DemoContactsStoreActions
>( (set, get) => ({
active: false,
contacts: [],
version: 0,
reset: () =>
set({
active: true,
contacts: createInitialContacts(),
version: get().version + 1,
}),
bump: () => set({ version: get().version + 1 }),
listBooks: () => [{ id: DEMO_BOOK_ID, name: "Contacts" }],
listContacts: (bookId) => {
if (bookId !== DEMO_BOOK_ID) return []
return get().contacts
},
searchContacts: (query) => rankApiContacts(get().contacts, query),
createContact: (bookId, contact) => {
const uid = contact.uid ?? `demo-contact-${crypto.randomUUID().slice(0, 8)}`
const created: ApiContact = {
uid,
full_name: contact.full_name ?? "Contact",
email: contact.email,
phone: contact.phone,
org: contact.org,
path: `books/${bookId}/${uid}.vcf`,
etag: `"demo-${uid}"`,
raw_vcard: contact.raw_vcard,
}
set((state) => ({
contacts: [...state.contacts, created],
version: state.version + 1,
}))
return created
},
updateContact: (path, contact) => {
set((state) => ({
contacts: state.contacts.map((c) =>
c.path === path || c.uid === path
? { ...c, ...contact, path: c.path, uid: c.uid, etag: `"demo-${c.uid}-v2"` }
: c
),
version: state.version + 1,
}))
},
deleteContact: (path) => {
set((state) => ({
contacts: state.contacts.filter((c) => c.path !== path && c.uid !== path),
version: state.version + 1,
}))
},
}))