From 689cfd3c65420b43c53f476f62002c0d8335dbf0 Mon Sep 17 00:00:00 2001 From: Julian Appel Date: Wed, 22 Jul 2026 19:23:30 +0200 Subject: [PATCH] Route boards to circuit-first editor --- docs/spec/07-implementation-phases-todo.md | 26 ++++++++ .../[circuitListId]/tree-edit/page.tsx | 11 ++-- src/app/projects/[projectId]/page.tsx | 63 ++++++++++++++----- 3 files changed, 82 insertions(+), 18 deletions(-) diff --git a/docs/spec/07-implementation-phases-todo.md b/docs/spec/07-implementation-phases-todo.md index 8c3ac28..7c3cd54 100644 --- a/docs/spec/07-implementation-phases-todo.md +++ b/docs/spec/07-implementation-phases-todo.md @@ -239,3 +239,29 @@ Acceptance criteria: - the codebase can later add rule-based sizing without redesigning circuits/devices - users can manually override calculated suggestions + +## Phase 9: Development Environment and Docker + +Goal: + +Make short development sessions quick to start and stop. + +Tasks: + +- add a Docker-based local development setup +- start frontend, API and SQLite persistence with one command +- keep the database in an explicit persistent volume +- run or document pending database migrations during startup +- add concise start, stop and reset instructions +- retain a non-Docker development path for direct debugging + +Acceptance criteria: + +- a new development session starts with one documented command +- stopping and restarting does not lose the local database +- frontend and API health can be checked without manual port setup +- the development workflow works consistently across short sessions + +Note: + +This phase may be moved earlier if repeated local startup overhead begins to slow down feature development. diff --git a/src/app/projects/[projectId]/circuit-lists/[circuitListId]/tree-edit/page.tsx b/src/app/projects/[projectId]/circuit-lists/[circuitListId]/tree-edit/page.tsx index 6b2ef6a..9d3ffc8 100644 --- a/src/app/projects/[projectId]/circuit-lists/[circuitListId]/tree-edit/page.tsx +++ b/src/app/projects/[projectId]/circuit-lists/[circuitListId]/tree-edit/page.tsx @@ -11,18 +11,21 @@ export default function CircuitTreeEditPage() {
-

Circuit Tree Editor

-

Basic editing for the circuit-first model.

+

Stromkreisliste

+

Stromkreise und zugeordnete Geräte bearbeiten.

- Read-only tree + Strukturvorschau + + + Zum Projekt - Legacy editor + Legacy-Editor
diff --git a/src/app/projects/[projectId]/page.tsx b/src/app/projects/[projectId]/page.tsx index 34f0832..cd20b3b 100644 --- a/src/app/projects/[projectId]/page.tsx +++ b/src/app/projects/[projectId]/page.tsx @@ -11,6 +11,7 @@ import { createProjectDevice, createRoom, deleteProjectDevice, + listCircuitLists, listDistributionBoards, listFloors, listGlobalDevices, @@ -21,6 +22,7 @@ import { updateProjectSettings, } from "../../../frontend/utils/api"; import type { + CircuitListDto, CreateProjectDeviceInput, DistributionBoardDto, FloorDto, @@ -56,6 +58,7 @@ export default function ProjectDetailPage() { const [projectId, setProjectId] = useState(""); const [project, setProject] = useState(null); const [boards, setBoards] = useState([]); + const [circuitLists, setCircuitLists] = useState([]); const [floors, setFloors] = useState([]); const [rooms, setRooms] = useState([]); const [projectDevices, setProjectDevices] = useState([]); @@ -94,12 +97,21 @@ export default function ProjectDetailPage() { Promise.all([ listProjects(), listDistributionBoards(projectId), + listCircuitLists(projectId), listFloors(projectId), listRooms(projectId), listProjectDevices(projectId), listGlobalDevices(), ]) - .then(([projects, distributionBoards, loadedFloors, loadedRooms, loadedProjectDevices, loadedGlobalDevices]) => { + .then(([ + projects, + distributionBoards, + loadedCircuitLists, + loadedFloors, + loadedRooms, + loadedProjectDevices, + loadedGlobalDevices, + ]) => { const currentProject = projects.find((item) => item.id === projectId) ?? null; setProject(currentProject); if (currentProject) { @@ -107,6 +119,7 @@ export default function ProjectDetailPage() { setThreePhaseVoltageV(String(currentProject.threePhaseVoltageV)); } setBoards(distributionBoards); + setCircuitLists(loadedCircuitLists); setFloors(loadedFloors); setRooms(loadedRooms); setProjectDevices(loadedProjectDevices); @@ -123,6 +136,10 @@ export default function ProjectDetailPage() { const roomCount = useMemo(() => rooms.length, [rooms.length]); const projectDeviceCount = useMemo(() => projectDevices.length, [projectDevices.length]); const floorById = useMemo(() => new Map(floors.map((item) => [item.id, item])), [floors]); + const circuitListByBoardId = useMemo( + () => new Map(circuitLists.map((circuitList) => [circuitList.distributionBoardId, circuitList])), + [circuitLists] + ); async function handleCreateBoard(event: FormEvent) { event.preventDefault(); @@ -134,6 +151,7 @@ export default function ProjectDetailPage() { try { const created = await createDistributionBoard(projectId, boardName.trim()); setBoards((current) => [...current, created]); + setCircuitLists(await listCircuitLists(projectId)); setBoardName(""); } catch (err) { setError(err instanceof Error ? err.message : "Verteilung konnte nicht erstellt werden."); @@ -415,19 +433,36 @@ export default function ProjectDetailPage() { - {boards.map((board) => ( - - {board.name} - - - Stromkreisliste öffnen - - - - ))} + {boards.map((board) => { + const circuitList = circuitListByBoardId.get(board.id); + return ( + + {board.name} + +
+ {circuitList ? ( + + Stromkreisliste öffnen + + ) : ( + + Keine Stromkreisliste vorhanden + + )} + + Legacy + +
+ + + ); + })} {!boards.length ? (