"use client"; /** * CloudSyncStatus — Compact sync status indicator for the sidebar * * Shows cloud sync connection state with a small icon + label. * Fetches status from /api/sync/cloud periodically. * Listens for 'cloud-status-changed' events to re-poll immediately. * * @module shared/components/CloudSyncStatus */ import { useState, useEffect, useRef, useCallback } from "react"; import { useRouter } from "next/navigation"; const STATUS_CONFIG = { connected: { icon: "cloud_done", color: "text-green-500", label: "Cloud" }, syncing: { icon: "cloud_sync", color: "text-blue-400 animate-pulse", label: "Syncing..." }, disconnected: { icon: "cloud_off", color: "text-amber-500", label: "Cloud Off" }, error: { icon: "cloud_off", color: "text-red-400", label: "Cloud Error" }, disabled: { icon: "cloud_off", color: "text-text-muted/50", label: "Disabled" }, }; export default function CloudSyncStatus({ collapsed = false }) { const [status, setStatus] = useState("disabled"); const [lastSync, setLastSync] = useState(null); const mountedRef = useRef(true); const router = useRouter(); const poll = useCallback(async () => { try { const res = await fetch("/api/sync/cloud"); if (!mountedRef.current) return; if (!res.ok) { setStatus("disconnected"); return; } const data = await res.json(); if (!mountedRef.current) return; if (!data.enabled) setStatus("disabled"); else if (data.syncing) setStatus("syncing"); else if (data.connected) { setStatus("connected"); if (data.lastSync) setLastSync(new Date(data.lastSync)); } else setStatus("disconnected"); } catch { if (mountedRef.current) setStatus("disconnected"); } }, []); useEffect(() => { mountedRef.current = true; // Schedule initial poll outside of effect body to avoid setState-in-effect lint queueMicrotask(poll); const interval = setInterval(poll, 30000); // Listen for immediate re-poll events from EndpointPageClient const handleCloudChange = () => { setTimeout(poll, 500); // Small delay to let backend settle }; globalThis.addEventListener("cloud-status-changed", handleCloudChange); return () => { mountedRef.current = false; clearInterval(interval); globalThis.removeEventListener("cloud-status-changed", handleCloudChange); }; }, [poll]); // Don't render if cloud sync is disabled if (status === "disabled") return null; const config = STATUS_CONFIG[status]; return ( ); }