Add distribution board copy and delete controls

This commit is contained in:
2026-07-31 12:03:52 +02:00
parent 86f1d42e60
commit 5bee3cb103
7 changed files with 196 additions and 2 deletions
+156 -1
View File
@@ -5,12 +5,14 @@ import { useParams } from "next/navigation";
import { FormEvent, useEffect, useMemo, useState } from "react";
import {
copyGlobalDeviceToProject,
copyDistributionBoard,
copyProjectDeviceToGlobal,
createDistributionBoard,
createFloor,
createProjectDevice,
createRoom,
deleteProjectDevice,
deleteDistributionBoard,
disconnectProjectDeviceRows,
exportProjectTransfer,
getProjectDeviceSyncPreview,
@@ -91,6 +93,7 @@ export default function ProjectDetailPage() {
editingBoardSimultaneityFactor,
setEditingBoardSimultaneityFactor,
] = useState("1");
const [editingBoardCopyName, setEditingBoardCopyName] = useState("");
const [floorName, setFloorName] = useState("");
const [roomNumber, setRoomNumber] = useState("");
const [roomName, setRoomName] = useState("");
@@ -405,6 +408,7 @@ export default function ProjectDetailPage() {
setEditingBoardSimultaneityFactor(
String(board.simultaneityFactor)
);
setEditingBoardCopyName(`${board.name} Kopie`);
}
function openBoardCreator() {
@@ -463,6 +467,88 @@ export default function ProjectDetailPage() {
}
}
async function handleCopyBoard() {
if (
!projectId ||
!project ||
!editingBoard ||
!editingBoardCopyName.trim()
) {
return;
}
setIsSaving(true);
setError(null);
try {
const result = await copyDistributionBoard(
projectId,
editingBoard.id,
editingBoardCopyName.trim(),
project.currentRevision
);
setBoards((current) => [
...current,
result.distributionBoard,
]);
setCircuitLists((current) => [
...current,
result.circuitList,
]);
applyProjectRevision(result.history.currentRevision);
setEditingBoard(null);
} catch (err) {
setError(
err instanceof Error
? err.message
: "Verteilung konnte nicht kopiert werden."
);
} finally {
setIsSaving(false);
}
}
async function handleDeleteBoard() {
if (!projectId || !project || !editingBoard) {
return;
}
const confirmed = window.confirm(
`Verteilung „${editingBoard.name}“ wirklich löschen?\n\n` +
"Dabei werden die Stromkreisliste, alle Gruppen, Stromkreise, Gerätezeilen, Schutzgeräte und weiteren Verteilergeräte entfernt. " +
"Der Vorgang kann anschließend über die projektweite Historie rückgängig gemacht werden."
);
if (!confirmed) {
return;
}
setIsSaving(true);
setError(null);
try {
const result = await deleteDistributionBoard(
projectId,
editingBoard.id,
project.currentRevision
);
setBoards((current) =>
current.filter((board) => board.id !== result.distributionBoardId)
);
setCircuitLists((current) =>
current.filter(
(circuitList) =>
circuitList.distributionBoardId !==
result.distributionBoardId
)
);
applyProjectRevision(result.history.currentRevision);
setEditingBoard(null);
} catch (err) {
setError(
err instanceof Error
? err.message
: "Verteilung konnte nicht gelöscht werden."
);
} finally {
setIsSaving(false);
}
}
async function handleExportProject() {
if (!project) {
return;
@@ -1111,7 +1197,7 @@ export default function ProjectDetailPage() {
{structureModal === "board" ? (
<FormModal
description="Eine Stromkreisliste mit den vier Standardbereichen wird automatisch angelegt."
description="Eine Stromkreisliste mit den drei Standardgruppen wird automatisch angelegt."
isSaving={isSaving}
onClose={() => setStructureModal(null)}
onSubmit={handleCreateBoard}
@@ -1271,6 +1357,75 @@ export default function ProjectDetailPage() {
</div>
</div>
</div>
<hr className="my-4" />
<section aria-labelledby="copy-distribution-board-heading">
<h3
className="h6"
id="copy-distribution-board-heading"
>
Verteilung kopieren
</h3>
<p className="text-secondary small">
Erstellt eine vollständige Kopie des zuletzt gespeicherten
Stands einschließlich Gruppen, Stromkreisen, Gerätezeilen und
Schutzgeräten. Noch nicht gespeicherte Änderungen oben werden
nicht übernommen.
</p>
<div className="row g-2 align-items-end">
<div className="col-12 col-md">
<label
className="form-label"
htmlFor="copy-distribution-board-name"
>
Bezeichnung der Kopie
</label>
<input
className="form-control"
id="copy-distribution-board-name"
maxLength={200}
onChange={(event) =>
setEditingBoardCopyName(event.target.value)
}
value={editingBoardCopyName}
/>
</div>
<div className="col-12 col-md-auto">
<button
className="btn btn-outline-primary"
disabled={isSaving || !editingBoardCopyName.trim()}
onClick={() => void handleCopyBoard()}
type="button"
>
Verteilung kopieren
</button>
</div>
</div>
</section>
<hr className="my-4" />
<section
aria-labelledby="delete-distribution-board-heading"
className="border border-danger-subtle rounded p-3"
>
<h3
className="h6 text-danger"
id="delete-distribution-board-heading"
>
Gefahrenbereich
</h3>
<p className="text-secondary small mb-3">
Entfernt die vollständige Verteilung. Die Aktion wird erst
nach einer ausdrücklichen Warnung ausgeführt und kann über die
projektweite Historie rückgängig gemacht werden.
</p>
<button
className="btn btn-outline-danger"
disabled={isSaving}
onClick={() => void handleDeleteBoard()}
type="button"
>
Verteilung löschen
</button>
</section>
</FormModal>
) : null}