import { authFetch } from "./client"; import { cachedGetJson, invalidateApiCache } from "./cache"; interface AuditUser { id: string; first_name?: string; last_name?: string; mobile?: string; } export interface ProjectClient { id: string; name: string; } export interface Project { id: string; name: string; description: string; color: string; created_at?: string; is_archived: boolean; is_deleted?: boolean; workspace: string; created_by?: AuditUser | null; client: ProjectClient | null; } export interface ProjectPayload { name: string; description: string; color: string; is_archived: boolean; workspace: string; client: string | null; } export const getProjects = async ( workspaceId: string, params: { limit?: number; offset?: number; search?: string; client?: string; clients?: string[]; is_archived?: boolean; ordering?: string; } = {} ) => { const queryParams = new URLSearchParams({ workspace: workspaceId }); if (params.limit !== undefined) queryParams.append("limit", params.limit.toString()); if (params.offset !== undefined) queryParams.append("offset", params.offset.toString()); if (params.search) queryParams.append("search", params.search); if (params.client) queryParams.append("client", params.client); params.clients?.forEach((clientId) => queryParams.append("clients", clientId)); if (params.is_archived !== undefined) queryParams.append("is_archived", params.is_archived.toString()); if (params.ordering !== undefined) queryParams.append("ordering", params.ordering.toString()); const data = await cachedGetJson(`/api/projects/?${queryParams.toString()}`, { ttlMs: 5 * 60 * 1000, namespaces: ["projects"], }); if (Array.isArray(data)) return data; if (Array.isArray(data?.items)) { return { ...data, results: data.items, count: data.total_items ?? data.items.length, }; } return data; }; export const getProject = async (id: string) => { const response = await authFetch(`/api/projects/${id}/`); if (!response.ok) { const errorData = await response.json().catch(() => null); throw new Error(errorData?.detail || errorData?.message || "Failed to fetch project"); } return response.json(); }; export const createProject = async ( data: Partial & { workspace: string; name: string } ) => { const response = await authFetch("/api/projects/", { method: "POST", body: JSON.stringify(data), }); if (!response.ok) { const errorData = await response.json().catch(() => null); throw new Error(errorData?.detail || errorData?.message || "Failed to create project"); } const payload = await response.json(); invalidateApiCache(["projects", "reports"]); return payload; }; export const updateProject = async ( id: string, data: Partial ) => { const response = await authFetch(`/api/projects/${id}/`, { method: "PATCH", body: JSON.stringify(data), }); if (!response.ok) { const errorData = await response.json().catch(() => null); throw new Error(errorData?.detail || errorData?.message || "Failed to update project"); } const payload = await response.json(); invalidateApiCache(["projects", "reports"]); return payload; }; export const deleteProject = async (id: string) => { const response = await authFetch(`/api/projects/${id}/`, { method: "DELETE", }); if (!response.ok) { const errorData = await response.json().catch(() => null); throw new Error(errorData?.detail || errorData?.message || "Failed to delete project"); } invalidateApiCache(["projects", "reports"]); if (response.status === 204) return { success: true }; return response.json().catch(() => ({ success: true })); }; export const toggleArchiveProject = async (id: string) => { const response = await authFetch(`/api/projects/${id}/archive/`, { method: "POST", }); if (!response.ok) { const errorData = await response.json().catch(() => null); throw new Error(errorData?.detail || errorData?.message || `Failed to archive project`); } const payload = await response.json(); invalidateApiCache(["projects", "reports"]); return payload; };