Mega push vol 7 mvp lesgoooo
This commit is contained in:
354
src/lib/api/department-dashboard.ts
Normal file
354
src/lib/api/department-dashboard.ts
Normal file
@@ -0,0 +1,354 @@
|
||||
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<Database>,
|
||||
departmentId: string
|
||||
): Promise<DashboardWithPanels | null> {
|
||||
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<Database>,
|
||||
dashboardId: string,
|
||||
layout: LayoutPreset
|
||||
): Promise<DepartmentDashboard> {
|
||||
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<Database>,
|
||||
dashboardId: string,
|
||||
module: ModuleType,
|
||||
position: number,
|
||||
width: string = 'half'
|
||||
): Promise<DashboardPanel> {
|
||||
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<Database>,
|
||||
panelId: string,
|
||||
params: Partial<Pick<DashboardPanel, 'position' | 'width' | 'config'>>
|
||||
): Promise<DashboardPanel> {
|
||||
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<Database>,
|
||||
panelId: string
|
||||
): Promise<void> {
|
||||
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<Database>,
|
||||
departmentId: string
|
||||
): Promise<ChecklistWithItems[]> {
|
||||
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<string, DepartmentChecklistItem[]> = {};
|
||||
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<Database>,
|
||||
departmentId: string,
|
||||
title: string,
|
||||
userId?: string
|
||||
): Promise<DepartmentChecklist> {
|
||||
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<Database>,
|
||||
checklistId: string
|
||||
): Promise<void> {
|
||||
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<Database>,
|
||||
checklistId: string,
|
||||
title: string
|
||||
): Promise<DepartmentChecklist> {
|
||||
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<Database>,
|
||||
checklistId: string,
|
||||
content: string,
|
||||
sortOrder: number = 0
|
||||
): Promise<DepartmentChecklistItem> {
|
||||
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<Database>,
|
||||
itemId: string,
|
||||
params: Partial<Pick<DepartmentChecklistItem, 'content' | 'is_completed' | 'assigned_to' | 'due_date' | 'sort_order'>>
|
||||
): Promise<DepartmentChecklistItem> {
|
||||
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<Database>,
|
||||
itemId: string
|
||||
): Promise<void> {
|
||||
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<Database>,
|
||||
itemId: string,
|
||||
isCompleted: boolean
|
||||
): Promise<DepartmentChecklistItem> {
|
||||
return updateChecklistItem(supabase, itemId, { is_completed: isCompleted });
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Notes
|
||||
// ============================================================
|
||||
|
||||
export async function fetchNotes(
|
||||
supabase: SupabaseClient<Database>,
|
||||
departmentId: string
|
||||
): Promise<DepartmentNote[]> {
|
||||
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<Database>,
|
||||
departmentId: string,
|
||||
title: string,
|
||||
userId?: string
|
||||
): Promise<DepartmentNote> {
|
||||
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<Database>,
|
||||
noteId: string,
|
||||
params: Partial<Pick<DepartmentNote, 'title' | 'content' | 'sort_order'>>
|
||||
): Promise<DepartmentNote> {
|
||||
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<Database>,
|
||||
noteId: string
|
||||
): Promise<void> {
|
||||
const { error } = await supabase
|
||||
.from('department_notes')
|
||||
.delete()
|
||||
.eq('id', noteId);
|
||||
|
||||
if (error) {
|
||||
log.error('deleteNote failed', { error, data: { noteId } });
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user