Align project devices with circuit model

This commit is contained in:
2026-07-22 19:31:08 +02:00
parent 689cfd3c65
commit 9d07ed9856
16 changed files with 301 additions and 106 deletions
+103 -43
View File
@@ -35,14 +35,15 @@ import type {
const emptyProjectDevice: CreateProjectDeviceInput = {
name: "",
displayName: "",
phaseType: "single_phase",
connectionKind: "",
costGroup: "",
category: "",
quantity: 1,
installedPowerPerUnitKw: 0.1,
demandFactor: 1,
voltageV: 230,
phaseCount: 1,
powerFactor: 1,
note: "",
powerPerUnit: 0.1,
simultaneityFactor: 1,
cosPhi: 1,
remark: "",
};
function toOptionalNumber(value: string) {
@@ -73,14 +74,15 @@ export default function ProjectDetailPage() {
const [projectDeviceForm, setProjectDeviceForm] = useState<Record<string, string>>({
name: "",
displayName: "",
phaseType: "single_phase",
connectionKind: "",
costGroup: "",
category: "",
quantity: "1",
installedPowerPerUnitKw: "0.1",
demandFactor: "1",
voltageV: "230",
phaseCount: "1",
powerFactor: "1",
note: "",
powerPerUnit: "0.1",
simultaneityFactor: "1",
cosPhi: "1",
remark: "",
});
const [selectedGlobalDeviceId, setSelectedGlobalDeviceId] = useState("");
const [error, setError] = useState<string | null>(null);
@@ -230,14 +232,15 @@ export default function ProjectDetailPage() {
const payload: CreateProjectDeviceInput = {
name: projectDeviceForm.name.trim(),
displayName: projectDeviceForm.displayName.trim() || projectDeviceForm.name.trim(),
phaseType: projectDeviceForm.phaseType === "three_phase" ? "three_phase" : "single_phase",
connectionKind: projectDeviceForm.connectionKind.trim() || undefined,
costGroup: projectDeviceForm.costGroup.trim() || undefined,
category: projectDeviceForm.category.trim() || undefined,
quantity: Number(projectDeviceForm.quantity),
installedPowerPerUnitKw: Number(projectDeviceForm.installedPowerPerUnitKw),
demandFactor: Number(projectDeviceForm.demandFactor),
voltageV: toOptionalNumber(projectDeviceForm.voltageV),
phaseCount: projectDeviceForm.phaseCount === "3" ? 3 : 1,
powerFactor: toOptionalNumber(projectDeviceForm.powerFactor),
note: projectDeviceForm.note.trim() || undefined,
powerPerUnit: Number(projectDeviceForm.powerPerUnit),
simultaneityFactor: Number(projectDeviceForm.simultaneityFactor),
cosPhi: toOptionalNumber(projectDeviceForm.cosPhi),
remark: projectDeviceForm.remark.trim() || undefined,
};
setIsSaving(true);
@@ -248,14 +251,15 @@ export default function ProjectDetailPage() {
setProjectDeviceForm({
name: emptyProjectDevice.name,
displayName: emptyProjectDevice.displayName,
phaseType: emptyProjectDevice.phaseType,
connectionKind: emptyProjectDevice.connectionKind ?? "",
costGroup: emptyProjectDevice.costGroup ?? "",
category: emptyProjectDevice.category ?? "",
quantity: String(emptyProjectDevice.quantity),
installedPowerPerUnitKw: String(emptyProjectDevice.installedPowerPerUnitKw),
demandFactor: String(emptyProjectDevice.demandFactor),
voltageV: String(emptyProjectDevice.voltageV ?? ""),
phaseCount: String(emptyProjectDevice.phaseCount ?? 1),
powerFactor: String(emptyProjectDevice.powerFactor ?? ""),
note: emptyProjectDevice.note ?? "",
powerPerUnit: String(emptyProjectDevice.powerPerUnit),
simultaneityFactor: String(emptyProjectDevice.simultaneityFactor),
cosPhi: String(emptyProjectDevice.cosPhi ?? ""),
remark: emptyProjectDevice.remark ?? "",
});
} catch (err) {
setError(err instanceof Error ? err.message : "Projektgerät konnte nicht erstellt werden.");
@@ -292,14 +296,16 @@ export default function ProjectDetailPage() {
const payload: CreateProjectDeviceInput = {
name: key === "name" ? value : device.name,
displayName: key === "displayName" ? value : device.displayName,
phaseType: device.phaseType,
connectionKind: device.connectionKind ?? undefined,
costGroup: device.costGroup ?? undefined,
category: key === "category" ? value : device.category ?? undefined,
quantity: device.quantity,
installedPowerPerUnitKw: device.installedPowerPerUnitKw,
demandFactor: device.demandFactor,
powerPerUnit: device.powerPerUnit,
simultaneityFactor: device.simultaneityFactor,
cosPhi: device.cosPhi ?? undefined,
remark: device.remark ?? undefined,
voltageV: device.voltageV ?? undefined,
phaseCount: device.phaseCount ?? undefined,
powerFactor: device.powerFactor ?? undefined,
note: device.note ?? undefined,
};
try {
@@ -591,7 +597,7 @@ export default function ProjectDetailPage() {
</div>
<div className="card-body border-bottom">
<form className="row g-2" onSubmit={handleCreateProjectDevice}>
<div className="col-12 col-md-3">
<div className="col-12 col-md-2">
<input
className="form-control"
placeholder="Interner Name"
@@ -601,7 +607,7 @@ export default function ProjectDetailPage() {
}
/>
</div>
<div className="col-12 col-md-3">
<div className="col-12 col-md-2">
<input
className="form-control"
placeholder="Anzeigename"
@@ -621,11 +627,32 @@ export default function ProjectDetailPage() {
}
/>
</div>
<div className="col-6 col-md-1">
<input
className="form-control"
placeholder="Anschlussart"
value={projectDeviceForm.connectionKind}
onChange={(event) =>
setProjectDeviceForm((current) => ({ ...current, connectionKind: event.target.value }))
}
/>
</div>
<div className="col-6 col-md-1">
<input
className="form-control"
placeholder="Kostengruppe"
value={projectDeviceForm.costGroup}
onChange={(event) =>
setProjectDeviceForm((current) => ({ ...current, costGroup: event.target.value }))
}
/>
</div>
<div className="col-6 col-md-1">
<input
className="form-control"
type="number"
min="0"
title="Anzahl"
value={projectDeviceForm.quantity}
onChange={(event) =>
setProjectDeviceForm((current) => ({ ...current, quantity: event.target.value }))
@@ -638,11 +665,12 @@ export default function ProjectDetailPage() {
type="number"
step="0.01"
min="0"
value={projectDeviceForm.installedPowerPerUnitKw}
title="Leistung je Stück [kW]"
value={projectDeviceForm.powerPerUnit}
onChange={(event) =>
setProjectDeviceForm((current) => ({
...current,
installedPowerPerUnitKw: event.target.value,
powerPerUnit: event.target.value,
}))
}
/>
@@ -654,25 +682,51 @@ export default function ProjectDetailPage() {
step="0.01"
min="0"
max="1"
value={projectDeviceForm.demandFactor}
title="Gleichzeitigkeitsfaktor"
value={projectDeviceForm.simultaneityFactor}
onChange={(event) =>
setProjectDeviceForm((current) => ({ ...current, demandFactor: event.target.value }))
setProjectDeviceForm((current) => ({ ...current, simultaneityFactor: event.target.value }))
}
/>
</div>
<div className="col-6 col-md-1">
<input
className="form-control"
type="number"
step="0.01"
min="0"
max="1"
title="cos Phi"
value={projectDeviceForm.cosPhi}
onChange={(event) =>
setProjectDeviceForm((current) => ({ ...current, cosPhi: event.target.value }))
}
/>
</div>
<div className="col-6 col-md-1">
<select
className="form-select"
value={projectDeviceForm.phaseCount}
title="Phasenart"
value={projectDeviceForm.phaseType}
onChange={(event) =>
setProjectDeviceForm((current) => ({ ...current, phaseCount: event.target.value }))
setProjectDeviceForm((current) => ({ ...current, phaseType: event.target.value }))
}
>
<option value="1">1-ph</option>
<option value="3">3-ph</option>
<option value="single_phase">1-ph</option>
<option value="three_phase">3-ph</option>
</select>
</div>
<div className="col-6 col-md-2">
<div className="col-12 col-md-10">
<input
className="form-control"
placeholder="Bemerkung"
value={projectDeviceForm.remark}
onChange={(event) =>
setProjectDeviceForm((current) => ({ ...current, remark: event.target.value }))
}
/>
</div>
<div className="col-12 col-md-2">
<button className="btn btn-primary w-100" type="submit" disabled={isSaving}>
Gerät anlegen
</button>
@@ -707,10 +761,13 @@ export default function ProjectDetailPage() {
<tr>
<th>Interner Name</th>
<th>Anzeigename</th>
<th>Phasenart</th>
<th>Kategorie</th>
<th>Kostengruppe</th>
<th>Anzahl</th>
<th>Leistung je Stück [kW]</th>
<th>GZF</th>
<th>Gesamtleistung [kW]</th>
<th>Aktionen</th>
</tr>
</thead>
@@ -739,6 +796,7 @@ export default function ProjectDetailPage() {
}
/>
</td>
<td>{device.phaseType === "three_phase" ? "3-ph" : "1-ph"}</td>
<td>
<input
className="form-control form-control-sm"
@@ -750,9 +808,11 @@ export default function ProjectDetailPage() {
}
/>
</td>
<td>{device.costGroup ?? "-"}</td>
<td>{device.quantity}</td>
<td>{device.installedPowerPerUnitKw}</td>
<td>{device.demandFactor}</td>
<td>{device.powerPerUnit}</td>
<td>{device.simultaneityFactor}</td>
<td>{device.totalPower}</td>
<td>
<div className="btn-group btn-group-sm">
<button
@@ -777,7 +837,7 @@ export default function ProjectDetailPage() {
))}
{!projectDevices.length ? (
<tr>
<td colSpan={7} className="text-center text-secondary py-4">
<td colSpan={10} className="text-center text-secondary py-4">
Noch keine Projektgeräte vorhanden.
</td>
</tr>