Add AMEV Gleichzeitigkeitsfaktor-Auswähler und einklappbare Seitenleiste

- Gzf-Picker-Modal mit AMEV-Tabelle 3 (Planungshilfe für elektrische
  Leistungsbilanzen) im Projektgerät-Modal und im globalen Geräteformular
- Docker-Deploy-Tooling (docker-start.sh, run-migrations.js) für den
  produktiven Container
- Seitenleiste ist jetzt einklappbar (Icon-only, Zustand in localStorage)
This commit is contained in:
Grovy311 2026-08-03 17:07:14 +02:00
parent 74bea1a3c9
commit 9bd22dfcb7
11 changed files with 349 additions and 41 deletions

View file

@ -0,0 +1,86 @@
"use client";
import { AMEV_GZF_TABLE } from "../../shared/constants/amev-gzf";
interface GzfPickerModalProps {
onClose: () => void;
onSelect: (value: number) => void;
}
function formatFactor(value: number) {
return value.toLocaleString("de-DE", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}
export function GzfPickerModal({ onClose, onSelect }: GzfPickerModalProps) {
return (
<>
<div aria-modal="true" className="modal fade show d-block" role="dialog" tabIndex={-1}>
<div className="modal-dialog modal-lg modal-dialog-centered">
<div className="modal-content">
<div className="modal-header">
<div>
<h2 className="modal-title fs-5">Gleichzeitigkeitsfaktor nach AMEV</h2>
<p className="text-secondary small mb-0">
Tabelle 3 Gleichzeitigkeitsfaktoren für Verbrauchergruppen
</p>
</div>
<button
aria-label="Schließen"
className="btn-close"
onClick={onClose}
type="button"
/>
</div>
<div className="modal-body">
<div className="table-responsive">
<table className="table table-hover align-middle mb-0">
<thead>
<tr>
<th>Verbrauchergruppe</th>
<th>Bereich</th>
<th className="text-end">Mittelwert</th>
<th className="text-end">Gfges</th>
<th className="text-end">Aktion</th>
</tr>
</thead>
<tbody>
{AMEV_GZF_TABLE.map((entry) => (
<tr key={entry.group}>
<td>{entry.group}</td>
<td>{entry.range}</td>
<td className="text-end">{formatFactor(entry.mean)}</td>
<td className="text-end text-secondary small">
{entry.overallRange ?? ""}
</td>
<td className="text-end">
<button
className="btn btn-sm btn-primary"
onClick={() => onSelect(entry.mean)}
type="button"
>
Übernehmen
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
<p className="text-secondary small mt-3 mb-0">
Quelle: AMEV Planungshilfe für elektrische Leistungsbilanzen", Tabelle 3.
Übernommen wird jeweils der Mittelwert Gf1 der angegebenen Bandbreite; Gfges"
ist der alternative Gesamtgleichzeitigkeitsfaktor für Verwaltungsgebäude.
</p>
</div>
<div className="modal-footer">
<button className="btn btn-outline-secondary" onClick={onClose} type="button">
Abbrechen
</button>
</div>
</div>
</div>
</div>
<div className="modal-backdrop fade show" />
</>
);
}