Persist circuit cell edits

This commit is contained in:
Julian Appel 2026-07-25 20:26:45 +02:00
parent 3977a6e6e1
commit 76d8d59391
24 changed files with 348 additions and 301 deletions

View file

@ -20,11 +20,17 @@ import type {
CircuitTreeCircuitDto,
CircuitTreeDeviceRowDto,
CreateCircuitInputDto,
UpdateCircuitInputDto,
CreateCircuitDeviceRowInputDto,
UpdateCircuitDeviceRowInputDto,
} from "../types";
import type { ProjectDeviceSyncField } from "../../shared/constants/project-device-sync-fields";
import {
createCircuitUpdateProjectCommand,
type CircuitUpdatePatch,
} from "../../domain/models/circuit-project-command.model";
import {
createCircuitDeviceRowUpdateProjectCommand,
type CircuitDeviceRowUpdatePatch,
} from "../../domain/models/circuit-device-row-project-command.model";
async function request<T>(url: string, init?: RequestInit): Promise<T> {
const response = await fetch(url, {
@ -180,11 +186,18 @@ export function createCircuitWithDeviceRows(
);
}
export function updateCircuitById(circuitId: string, input: UpdateCircuitInputDto) {
return request(`/api/circuits/${circuitId}`, {
method: "PATCH",
body: JSON.stringify(input),
});
export function updateCircuitById(
projectId: string,
expectedRevision: number,
circuitId: string,
input: CircuitUpdatePatch
) {
return executeProjectCommand(
projectId,
expectedRevision,
createCircuitUpdateProjectCommand(circuitId, input),
"Stromkreisfeld bearbeiten"
);
}
export function deleteCircuitById(circuitId: string) {
@ -206,11 +219,18 @@ export function createCircuitDeviceRow(circuitId: string, input: CreateCircuitDe
});
}
export function updateCircuitDeviceRowById(rowId: string, input: UpdateCircuitDeviceRowInputDto) {
return request(`/api/circuit-device-rows/${rowId}`, {
method: "PATCH",
body: JSON.stringify(input),
});
export function updateCircuitDeviceRowById(
projectId: string,
expectedRevision: number,
rowId: string,
input: CircuitDeviceRowUpdatePatch
) {
return executeProjectCommand(
projectId,
expectedRevision,
createCircuitDeviceRowUpdateProjectCommand(rowId, input),
"Gerätezeilenfeld bearbeiten"
);
}
export function deleteCircuitDeviceRowById(rowId: string) {

View file

@ -1,4 +1,6 @@
import type { CircuitTreeCircuitDto, CircuitTreeDeviceRowDto } from "../types.js";
import type { CircuitUpdatePatch } from "../../domain/models/circuit-project-command.model.js";
import type { CircuitDeviceRowUpdatePatch } from "../../domain/models/circuit-device-row-project-command.model.js";
export type CellKey =
| "equipmentIdentifier"
@ -189,6 +191,78 @@ export function parseNumeric(cellKey: CellKey, draft: string): number | undefine
return parsed;
}
export function buildCircuitEditPatch(
key: CellKey,
draft: string
): CircuitUpdatePatch {
if (key === "protectionSummary" || key === "cableSummary") {
return { remark: draft.trim() || null };
}
if (
key === "protectionRatedCurrent" ||
key === "cableLength" ||
key === "voltage"
) {
return { [key]: parseNumeric(key, draft) ?? null };
}
if (key === "isReserve") {
const normalized = draft.trim().toLowerCase();
return {
isReserve: ["1", "true", "yes", "ja"].includes(normalized),
};
}
if (key === "equipmentIdentifier") {
return { equipmentIdentifier: draft.trim() };
}
return { [key]: draft.trim() || null } as CircuitUpdatePatch;
}
export function buildDeviceRowEditPatch(
key: CellKey,
draft: string
): CircuitDeviceRowUpdatePatch {
if (
key === "quantity" ||
key === "powerPerUnit" ||
key === "simultaneityFactor"
) {
const value = parseNumeric(key, draft);
if (value === undefined) {
throw new Error("Dieses Zahlenfeld darf nicht leer sein.");
}
return { [key]: value };
}
if (key === "cosPhi") {
return { cosPhi: parseNumeric(key, draft) ?? null };
}
if (key === "roomSummary") {
const trimmed = draft.trim();
if (!trimmed) {
return {
roomNumberSnapshot: null,
roomNameSnapshot: null,
};
}
const firstSpace = trimmed.indexOf(" ");
return firstSpace > 0
? {
roomNumberSnapshot: trimmed.slice(0, firstSpace).trim(),
roomNameSnapshot: trimmed.slice(firstSpace + 1).trim() || null,
}
: {
roomNumberSnapshot: trimmed,
roomNameSnapshot: null,
};
}
if (key === "technicalName") {
return { name: draft.trim() };
}
if (key === "displayName") {
return { displayName: draft.trim() };
}
return { [key]: draft.trim() || null } as CircuitDeviceRowUpdatePatch;
}
export function getDeviceValue(device: CircuitTreeDeviceRowDto, key: CellKey): GridValue {
switch (key) {
case "technicalName": return device.name;