diff options
Diffstat (limited to 'renderer/src/components/Header.tsx')
| -rw-r--r-- | renderer/src/components/Header.tsx | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/renderer/src/components/Header.tsx b/renderer/src/components/Header.tsx new file mode 100644 index 0000000..3dcbba9 --- /dev/null +++ b/renderer/src/components/Header.tsx | |||
| @@ -0,0 +1,99 @@ | |||
| 1 | import React from "react"; | ||
| 2 | import type { Project, Session, Phase } from "../types"; | ||
| 3 | |||
| 4 | interface HeaderProps { | ||
| 5 | projects: Project[]; | ||
| 6 | sessions: Session[]; | ||
| 7 | selectedProject: Project | null; | ||
| 8 | selectedSession: Session | null; | ||
| 9 | onSelectProject: (project: Project | null) => void; | ||
| 10 | onSelectSession: (session: Session | null) => void; | ||
| 11 | onCreateProject: () => void; | ||
| 12 | onCreateSession: () => void; | ||
| 13 | } | ||
| 14 | |||
| 15 | const phaseLabels: Record<Phase, string> = { | ||
| 16 | research: "Research", | ||
| 17 | plan: "Plan", | ||
| 18 | implement: "Implement", | ||
| 19 | }; | ||
| 20 | |||
| 21 | const phases: Phase[] = ["research", "plan", "implement"]; | ||
| 22 | |||
| 23 | export function Header({ | ||
| 24 | projects, | ||
| 25 | sessions, | ||
| 26 | selectedProject, | ||
| 27 | selectedSession, | ||
| 28 | onSelectProject, | ||
| 29 | onSelectSession, | ||
| 30 | onCreateProject, | ||
| 31 | onCreateSession, | ||
| 32 | }: HeaderProps) { | ||
| 33 | return ( | ||
| 34 | <header className="header"> | ||
| 35 | <div className="header-left"> | ||
| 36 | <select | ||
| 37 | value={selectedProject?.id || ""} | ||
| 38 | onChange={(e) => { | ||
| 39 | const project = projects.find((p) => p.id === e.target.value); | ||
| 40 | onSelectProject(project || null); | ||
| 41 | onSelectSession(null); | ||
| 42 | }} | ||
| 43 | > | ||
| 44 | <option value="">Select Project...</option> | ||
| 45 | {projects.map((p) => ( | ||
| 46 | <option key={p.id} value={p.id}> | ||
| 47 | {p.name} | ||
| 48 | </option> | ||
| 49 | ))} | ||
| 50 | </select> | ||
| 51 | <button onClick={onCreateProject}>+ Project</button> | ||
| 52 | |||
| 53 | {selectedProject && ( | ||
| 54 | <> | ||
| 55 | <select | ||
| 56 | value={selectedSession?.id || ""} | ||
| 57 | onChange={(e) => { | ||
| 58 | const session = sessions.find((s) => s.id === e.target.value); | ||
| 59 | onSelectSession(session || null); | ||
| 60 | }} | ||
| 61 | > | ||
| 62 | <option value="">Select Session...</option> | ||
| 63 | {sessions.map((s) => ( | ||
| 64 | <option key={s.id} value={s.id}> | ||
| 65 | {s.name} | ||
| 66 | </option> | ||
| 67 | ))} | ||
| 68 | </select> | ||
| 69 | <button onClick={onCreateSession}>+ Session</button> | ||
| 70 | </> | ||
| 71 | )} | ||
| 72 | </div> | ||
| 73 | |||
| 74 | <div className="header-right"> | ||
| 75 | {selectedSession && ( | ||
| 76 | <div className="phase-indicator"> | ||
| 77 | {phases.map((phase) => { | ||
| 78 | const phaseIndex = phases.indexOf(phase); | ||
| 79 | const currentIndex = phases.indexOf(selectedSession.phase); | ||
| 80 | const isComplete = phaseIndex < currentIndex; | ||
| 81 | const isActive = phase === selectedSession.phase; | ||
| 82 | |||
| 83 | return ( | ||
| 84 | <span | ||
| 85 | key={phase} | ||
| 86 | className={`phase-step ${isActive ? "active" : ""} ${ | ||
| 87 | isComplete ? "complete" : "" | ||
| 88 | }`} | ||
| 89 | > | ||
| 90 | {phaseLabels[phase]} | ||
| 91 | </span> | ||
| 92 | ); | ||
| 93 | })} | ||
| 94 | </div> | ||
| 95 | )} | ||
| 96 | </div> | ||
| 97 | </header> | ||
| 98 | ); | ||
| 99 | } | ||
