diff --git a/apps/web/src/app/(dashboard)/projects/page.tsx b/apps/web/src/app/(dashboard)/projects/page.tsx new file mode 100644 index 0000000..a5b3510 --- /dev/null +++ b/apps/web/src/app/(dashboard)/projects/page.tsx @@ -0,0 +1,96 @@ +'use client'; + +import { useCallback, useEffect, useState } from 'react'; +import { api } from '@/lib/api'; +import type { Project } from '@/lib/types'; +import { ProjectCard } from '@/components/projects/project-card'; + +export default function ProjectsPage(): React.ReactElement { + const [projects, setProjects] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + api('/api/projects') + .then(setProjects) + .catch(() => {}) + .finally(() => setLoading(false)); + }, []); + + const handleProjectClick = useCallback((project: Project) => { + console.log('Project clicked:', project.id); + }, []); + + return ( +
+
+

Projects

+
+ + {loading ? ( +

Loading projects...

+ ) : projects.length === 0 ? ( +
+

No projects yet

+

+ Projects will appear here when created via the gateway API +

+
+ ) : ( +
+ {projects.map((project) => ( + + ))} +
+ )} + + {/* Mission status section */} + +
+ ); +} + +function MissionStatus(): React.ReactElement { + const [mission, setMission] = useState | null>(null); + const [loading, setLoading] = useState(true); + + useEffect(() => { + api>('/api/coord/status') + .then(setMission) + .catch(() => setMission(null)) + .finally(() => setLoading(false)); + }, []); + + return ( +
+

Active Mission

+ {loading ? ( +

Loading mission status...

+ ) : !mission ? ( +
+

No active mission detected

+
+ ) : ( +
+
+ + + + +
+
+ )} +
+ ); +} + +function StatCard({ label, value }: { label: string; value: string }): React.ReactElement { + return ( +
+

{label}

+

{value}

+
+ ); +} diff --git a/apps/web/src/components/projects/project-card.tsx b/apps/web/src/components/projects/project-card.tsx new file mode 100644 index 0000000..8e740a2 --- /dev/null +++ b/apps/web/src/components/projects/project-card.tsx @@ -0,0 +1,44 @@ +'use client'; + +import { cn } from '@/lib/cn'; +import type { Project } from '@/lib/types'; + +interface ProjectCardProps { + project: Project; + onClick: (project: Project) => void; +} + +const statusColors: Record = { + active: 'bg-success/20 text-success', + paused: 'bg-warning/20 text-warning', + completed: 'bg-blue-600/20 text-blue-400', + archived: 'bg-gray-600/20 text-gray-400', +}; + +export function ProjectCard({ project, onClick }: ProjectCardProps): React.ReactElement { + return ( + + ); +} diff --git a/docs/TASKS.md b/docs/TASKS.md index f50cc2c..dc4feda 100644 --- a/docs/TASKS.md +++ b/docs/TASKS.md @@ -32,8 +32,8 @@ | P3-001 | done | Phase 3 | apps/web scaffold — Next.js 16 + BetterAuth + Tailwind | #82 | #26 | | P3-002 | done | Phase 3 | Auth pages — login, registration, SSO redirect | #83 | #27 | | P3-003 | done | Phase 3 | Chat UI — conversations, messages, streaming | #84 | #28 | -| P3-004 | in-progress | Phase 3 | Task management — list view + kanban board | — | #29 | -| P3-005 | not-started | Phase 3 | Project & mission views — dashboard + PRD viewer | — | #30 | +| P3-004 | done | Phase 3 | Task management — list view + kanban board | #86 | #29 | +| P3-005 | in-progress | Phase 3 | Project & mission views — dashboard + PRD viewer | — | #30 | | P3-006 | not-started | Phase 3 | Settings — provider config, profile, integrations | — | #31 | | P3-007 | not-started | Phase 3 | Admin panel — user management, RBAC | — | #32 | | P3-008 | not-started | Phase 3 | Verify Phase 3 — web dashboard functional E2E | — | #33 |