diff --git a/vibn-frontend/app/[workspace]/project/[projectId]/(home)/plan/page.tsx b/vibn-frontend/app/[workspace]/project/[projectId]/(home)/plan/page.tsx index 16e775d..fe04242 100644 --- a/vibn-frontend/app/[workspace]/project/[projectId]/(home)/plan/page.tsx +++ b/vibn-frontend/app/[workspace]/project/[projectId]/(home)/plan/page.tsx @@ -4,6 +4,7 @@ import React, { useState, useEffect, useCallback } from "react"; import { useParams } from "next/navigation"; import { Loader2, Target, BookOpen, Layers, GitBranch, Pencil, FileText, Check, Plus } from "lucide-react"; import ReactMarkdown from "react-markdown"; +import useSWR from "swr"; // Types mapping to our Postgres plan shape type Plan = { @@ -25,37 +26,29 @@ const INK = { bgHover: "#f8f6f2", }; +const fetcher = async (url: string) => { + const res = await fetch(url, { credentials: "include" }); + if (!res.ok) throw new Error(`HTTP ${res.status}`); + const data = await res.json(); + return data.plan; +}; + export default function PlanPageV2() { const params = useParams(); const projectId = (params?.projectId as string) || ""; - const [plan, setPlan] = useState(null); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); const [activeTab, setActiveTab] = useState("objective"); - const load = useCallback(async () => { - try { - const res = await fetch(`/api/projects/${projectId}/plan`, { credentials: "include" }); - if (!res.ok) throw new Error(`HTTP ${res.status}`); - const data = await res.json(); - setPlan(data.plan); - setError(null); - } catch (e: any) { - setError(e?.message ?? "Failed to load plan"); - } finally { - setLoading(false); - } - }, [projectId]); + const { data: plan, error, mutate: mutatePlan } = useSWR( + projectId ? `/api/projects/${projectId}/plan` : null, + fetcher, + { refreshInterval: 15000, dedupingInterval: 5000 } + ); + + // Wrapper for child components to update SWR cache optimally + const setPlan = (newPlan: Plan) => { mutatePlan(newPlan, false); }; - useEffect(() => { - load(); - // Safe polling interval - const intervalId = setInterval(load, 15000); - return () => clearInterval(intervalId); - }, [load]); - - if (loading && !plan) { + if (!plan && !error) { return (