import type { CircuitListDto, CreateFloorInput, CreateProjectDeviceInput, CreateRoomInput, CreateGlobalDeviceInput, DistributionBoardDto, DistributionBoardCommandResultDto, FloorDto, GlobalDeviceDto, ProjectCommandDto, ProjectCommandResultDto, ProjectDeviceCommandResultDto, ProjectDeviceDto, ProjectFloorCommandResultDto, ProjectHistoryStateDto, ProjectRevisionPageDto, ProjectSnapshotMetadataDto, ProjectSnapshotRestoreResultDto, ProjectSettingsCommandResultDto, ProjectRoomCommandResultDto, ProjectDeviceSyncCommandResultDto, ProjectDeviceSyncPreviewDto, ProjectDto, RoomDto, CircuitTreeResponseDto, } 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"; import type { CircuitDeviceRowSnapshot, } from "../../domain/models/circuit-device-row-structure-project-command.model"; import type { CircuitSnapshot, } from "../../domain/models/circuit-structure-project-command.model"; import type { CircuitDeviceRowMoveAssignment, } from "../../domain/models/circuit-device-row-move-project-command.model"; import type { CircuitSectionReorderAssignment, } from "../../domain/models/circuit-section-reorder-project-command.model"; import type { CircuitSectionsReorderSection, } from "../../domain/models/circuit-sections-reorder-project-command.model"; import type { CircuitSectionRenumberAssignment, } from "../../domain/models/circuit-section-renumber-project-command.model"; async function request(url: string, init?: RequestInit): Promise { const response = await fetch(url, { ...init, headers: { "Content-Type": "application/json", ...init?.headers, }, cache: "no-store", }); if (!response.ok) { const details = await response.text(); throw new Error(details || `Anfrage fehlgeschlagen (Status ${response.status})`); } if (response.status === 204) { return undefined as T; } return response.json() as Promise; } export function listProjects() { return request("/api/projects"); } export function getProject(projectId: string) { return request(`/api/projects/${projectId}`); } export function getProjectHistory(projectId: string) { return request( `/api/projects/${projectId}/history` ); } export function listProjectRevisions( projectId: string, input: { limit?: number; beforeRevision?: number } = {} ) { const query = new URLSearchParams(); if (input.limit !== undefined) { query.set("limit", String(input.limit)); } if (input.beforeRevision !== undefined) { query.set("beforeRevision", String(input.beforeRevision)); } const suffix = query.size ? `?${query.toString()}` : ""; return request( `/api/projects/${projectId}/history/revisions${suffix}` ); } export function listProjectSnapshots(projectId: string) { return request( `/api/projects/${projectId}/snapshots` ); } export function createNamedProjectSnapshot( projectId: string, expectedRevision: number, name: string, description?: string ) { return request( `/api/projects/${projectId}/snapshots`, { method: "POST", body: JSON.stringify({ expectedRevision, name, ...(description ? { description } : {}), }), } ); } export function restoreProjectSnapshot( projectId: string, snapshotId: string, expectedRevision: number ) { return request( `/api/projects/${projectId}/snapshots/${snapshotId}/restore`, { method: "POST", body: JSON.stringify({ expectedRevision }), } ); } export function executeProjectCommand( projectId: string, expectedRevision: number, command: ProjectCommandDto, description?: string ) { return request( `/api/projects/${projectId}/commands`, { method: "POST", body: JSON.stringify({ expectedRevision, command, ...(description ? { description } : {}), }), } ); } export function undoProjectCommand( projectId: string, expectedRevision: number ) { return executeProjectHistoryCommand( projectId, expectedRevision, "undo" ); } export function redoProjectCommand( projectId: string, expectedRevision: number ) { return executeProjectHistoryCommand( projectId, expectedRevision, "redo" ); } function executeProjectHistoryCommand( projectId: string, expectedRevision: number, direction: "undo" | "redo" ) { return request( `/api/projects/${projectId}/history/${direction}`, { method: "POST", body: JSON.stringify({ expectedRevision }), } ); } export function createProject(name: string) { return request("/api/projects", { method: "POST", body: JSON.stringify({ name }), }); } export function updateProjectSettings( projectId: string, expectedRevision: number, input: { name: string; internalProjectNumber: string | null; externalProjectNumber: string | null; buildingOwner: string | null; description: string | null; singlePhaseVoltageV: number; threePhaseVoltageV: number; } ) { return request( `/api/projects/${projectId}`, { method: "PUT", body: JSON.stringify({ expectedRevision, ...input }), } ); } export function exportProjectTransfer(projectId: string) { return request(`/api/projects/${projectId}/export`); } export function importProjectTransfer( projectId: string, mode: "replace" | "duplicate", expectedRevision: number, transfer: unknown ) { return request< | { projectId: string; name: string } | ProjectSettingsCommandResultDto >(`/api/projects/${projectId}/import`, { method: "POST", body: JSON.stringify( mode === "replace" ? { mode, expectedRevision, transfer } : { mode, transfer } ), }); } export function listDistributionBoards(projectId: string) { return request(`/api/projects/${projectId}/distribution-boards`); } export function createDistributionBoard( projectId: string, name: string, expectedRevision: number ) { return request( `/api/projects/${projectId}/distribution-boards`, { method: "POST", body: JSON.stringify({ name, expectedRevision }), } ); } export function listCircuitLists(projectId: string) { return request(`/api/projects/${projectId}/circuit-lists`); } export function getCircuitTree(projectId: string, circuitListId: string) { return request(`/api/projects/${projectId}/circuit-lists/${circuitListId}/tree`); } export function updateCircuitById( projectId: string, expectedRevision: number, circuitId: string, input: CircuitUpdatePatch ) { return executeProjectCommand( projectId, expectedRevision, createCircuitUpdateProjectCommand(circuitId, input), "Stromkreisfeld bearbeiten" ); } export function insertCircuitCommand( projectId: string, expectedRevision: number, circuit: CircuitSnapshot, description: string ) { return executeProjectCommand( projectId, expectedRevision, { schemaVersion: 1, type: "circuit.insert", payload: { circuit }, }, description ); } export function deleteCircuitCommand( projectId: string, expectedRevision: number, circuitId: string, expectedCircuitListId: string, description: string ) { return executeProjectCommand( projectId, expectedRevision, { schemaVersion: 1, type: "circuit.delete", payload: { circuitId, expectedCircuitListId }, }, description ); } export function getNextCircuitIdentifier(sectionId: string) { return request<{ sectionId: string; nextIdentifier: string }>( `/api/circuit-sections/${sectionId}/next-identifier` ); } export function updateCircuitDeviceRowById( projectId: string, expectedRevision: number, rowId: string, input: CircuitDeviceRowUpdatePatch ) { return executeProjectCommand( projectId, expectedRevision, createCircuitDeviceRowUpdateProjectCommand(rowId, input), "Gerätezeilenfeld bearbeiten" ); } export function insertCircuitDeviceRowCommand( projectId: string, expectedRevision: number, row: CircuitDeviceRowSnapshot, description: string ) { return executeProjectCommand( projectId, expectedRevision, { schemaVersion: 1, type: "circuit-device-row.insert", payload: { row }, }, description ); } export function deleteCircuitDeviceRowCommand( projectId: string, expectedRevision: number, rowId: string, expectedCircuitId: string, description: string ) { return executeProjectCommand( projectId, expectedRevision, { schemaVersion: 1, type: "circuit-device-row.delete", payload: { rowId, expectedCircuitId }, }, description ); } export function moveCircuitDeviceRowsCommand( projectId: string, expectedRevision: number, moves: CircuitDeviceRowMoveAssignment[], description: string ) { return executeProjectCommand( projectId, expectedRevision, { schemaVersion: 1, type: "circuit-device-row.move", payload: { moves }, }, description ); } export function moveCircuitDeviceRowsToNewCircuitCommand( projectId: string, expectedRevision: number, targetCircuit: CircuitSnapshot, moves: CircuitDeviceRowMoveAssignment[], description: string ) { return executeProjectCommand( projectId, expectedRevision, { schemaVersion: 1, type: "circuit-device-row.move-with-new-circuit", payload: { targetCircuitAction: "create", targetCircuit, moves, }, }, description ); } export function reorderCircuitSectionCommand( projectId: string, expectedRevision: number, sectionId: string, assignments: CircuitSectionReorderAssignment[], description: string ) { return executeProjectCommand( projectId, expectedRevision, { schemaVersion: 1, type: "circuit.reorder-section", payload: { sectionId, assignments }, }, description ); } export function reorderCircuitSectionsCommand( projectId: string, expectedRevision: number, sections: CircuitSectionsReorderSection[], description: string ) { return executeProjectCommand( projectId, expectedRevision, { schemaVersion: 1, type: "circuit.reorder-sections", payload: { sections }, }, description ); } export function renumberCircuitSectionCommand( projectId: string, expectedRevision: number, sectionId: string, assignments: CircuitSectionRenumberAssignment[], description: string ) { return executeProjectCommand( projectId, expectedRevision, { schemaVersion: 1, type: "circuit.renumber-section", payload: { sectionId, assignments }, }, description ); } export function listFloors(projectId: string) { return request(`/api/projects/${projectId}/floors`); } export function createFloor( projectId: string, input: CreateFloorInput, expectedRevision: number ) { return request( `/api/projects/${projectId}/floors`, { method: "POST", body: JSON.stringify({ ...input, expectedRevision }), } ); } export function listRooms(projectId: string) { return request(`/api/projects/${projectId}/rooms`); } export function createRoom( projectId: string, input: CreateRoomInput, expectedRevision: number ) { return request( `/api/projects/${projectId}/rooms`, { method: "POST", body: JSON.stringify({ ...input, expectedRevision }), } ); } export function listGlobalDevices() { return request("/api/global-devices"); } export function createGlobalDevice(input: CreateGlobalDeviceInput) { return request("/api/global-devices", { method: "POST", body: JSON.stringify(input), }); } export function updateGlobalDevice(globalDeviceId: string, input: CreateGlobalDeviceInput) { return request(`/api/global-devices/${globalDeviceId}`, { method: "PUT", body: JSON.stringify(input), }); } export function deleteGlobalDevice(globalDeviceId: string) { return request(`/api/global-devices/${globalDeviceId}`, { method: "DELETE" }); } export function copyProjectDeviceToGlobal(projectId: string, projectDeviceId: string) { return request(`/api/global-devices/import-project/${projectId}/${projectDeviceId}`, { method: "POST", }); } export function listProjectDevices(projectId: string) { return request(`/api/project-devices/projects/${projectId}`); } export function createProjectDevice( projectId: string, input: CreateProjectDeviceInput, expectedRevision: number ) { return request(`/api/project-devices/projects/${projectId}`, { method: "POST", body: JSON.stringify({ ...input, expectedRevision }), }); } export function updateProjectDevice( projectId: string, projectDeviceId: string, input: CreateProjectDeviceInput, expectedRevision: number ) { return request( `/api/project-devices/projects/${projectId}/${projectDeviceId}`, { method: "PUT", body: JSON.stringify({ ...input, expectedRevision }), } ); } export function deleteProjectDevice( projectId: string, projectDeviceId: string, expectedRevision: number ) { return request( `/api/project-devices/projects/${projectId}/${projectDeviceId}`, { method: "DELETE", body: JSON.stringify({ expectedRevision }), } ); } export function copyGlobalDeviceToProject( projectId: string, globalDeviceId: string, expectedRevision: number ) { return request( `/api/project-devices/projects/${projectId}/import-global/${globalDeviceId}`, { method: "POST", body: JSON.stringify({ expectedRevision }), } ); } export function getProjectDeviceSyncPreview(projectId: string, projectDeviceId: string) { return request( `/api/project-devices/projects/${projectId}/${projectDeviceId}/links` ); } export function synchronizeProjectDeviceRows( projectId: string, projectDeviceId: string, rowIds: string[], fields: ProjectDeviceSyncField[], expectedRevision: number ) { return request( `/api/project-devices/projects/${projectId}/${projectDeviceId}/synchronize`, { method: "POST", body: JSON.stringify({ rowIds, fields, expectedRevision }), } ); } export function disconnectProjectDeviceRows( projectId: string, projectDeviceId: string, rowIds: string[], expectedRevision: number ) { return request( `/api/project-devices/projects/${projectId}/${projectDeviceId}/disconnect`, { method: "POST", body: JSON.stringify({ rowIds, expectedRevision }), } ); }