import { useState } from "react"; import { EmptyState, ErrorState, LoadingState, } from "../components/data-states"; import { Icon } from "../components/icon"; import { useMobileViewport } from "../hooks/use-mobile-viewport"; import { ProjectCard } from "../components/features/project/ProjectCard"; import { ProjectDialog } from "../components/features/project/ProjectDialog"; import { RepositoryCreateDialog } from "../components/features/project/repository-create-dialog"; import { MobileListView } from "../components/features/mobile/mobile-list-view"; import { MobileFAB } from "../components/features/mobile/mobile-fab"; import { useProjects } from "../hooks/use-projects"; import type { ProjectWithRepos } from "../types"; type MobileView = "list" | "detail" | "create-project" | "create-repo"; export const ProjectsPage = () => { const isMobile = useMobileViewport(); const [mobileView, setMobileView] = useState("list"); const [selectedProject, setSelectedProject] = useState(null); const { projects, status, reload, dialogMode, formName, setFormName, formDescription, setFormDescription, formError, deleteConfirmId, setDeleteConfirmId, expandedProject, setExpandedProject, creatingWorkspace, setCreatingWorkspace, workspaceLoading, openCreate, openEdit, closeDialog, handleSubmit, handleDelete, handleSyncWorkspace, handleDeleteWorkspace, } = useProjects(); const isEmpty = status === "ready" && projects.length === 0; /* ── Mobile views ── */ if (isMobile) { if (mobileView === "create-project") { return (
{ closeDialog(); setMobileView("list"); }} />
); } if (mobileView === "create-repo" && selectedProject) { return (
setMobileView("detail")} onCreated={async () => { setMobileView("detail"); await reload(); }} />
); } if (mobileView === "detail" && selectedProject) { return (
{ setMobileView("list"); setSelectedProject(null); }} onEdit={() => { setFormName(selectedProject.name); setFormDescription(selectedProject.description ?? ""); setMobileView("create-project"); }} onDelete={() => setDeleteConfirmId(selectedProject.id)} onConfirmDelete={() => { void handleDelete(selectedProject.id); setMobileView("list"); setSelectedProject(null); }} onCancelDelete={() => setDeleteConfirmId(null)} onCreateWorkspace={(repoId) => setCreatingWorkspace({ projectId: selectedProject.id, repoId, }) } onWorkspaceAction={(repoId, workspace, action) => { if (action === "sync") { void handleSyncWorkspace( selectedProject.id, repoId, workspace, ); } else if (action === "delete") { void handleDeleteWorkspace(workspace); } }} onAddRepository={() => setMobileView("create-repo")} onCancelCreate={() => setCreatingWorkspace(null)} onCreated={() => { setCreatingWorkspace(null); reload(); }} />
); } /* Mobile list view */ return (

Projects

{projects.length} project{projects.length !== 1 ? "s" : ""}
{status === "loading" && } {status === "error" && ( )} {isEmpty && ( )} {status === "ready" && projects.length > 0 && ( ({ id: p.id, title: p.name, subtitle: `${p.repositories?.length ?? 0} repo${(p.repositories?.length ?? 0) !== 1 ? "s" : ""}${p.description ? " · " + p.description : ""}`, }))} onItemClick={(id) => { const project = projects.find((p) => p.id === id); if (project) { setSelectedProject(project); setMobileView("detail"); } }} emptyMessage="No projects yet" /> )} { openCreate(); setMobileView("create-project"); }} label="Create project" />
); } /* ── Desktop view ── */ return (

Projects

{status === "loading" && } {status === "error" && ( )} {isEmpty && ( )} {status === "ready" && projects.length > 0 && (
{projects.map((project) => ( setExpandedProject( expandedProject === project.id ? null : project.id, ) } onEdit={() => openEdit(project)} onDelete={() => setDeleteConfirmId(project.id)} onConfirmDelete={() => void handleDelete(project.id)} onCancelDelete={() => setDeleteConfirmId(null)} onCreateWorkspace={(repoId) => setCreatingWorkspace({ projectId: project.id, repoId }) } onWorkspaceAction={(repoId, workspace, action) => { if (action === "sync") { void handleSyncWorkspace(project.id, repoId, workspace); } else if (action === "delete") { void handleDeleteWorkspace(workspace); } }} onCancelCreate={() => setCreatingWorkspace(null)} onAddRepository={() => { setSelectedProject(project); setMobileView("create-repo"); }} onCreated={() => { setCreatingWorkspace(null); reload(); }} /> ))}
)} {dialogMode !== "none" && ( )}
); };