"use client"; import { useEffect, useState } from "react"; import { useParams } from "next/navigation"; // Maps each PRD section to the discovery phase that populates it const PRD_SECTIONS = [ { id: "executive_summary", label: "Executive Summary", phaseId: "big_picture" }, { id: "problem_statement", label: "Problem Statement", phaseId: "big_picture" }, { id: "vision_metrics", label: "Vision & Success Metrics", phaseId: "big_picture" }, { id: "users_personas", label: "Users & Personas", phaseId: "users_personas" }, { id: "user_flows", label: "User Flows", phaseId: "users_personas" }, { id: "feature_requirements", label: "Feature Requirements", phaseId: "features_scope" }, { id: "screen_specs", label: "Screen Specs", phaseId: "screens_data" }, { id: "business_model", label: "Business Model", phaseId: "business_model" }, { id: "integrations", label: "Integrations & Dependencies", phaseId: "features_scope" }, { id: "non_functional", label: "Non-Functional Reqs", phaseId: null }, { id: "risks", label: "Risks & Mitigations", phaseId: "risks_questions" }, { id: "open_questions", label: "Open Questions", phaseId: "risks_questions" }, ]; interface SavedPhase { phase: string; title: string; summary: string; data: Record; saved_at: string; } function formatValue(v: unknown): string { if (v === null || v === undefined) return "—"; if (Array.isArray(v)) return v.map(item => typeof item === "object" ? JSON.stringify(item) : String(item)).join(", "); return String(v); } function PhaseDataCard({ phase }: { phase: SavedPhase }) { const [expanded, setExpanded] = useState(false); const entries = Object.entries(phase.data).filter(([, v]) => v !== null && v !== undefined && v !== ""); return (
{expanded && entries.length > 0 && (
{entries.map(([k, v]) => (
{k.replace(/_/g, " ")}
{formatValue(v)}
))}
)}
); } export default function PRDPage() { const params = useParams(); const projectId = params.projectId as string; const [prd, setPrd] = useState(null); const [savedPhases, setSavedPhases] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { Promise.all([ fetch(`/api/projects/${projectId}`).then(r => r.json()).catch(() => ({})), fetch(`/api/projects/${projectId}/save-phase`).then(r => r.json()).catch(() => ({ phases: [] })), ]).then(([projectData, phaseData]) => { setPrd(projectData?.project?.prd ?? null); setSavedPhases(phaseData?.phases ?? []); setLoading(false); }); }, [projectId]); const phaseMap = new Map(savedPhases.map(p => [p.phase, p])); const savedPhaseIds = new Set(savedPhases.map(p => p.phase)); const sections = PRD_SECTIONS.map(s => ({ ...s, savedPhase: s.phaseId ? phaseMap.get(s.phaseId) ?? null : null, isDone: s.phaseId ? savedPhaseIds.has(s.phaseId) : false, })); const doneCount = sections.filter(s => s.isDone).length; const totalPct = Math.round((doneCount / sections.length) * 100); if (loading) { return (
Loading…
); } return (
{prd ? ( /* ── Finalized PRD view ── */

Product Requirements

PRD complete
{prd}
) : ( /* ── Section progress view ── */
{/* Progress bar */}
{totalPct}%
{doneCount}/{sections.length} sections
{/* Sections */} {sections.map((s, i) => (
{/* Status icon */}
{s.isDone ? "✓" : "○"}
{s.label} {s.isDone && s.savedPhase && ( saved )} {!s.isDone && !s.phaseId && ( generated )}
{/* Expandable phase data */} {s.isDone && s.savedPhase && ( )} {/* Pending hint */} {!s.isDone && (
{s.phaseId ? `Complete the ${s.savedPhase ? s.savedPhase.title : "discovery"} phase in Atlas` : "Will be generated when PRD is finalized"}
)}
))} {doneCount === 0 && (

Continue chatting with Atlas — saved phases will appear here automatically.

)}
)}
); }