import { useState } from "react"; import { Link } from "react-router-dom"; import { createProject, deleteProject, listProjects, updateProject, type ProjectCreateInput, type ProjectUpdateInput, } from "../api/projects"; import { EmptyState, ErrorState, LoadingState } from "../components/data-states"; import { Icon } from "../components/icon"; import { useAsyncData } from "../hooks/use-async-data"; import type { Project } from "../types"; type DialogMode = "none" | "create" | "edit"; export const ProjectsPage = () => { const { data: projects, status, reload } = useAsyncData(listProjects, []); const [dialogMode, setDialogMode] = useState("none"); const [editingProject, setEditingProject] = useState(null); const [formName, setFormName] = useState(""); const [formDescription, setFormDescription] = useState(""); const [formError, setFormError] = useState(null); const [deleteConfirmId, setDeleteConfirmId] = useState(null); const safeProjects = projects ?? []; const openCreate = () => { setFormName(""); setFormDescription(""); setFormError(null); setEditingProject(null); setDialogMode("create"); }; const openEdit = (project: Project) => { setFormName(project.name); setFormDescription(project.description ?? ""); setFormError(null); setEditingProject(project); setDialogMode("edit"); }; const closeDialog = () => { setDialogMode("none"); setEditingProject(null); setFormError(null); }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setFormError(null); if (!formName.trim()) { setFormError("Project name is required"); return; } try { if (dialogMode === "create") { const input: ProjectCreateInput = { name: formName.trim(), description: formDescription.trim() || null, }; await createProject(input); } else if (dialogMode === "edit" && editingProject) { const input: ProjectUpdateInput = { name: formName.trim(), description: formDescription.trim() || null, }; await updateProject(editingProject.id, input); } closeDialog(); reload(); } catch { setFormError("Failed to save project"); } }; const handleDelete = async (projectId: string) => { try { await deleteProject(projectId); setDeleteConfirmId(null); reload(); } catch { setDeleteConfirmId(null); } }; const isEmpty = status === "ready" && safeProjects.length === 0; return (

Projects

{status === "loading" && } {status === "error" && } {isEmpty && } {status === "ready" && safeProjects.length > 0 && (
{safeProjects.map((project) => (

{project.name}

{project.description &&

{project.description}

}
Open Workspace {deleteConfirmId === project.id ? (
Are you sure?
) : ( )}
))}
)} {dialogMode !== "none" && (

{dialogMode === "create" ? "Create Project" : "Edit Project"}