forked from jappel/leistungsbilanz-ts
Offer supply suggestions, drop the circuit column, center cells
The Versorgung field suggests ELT and MSR (plus values already used in the balance) through a datalist and still accepts free text. The circuit number column is not needed in early design phases; it is removed from the data model, the regenerated migration 0010, the editor and the print. All cells are centered except "Verbraucher / Flächen", group titles and total labels. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
e06c7d91e2
commit
72189d23a5
12 changed files with 60 additions and 42 deletions
|
|
@ -34,7 +34,7 @@ das Frontend sie direkt nutzt (Turbopack löst die `.js`-Suffixe der API nicht a
|
|||
|---|---|
|
||||
| `estimate_balances` | ein **Stand** je Projekt (z. B. Vorplanung, Entwurfsplanung): Name, LPH, Datum, Reserve AV/SV in %, Sortierung |
|
||||
| `estimate_groups` | Kostengruppe (`"410"` … `"480"`, `""` für „Allgemein“), Titel, „bearbeitet von“, Sortierung |
|
||||
| `estimate_rows` | Versorgung, Stromkreis-Nr. (Freitext), Verbraucher/Fläche, Anzahl bzw. Fläche, Einheit (`piece` = St., `area` = m²), Anschluss (fest/Steckdose), Einzelleistung in W bzw. W/m², GLF, cos φ, SV ja/nein, Anmerkung |
|
||||
| `estimate_rows` | Versorgung (Auswahl ELT/MSR oder Freitext), Verbraucher/Fläche, Anzahl bzw. Fläche, Einheit (`piece` = St., `area` = m²), Anschluss (fest/Steckdose), Einzelleistung in W bzw. W/m², GLF, cos φ, SV ja/nein, Anmerkung |
|
||||
|
||||
Neue Stände entstehen aus der Vorlage KG 400 (410 Sanitär, 420 Wärme, 430 Luft,
|
||||
434 Kälte, 440 Starkstrom, 450 Schwachstrom, 460 Förder, 470 Nutzungsspezifisch,
|
||||
|
|
|
|||
|
|
@ -1731,7 +1731,6 @@ button.structure-entry-main:focus-visible {
|
|||
|
||||
.estimate-col-kg { width: 3rem; }
|
||||
.estimate-col-supply { width: 4rem; }
|
||||
.estimate-col-circuit { width: 4.6rem; }
|
||||
.estimate-col-name { width: auto; }
|
||||
.estimate-col-quantity { width: 4.8rem; }
|
||||
.estimate-col-unit { width: 3.8rem; }
|
||||
|
|
@ -1965,6 +1964,36 @@ button.structure-entry-main:focus-visible {
|
|||
display: none;
|
||||
}
|
||||
|
||||
/* Ausrichtung: alle Zellen zentriert, nur „Verbraucher / Flächen“, die
|
||||
Gruppentitel und die Summenbeschriftungen stehen links bzw. rechts. */
|
||||
.estimate-sheet td,
|
||||
.estimate-sheet td.estimate-number,
|
||||
.estimate-sheet .estimate-cell-input,
|
||||
.estimate-sheet .estimate-cell-input.is-numeric {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.estimate-sheet .estimate-cell-select {
|
||||
text-align: center;
|
||||
text-align-last: center;
|
||||
}
|
||||
|
||||
.estimate-sheet .estimate-unit-input,
|
||||
.estimate-sheet .estimate-gzf-input {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.estimate-sheet td.estimate-name-cell,
|
||||
.estimate-sheet td.estimate-name-cell .estimate-cell-input,
|
||||
.estimate-sheet .estimate-group-title-row td:not(.estimate-cost-group-cell),
|
||||
.estimate-comparison td:nth-child(2) {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.estimate-sheet td.estimate-total-label {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* Druck im kbp-CD der Seitenansicht (src/frontend/print/print-document.css):
|
||||
gleiche Farben, Schrift, Titelblock und Fußzeile. Die Fußzeile mit
|
||||
Seitenzahlen setzt EstimatePrintHeader als @page-Regel mit Projektdaten. */
|
||||
|
|
@ -2251,6 +2280,6 @@ button.structure-entry-main:focus-visible {
|
|||
|
||||
.estimate-unit-input,
|
||||
.estimate-gzf-input {
|
||||
justify-content: flex-end;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ CREATE TABLE `estimate_rows` (
|
|||
`group_id` text NOT NULL,
|
||||
`sort_order` integer DEFAULT 0 NOT NULL,
|
||||
`supply` text,
|
||||
`circuit_ref` text,
|
||||
`name` text DEFAULT '' NOT NULL,
|
||||
`quantity` real DEFAULT 0 NOT NULL,
|
||||
`unit` text DEFAULT 'piece' NOT NULL,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"version": "6",
|
||||
"dialect": "sqlite",
|
||||
"id": "6df688bd-a78a-46a1-ba7a-4068119bf8bd",
|
||||
"id": "5376ae9f-67c7-4603-b3d2-8527136436f9",
|
||||
"prevId": "2cd9adef-2f08-4635-b3d9-ecf71f624c7f",
|
||||
"tables": {
|
||||
"buildings": {
|
||||
|
|
@ -1322,13 +1322,6 @@
|
|||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"circuit_ref": {
|
||||
"name": "circuit_ref",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@
|
|||
{
|
||||
"idx": 10,
|
||||
"version": "6",
|
||||
"when": 1790425784626,
|
||||
"when": 1790438092269,
|
||||
"tag": "0010_estimate_balances",
|
||||
"breakpoints": true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ export const estimateRows = sqliteTable(
|
|||
.references(() => estimateGroups.id, { onDelete: "cascade" }),
|
||||
sortOrder: integer("sort_order").notNull().default(0),
|
||||
supply: text("supply"),
|
||||
circuitRef: text("circuit_ref"),
|
||||
name: text("name").notNull().default(""),
|
||||
quantity: real("quantity").notNull().default(0),
|
||||
unit: text("unit", { enum: ["piece", "area"] }).notNull().default("piece"),
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ export const estimateRowSnapshotSchema = z
|
|||
id: idSchema,
|
||||
sortOrder: z.number().int().min(0),
|
||||
supply: nullableText(50),
|
||||
circuitRef: nullableText(50),
|
||||
name: trimmed(200),
|
||||
quantity: finite.min(0),
|
||||
unit: z.enum(["piece", "area"]),
|
||||
|
|
@ -158,7 +157,6 @@ export function canonicalEstimateBalance(balance: EstimateBalanceSnapshot): stri
|
|||
id: row.id,
|
||||
sortOrder: row.sortOrder,
|
||||
supply: row.supply,
|
||||
circuitRef: row.circuitRef,
|
||||
name: row.name,
|
||||
quantity: row.quantity,
|
||||
unit: row.unit,
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ export const estimateTextLimits = {
|
|||
groupTitle: 200,
|
||||
groupEditor: 100,
|
||||
supply: 50,
|
||||
circuitRef: 50,
|
||||
rowName: 200,
|
||||
remark: 500,
|
||||
} as const;
|
||||
|
|
@ -34,7 +33,6 @@ export function createEstimateRow(
|
|||
id: createId(),
|
||||
sortOrder,
|
||||
supply: null,
|
||||
circuitRef: null,
|
||||
name: "",
|
||||
quantity: 1,
|
||||
unit: "piece",
|
||||
|
|
@ -257,7 +255,6 @@ export function toSaveableEstimateBalance(
|
|||
id: row.id,
|
||||
sortOrder: row.sortOrder,
|
||||
supply: optionalText(row.supply),
|
||||
circuitRef: optionalText(row.circuitRef),
|
||||
name: requiredText(row.name),
|
||||
quantity: row.quantity,
|
||||
unit: row.unit,
|
||||
|
|
|
|||
|
|
@ -50,8 +50,12 @@ interface EstimateBalanceSheetProps {
|
|||
}
|
||||
|
||||
// Leading columns up to cos φ; the power columns follow.
|
||||
const LEADING_COLUMN_COUNT = 10;
|
||||
const COLUMN_COUNT = 17;
|
||||
const LEADING_COLUMN_COUNT = 9;
|
||||
const COLUMN_COUNT = 16;
|
||||
|
||||
/** Suggested supply values; free text stays possible. */
|
||||
const SUPPLY_SUGGESTIONS = ["ELT", "MSR"];
|
||||
const SUPPLY_LIST_ID = "estimate-supply-options";
|
||||
|
||||
function NumberInput({
|
||||
ariaLabel,
|
||||
|
|
@ -85,9 +89,17 @@ function NumberInput({
|
|||
);
|
||||
}
|
||||
|
||||
function supplyOptions(balance: EstimateBalanceSnapshot): string[] {
|
||||
const used = balance.groups.flatMap((group) =>
|
||||
group.rows.map((row) => row.supply?.trim() ?? "")
|
||||
);
|
||||
return [...new Set([...SUPPLY_SUGGESTIONS, ...used.filter(Boolean)])];
|
||||
}
|
||||
|
||||
function TextInput({
|
||||
ariaLabel,
|
||||
disabled,
|
||||
list,
|
||||
maxLength,
|
||||
onChange,
|
||||
placeholder,
|
||||
|
|
@ -95,6 +107,7 @@ function TextInput({
|
|||
}: {
|
||||
ariaLabel: string;
|
||||
disabled: boolean;
|
||||
list?: string;
|
||||
maxLength: number;
|
||||
onChange: (value: string) => void;
|
||||
placeholder?: string;
|
||||
|
|
@ -106,6 +119,7 @@ function TextInput({
|
|||
aria-label={ariaLabel}
|
||||
className="estimate-cell-input"
|
||||
disabled={disabled}
|
||||
list={list}
|
||||
maxLength={maxLength}
|
||||
onChange={(event) => onChange(event.target.value)}
|
||||
placeholder={placeholder}
|
||||
|
|
@ -189,22 +203,14 @@ function EstimateRowLine({
|
|||
<TextInput
|
||||
ariaLabel={`Versorgung (${rowLabel})`}
|
||||
disabled={disabled}
|
||||
list={SUPPLY_LIST_ID}
|
||||
maxLength={estimateTextLimits.supply}
|
||||
onChange={(supply) => patch({ supply })}
|
||||
placeholder="ELT"
|
||||
value={row.supply}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<TextInput
|
||||
ariaLabel={`Stromkreis-Nr. (${rowLabel})`}
|
||||
disabled={disabled}
|
||||
maxLength={estimateTextLimits.circuitRef}
|
||||
onChange={(circuitRef) => patch({ circuitRef })}
|
||||
value={row.circuitRef}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<td className="estimate-name-cell">
|
||||
<TextInput
|
||||
ariaLabel={`Verbraucher / Fläche (${rowLabel})`}
|
||||
disabled={disabled}
|
||||
|
|
@ -384,11 +390,15 @@ export function EstimateBalanceSheet({
|
|||
|
||||
return (
|
||||
<div className="estimate-sheet-wrap">
|
||||
<datalist id={SUPPLY_LIST_ID}>
|
||||
{supplyOptions(balance).map((supply) => (
|
||||
<option key={supply} value={supply} />
|
||||
))}
|
||||
</datalist>
|
||||
<table className="estimate-sheet">
|
||||
<colgroup>
|
||||
<col className="estimate-col-kg" />
|
||||
<col className="estimate-col-supply" />
|
||||
<col className="estimate-col-circuit" />
|
||||
<col className="estimate-col-name" />
|
||||
<col className="estimate-col-quantity" />
|
||||
<col className="estimate-col-unit" />
|
||||
|
|
@ -409,9 +419,8 @@ export function EstimateBalanceSheet({
|
|||
<th rowSpan={2}>KG</th>
|
||||
<th rowSpan={2}>
|
||||
Versorgung
|
||||
<span className="estimate-th-hint">ELT/ISP …</span>
|
||||
<span className="estimate-th-hint">ELT/MSR …</span>
|
||||
</th>
|
||||
<th rowSpan={2}>Stromkreis-Nr.</th>
|
||||
<th rowSpan={2}>Verbraucher / Flächen</th>
|
||||
<th colSpan={2}>
|
||||
Anzahl / Fläche
|
||||
|
|
|
|||
|
|
@ -12,10 +12,8 @@ export type EstimateRowConnection = "fixed" | "socket";
|
|||
export interface EstimateRowSnapshot {
|
||||
id: string;
|
||||
sortOrder: number;
|
||||
/** Versorgung, e.g. "ELT" or "ISP". */
|
||||
/** Versorgung, e.g. "ELT" or "MSR" (free text). */
|
||||
supply: string | null;
|
||||
/** Optional circuit reference, free text. */
|
||||
circuitRef: string | null;
|
||||
/** Verbraucher / Fläche. May be empty while a row is being typed. */
|
||||
name: string;
|
||||
/** Anzahl (unit "piece") or area in m² (unit "area"). */
|
||||
|
|
|
|||
|
|
@ -165,7 +165,6 @@ describe("estimate balance document editing", () => {
|
|||
id: "row-x",
|
||||
sortOrder: 3,
|
||||
supply: null,
|
||||
circuitRef: null,
|
||||
name: "",
|
||||
quantity: 1,
|
||||
unit: "piece",
|
||||
|
|
@ -273,7 +272,6 @@ describe("estimate balance saving", () => {
|
|||
balance = updateEstimateRow(balance, "group-410", "row-a", {
|
||||
name: " Hebeanlage ",
|
||||
supply: " ELT ",
|
||||
circuitRef: "",
|
||||
remark: " ",
|
||||
});
|
||||
const saveable = toSaveableEstimateBalance(balance);
|
||||
|
|
@ -286,10 +284,9 @@ describe("estimate balance saving", () => {
|
|||
{
|
||||
name: saveable.groups[0]!.rows[0]!.name,
|
||||
supply: saveable.groups[0]!.rows[0]!.supply,
|
||||
circuitRef: saveable.groups[0]!.rows[0]!.circuitRef,
|
||||
remark: saveable.groups[0]!.rows[0]!.remark,
|
||||
},
|
||||
{ name: "Hebeanlage", supply: "ELT", circuitRef: null, remark: null }
|
||||
{ name: "Hebeanlage", supply: "ELT", remark: null }
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ function row(
|
|||
id: id(),
|
||||
sortOrder: 0,
|
||||
supply: "ELT",
|
||||
circuitRef: null,
|
||||
name,
|
||||
quantity,
|
||||
unit: "piece",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue