forked from jappel/leistungsbilanz-ts
Compact circuit editor header, pin grid headers, scope sidebar to project
The circuit editor page now fills the viewport so only the grid scrolls and its sticky column headers stay visible. The large page title is replaced by a compact title bar with back link, board number/name, the feeding reference, the toolbar and a condensed power summary. Inside a project the sidebar shows only the active project with its sections, an expandable board list ordered by logical feed (current board highlighted), Revit and the print view. The feed ordering is shared with the print view through orderDistributionBoardsByFeed. Refs #26 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
898be43ebc
commit
07bc52a134
7 changed files with 444 additions and 156 deletions
|
|
@ -1,10 +1,11 @@
|
|||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { DragEvent, KeyboardEvent, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { DragEvent, KeyboardEvent, type ReactNode, useEffect, useMemo, useRef, useState } from "react";
|
||||
import {
|
||||
ArrowDown,
|
||||
ArrowDown01,
|
||||
ArrowLeft,
|
||||
ArrowUp,
|
||||
Calculator,
|
||||
Check,
|
||||
|
|
@ -27,6 +28,7 @@ import {
|
|||
Undo2,
|
||||
} from "lucide-react";
|
||||
import { IconButton, IconButtonSeparator } from "./icon-button";
|
||||
import { IconLink } from "./icon-link";
|
||||
import {
|
||||
inferProjectDeviceSectionKey,
|
||||
isProjectDevicePlacementValid,
|
||||
|
|
@ -652,6 +654,66 @@ export function CircuitTreeEditor(props: { projectId: string; circuitListId: str
|
|||
);
|
||||
}
|
||||
|
||||
// Compact title block at the start of the toolbar: back link, board
|
||||
// number/name and the optional feeding reference in one line.
|
||||
function renderEditorHeading() {
|
||||
const feedingReference = data?.feedingReference;
|
||||
return (
|
||||
<div className="editor-heading">
|
||||
<IconLink
|
||||
href={`/projects/${projectId}`}
|
||||
icon={ArrowLeft}
|
||||
label="Zurück zum Projekt"
|
||||
/>
|
||||
<div className="editor-heading-text">
|
||||
<span className="editor-heading-kicker">
|
||||
Stromkreisliste
|
||||
{feedingReference ? (
|
||||
<>
|
||||
{" · gespeist von "}
|
||||
<Link
|
||||
href={`/projects/${projectId}/circuit-lists/${feedingReference.circuitListId}/tree-edit`}
|
||||
title={
|
||||
feedingReference.circuitId
|
||||
? undefined
|
||||
: "Speisender Stromkreis noch nicht festgelegt"
|
||||
}
|
||||
>
|
||||
{feedingReference.distributionBoardNumber ??
|
||||
feedingReference.distributionBoardName}
|
||||
{feedingReference.circuitEquipmentIdentifier ?? ""}
|
||||
</Link>
|
||||
{feedingReference.circuitId ? null : " (Stromkreis offen)"}
|
||||
</>
|
||||
) : null}
|
||||
</span>
|
||||
<h1 className="editor-heading-title">
|
||||
{data ? (
|
||||
<>
|
||||
{data.distributionBoardNumber ? (
|
||||
<strong>{data.distributionBoardNumber}</strong>
|
||||
) : null}
|
||||
<span>{data.distributionBoardName}</span>
|
||||
</>
|
||||
) : (
|
||||
"Verteiler"
|
||||
)}
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Loading/error states keep the title bar so the back link is always there.
|
||||
function renderEditorStatus(notice: ReactNode) {
|
||||
return (
|
||||
<div className="tree-editor-shell">
|
||||
<div className="editor-toolbar">{renderEditorHeading()}</div>
|
||||
{notice}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function renderDistributionPowerSummary() {
|
||||
if (!data) {
|
||||
return null;
|
||||
|
|
@ -661,8 +723,8 @@ export function CircuitTreeEditor(props: { projectId: string; circuitListId: str
|
|||
className="distribution-power-summary"
|
||||
aria-label="Leistungszusammenfassung des Verteilers"
|
||||
>
|
||||
<div>
|
||||
<span>Gesamtleistung Verteiler</span>
|
||||
<div title="Gesamtleistung Verteiler">
|
||||
<span>Gesamtleistung</span>
|
||||
<strong>
|
||||
{formatValue(
|
||||
data.distributionBoardTotalPower,
|
||||
|
|
@ -671,8 +733,8 @@ export function CircuitTreeEditor(props: { projectId: string; circuitListId: str
|
|||
kW
|
||||
</strong>
|
||||
</div>
|
||||
<div>
|
||||
<span>Verteilerweiter Gleichzeitigkeitsfaktor</span>
|
||||
<div title="Verteilerweiter Gleichzeitigkeitsfaktor">
|
||||
<span>GZF Verteiler</span>
|
||||
<strong>
|
||||
{formatValue(
|
||||
data.distributionBoardSimultaneityFactor,
|
||||
|
|
@ -680,11 +742,8 @@ export function CircuitTreeEditor(props: { projectId: string; circuitListId: str
|
|||
)}
|
||||
</strong>
|
||||
</div>
|
||||
<div>
|
||||
<span>
|
||||
Gesamtleistung Verteiler unter Berücksichtigung des
|
||||
Gleichzeitigkeitsfaktors
|
||||
</span>
|
||||
<div title="Gesamtleistung Verteiler unter Berücksichtigung des Gleichzeitigkeitsfaktors">
|
||||
<span>Leistung mit GZF</span>
|
||||
<strong>
|
||||
{formatValue(
|
||||
data.distributionBoardTotalPowerWithSimultaneityFactor,
|
||||
|
|
@ -3217,18 +3276,24 @@ export function CircuitTreeEditor(props: { projectId: string; circuitListId: str
|
|||
}
|
||||
|
||||
if (isLoading && !data) {
|
||||
return <div className="notice info">Stromkreislisteneditor wird geladen …</div>;
|
||||
return renderEditorStatus(
|
||||
<div className="notice info">Stromkreislisteneditor wird geladen …</div>
|
||||
);
|
||||
}
|
||||
if (error && !data) {
|
||||
return <div className="notice error">{error}</div>;
|
||||
return renderEditorStatus(<div className="notice error">{error}</div>);
|
||||
}
|
||||
if (!data || data.sections.length === 0) {
|
||||
return <div className="notice muted">Keine Bereiche oder Stromkreise vorhanden.</div>;
|
||||
return renderEditorStatus(
|
||||
<div className="notice muted">Keine Bereiche oder Stromkreise vorhanden.</div>
|
||||
);
|
||||
}
|
||||
if (filteredSortedSections.length === 0) {
|
||||
return (
|
||||
<div className="tree-editor-shell">
|
||||
<div className="editor-toolbar">
|
||||
{renderEditorHeading()}
|
||||
<IconButtonSeparator />
|
||||
<IconButton
|
||||
disabled={!historyState || historyState.undoDepth === 0 || historyBusy || isSaving}
|
||||
icon={Undo2}
|
||||
|
|
@ -3258,10 +3323,10 @@ export function CircuitTreeEditor(props: { projectId: string; circuitListId: str
|
|||
onClick={clearSortAndFilters}
|
||||
showLabel
|
||||
/>
|
||||
{renderDistributionPowerSummary()}
|
||||
{renderColumnSettingsMenu("col-empty")}
|
||||
</div>
|
||||
{renderActiveViewSummary()}
|
||||
{renderDistributionPowerSummary()}
|
||||
{error ? (
|
||||
<div className="notice error editor-error-notice" role="alert">
|
||||
<span>{error}</span>
|
||||
|
|
@ -3396,24 +3461,9 @@ export function CircuitTreeEditor(props: { projectId: string; circuitListId: str
|
|||
threePhaseVoltageV={data.threePhaseVoltageV}
|
||||
/>
|
||||
) : null}
|
||||
{data.feedingReference ? (
|
||||
<div className="alert alert-info py-2" role="status">
|
||||
Gespeist von{" "}
|
||||
<Link
|
||||
href={`/projects/${projectId}/circuit-lists/${
|
||||
data.feedingReference.circuitListId
|
||||
}/tree-edit`}
|
||||
>
|
||||
{data.feedingReference.distributionBoardNumber ??
|
||||
data.feedingReference.distributionBoardName}
|
||||
{data.feedingReference.circuitEquipmentIdentifier ?? ""}
|
||||
</Link>
|
||||
{data.feedingReference.circuitId
|
||||
? null
|
||||
: " (speisender Stromkreis noch nicht festgelegt)"}
|
||||
</div>
|
||||
) : null}
|
||||
<div className="editor-toolbar">
|
||||
{renderEditorHeading()}
|
||||
<IconButtonSeparator />
|
||||
<IconButton
|
||||
disabled={!historyState || historyState.undoDepth === 0 || historyBusy || isSaving}
|
||||
icon={Undo2}
|
||||
|
|
@ -3507,10 +3557,10 @@ export function CircuitTreeEditor(props: { projectId: string; circuitListId: str
|
|||
}
|
||||
showLabel
|
||||
/>
|
||||
{renderDistributionPowerSummary()}
|
||||
{renderColumnSettingsMenu("col")}
|
||||
</div>
|
||||
{renderActiveViewSummary()}
|
||||
{renderDistributionPowerSummary()}
|
||||
{hasActiveSortOrFilter ? (
|
||||
<div className="notice muted">Sortierung und Filter verändern nur die Ansicht. Die Neunummerierung ist währenddessen deaktiviert.</div>
|
||||
) : null}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue