import React, { useEffect, useCallback } from 'react' import { createFileRoute, useNavigate } from '@tanstack/react-router' import { SubBar } from '../shell/SubBar' import { Sub, EmptyState } from '../primitives' import { ProjectHeader } from '../features/projects/ProjectHeader' import { SessionsTable } from '../features/home/SessionsTable' import { useSessions } from '../features/home/useSessions' import { useProjects } from '../features/projects/useProjects' import { useHomeCursor } from '../features/home/useHomeCursor' import { useKeyboardCursor } from './__root' import { AuthError, APIError } from '../api/client' import type { Session } from '../api/adapters' import '../styles/projects.css' export const Route = createFileRoute('/project/$')({ component: ProjectRoute, }) function ProjectRoute(): React.JSX.Element { const navigate = useNavigate() const { _splat } = Route.useParams() const cwd = decodeURIComponent(_splat ?? '') const { data: sessions, isLoading: sessionsLoading, error: sessionsError } = useSessions({ cwd, since: 'all' }) const { data: projects, isLoading: projectsLoading } = useProjects({ since: 'all' }) const project = projects?.find(p => p.cwd === cwd) const isLoading = sessionsLoading || projectsLoading const error = sessionsError const handleOpen = useCallback((s: Session) => { void navigate({ to: '/session/$tool/$host/$id', params: { tool: s.tool, host: s.host, id: s.id } }) }, [navigate]) const { cursor, move, activate, jumpTo } = useHomeCursor( sessions?.length ?? 0, useCallback((idx: number) => { if (sessions && sessions[idx]) handleOpen(sessions[idx]) }, [sessions, handleOpen]), ) const cursorRef = useKeyboardCursor() useEffect(() => { cursorRef.current = { move, activate } return () => { cursorRef.current = { move: (_d: 1 | -1) => { /* no-op */ }, activate: () => { /* no-op */ }, } } }, [cursorRef, move, activate]) // Collect unique hosts from the loaded sessions const hosts = sessions != null ? Array.from(new Set(sessions.map(s => s.host))).sort() : (project?.hosts ?? []) const sessionCount = sessions?.length ?? project?.sessions ?? 0 if (isLoading) { return ( <> {cwd}
loading…
) } if (error != null) { if (error instanceof AuthError) { return (
not authenticated
Sign in to view this project.
) } const detail = error instanceof APIError ? error.message : String(error) return (
error
{detail}
) } // If the project was not found in the index and sessions came back empty, // render an EmptyState rather than a blank page. if (project === undefined && (sessions == null || sessions.length === 0)) { return ( <>
) } return ( <> {sessionCount} sessions ) }