Add configurable distribution supply types

This commit is contained in:
Julian Appel 2026-07-29 09:31:20 +02:00
parent 194bc9c0b1
commit b1a11397b3
43 changed files with 5697 additions and 126 deletions

View file

@ -1,7 +1,12 @@
"use client";
import { FormEvent, useState } from "react";
import React, { FormEvent, useState } from "react";
import type { ProjectDto } from "../types";
import {
distributionBoardSupplyTypeLabels,
distributionBoardSupplyTypes,
type DistributionBoardSupplyType,
} from "../../shared/constants/distribution-board";
export interface ProjectSettingsInput {
name: string;
@ -11,6 +16,7 @@ export interface ProjectSettingsInput {
description: string | null;
singlePhaseVoltageV: number;
threePhaseVoltageV: number;
enabledDistributionBoardSupplyTypes: DistributionBoardSupplyType[];
}
interface ProjectSettingsModalProps {
@ -23,6 +29,7 @@ interface ProjectSettingsModalProps {
) => Promise<void>;
onSave: (input: ProjectSettingsInput) => Promise<void>;
project: ProjectDto;
usedDistributionBoardSupplyTypes: DistributionBoardSupplyType[];
}
export function ProjectSettingsModal({
@ -32,6 +39,7 @@ export function ProjectSettingsModal({
onImport,
onSave,
project,
usedDistributionBoardSupplyTypes,
}: ProjectSettingsModalProps) {
const [name, setName] = useState(project.name);
const [internalProjectNumber, setInternalProjectNumber] = useState(
@ -52,6 +60,12 @@ export function ProjectSettingsModal({
const [threePhaseVoltageV, setThreePhaseVoltageV] = useState(
String(project.threePhaseVoltageV)
);
const [
enabledDistributionBoardSupplyTypes,
setEnabledDistributionBoardSupplyTypes,
] = useState<DistributionBoardSupplyType[]>(
project.enabledDistributionBoardSupplyTypes
);
const [transfer, setTransfer] = useState<unknown>(null);
const [transferFilename, setTransferFilename] = useState("");
const [importMode, setImportMode] = useState<"replace" | "duplicate">(
@ -70,13 +84,31 @@ export function ProjectSettingsModal({
description: toNullableString(description),
singlePhaseVoltageV: Number(singlePhaseVoltageV),
threePhaseVoltageV: Number(threePhaseVoltageV),
enabledDistributionBoardSupplyTypes,
});
}
const isValid =
name.trim().length > 0 &&
Number(singlePhaseVoltageV) > 0 &&
Number(threePhaseVoltageV) > 0;
Number(threePhaseVoltageV) > 0 &&
enabledDistributionBoardSupplyTypes.length > 0;
function toggleSupplyType(supplyType: DistributionBoardSupplyType) {
if (
enabledDistributionBoardSupplyTypes.includes(supplyType) &&
usedDistributionBoardSupplyTypes.includes(supplyType)
) {
return;
}
setEnabledDistributionBoardSupplyTypes((current) =>
current.includes(supplyType)
? current.filter((entry) => entry !== supplyType)
: distributionBoardSupplyTypes.filter(
(entry) => entry === supplyType || current.includes(entry)
)
);
}
async function handleTransferFile(file: File | undefined) {
setTransfer(null);
@ -165,6 +197,53 @@ export function ProjectSettingsModal({
value={externalProjectNumber}
/>
</div>
<div className="col-12">
<fieldset>
<legend className="form-label mb-1">
Verwendete Netzarten
</legend>
<p className="form-text mt-0">
Nur ausgewählte Netzarten stehen bei Verteilungen zur
Auswahl. Bereits verwendete Netzarten können nicht
deaktiviert werden.
</p>
<div className="row g-2">
{distributionBoardSupplyTypes.map((supplyType) => (
<div
className="col-12 col-md-6"
key={supplyType}
>
<label className="form-check">
<input
checked={enabledDistributionBoardSupplyTypes.includes(
supplyType
)}
className="form-check-input"
disabled={usedDistributionBoardSupplyTypes.includes(
supplyType
)}
onChange={() => toggleSupplyType(supplyType)}
type="checkbox"
/>
<span className="form-check-label">
{distributionBoardSupplyTypeLabels[supplyType]}
{usedDistributionBoardSupplyTypes.includes(
supplyType
)
? " (in Verwendung)"
: ""}
</span>
</label>
</div>
))}
</div>
{enabledDistributionBoardSupplyTypes.length === 0 ? (
<div className="text-danger small mt-2">
Mindestens eine Netzart muss aktiviert sein.
</div>
) : null}
</fieldset>
</div>
<div className="col-12">
<label className="form-label" htmlFor="building-owner">
Bauherr

View file

@ -1,3 +1,5 @@
import type { DistributionBoardSupplyType } from "../shared/constants/distribution-board";
export interface ProjectDto {
id: string;
name: string;
@ -7,6 +9,7 @@ export interface ProjectDto {
description: string | null;
singlePhaseVoltageV: number;
threePhaseVoltageV: number;
enabledDistributionBoardSupplyTypes: DistributionBoardSupplyType[];
currentRevision: number;
}
@ -89,6 +92,8 @@ export interface DistributionBoardDto {
id: string;
projectId: string;
name: string;
floorId: string | null;
supplyType: DistributionBoardSupplyType | null;
}
export interface DistributionBoardCommandResultDto

View file

@ -226,6 +226,7 @@ export function updateProjectSettings(
description: string | null;
singlePhaseVoltageV: number;
threePhaseVoltageV: number;
enabledDistributionBoardSupplyTypes: ProjectDto["enabledDistributionBoardSupplyTypes"];
}
) {
return request<ProjectSettingsCommandResultDto>(
@ -276,14 +277,36 @@ export function listDistributionBoards(projectId: string) {
export function createDistributionBoard(
projectId: string,
name: string,
input: {
name: string;
floorId: string | null;
supplyType: NonNullable<DistributionBoardDto["supplyType"]>;
},
expectedRevision: number
) {
return request<DistributionBoardCommandResultDto>(
`/api/projects/${projectId}/distribution-boards`,
{
method: "POST",
body: JSON.stringify({ name, expectedRevision }),
body: JSON.stringify({ ...input, expectedRevision }),
}
);
}
export function updateDistributionBoard(
projectId: string,
distributionBoardId: string,
input: {
floorId: string | null;
supplyType: NonNullable<DistributionBoardDto["supplyType"]>;
},
expectedRevision: number
) {
return request<DistributionBoardCommandResultDto>(
`/api/projects/${projectId}/distribution-boards/${distributionBoardId}`,
{
method: "PUT",
body: JSON.stringify({ ...input, expectedRevision }),
}
);
}

View file

@ -31,6 +31,7 @@ const commandTypeLabels: Record<string, string> = {
"project-device.sync-rows": "Projektgerät-Verknüpfungen geändert",
"project.update-settings": "Projekteinstellungen bearbeitet",
"distribution-board.insert": "Verteilung angelegt",
"distribution-board.update": "Verteilung bearbeitet",
"distribution-board.delete": "Verteilung entfernt",
"project-floor.insert": "Geschoss angelegt",
"project-floor.delete": "Geschoss entfernt",