Support decimal commas and cell units

This commit is contained in:
2026-07-31 14:33:47 +02:00
parent 734a2bcfc4
commit 5fb81bab04
4 changed files with 36 additions and 10 deletions
@@ -27,6 +27,7 @@ import {
buildDeviceRowEditPatch, buildDeviceRowEditPatch,
defaultVisibleColumnKeys, defaultVisibleColumnKeys,
deviceFieldKeys, deviceFieldKeys,
formatCellValue,
formatPhaseTypeLabel, formatPhaseTypeLabel,
formatValue, formatValue,
getCircuitSectionLabel, getCircuitSectionLabel,
@@ -4392,7 +4393,7 @@ export function CircuitTreeEditor(props: { projectId: string; circuitListId: str
}} }}
/> />
) : ( ) : (
formatValue(cell.value, column.key) formatCellValue(cell.value, column.key)
)} )}
</td> </td>
); );
@@ -5,6 +5,7 @@ import { Fragment } from "react";
import { getCircuitTree } from "../utils/api"; import { getCircuitTree } from "../utils/api";
import type { CircuitTreeCircuitDto, CircuitTreeResponseDto } from "../types"; import type { CircuitTreeCircuitDto, CircuitTreeResponseDto } from "../types";
import { import {
formatCellValue,
formatValue, formatValue,
getCircuitSectionLabel, getCircuitSectionLabel,
} from "../utils/circuit-grid-model"; } from "../utils/circuit-grid-model";
@@ -112,7 +113,7 @@ function SectionRows(props: { section: CircuitTreeResponseDto["sections"][number
<td>{circuit.displayName?.trim() || "Reserve"}</td> <td>{circuit.displayName?.trim() || "Reserve"}</td>
<td colSpan={11}>-</td> <td colSpan={11}>-</td>
<td className="text-end"> <td className="text-end">
{formatValue(circuit.circuitTotalPower, "circuitTotalPower")} {formatCellValue(circuit.circuitTotalPower, "circuitTotalPower")}
</td> </td>
<td>{circuit.protectionDevice?.type ?? "-"}</td> <td>{circuit.protectionDevice?.type ?? "-"}</td>
<td className="text-end"> <td className="text-end">
@@ -140,13 +141,13 @@ function SectionRows(props: { section: CircuitTreeResponseDto["sections"][number
<td>{row.level ?? "-"}</td> <td>{row.level ?? "-"}</td>
<td>{row.roomNumberSnapshot ?? "-"}</td> <td>{row.roomNumberSnapshot ?? "-"}</td>
<td>{row.roomNameSnapshot ?? "-"}</td> <td>{row.roomNameSnapshot ?? "-"}</td>
<td className="text-end">{formatValue(row.quantity, "quantity")}</td> <td className="text-end">{formatCellValue(row.quantity, "quantity")}</td>
<td className="text-end">{formatValue(row.powerPerUnit, "powerPerUnit")}</td> <td className="text-end">{formatCellValue(row.powerPerUnit, "powerPerUnit")}</td>
<td className="text-end"> <td className="text-end">
{formatValue(row.simultaneityFactor, "simultaneityFactor")} {formatValue(row.simultaneityFactor, "simultaneityFactor")}
</td> </td>
<td className="text-end">{formatValue(row.cosPhi, "cosPhi")}</td> <td className="text-end">{formatValue(row.cosPhi, "cosPhi")}</td>
<td className="text-end">{formatValue(row.rowTotalPower, "rowTotalPower")}</td> <td className="text-end">{formatCellValue(row.rowTotalPower, "rowTotalPower")}</td>
<td>{circuit.protectionDevice?.type ?? "-"}</td> <td>{circuit.protectionDevice?.type ?? "-"}</td>
<td className="text-end"> <td className="text-end">
{formatValue(circuit.protectionDevice?.ratedCurrentA, "protectionRatedCurrent")} {formatValue(circuit.protectionDevice?.ratedCurrentA, "protectionRatedCurrent")}
@@ -167,7 +168,7 @@ function SectionRows(props: { section: CircuitTreeResponseDto["sections"][number
<td>{renderCircuitSummaryLabel(circuit)}</td> <td>{renderCircuitSummaryLabel(circuit)}</td>
<td colSpan={11}>-</td> <td colSpan={11}>-</td>
<td className="text-end"> <td className="text-end">
{formatValue(circuit.circuitTotalPower, "circuitTotalPower")} {formatCellValue(circuit.circuitTotalPower, "circuitTotalPower")}
</td> </td>
<td>{circuit.protectionDevice?.type ?? "-"}</td> <td>{circuit.protectionDevice?.type ?? "-"}</td>
<td className="text-end"> <td className="text-end">
@@ -190,13 +191,13 @@ function SectionRows(props: { section: CircuitTreeResponseDto["sections"][number
<td>{row.level ?? "-"}</td> <td>{row.level ?? "-"}</td>
<td>{row.roomNumberSnapshot ?? "-"}</td> <td>{row.roomNumberSnapshot ?? "-"}</td>
<td>{row.roomNameSnapshot ?? "-"}</td> <td>{row.roomNameSnapshot ?? "-"}</td>
<td className="text-end">{formatValue(row.quantity, "quantity")}</td> <td className="text-end">{formatCellValue(row.quantity, "quantity")}</td>
<td className="text-end">{formatValue(row.powerPerUnit, "powerPerUnit")}</td> <td className="text-end">{formatCellValue(row.powerPerUnit, "powerPerUnit")}</td>
<td className="text-end"> <td className="text-end">
{formatValue(row.simultaneityFactor, "simultaneityFactor")} {formatValue(row.simultaneityFactor, "simultaneityFactor")}
</td> </td>
<td className="text-end">{formatValue(row.cosPhi, "cosPhi")}</td> <td className="text-end">{formatValue(row.cosPhi, "cosPhi")}</td>
<td className="text-end">{formatValue(row.rowTotalPower, "rowTotalPower")}</td> <td className="text-end">{formatCellValue(row.rowTotalPower, "rowTotalPower")}</td>
<td>-</td> <td>-</td>
<td className="text-end">-</td> <td className="text-end">-</td>
<td>-</td> <td>-</td>
+19 -1
View File
@@ -351,6 +351,24 @@ export function formatValue(value: GridValue, key?: CellKey): string {
return String(value); return String(value);
} }
export function formatCellValue(value: GridValue, key: CellKey): string {
const formatted = formatValue(value, key);
if (formatted === "-" || typeof value !== "number") {
return formatted;
}
if (key === "quantity") {
return `${formatted} St.`;
}
if (
key === "powerPerUnit" ||
key === "rowTotalPower" ||
key === "circuitTotalPower"
) {
return `${formatted} kW`;
}
return formatted;
}
export function formatPhaseTypeLabel(value: string): string { export function formatPhaseTypeLabel(value: string): string {
if (value === "single_phase") { if (value === "single_phase") {
return "1-phasig"; return "1-phasig";
@@ -378,7 +396,7 @@ export function parseNumeric(cellKey: CellKey, draft: string): number | undefine
if (trimmed === "") { if (trimmed === "") {
return undefined; return undefined;
} }
const parsed = Number(trimmed); const parsed = Number(trimmed.replace(",", "."));
if (Number.isNaN(parsed)) { if (Number.isNaN(parsed)) {
throw new Error(`Ungültiger Zahlenwert in ${cellKey}`); throw new Error(`Ungültiger Zahlenwert in ${cellKey}`);
} }
+6
View File
@@ -5,6 +5,7 @@ import {
buildCircuitEditPatch, buildCircuitEditPatch,
buildDeviceRowEditPatch, buildDeviceRowEditPatch,
formatValue, formatValue,
formatCellValue,
getCircuitSectionLabel, getCircuitSectionLabel,
getProjectColumnLayoutStorageKey, getProjectColumnLayoutStorageKey,
isGridEditorControlTarget, isGridEditorControlTarget,
@@ -173,6 +174,10 @@ describe("circuit grid model", () => {
assert.equal(formatValue(16, "protectionRatedCurrent"), "16"); assert.equal(formatValue(16, "protectionRatedCurrent"), "16");
assert.equal(formatValue("single_phase", "phaseType"), "1-phasig"); assert.equal(formatValue("single_phase", "phaseType"), "1-phasig");
assert.equal(formatValue("three_phase", "phaseType"), "3-phasig"); assert.equal(formatValue("three_phase", "phaseType"), "3-phasig");
assert.equal(formatCellValue(2, "quantity"), "2 St.");
assert.equal(formatCellValue(0.123456, "powerPerUnit"), "0,123 kW");
assert.equal(formatCellValue(1.25, "rowTotalPower"), "1,25 kW");
assert.equal(formatCellValue(undefined, "circuitTotalPower"), "-");
}); });
it("uses circuit display values for block sorting and falls back to the first device", () => { it("uses circuit display values for block sorting and falls back to the first device", () => {
@@ -183,6 +188,7 @@ describe("circuit grid model", () => {
it("parses numeric drafts and rejects invalid values", () => { it("parses numeric drafts and rejects invalid values", () => {
assert.equal(parseNumeric("quantity", " 2.5 "), 2.5); assert.equal(parseNumeric("quantity", " 2.5 "), 2.5);
assert.equal(parseNumeric("powerPerUnit", " 1,25 "), 1.25);
assert.equal(parseNumeric("quantity", ""), undefined); assert.equal(parseNumeric("quantity", ""), undefined);
assert.throws(() => parseNumeric("quantity", "two"), /Ungültiger Zahlenwert/); assert.throws(() => parseNumeric("quantity", "two"), /Ungültiger Zahlenwert/);
}); });