Personen-Belegung pro Raum + Stempel-Aggregation
Architekten-Workflow: bei Schulen/Buero/Versammlungsstaetten muss die Personenzahl pro Raum erfasst werden (SIA: m²/Person als Indikator). Backend: - UserString dossier_raum_personen (int) - _attach_meta + _read_meta + state-emit - _update_wall raum-Branch akzeptiert "personen" im Patch - compute_sia_bilanz aggregiert personen-Summe ueber Scope - Stempel: neue Show-Flag stempel_show_personen (default false) + Bilanz-Renderer-Zeile "N Personen" - Stempel-Stil-Field showPersonen mit dabei Frontend (RaumProperties): - Personen-Input (number, min 0) zwischen Funktion + Layout-Builder - Nur sichtbar bei normalen Raeumen (nicht GF/AGF) - Live-Anzeige "m²/Person" Suffix wenn area + personen > 0 → User sieht sofort ob die Belegung sinnvoll ist (SIA-Vergleich) Frontend (StempelProperties): - Neuer Show-Toggle "Personen" (default off) - Live-Vorschau zeigt Personen-Summe wenn aktiv + > 0 - _OFF_BY_DEFAULT Set generalisiert Default-Handling (showCount, showPersonen)
This commit is contained in:
+47
-5
@@ -937,6 +937,7 @@ function RaumProperties({ raum, geschosse, onUpdate, onDelete, hatchPatterns, fo
|
||||
const [name, setName] = useState(raum.name || 'Raum')
|
||||
const [nummer, setNummer] = useState(raum.nummer || '')
|
||||
const [funktion, setFunktion] = useState(raum.funktion || '')
|
||||
const [personenStr, setPersonenStr] = useState(String(raum.personen || 0))
|
||||
// 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'
|
||||
@@ -948,7 +949,8 @@ function RaumProperties({ raum, geschosse, onUpdate, onDelete, hatchPatterns, fo
|
||||
setName(raum.name || 'Raum')
|
||||
setNummer(raum.nummer || '')
|
||||
setFunktion(raum.funktion || '')
|
||||
}, [raum.id, raum.name, raum.nummer, raum.funktion])
|
||||
setPersonenStr(String(raum.personen || 0))
|
||||
}, [raum.id, raum.name, raum.nummer, raum.funktion, raum.personen])
|
||||
|
||||
// Aktueller Wert von raum_fuellung: "" | "Solid" | "Hatch1" | … | "ByLayer"
|
||||
const fuell = raum.fuellung || ''
|
||||
@@ -1133,6 +1135,33 @@ function RaumProperties({ raum, geschosse, onUpdate, onDelete, hatchPatterns, fo
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Personen-Belegung (SIA: Schulen, Bueros, Versammlungen) —
|
||||
aggregiert im Bilanz-Stempel als "Personen"-Zeile wenn aktiv. */}
|
||||
{!isFlaeche && (
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
|
||||
<span style={{ fontSize: 10, color: 'var(--text-secondary)', width: 60 }}>Personen</span>
|
||||
<input type="number" min="0" step="1" value={personenStr}
|
||||
onChange={(e) => setPersonenStr(e.target.value)}
|
||||
onBlur={() => {
|
||||
const n = parseInt(personenStr, 10)
|
||||
const v = Number.isFinite(n) && n >= 0 ? n : 0
|
||||
if (v !== (raum.personen || 0)) onUpdate({ personen: v })
|
||||
setPersonenStr(String(v))
|
||||
}}
|
||||
onKeyDown={(e) => { if (e.key === 'Enter') e.target.blur() }}
|
||||
placeholder="0"
|
||||
title="Anzahl Personen — wird im Bilanz-Stempel summiert (m²/Person nach SIA)"
|
||||
style={{ width: 64, fontSize: 11, textAlign: 'right',
|
||||
fontFamily: 'DM Mono, monospace' }} />
|
||||
{raum.area > 0 && raum.personen > 0 && (
|
||||
<span style={{ fontSize: 9, color: 'var(--text-muted)',
|
||||
fontFamily: 'DM Mono, monospace' }}>
|
||||
{(raum.area / raum.personen).toFixed(1)} m²/Person
|
||||
</span>
|
||||
)}
|
||||
</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
|
||||
@@ -1185,7 +1214,8 @@ function StempelProperties({ stempel, geschosse, stempelStile, onUpdate, onDelet
|
||||
setHeaderDraft(stempel.header || 'Nutzflächen')
|
||||
}, [stempel.id, stempel.header])
|
||||
|
||||
// Show-Flags vom Backend (default true ausser showCount)
|
||||
// Show-Flags vom Backend — default true ausser folgende:
|
||||
const _OFF_BY_DEFAULT = new Set(['showCount', 'showPersonen'])
|
||||
const _show = (k, def = true) =>
|
||||
(stempel[k] !== undefined ? !!stempel[k] : def)
|
||||
|
||||
@@ -1205,6 +1235,7 @@ function StempelProperties({ stempel, geschosse, stempelStile, onUpdate, onDelet
|
||||
showGf: _show('showGf'),
|
||||
showAgf: _show('showAgf'),
|
||||
showCount: _show('showCount', false),
|
||||
showPersonen: _show('showPersonen', false),
|
||||
showSeparators: _show('showSeparators'),
|
||||
font: stempel.font || '',
|
||||
bold: !!stempel.bold,
|
||||
@@ -1239,9 +1270,9 @@ function StempelProperties({ stempel, geschosse, stempelStile, onUpdate, onDelet
|
||||
|
||||
const ShowTog = ({ field, label, hint }) => (
|
||||
<BarToggle label={label}
|
||||
icon={_show(field, field === 'showCount' ? false : true) ? 'check_box' : 'check_box_outline_blank'}
|
||||
active={_show(field, field === 'showCount' ? false : true)}
|
||||
onClick={() => onUpdate({ [field]: !_show(field, field === 'showCount' ? false : true) })}
|
||||
icon={_show(field, _OFF_BY_DEFAULT.has(field) ? false : true) ? 'check_box' : 'check_box_outline_blank'}
|
||||
active={_show(field, _OFF_BY_DEFAULT.has(field) ? false : true)}
|
||||
onClick={() => onUpdate({ [field]: !_show(field, _OFF_BY_DEFAULT.has(field) ? false : true) })}
|
||||
title={hint || label} />
|
||||
)
|
||||
|
||||
@@ -1327,6 +1358,7 @@ function StempelProperties({ stempel, geschosse, stempelStile, onUpdate, onDelet
|
||||
<ShowTog field="showGf" label="GF" />
|
||||
<ShowTog field="showAgf" label="AGF" />
|
||||
<ShowTog field="showCount" label="Anzahl" hint="Anzahl klassifizierter Räume" />
|
||||
<ShowTog field="showPersonen" label="Personen" hint="Summe der Personen-Belegung (SIA)" />
|
||||
<ShowTog field="showSeparators" label="Linien" hint="Trennlinien zwischen Sections" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -1357,6 +1389,16 @@ function StempelProperties({ stempel, geschosse, stempelStile, onUpdate, onDelet
|
||||
<span>{r.val.toFixed(1)} m²</span>
|
||||
</div>
|
||||
))}
|
||||
{_show('showPersonen', false) && (bilanz.personen || 0) > 0 && (
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between',
|
||||
padding: '2px 0',
|
||||
borderTop: '1px dashed var(--border-light)',
|
||||
marginTop: 2 }}
|
||||
title="Summe Personen über alle Räume im Scope">
|
||||
<span>Personen</span>
|
||||
<span>{bilanz.personen}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div style={{
|
||||
|
||||
Reference in New Issue
Block a user