diff options
| -rw-r--r-- | renderer/src/App.tsx | 34 | ||||
| -rw-r--r-- | renderer/src/components/Header.tsx | 36 | ||||
| -rw-r--r-- | renderer/src/styles/globals.css | 12 |
3 files changed, 82 insertions, 0 deletions
diff --git a/renderer/src/App.tsx b/renderer/src/App.tsx index d5a2efd..26ac252 100644 --- a/renderer/src/App.tsx +++ b/renderer/src/App.tsx | |||
| @@ -237,6 +237,38 @@ export function App() { | |||
| 237 | setOriginalContent(""); | 237 | setOriginalContent(""); |
| 238 | }; | 238 | }; |
| 239 | 239 | ||
| 240 | const handleDeleteProject = async (id: string) => { | ||
| 241 | try { | ||
| 242 | await api.deleteProject(id); | ||
| 243 | setProjects((prev) => prev.filter((p) => p.id !== id)); | ||
| 244 | if (selectedProject?.id === id) { | ||
| 245 | setSelectedProject(null); | ||
| 246 | setSelectedSession(null); | ||
| 247 | setSessions([]); | ||
| 248 | setMessages([]); | ||
| 249 | setDocumentContent(""); | ||
| 250 | setOriginalContent(""); | ||
| 251 | } | ||
| 252 | } catch (err) { | ||
| 253 | setError(err instanceof Error ? err.message : "Failed to delete project"); | ||
| 254 | } | ||
| 255 | }; | ||
| 256 | |||
| 257 | const handleDeleteSession = async (id: string) => { | ||
| 258 | try { | ||
| 259 | await api.deleteSession(id); | ||
| 260 | setSessions((prev) => prev.filter((s) => s.id !== id)); | ||
| 261 | if (selectedSession?.id === id) { | ||
| 262 | setSelectedSession(null); | ||
| 263 | setMessages([]); | ||
| 264 | setDocumentContent(""); | ||
| 265 | setOriginalContent(""); | ||
| 266 | } | ||
| 267 | } catch (err) { | ||
| 268 | setError(err instanceof Error ? err.message : "Failed to delete session"); | ||
| 269 | } | ||
| 270 | }; | ||
| 271 | |||
| 240 | return ( | 272 | return ( |
| 241 | <div className="app"> | 273 | <div className="app"> |
| 242 | <Header | 274 | <Header |
| @@ -248,6 +280,8 @@ export function App() { | |||
| 248 | onSelectSession={setSelectedSession} | 280 | onSelectSession={setSelectedSession} |
| 249 | onCreateProject={handleCreateProject} | 281 | onCreateProject={handleCreateProject} |
| 250 | onCreateSession={handleCreateSession} | 282 | onCreateSession={handleCreateSession} |
| 283 | onDeleteProject={handleDeleteProject} | ||
| 284 | onDeleteSession={handleDeleteSession} | ||
| 251 | /> | 285 | /> |
| 252 | 286 | ||
| 253 | <div className="main-content"> | 287 | <div className="main-content"> |
diff --git a/renderer/src/components/Header.tsx b/renderer/src/components/Header.tsx index 3dcbba9..b6bed26 100644 --- a/renderer/src/components/Header.tsx +++ b/renderer/src/components/Header.tsx | |||
| @@ -10,6 +10,8 @@ interface HeaderProps { | |||
| 10 | onSelectSession: (session: Session | null) => void; | 10 | onSelectSession: (session: Session | null) => void; |
| 11 | onCreateProject: () => void; | 11 | onCreateProject: () => void; |
| 12 | onCreateSession: () => void; | 12 | onCreateSession: () => void; |
| 13 | onDeleteProject?: (id: string) => void; | ||
| 14 | onDeleteSession?: (id: string) => void; | ||
| 13 | } | 15 | } |
| 14 | 16 | ||
| 15 | const phaseLabels: Record<Phase, string> = { | 17 | const phaseLabels: Record<Phase, string> = { |
| @@ -29,7 +31,23 @@ export function Header({ | |||
| 29 | onSelectSession, | 31 | onSelectSession, |
| 30 | onCreateProject, | 32 | onCreateProject, |
| 31 | onCreateSession, | 33 | onCreateSession, |
| 34 | onDeleteProject, | ||
| 35 | onDeleteSession, | ||
| 32 | }: HeaderProps) { | 36 | }: HeaderProps) { |
| 37 | const handleDeleteProject = () => { | ||
| 38 | if (!selectedProject || !onDeleteProject) return; | ||
| 39 | if (confirm(`Delete project "${selectedProject.name}"? This cannot be undone.`)) { | ||
| 40 | onDeleteProject(selectedProject.id); | ||
| 41 | } | ||
| 42 | }; | ||
| 43 | |||
| 44 | const handleDeleteSession = () => { | ||
| 45 | if (!selectedSession || !onDeleteSession) return; | ||
| 46 | if (confirm(`Delete session "${selectedSession.name}"? This cannot be undone.`)) { | ||
| 47 | onDeleteSession(selectedSession.id); | ||
| 48 | } | ||
| 49 | }; | ||
| 50 | |||
| 33 | return ( | 51 | return ( |
| 34 | <header className="header"> | 52 | <header className="header"> |
| 35 | <div className="header-left"> | 53 | <div className="header-left"> |
| @@ -49,6 +67,15 @@ export function Header({ | |||
| 49 | ))} | 67 | ))} |
| 50 | </select> | 68 | </select> |
| 51 | <button onClick={onCreateProject}>+ Project</button> | 69 | <button onClick={onCreateProject}>+ Project</button> |
| 70 | {selectedProject && onDeleteProject && ( | ||
| 71 | <button | ||
| 72 | onClick={handleDeleteProject} | ||
| 73 | className="btn-delete" | ||
| 74 | title="Delete project" | ||
| 75 | > | ||
| 76 | 🗑️ | ||
| 77 | </button> | ||
| 78 | )} | ||
| 52 | 79 | ||
| 53 | {selectedProject && ( | 80 | {selectedProject && ( |
| 54 | <> | 81 | <> |
| @@ -67,6 +94,15 @@ export function Header({ | |||
| 67 | ))} | 94 | ))} |
| 68 | </select> | 95 | </select> |
| 69 | <button onClick={onCreateSession}>+ Session</button> | 96 | <button onClick={onCreateSession}>+ Session</button> |
| 97 | {selectedSession && onDeleteSession && ( | ||
| 98 | <button | ||
| 99 | onClick={handleDeleteSession} | ||
| 100 | className="btn-delete" | ||
| 101 | title="Delete session" | ||
| 102 | > | ||
| 103 | 🗑️ | ||
| 104 | </button> | ||
| 105 | )} | ||
| 70 | </> | 106 | </> |
| 71 | )} | 107 | )} |
| 72 | </div> | 108 | </div> |
diff --git a/renderer/src/styles/globals.css b/renderer/src/styles/globals.css index 809ff15..e1d945a 100644 --- a/renderer/src/styles/globals.css +++ b/renderer/src/styles/globals.css | |||
| @@ -65,6 +65,18 @@ body { | |||
| 65 | background: var(--border); | 65 | background: var(--border); |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | .header button.btn-delete { | ||
| 69 | background: transparent; | ||
| 70 | border: 1px solid var(--border); | ||
| 71 | padding: 6px 8px; | ||
| 72 | font-size: 14px; | ||
| 73 | } | ||
| 74 | |||
| 75 | .header button.btn-delete:hover { | ||
| 76 | background: var(--danger); | ||
| 77 | border-color: var(--danger); | ||
| 78 | } | ||
| 79 | |||
| 68 | .phase-indicator { | 80 | .phase-indicator { |
| 69 | display: flex; | 81 | display: flex; |
| 70 | gap: 4px; | 82 | gap: 4px; |
