import { useEffect, useRef, useState } from "react"; import type { WorkspaceChartInterval, WorkspaceChartMode, WorkspaceChartTimeRange, } from "../../../components/charts/WorkspaceChart"; const API_BASE_URL = "http://localhost:18450"; const SAVE_DEBOUNCE_MS = 800; export type ChartLayoutMode = | "single" | "twoColumns" | "twoRows" | "fourGrid"; export type PersistedChartWorkspaceItem = { id: string; title: string; subtitle: string; mode: WorkspaceChartMode; selectedSensorKeys: string[]; timeRange: WorkspaceChartTimeRange; interval: WorkspaceChartInterval; }; type ChartWorkspaceScope = | "GLOBAL" | "CLIMATE" | "IRRIGATION" | "METEO" | "LIGHTING" | "HYDRO" | "AEROPONICS"; type ChartWorkspaceResponse = { id: number; scope: ChartWorkspaceScope; layoutMode: ChartLayoutMode; chartsJson: string; createdAt: string; updatedAt: string; }; type UseChartWorkspacePersistenceParams = { scope: ChartWorkspaceScope; layoutMode: ChartLayoutMode; charts: PersistedChartWorkspaceItem[]; onLoaded: (workspace: { layoutMode: ChartLayoutMode; charts: PersistedChartWorkspaceItem[]; }) => void; }; export function useChartWorkspacePersistence({ scope, layoutMode, charts, onLoaded, }: UseChartWorkspacePersistenceParams) { const [loaded, setLoaded] = useState(false); const [saving, setSaving] = useState(false); const [error, setError] = useState(null); const saveTimeoutRef = useRef(null); useEffect(() => { let cancelled = false; async function loadWorkspace() { try { const response = await fetch( `${API_BASE_URL}/api/chart-workspaces/${scope}`, ); if (response.status === 404 || response.status === 500) { return; } if (!response.ok) { throw new Error(`Failed to load workspace: ${response.status}`); } const payload = (await response.json()) as ChartWorkspaceResponse; if (cancelled) return; onLoaded({ layoutMode: payload.layoutMode, charts: JSON.parse(payload.chartsJson) as PersistedChartWorkspaceItem[], }); setError(null); } catch (error) { if (!cancelled) { console.error("Failed to load chart workspace", error); setError("Não foi possível carregar o workspace."); } } finally { if (!cancelled) { setLoaded(true); } } } loadWorkspace(); return () => { cancelled = true; }; }, [scope]); useEffect(() => { if (!loaded) return; if (saveTimeoutRef.current !== null) { window.clearTimeout(saveTimeoutRef.current); } saveTimeoutRef.current = window.setTimeout(() => { async function saveWorkspace() { try { setSaving(true); const response = await fetch( `${API_BASE_URL}/api/chart-workspaces/${scope}`, { method: "PUT", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ layoutMode, chartsJson: JSON.stringify(charts), }), }, ); if (!response.ok) { throw new Error(`Failed to save workspace: ${response.status}`); } setError(null); } catch (error) { console.error("Failed to save chart workspace", error); setError("Não foi possível guardar o workspace."); } finally { setSaving(false); } } saveWorkspace(); }, SAVE_DEBOUNCE_MS); return () => { if (saveTimeoutRef.current !== null) { window.clearTimeout(saveTimeoutRef.current); } }; }, [charts, layoutMode, loaded, scope]); return { loaded, saving, error, }; }