import { pb } from "@/lib/pocketbase"; import { toast } from "solid-sonner"; import { createDefaultFilter, type Filter, type FilterTemplate, readScopedPrefs, setStore, store, writeScopedPrefs } from "./state"; export const syncPreferences = async () => { const userId = pb.authStore.model?.id; if (!userId) return; try { const user = await pb.collection("users").getOne(userId, { requestKey: null }); const rawPrefs = user.Taskgrid_pref || {}; const prefs = { pWeight: store.pWeight, uWeight: store.uWeight, matrixScaleDays: store.matrixScaleDays, tagDefinitions: store.tagDefinitions.filter(def => !def.name.startsWith("@")), filterTemplates: store.filterTemplates, quickloadTasks: store.quickloadTasks, dismissedTaskUpdateIndicators: store.dismissedTaskUpdateIndicators, collapsedUntilUpdatedTasks: store.collapsedUntilUpdatedTasks, subscribedBuckets: store.subscribedBuckets, supervisorUserIds: store.personalContextSupervisorIds, aiHelpTipHistory: store.aiHelpTipHistory, lastCompletedTaskCleanupDate: store.lastCompletedTaskCleanupDate }; await pb.collection("users").update(userId, { Taskgrid_pref: writeScopedPrefs(rawPrefs, { ...readScopedPrefs(rawPrefs), ...prefs }) }, { requestKey: null }); } catch (e: any) { if (e.isAbort) return; console.error("Failed to sync preferences", e); } }; export const setFilter = (update: Partial) => { setStore("filter", f => ({ ...f, ...update })); }; export const loadFilterTemplates = async () => { if (!pb.authStore.isValid) return; const userId = pb.authStore.model?.id; if (!userId) return; const user = await pb.collection("users").getOne(userId, { requestKey: null }); const prefs = readScopedPrefs(user.Taskgrid_pref || {}); setStore("filterTemplates", prefs.filterTemplates || []); }; export const saveFilterTemplate = async (name: string) => { if (!pb.authStore.isValid) return; try { const newTemplate: FilterTemplate = { id: `filter-${Date.now()}`, name, filter: store.filter }; setStore("filterTemplates", prev => [...prev, newTemplate]); await syncPreferences(); toast.success(`Filter template "${name}" saved`); } catch (err) { console.error("Failed to save filter template:", err); toast.error("Failed to save filter template."); } }; export const applyFilterTemplate = (id: string) => { const template = store.filterTemplates.find(t => t.id === id); if (template) { setFilter(template.filter); toast.success(`Applied filter: ${template.name}`); } }; export const removeFilterTemplate = async (id: string) => { if (!pb.authStore.isValid) return; try { setStore("filterTemplates", prev => prev.filter(t => t.id !== id)); await syncPreferences(); toast.success("Filter template deleted"); } catch (err) { console.error("Failed to delete filter template:", err); toast.error("Failed to delete filter template."); } }; export const clearFilter = () => { setStore("filter", createDefaultFilter()); }; export const setNoteFilter = (update: Partial) => { setStore("noteFilter", f => ({ ...f, ...update })); }; export const loadNoteFilterTemplates = async () => { if (!pb.authStore.isValid) return; const userId = pb.authStore.model?.id; if (!userId) return; const user = await pb.collection("users").getOne(userId, { requestKey: null }); const prefs = readScopedPrefs(user.Taskgrid_pref || {}); setStore("filterTemplates", prefs.noteFilterTemplates || []); }; export const saveNoteFilterTemplate = async (name: string) => { if (!pb.authStore.isValid) return; try { const newTemplate: FilterTemplate = { id: `note-filter-${Date.now()}`, name, filter: store.noteFilter }; setStore("filterTemplates", prev => [...prev, newTemplate]); const userId = pb.authStore.model?.id; if (userId) { const user = await pb.collection("users").getOne(userId, { requestKey: null }); const rawPrefs = user.Taskgrid_pref || {}; const prefs = readScopedPrefs(rawPrefs); await pb.collection("users").update(userId, { Taskgrid_pref: writeScopedPrefs(rawPrefs, { ...prefs, noteFilterTemplates: [...(prefs.noteFilterTemplates || []), newTemplate] }) }, { requestKey: null }); } toast.success(`Note filter template "${name}" saved`); } catch (err) { console.error("Failed to save note filter template:", err); toast.error("Failed to save note filter template."); } }; export const applyNoteFilterTemplate = (id: string) => { const template = store.filterTemplates.find(t => t.id === id); if (template) { setNoteFilter(template.filter); toast.success(`Applied note filter: ${template.name}`); } }; export const removeNoteFilterTemplate = async (id: string) => { if (!pb.authStore.isValid) return; try { setStore("filterTemplates", prev => prev.filter(t => t.id !== id)); const userId = pb.authStore.model?.id; if (userId) { const user = await pb.collection("users").getOne(userId, { requestKey: null }); const rawPrefs = user.Taskgrid_pref || {}; const prefs = readScopedPrefs(rawPrefs); await pb.collection("users").update(userId, { Taskgrid_pref: writeScopedPrefs(rawPrefs, { ...prefs, noteFilterTemplates: (prefs.noteFilterTemplates || []).filter((template: FilterTemplate) => template.id !== id) }) }, { requestKey: null }); } toast.success("Note filter template deleted"); } catch (err) { console.error("Failed to delete note filter template:", err); toast.error("Failed to delete note filter template."); } }; export const clearNoteFilter = () => { setStore("noteFilter", createDefaultFilter()); }; export const appendAIHelpTipHistory = async (tip: string) => { const normalizedTip = tip.trim(); if (!normalizedTip) return; setStore("aiHelpTipHistory", prev => { const next = [...prev.filter(existing => existing !== normalizedTip), normalizedTip]; return next.slice(-10); }); await syncPreferences(); };