feat: restore PRD section tracker on the right side of Atlas chat
Two-column layout on the Atlas tab: - Left: Atlas discovery chat (full height, flex 1) - Right: 240px PRD section panel showing all 12 sections with live status dots (filled = phase saved, empty = pending) plus a progress bar showing phases complete out of 6 - Discovery banner (all 6 done) now lives inside the left column - "Generate PRD" footer CTA appears in right panel when all done Made-with: Cursor
This commit is contained in:
@@ -14,6 +14,22 @@ const DISCOVERY_PHASES = [
|
||||
"risks_questions",
|
||||
];
|
||||
|
||||
// Maps discovery phases → the PRD sections they populate
|
||||
const PRD_SECTIONS: { label: string; phase: string | null }[] = [
|
||||
{ label: "Executive Summary", phase: "big_picture" },
|
||||
{ label: "Problem Statement", phase: "big_picture" },
|
||||
{ label: "Vision & Success Metrics", phase: "big_picture" },
|
||||
{ label: "Users & Personas", phase: "users_personas" },
|
||||
{ label: "User Flows", phase: "users_personas" },
|
||||
{ label: "Feature Requirements", phase: "features_scope" },
|
||||
{ label: "Screen Specs", phase: "features_scope" },
|
||||
{ label: "Business Model", phase: "business_model" },
|
||||
{ label: "Integrations & Dependencies", phase: "screens_data" },
|
||||
{ label: "Non-Functional Reqs", phase: null }, // generated at PRD finalization
|
||||
{ label: "Risks & Mitigations", phase: "risks_questions" },
|
||||
{ label: "Open Questions", phase: "risks_questions" },
|
||||
];
|
||||
|
||||
interface FreshIdeaMainProps {
|
||||
projectId: string;
|
||||
projectName: string;
|
||||
@@ -123,33 +139,39 @@ export function FreshIdeaMain({ projectId, projectName }: FreshIdeaMainProps) {
|
||||
);
|
||||
}
|
||||
|
||||
const completedCount = savedPhaseIds.size;
|
||||
const totalPhases = DISCOVERY_PHASES.length;
|
||||
|
||||
return (
|
||||
<div style={{ height: "100%", display: "flex", flexDirection: "column", position: "relative" }}>
|
||||
<div style={{ height: "100%", display: "flex", flexDirection: "row", overflow: "hidden" }}>
|
||||
|
||||
{/* ── Left: Atlas chat ── */}
|
||||
<div style={{ flex: 1, display: "flex", flexDirection: "column", overflow: "hidden", minWidth: 0 }}>
|
||||
{/* Decision banner — shown when all 6 phases are saved */}
|
||||
{allDone && !dismissed && (
|
||||
<div style={{
|
||||
background: "linear-gradient(135deg, #1a1a1a 0%, #2d2d2d 100%)",
|
||||
padding: "18px 28px",
|
||||
padding: "14px 20px",
|
||||
display: "flex", alignItems: "center", justifyContent: "space-between",
|
||||
gap: 16, flexShrink: 0, flexWrap: "wrap",
|
||||
borderBottom: "1px solid #333",
|
||||
}}>
|
||||
<div>
|
||||
<div style={{ fontSize: "0.88rem", fontWeight: 700, color: "#fff", fontFamily: "Outfit, sans-serif", marginBottom: 3 }}>
|
||||
<div style={{ fontSize: "0.84rem", fontWeight: 700, color: "#fff", fontFamily: "Outfit, sans-serif", marginBottom: 2 }}>
|
||||
✦ Discovery complete — what's next?
|
||||
</div>
|
||||
<div style={{ fontSize: "0.75rem", color: "#a09a90", fontFamily: "Outfit, sans-serif" }}>
|
||||
Atlas has captured all 6 discovery phases. Choose your next step.
|
||||
<div style={{ fontSize: "0.72rem", color: "#a09a90", fontFamily: "Outfit, sans-serif" }}>
|
||||
All 6 phases captured. Generate your PRD or jump into Build.
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ display: "flex", gap: 10, flexShrink: 0 }}>
|
||||
<div style={{ display: "flex", gap: 8, flexShrink: 0 }}>
|
||||
<button
|
||||
onClick={handleGeneratePRD}
|
||||
disabled={prdLoading}
|
||||
style={{
|
||||
padding: "10px 20px", borderRadius: 8, border: "none",
|
||||
padding: "8px 16px", borderRadius: 7, border: "none",
|
||||
background: "#fff", color: "#1a1a1a",
|
||||
fontSize: "0.84rem", fontWeight: 700,
|
||||
fontSize: "0.8rem", fontWeight: 700,
|
||||
fontFamily: "Outfit, sans-serif", cursor: "pointer",
|
||||
transition: "opacity 0.12s",
|
||||
}}
|
||||
@@ -161,37 +183,122 @@ export function FreshIdeaMain({ projectId, projectName }: FreshIdeaMainProps) {
|
||||
<button
|
||||
onClick={handleMVP}
|
||||
style={{
|
||||
padding: "10px 20px", borderRadius: 8,
|
||||
padding: "8px 16px", borderRadius: 7,
|
||||
border: "1px solid rgba(255,255,255,0.2)",
|
||||
background: "transparent", color: "#fff",
|
||||
fontSize: "0.84rem", fontWeight: 600,
|
||||
fontSize: "0.8rem", fontWeight: 600,
|
||||
fontFamily: "Outfit, sans-serif", cursor: "pointer",
|
||||
transition: "background 0.12s",
|
||||
}}
|
||||
onMouseEnter={e => (e.currentTarget.style.background = "rgba(255,255,255,0.08)")}
|
||||
onMouseLeave={e => (e.currentTarget.style.background = "transparent")}
|
||||
>
|
||||
Plan MVP Test →
|
||||
Plan MVP →
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setDismissed(true)}
|
||||
style={{
|
||||
background: "none", border: "none", cursor: "pointer",
|
||||
color: "#666", fontSize: "1rem", padding: "4px 6px",
|
||||
fontFamily: "Outfit, sans-serif",
|
||||
color: "#888", fontSize: "1rem", padding: "4px 6px",
|
||||
}}
|
||||
title="Dismiss"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
>×</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<AtlasChat
|
||||
projectId={projectId}
|
||||
projectName={projectName}
|
||||
/>
|
||||
<AtlasChat projectId={projectId} projectName={projectName} />
|
||||
</div>
|
||||
|
||||
{/* ── Right: PRD section tracker ── */}
|
||||
<div style={{
|
||||
width: 240, flexShrink: 0,
|
||||
background: "#faf8f5",
|
||||
borderLeft: "1px solid #e8e4dc",
|
||||
display: "flex", flexDirection: "column",
|
||||
overflow: "hidden",
|
||||
}}>
|
||||
{/* Header */}
|
||||
<div style={{
|
||||
padding: "14px 16px 10px",
|
||||
borderBottom: "1px solid #e8e4dc",
|
||||
flexShrink: 0,
|
||||
}}>
|
||||
<div style={{ fontSize: "0.72rem", fontWeight: 700, color: "#1a1a1a", letterSpacing: "0.06em", textTransform: "uppercase", marginBottom: 6 }}>
|
||||
PRD Sections
|
||||
</div>
|
||||
{/* Progress bar */}
|
||||
<div style={{ height: 3, background: "#e8e4dc", borderRadius: 99, overflow: "hidden" }}>
|
||||
<div style={{
|
||||
height: "100%", borderRadius: 99,
|
||||
background: "#1a1a1a",
|
||||
width: `${Math.round((completedCount / totalPhases) * 100)}%`,
|
||||
transition: "width 0.4s ease",
|
||||
}} />
|
||||
</div>
|
||||
<div style={{ fontSize: "0.68rem", color: "#a09a90", marginTop: 5 }}>
|
||||
{completedCount} of {totalPhases} phases complete
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Section list */}
|
||||
<div style={{ flex: 1, overflowY: "auto", padding: "8px 0" }}>
|
||||
{PRD_SECTIONS.map(({ label, phase }) => {
|
||||
const isDone = phase === null
|
||||
? allDone // non-functional reqs generated when all done
|
||||
: savedPhaseIds.has(phase);
|
||||
return (
|
||||
<div
|
||||
key={label}
|
||||
style={{
|
||||
padding: "8px 16px",
|
||||
display: "flex", alignItems: "flex-start", gap: 10,
|
||||
}}
|
||||
>
|
||||
{/* Status dot */}
|
||||
<div style={{
|
||||
width: 8, height: 8, borderRadius: "50%", flexShrink: 0, marginTop: 4,
|
||||
background: isDone ? "#1a1a1a" : "transparent",
|
||||
border: isDone ? "none" : "1.5px solid #c8c4bc",
|
||||
transition: "all 0.3s",
|
||||
}} />
|
||||
<div style={{ minWidth: 0 }}>
|
||||
<div style={{
|
||||
fontSize: "0.78rem", fontWeight: isDone ? 600 : 400,
|
||||
color: isDone ? "#1a1a1a" : "#6b6560",
|
||||
lineHeight: 1.3,
|
||||
}}>
|
||||
{label}
|
||||
</div>
|
||||
{!isDone && (
|
||||
<div style={{ fontSize: "0.65rem", color: "#a09a90", marginTop: 2, lineHeight: 1.3 }}>
|
||||
{phase === null
|
||||
? "Generated when PRD is finalized"
|
||||
: "Complete this phase in Atlas"
|
||||
}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Footer CTA */}
|
||||
{allDone && (
|
||||
<div style={{ padding: "12px 16px", borderTop: "1px solid #e8e4dc", flexShrink: 0 }}>
|
||||
<Link
|
||||
href={`/${workspace}/project/${projectId}/prd`}
|
||||
style={{
|
||||
display: "block", textAlign: "center",
|
||||
padding: "9px 0", borderRadius: 7,
|
||||
background: "#1a1a1a", color: "#fff",
|
||||
fontSize: "0.78rem", fontWeight: 600,
|
||||
textDecoration: "none",
|
||||
}}
|
||||
>
|
||||
Generate PRD →
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user