"use client"; import { useState, useEffect } from "react"; import { useQuery } from "@tanstack/react-query"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { ProjectCard } from "@/components/projects/ProjectCard"; import { NewProjectDialog } from "@/components/projects/NewProjectDialog"; import { Plus, Search, Loader2 } from "lucide-react"; import { HIDE_ARCHIVED_KEY } from "@/components/settings/HideArchivedToggle"; export default function ProjectsPage() { const [search, setSearch] = useState(""); const [showNew, setShowNew] = useState(false); const [hideArchived, setHideArchived] = useState(false); useEffect(() => { setHideArchived(localStorage.getItem(HIDE_ARCHIVED_KEY) === "1"); }, []); const { data, isLoading } = useQuery({ queryKey: ["projects", search], queryFn: async () => { const res = await fetch(`/api/projects?q=${encodeURIComponent(search)}`); if (!res.ok) throw new Error("Failed to fetch projects"); return res.json() as Promise<{ projects: any[] }>; }, staleTime: 30_000, }); const { data: clientsData } = useQuery({ queryKey: ["clients"], queryFn: async () => { const res = await fetch("/api/clients"); if (!res.ok) return { clients: [] }; return res.json() as Promise<{ clients: { id: string; company: string }[] }>; }, staleTime: 60_000, }); const projects = data?.projects ?? []; const clients = clientsData?.clients ?? []; const visibleProjects = hideArchived ? projects.filter((p: any) => p.status !== "ARCHIVED") : projects; const SCROLL_KEY = 'projects-scroll'; useEffect(() => { if (!isLoading) { const saved = sessionStorage.getItem(SCROLL_KEY); if (saved) { sessionStorage.removeItem(SCROLL_KEY); requestAnimationFrame(() => window.scrollTo(0, parseInt(saved, 10))); } } }, [isLoading]); const saveScroll = () => sessionStorage.setItem(SCROLL_KEY, String(window.scrollY)); return (

Projects

{projects.length} project{projects.length !== 1 ? "s" : ""} {hideArchived && projects.length !== visibleProjects.length && ( ({projects.length - visibleProjects.length} archived hidden) )}

{/* Search */}
setSearch(e.target.value)} className="pl-9" />
{/* Grid */} {isLoading ? (
) : projects.length === 0 ? (

No projects found.

) : (
{visibleProjects.map((project: any) => (
))}
)} setShowNew(false)} clients={clients} />
); }