import type { ProjectSummary, RunStatus } from "@/contracts"; import { useQuery } from "@tanstack/react-query"; import { FolderGit2, FolderPlus, GitBranch, RefreshCw } from "lucide-react"; import { Link } from "react-router-dom"; import { useAuth } from "@/client/auth"; import { StatusPill } from "@/client/components"; import { Badge, Button, ButtonLink, EmptyState, ErrorBanner, PageHeader, Skeleton } from "@/client/components/ui"; import { formatApiError, formatProjectUpdatedLabel, getApiClient, inferRepositoryProvider, queryKeys, } from "@/client/lib"; const countByStatus = (projects: ProjectSummary[], target: RunStatus): number => projects.filter((project) => project.lastRunStatus === target).length; const ProjectCard = ({ project }: { project: ProjectSummary }) => (

{project.name}

{project.ownerSlug}/{project.projectSlug}

{inferRepositoryProvider(project.repoUrl)} {project.defaultBranch}

updated {formatProjectUpdatedLabel(project)}

); const ProjectCardSkeleton = () => (
); export const ProjectsPage = () => { const { user } = useAuth(); const userId = user?.id ?? ""; const projectsQuery = useQuery({ queryKey: queryKeys.projects(userId), queryFn: () => getApiClient().getProjects(), enabled: userId.length > 0, }); const projects = projectsQuery.data?.projects ?? []; const loading = projectsQuery.isPending; const error = projectsQuery.isError ? formatApiError(projectsQuery.error) : null; const activeCount = countByStatus(projects, "queued") + countByStatus(projects, "starting") + countByStatus(projects, "running") + countByStatus(projects, "cancel_requested") + countByStatus(projects, "canceling"); const healthyCount = countByStatus(projects, "passed"); return (
0 ? `${projects.length} project${projects.length !== 1 ? "s" : ""} \u00b7 ${activeCount} active, ${healthyCount} passing` : undefined } actions={ <> New Project
); };