import type { SupabaseClient } from '@supabase/supabase-js'; import type { Database, DepartmentDashboard, DashboardPanel, DepartmentChecklist, DepartmentChecklistItem, DepartmentNote, ModuleType, LayoutPreset } from '$lib/supabase/types'; import { createLogger } from '$lib/utils/logger'; const log = createLogger('api.department-dashboard'); // ============================================================ // Dashboard // ============================================================ export interface DashboardWithPanels extends DepartmentDashboard { panels: DashboardPanel[]; } export async function fetchDashboard( supabase: SupabaseClient, departmentId: string ): Promise { const { data, error } = await supabase .from('department_dashboards') .select('*, panels:dashboard_panels(*)') .eq('department_id', departmentId) .single(); if (error) { if (error.code === 'PGRST116') return null; log.error('fetchDashboard failed', { error, data: { departmentId } }); throw error; } const dashboard = data as any; return { ...dashboard, panels: (dashboard.panels ?? []).sort((a: DashboardPanel, b: DashboardPanel) => a.position - b.position), }; } export async function updateDashboardLayout( supabase: SupabaseClient, dashboardId: string, layout: LayoutPreset ): Promise { const { data, error } = await supabase .from('department_dashboards') .update({ layout, updated_at: new Date().toISOString() }) .eq('id', dashboardId) .select() .single(); if (error) { log.error('updateDashboardLayout failed', { error, data: { dashboardId, layout } }); throw error; } return data as unknown as DepartmentDashboard; } // ============================================================ // Panels // ============================================================ export async function addPanel( supabase: SupabaseClient, dashboardId: string, module: ModuleType, position: number, width: string = 'half' ): Promise { const { data, error } = await supabase .from('dashboard_panels') .insert({ dashboard_id: dashboardId, module, position, width }) .select() .single(); if (error) { log.error('addPanel failed', { error, data: { dashboardId, module } }); throw error; } return data as unknown as DashboardPanel; } export async function updatePanel( supabase: SupabaseClient, panelId: string, params: Partial> ): Promise { const { data, error } = await supabase .from('dashboard_panels') .update(params) .eq('id', panelId) .select() .single(); if (error) { log.error('updatePanel failed', { error, data: { panelId } }); throw error; } return data as unknown as DashboardPanel; } export async function removePanel( supabase: SupabaseClient, panelId: string ): Promise { const { error } = await supabase .from('dashboard_panels') .delete() .eq('id', panelId); if (error) { log.error('removePanel failed', { error, data: { panelId } }); throw error; } } // ============================================================ // Checklists // ============================================================ export interface ChecklistWithItems extends DepartmentChecklist { items: DepartmentChecklistItem[]; } export async function fetchChecklists( supabase: SupabaseClient, departmentId: string ): Promise { const { data: checklists, error } = await supabase .from('department_checklists') .select('*') .eq('department_id', departmentId) .order('sort_order'); if (error) { log.error('fetchChecklists failed', { error, data: { departmentId } }); throw error; } if (!checklists || checklists.length === 0) return []; const checklistIds = checklists.map(c => c.id); const { data: items, error: itemsError } = await supabase .from('department_checklist_items') .select('*') .in('checklist_id', checklistIds) .order('sort_order'); if (itemsError) { log.error('fetchChecklistItems failed', { error: itemsError }); throw itemsError; } const itemsByChecklist: Record = {}; for (const item of (items ?? [])) { if (!itemsByChecklist[item.checklist_id]) itemsByChecklist[item.checklist_id] = []; itemsByChecklist[item.checklist_id].push(item as unknown as DepartmentChecklistItem); } return checklists.map(c => ({ ...(c as unknown as DepartmentChecklist), items: itemsByChecklist[c.id] ?? [], })); } export async function createChecklist( supabase: SupabaseClient, departmentId: string, title: string, userId?: string ): Promise { const { data, error } = await supabase .from('department_checklists') .insert({ department_id: departmentId, title, created_by: userId ?? null }) .select() .single(); if (error) { log.error('createChecklist failed', { error, data: { departmentId, title } }); throw error; } return data as unknown as DepartmentChecklist; } export async function deleteChecklist( supabase: SupabaseClient, checklistId: string ): Promise { const { error } = await supabase .from('department_checklists') .delete() .eq('id', checklistId); if (error) { log.error('deleteChecklist failed', { error, data: { checklistId } }); throw error; } } export async function renameChecklist( supabase: SupabaseClient, checklistId: string, title: string ): Promise { const { data, error } = await supabase .from('department_checklists') .update({ title }) .eq('id', checklistId) .select() .single(); if (error) { log.error('renameChecklist failed', { error, data: { checklistId, title } }); throw error; } return data as unknown as DepartmentChecklist; } // ============================================================ // Checklist Items // ============================================================ export async function addChecklistItem( supabase: SupabaseClient, checklistId: string, content: string, sortOrder: number = 0 ): Promise { const { data, error } = await supabase .from('department_checklist_items') .insert({ checklist_id: checklistId, content, sort_order: sortOrder }) .select() .single(); if (error) { log.error('addChecklistItem failed', { error, data: { checklistId, content } }); throw error; } return data as unknown as DepartmentChecklistItem; } export async function updateChecklistItem( supabase: SupabaseClient, itemId: string, params: Partial> ): Promise { const { data, error } = await supabase .from('department_checklist_items') .update({ ...params, updated_at: new Date().toISOString() }) .eq('id', itemId) .select() .single(); if (error) { log.error('updateChecklistItem failed', { error, data: { itemId } }); throw error; } return data as unknown as DepartmentChecklistItem; } export async function deleteChecklistItem( supabase: SupabaseClient, itemId: string ): Promise { const { error } = await supabase .from('department_checklist_items') .delete() .eq('id', itemId); if (error) { log.error('deleteChecklistItem failed', { error, data: { itemId } }); throw error; } } export async function toggleChecklistItem( supabase: SupabaseClient, itemId: string, isCompleted: boolean ): Promise { return updateChecklistItem(supabase, itemId, { is_completed: isCompleted }); } // ============================================================ // Notes // ============================================================ export async function fetchNotes( supabase: SupabaseClient, departmentId: string ): Promise { const { data, error } = await supabase .from('department_notes') .select('*') .eq('department_id', departmentId) .order('sort_order'); if (error) { log.error('fetchNotes failed', { error, data: { departmentId } }); throw error; } return (data ?? []) as unknown as DepartmentNote[]; } export async function createNote( supabase: SupabaseClient, departmentId: string, title: string, userId?: string ): Promise { const { data, error } = await supabase .from('department_notes') .insert({ department_id: departmentId, title, created_by: userId ?? null }) .select() .single(); if (error) { log.error('createNote failed', { error, data: { departmentId, title } }); throw error; } return data as unknown as DepartmentNote; } export async function updateNote( supabase: SupabaseClient, noteId: string, params: Partial> ): Promise { const { data, error } = await supabase .from('department_notes') .update({ ...params, updated_at: new Date().toISOString() }) .eq('id', noteId) .select() .single(); if (error) { log.error('updateNote failed', { error, data: { noteId } }); throw error; } return data as unknown as DepartmentNote; } export async function deleteNote( supabase: SupabaseClient, noteId: string ): Promise { const { error } = await supabase .from('department_notes') .delete() .eq('id', noteId); if (error) { log.error('deleteNote failed', { error, data: { noteId } }); throw error; } }