GF/AGF-Outlines: eigene Layer + minimaler Stempel/UI
Geschossflaeche (GF) und Aussengeschossflaeche (AGF) sind reine Flaechen-Ausweisungs-Outlines — keine Raeume mit Name/Nummer/Funktion. Backend: - Neue Layer-Helpers _layer_path_raum_gf (61_GF) und _layer_path_raum_agf (62_AGF) — eigene Sublayer pro Geschoss, eigene Default-Farben - _layer_path_for_raum_sia(doc, gname, sia): routet sia=gf → GF-Layer, sia=agf → AGF-Layer, sonst RAEUME-Layer (HNF/NNF/VF/FF/leer) - _regenerate_element_body raum_outline-Branch nutzt das Routing → Source-Outline migriert automatisch auf den richtigen Layer - _update_wall raum-Branch: bei SIA-Wechsel (z.B. HNF → GF) auch Layer-Migration - _make_raum_stamp_text: bei sia=gf/agf default-layout override auf [["sia", "area"]] → Stempel zeigt nur "GF 234.5 m²" / "AGF 18.0 m²" ohne Nummer/Name/Funktion Frontend (RaumProperties): - Conditional isFlaeche = sia in (gf, agf) - Versteckt bei isFlaeche: Stil-Picker, Nummer-Input, Name-Input, Funktion-Input, StempelLayoutBuilder - Bleibt sichtbar: Geschoss, SIA-Tag-Selector, Fuellung, Rundung, Skala-Modus, Flaeche/Umfang-Footer - Info-Zeile zeigt bei isFlaeche: "Flaechen-Outline (GF) auf eigenem Layer · Stempel zeigt nur GF + Flaeche"
This commit is contained in:
+75
-57
@@ -937,6 +937,10 @@ function RaumProperties({ raum, geschosse, onUpdate, onDelete, hatchPatterns, fo
|
||||
// Texthoehe (raum.txtH) + Ausrichtung (raum.align) werden via Oberleiste
|
||||
// gesetzt — kein Local-State noetig, Stil-Speichern liest direkt aus raum.
|
||||
const txtModus = raum.txtModus || 'fix'
|
||||
// Sonderfall: GF/AGF sind reine Flaechen-Outlines (keine Raum-Inhalte
|
||||
// wie Name/Nummer/Funktion). UI wird darunter minimiert auf SIA-Tag +
|
||||
// Skala + Fluessigkeits-Anzeige.
|
||||
const isFlaeche = (raum.sia === 'gf' || raum.sia === 'agf')
|
||||
useEffect(() => {
|
||||
setName(raum.name || 'Raum')
|
||||
setNummer(raum.nummer || '')
|
||||
@@ -988,21 +992,23 @@ function RaumProperties({ raum, geschosse, onUpdate, onDelete, hatchPatterns, fo
|
||||
{/* Stempel-Stil Preset-Picker — apply einer gespeicherten Visual-Vorlage
|
||||
auf den Raum. "+ Aktuell speichern" frischt die Liste mit den
|
||||
jetzigen Settings als neuen Stil. Stile sind per-Doc. */}
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
|
||||
<span style={{ fontSize: 10, color: 'var(--text-secondary)', width: 60 }}>Stil</span>
|
||||
<select value={activeStilId}
|
||||
onChange={(e) => handleStilChange(e.target.value)}
|
||||
style={{ flex: 1, fontSize: 11 }}
|
||||
title="Gespeicherter Stempel-Stil — Klick wendet die Vorlage an">
|
||||
<option value="">— Stil wählen —</option>
|
||||
{stilList.map(s => (
|
||||
<option key={s.id} value={s.id}>{s.name}</option>
|
||||
))}
|
||||
<option disabled>──────────</option>
|
||||
<option value="__save__">+ Aktuelle Settings als Stil speichern…</option>
|
||||
{activeStilId && <option value="__delete__">🗑 Aktiven Stil löschen</option>}
|
||||
</select>
|
||||
</div>
|
||||
{!isFlaeche && (
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
|
||||
<span style={{ fontSize: 10, color: 'var(--text-secondary)', width: 60 }}>Stil</span>
|
||||
<select value={activeStilId}
|
||||
onChange={(e) => handleStilChange(e.target.value)}
|
||||
style={{ flex: 1, fontSize: 11 }}
|
||||
title="Gespeicherter Stempel-Stil — Klick wendet die Vorlage an">
|
||||
<option value="">— Stil wählen —</option>
|
||||
{stilList.map(s => (
|
||||
<option key={s.id} value={s.id}>{s.name}</option>
|
||||
))}
|
||||
<option disabled>──────────</option>
|
||||
<option value="__save__">+ Aktuelle Settings als Stil speichern…</option>
|
||||
{activeStilId && <option value="__delete__">🗑 Aktiven Stil löschen</option>}
|
||||
</select>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
|
||||
<span style={{ fontSize: 10, color: 'var(--text-secondary)', width: 60 }}>Geschoss</span>
|
||||
@@ -1013,30 +1019,35 @@ function RaumProperties({ raum, geschosse, onUpdate, onDelete, hatchPatterns, fo
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
|
||||
<span style={{ fontSize: 10, color: 'var(--text-secondary)', width: 60 }}>Nummer</span>
|
||||
<input type="text" value={nummer}
|
||||
onChange={(e) => setNummer(e.target.value)}
|
||||
onBlur={() => {
|
||||
if (nummer !== (raum.nummer || '')) onUpdate({ nummer })
|
||||
}}
|
||||
onKeyDown={(e) => { if (e.key === 'Enter') e.target.blur() }}
|
||||
style={{ flex: 1, fontSize: 11,
|
||||
fontFamily: 'DM Mono, monospace' }} />
|
||||
</div>
|
||||
{/* Nummer + Name nur bei normalen Raeumen (nicht GF/AGF-Flaechen) */}
|
||||
{!isFlaeche && (
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
|
||||
<span style={{ fontSize: 10, color: 'var(--text-secondary)', width: 60 }}>Nummer</span>
|
||||
<input type="text" value={nummer}
|
||||
onChange={(e) => setNummer(e.target.value)}
|
||||
onBlur={() => {
|
||||
if (nummer !== (raum.nummer || '')) onUpdate({ nummer })
|
||||
}}
|
||||
onKeyDown={(e) => { if (e.key === 'Enter') e.target.blur() }}
|
||||
style={{ flex: 1, fontSize: 11,
|
||||
fontFamily: 'DM Mono, monospace' }} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
|
||||
<span style={{ fontSize: 10, color: 'var(--text-secondary)', width: 60 }}>Name</span>
|
||||
<input type="text" value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
onBlur={() => {
|
||||
const v = (name || 'Raum').trim()
|
||||
if (v !== raum.name) onUpdate({ name: v })
|
||||
else setName(v)
|
||||
}}
|
||||
onKeyDown={(e) => { if (e.key === 'Enter') e.target.blur() }}
|
||||
style={{ flex: 1, fontSize: 11 }} />
|
||||
</div>
|
||||
{!isFlaeche && (
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
|
||||
<span style={{ fontSize: 10, color: 'var(--text-secondary)', width: 60 }}>Name</span>
|
||||
<input type="text" value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
onBlur={() => {
|
||||
const v = (name || 'Raum').trim()
|
||||
if (v !== raum.name) onUpdate({ name: v })
|
||||
else setName(v)
|
||||
}}
|
||||
onKeyDown={(e) => { if (e.key === 'Enter') e.target.blur() }}
|
||||
style={{ flex: 1, fontSize: 11 }} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
|
||||
<span style={{ fontSize: 10, color: 'var(--text-secondary)', width: 60 }}>Typ</span>
|
||||
@@ -1100,27 +1111,33 @@ function RaumProperties({ raum, geschosse, onUpdate, onDelete, hatchPatterns, fo
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
|
||||
<span style={{ fontSize: 10, color: 'var(--text-secondary)', width: 60 }}>Funktion</span>
|
||||
<input type="text" value={funktion}
|
||||
onChange={(e) => setFunktion(e.target.value)}
|
||||
onBlur={() => {
|
||||
const v = (funktion || '').trim()
|
||||
if (v !== (raum.funktion || '')) onUpdate({ funktion: v })
|
||||
}}
|
||||
onKeyDown={(e) => { if (e.key === 'Enter') e.target.blur() }}
|
||||
placeholder="z.B. Wohnen, Bad, Büro …"
|
||||
style={{ flex: 1, fontSize: 11 }} />
|
||||
</div>
|
||||
{!isFlaeche && (
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
|
||||
<span style={{ fontSize: 10, color: 'var(--text-secondary)', width: 60 }}>Funktion</span>
|
||||
<input type="text" value={funktion}
|
||||
onChange={(e) => setFunktion(e.target.value)}
|
||||
onBlur={() => {
|
||||
const v = (funktion || '').trim()
|
||||
if (v !== (raum.funktion || '')) onUpdate({ funktion: v })
|
||||
}}
|
||||
onKeyDown={(e) => { if (e.key === 'Enter') e.target.blur() }}
|
||||
placeholder="z.B. Wohnen, Bad, Büro …"
|
||||
style={{ flex: 1, fontSize: 11 }} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Stempel-Layout — Drag-and-Drop. Jede Row ist eine Textzeile,
|
||||
Felder innerhalb einer Row landen in derselben Zeile. Drag
|
||||
zwischen Rows um umzuordnen. Klick auf Field oben fügt es in
|
||||
eine eigene neue Row hinzu. */}
|
||||
<StempelLayoutBuilder
|
||||
layout={layout}
|
||||
availableFields={availableFields}
|
||||
onChange={(newLayout) => onUpdate({ layout: newLayout })} />
|
||||
eine eigene neue Row hinzu.
|
||||
Bei GF/AGF-Flaechen wird das ausgeblendet — Stempel zeigt da
|
||||
automatisch nur den SIA-Tag + Flaeche (z.B. "GF · 234.5 m²"). */}
|
||||
{!isFlaeche && (
|
||||
<StempelLayoutBuilder
|
||||
layout={layout}
|
||||
availableFields={availableFields}
|
||||
onChange={(newLayout) => onUpdate({ layout: newLayout })} />
|
||||
)}
|
||||
|
||||
{/* Hinweis: Typografie (Font/Stil/Höhe) wird in der OBERLEISTE
|
||||
gesetzt — den Stempel im Viewport anklicken. Aenderungen werden
|
||||
@@ -1132,8 +1149,9 @@ function RaumProperties({ raum, geschosse, onUpdate, onDelete, hatchPatterns, fo
|
||||
display: 'flex', alignItems: 'center', gap: 4,
|
||||
}}>
|
||||
<Icon name="info" size={11} style={{ color: 'var(--text-muted)' }} />
|
||||
Typografie (Font/Stil/Höhe): Stempel im Viewport selektieren →
|
||||
Oberleiste.
|
||||
{isFlaeche
|
||||
? `Flächen-Outline (${(raum.sia || '').toUpperCase()}) auf eigenem Layer · Stempel zeigt nur ${(raum.sia || '').toUpperCase()} + Fläche`
|
||||
: 'Typografie (Font/Stil/Höhe): Stempel im Viewport selektieren → Oberleiste.'}
|
||||
</div>
|
||||
|
||||
<div style={{
|
||||
|
||||
Reference in New Issue
Block a user