v0.4.1: UI opgeschoond — tabbladen, iconen, uniforme labels, T-cyclus

- core/ui-kit.js: gedeelde velden/schakelaars/tabs/specificatiekaarten
- Bootstrap Icons lokaal (css/vendor, font ingebed)
- Woning- en unit-instellingen in tabbladen, labels gestandaardiseerd
- Specificaties onder 3D als kaarten
- T: standaard -> 3D groot -> alleen render -> standaard

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Machiel
2026-09-30 11:51:18 +02:00
co-authored by Claude Opus 5.5
parent c690e72d13
commit 3591fad220
11 changed files with 597 additions and 426 deletions
+68 -75
View File
@@ -25,16 +25,16 @@ const WALL_TEMPLATE = `
<div id="left-column">
<div id="pane-2d-container">
<div class="pane-2d-sub pane-2d-primary" id="pane-2d-front">
<div class="pane-label">2D BUITENAANZICHT</div>
<div class="pane-label">BUITENAANZICHT</div>
<canvas id="canvas-2d-front"></canvas>
</div>
<div class="pane-2d-sub pane-2d-row" id="pane-2d-bottom-row">
<div class="pane-2d-half" id="pane-2d-top">
<div class="pane-label">2D BOVENAANZICHT</div>
<div class="pane-label">BOVENAANZICHT</div>
<canvas id="canvas-2d-top"></canvas>
</div>
<div class="pane-2d-half" id="pane-2d-side">
<div class="pane-label">2D ZIJAANZICHT</div>
<div class="pane-label">ZIJAANZICHT</div>
<canvas id="canvas-2d-side"></canvas>
</div>
</div>
@@ -46,100 +46,97 @@ const WALL_TEMPLATE = `
<span id="io-status" class="io-status"></span>
</div>
<div class="tab-bar">
<button class="tab-btn active" data-tab="tab-wall">1. Wand Opbouw</button>
<button class="tab-btn" data-tab="tab-opening">2. Openingen</button>
<button class="tab-btn" data-tab="tab-materials">3. Materiaalkeuze</button>
<button class="tab-btn active" data-tab="tab-wall"><i class="bi bi-rulers"></i> Opbouw</button>
<button class="tab-btn" data-tab="tab-opening"><i class="bi bi-door-open"></i> Openingen</button>
<button class="tab-btn" data-tab="tab-materials"><i class="bi bi-layers"></i> Materiaal</button>
</div>
<!-- TAB 1: WAND -->
<div id="tab-wall" class="tab-content active">
<div class="controls-grid">
<div>
<h1>Wand Dimensies (mm)</h1>
<h1><i class="bi bi-rulers"></i> Afmetingen</h1>
<div class="control-group">
<label for="inp-wall-w">Wand Breedte:</label>
<label for="inp-wall-w">Breedte</label>
<div><input type="number" id="inp-wall-w" value="6000" step="50" min="800" max="10000"><span class="unit">mm</span></div>
</div>
<div class="control-group">
<label for="inp-wall-h-all">Totale Hoogte:</label>
<label for="inp-wall-h-all">Hoogte</label>
<div><input type="number" id="inp-wall-h-all" value="2400" step="50" min="500" max="5000"><span class="unit">mm</span></div>
</div>
<div class="control-group">
<label for="inp-wall-h-left">Hoogte Links ($Y_1$):</label>
<label for="inp-wall-h-left">Hoogte links</label>
<div><input type="number" id="inp-wall-h-left" value="2400" step="50" min="500" max="5000"><span class="unit">mm</span></div>
</div>
<div class="control-group">
<label for="inp-wall-h-right">Hoogte Rechts ($Y_2$):</label>
<label for="inp-wall-h-right">Hoogte rechts</label>
<div><input type="number" id="inp-wall-h-right" value="2400" step="50" min="500" max="5000"><span class="unit">mm</span></div>
</div>
<div class="divider"></div>
<h1>Verticale Balken & Dorpels</h1>
<h1><i class="bi bi-columns-gap"></i> Stijlen</h1>
<div class="control-group">
<label for="inp-stud-w">Verticale Balk Dikte/Breedte:</label>
<label for="inp-stud-w">Dikte</label>
<div><input type="number" id="inp-stud-w" value="38" step="5" min="20" max="300"><span class="unit">mm</span></div>
</div>
<div class="control-group">
<label for="inp-stud-d">Verticale Balk Diepte:</label>
<label for="inp-stud-d">Diepte</label>
<div><input type="number" id="inp-stud-d" value="235" step="5" min="20" max="400"><span class="unit">mm</span></div>
</div>
</div>
<div>
<h1>Muur Liggers (Top & Onder)</h1>
<h1><i class="bi bi-distribute-vertical"></i> Regels (boven en onder)</h1>
<div class="control-group">
<label for="inp-plate-w">Ligger Dikte:</label>
<label for="inp-plate-w">Dikte</label>
<div><input type="number" id="inp-plate-w" value="38" step="5" min="20" max="200"><span class="unit">mm</span></div>
</div>
<div class="control-group">
<label for="inp-plate-d">Ligger Diepte:</label>
<label for="inp-plate-d">Diepte</label>
<div><input type="number" id="inp-plate-d" value="235" step="5" min="20" max="400"><span class="unit">mm</span></div>
</div>
<div class="control-group">
<label for="inp-sheathing-t">Beplating Dikte:</label>
<label for="inp-sheathing-t">Dikte beplating</label>
<div><input type="number" id="inp-sheathing-t" value="10" step="1" min="3" max="30"><span class="unit">mm</span></div>
</div>
<div class="divider"></div>
<h1>Regelwerk Afstand (h.o.h.)</h1>
<h1><i class="bi bi-arrows"></i> Regelwerk</h1>
<div class="control-group">
<label for="inp-min-sp">Min. h.o.h.:</label>
<label for="inp-min-sp">Afstand min.</label>
<div><input type="number" id="inp-min-sp" value="240" step="10" min="100" max="1000"><span class="unit">mm</span></div>
</div>
<div class="control-group">
<label for="inp-max-sp">Max. h.o.h.:</label>
<label for="inp-max-sp">Afstand max.</label>
<div><input type="number" id="inp-max-sp" value="480" step="10" min="150" max="1500"><span class="unit">mm</span></div>
</div>
<div class="divider"></div>
<div class="result-row"><span>Totaal verticale balken:</span><span data-spec="vert-beams" class="highlight">-</span></div>
<div class="result-row"><span>Totaal horizontale balken:</span><span data-spec="horiz-beams" class="highlight">-</span></div>
<div class="result-row"><span>Dakhelling:</span><span data-spec="roof-angle" class="highlight">-</span></div>
<div class="result-row"><span>Verticale balken</span><span data-spec="vert-beams" class="highlight">-</span></div>
<div class="result-row"><span>Horizontale balken</span><span data-spec="horiz-beams" class="highlight">-</span></div>
<div class="result-row"><span>Dakhelling</span><span data-spec="roof-angle" class="highlight">-</span></div>
</div>
</div>
</div>
<!-- TAB 2: OPENINGEN (meerdere, ankerbaar) -->
<div id="tab-opening" class="tab-content">
<button id="btn-add-opening" class="add-opening-btn">+ Opening Toevoegen</button>
<button id="btn-add-opening" class="add-opening-btn"><i class="bi bi-plus-lg"></i> Opening toevoegen</button>
<div id="openings-global-warning" class="global-warning" style="display:none;"></div>
<div id="openings-list"></div>
</div>
<!-- TAB 3: MATERIAALKEUZE -->
<div id="tab-materials" class="tab-content">
<h1>Binnenzijde</h1>
<div class="divider"></div>
<h1>Buitenzijde</h1>
<h1><i class="bi bi-layers"></i> Buitenzijde</h1>
<div class="material-toggle-group">
<button type="button" id="btn-mat-vochtdoek" class="material-toggle-btn active" data-material="vochtdoek">Vochtdoek</button>
<button type="button" id="btn-mat-cementplaat" class="material-toggle-btn" data-material="cementplaat">Cement-gebonden platen</button>
<button type="button" id="btn-mat-cementplaat" class="material-toggle-btn" data-material="cementplaat">Cementplaat</button>
<button type="button" id="btn-mat-spaanplaat" class="material-toggle-btn" data-material="spaanplaat">Spaanplaat</button>
</div>
<div id="cladding-section">
<div class="divider"></div>
<h1>Gevelbekleding (WEO/Novalit) &mdash; richting</h1>
<h1><i class="bi bi-grip-horizontal"></i> Richting gevelbekleding</h1>
<div class="material-toggle-group">
<button type="button" class="material-toggle-btn active" data-cladding="horizontaal">Horizontaal</button>
<button type="button" class="material-toggle-btn" data-cladding="verticaal">Verticaal</button>
@@ -153,7 +150,7 @@ const WALL_TEMPLATE = `
<div id="right-column">
<div id="pane-3d">
<div class="pane-label">3D PERSPECTIEF</div>
<div class="pane-label">3D</div>
<div class="toolbar-3d" id="wall-toolbar-3d"></div>
</div>
@@ -161,37 +158,37 @@ const WALL_TEMPLATE = `
<div class="controls-grid">
<div>
<div class="spec-section">
<h1>Balken &amp; Dak</h1>
<div class="result-row"><span>Verticale balken:</span><span data-spec="vert-beams" class="highlight">-</span></div>
<div class="result-row"><span>Horizontale balken:</span><span data-spec="horiz-beams" class="highlight">-</span></div>
<div class="result-row"><span>Dakhelling:</span><span data-spec="roof-angle" class="highlight">-</span></div>
<h1><i class="bi bi-columns-gap"></i> Balken</h1>
<div class="result-row"><span>Verticale balken</span><span data-spec="vert-beams" class="highlight">-</span></div>
<div class="result-row"><span>Horizontale balken</span><span data-spec="horiz-beams" class="highlight">-</span></div>
<div class="result-row"><span>Dakhelling</span><span data-spec="roof-angle" class="highlight">-</span></div>
</div>
<div class="spec-section">
<h1>Houtwerk</h1>
<div class="result-row"><span>Volume hout:</span><span data-spec="wood-m3" class="highlight">-</span></div>
<div class="result-row"><span>Gewicht hout:</span><span data-spec="wood-kg" class="highlight">-</span></div>
<div class="result-row"><span>Inkoop balken:</span><span data-spec="stock-list" class="highlight">-</span></div>
<div class="result-row"><span>Snijverlies:</span><span data-spec="stock-waste" class="highlight">-</span></div>
<h1><i class="bi bi-tree"></i> Houtwerk</h1>
<div class="result-row"><span>Volume hout</span><span data-spec="wood-m3" class="highlight">-</span></div>
<div class="result-row"><span>Gewicht hout</span><span data-spec="wood-kg" class="highlight">-</span></div>
<div class="result-row"><span>Inkoop balken</span><span data-spec="stock-list" class="highlight">-</span></div>
<div class="result-row"><span>Snijverlies</span><span data-spec="stock-waste" class="highlight">-</span></div>
</div>
<div class="spec-section">
<h1>Spaanplaat (binnenzijde)</h1>
<div class="result-row"><span>Oppervlak:</span><span data-spec="spaanplaat-m2" class="highlight">-</span></div>
<div class="result-row"><span>Volume:</span><span data-spec="spaanplaat-m3" class="highlight">-</span></div>
<div class="result-row"><span>Gewicht:</span><span data-spec="spaanplaat-kg" class="highlight">-</span></div>
<h1><i class="bi bi-layers"></i> Binnenzijde: spaanplaat</h1>
<div class="result-row"><span>Oppervlak</span><span data-spec="spaanplaat-m2" class="highlight">-</span></div>
<div class="result-row"><span>Volume</span><span data-spec="spaanplaat-m3" class="highlight">-</span></div>
<div class="result-row"><span>Gewicht</span><span data-spec="spaanplaat-kg" class="highlight">-</span></div>
</div>
</div>
<div>
<div class="spec-section">
<h1>Buitenzijde (<span data-spec="buiten-materiaalnaam">Vochtdoek</span>)</h1>
<div class="result-row"><span>Oppervlak:</span><span data-spec="buiten-m2" class="highlight">-</span></div>
<div class="result-row"><span>Volume:</span><span data-spec="buiten-m3" class="highlight">-</span></div>
<div class="result-row"><span>Gewicht:</span><span data-spec="buiten-kg" class="highlight">-</span></div>
<div class="result-row"><span>Latwerk 20x30 (kruislat):</span><span data-spec="latten" class="highlight">-</span></div>
<h1><i class="bi bi-layers-half"></i> Buitenzijde: <span data-spec="buiten-materiaalnaam">Vochtdoek</span></h1>
<div class="result-row"><span>Oppervlak</span><span data-spec="buiten-m2" class="highlight">-</span></div>
<div class="result-row"><span>Volume</span><span data-spec="buiten-m3" class="highlight">-</span></div>
<div class="result-row"><span>Gewicht</span><span data-spec="buiten-kg" class="highlight">-</span></div>
<div class="result-row"><span>Latwerk 20×30</span><span data-spec="latten" class="highlight">-</span></div>
</div>
<div class="spec-section">
<h1>Isolatie &amp; totaal</h1>
<div class="result-row"><span>Inhoud leegtes:</span><span data-spec="void-m3" class="highlight">-</span></div>
<div class="result-row"><span>Totaal gewicht wand:</span><span data-spec="total-kg" class="highlight">-</span></div>
<h1><i class="bi bi-speedometer2"></i> Isolatie en gewicht</h1>
<div class="result-row"><span>Isolatie</span><span data-spec="void-m3" class="highlight">-</span></div>
<div class="result-row"><span>Totaal gewicht</span><span data-spec="total-kg" class="highlight">-</span></div>
</div>
</div>
</div>
@@ -207,23 +204,23 @@ const WALL_TEMPLATE = `
</div>
<div class="controls-grid">
<div>
<div class="control-group"><label for="inp-proj-naam">Projectnaam:</label>
<div class="control-group"><label for="inp-proj-naam">Projectnaam</label>
<div><input type="text" id="inp-proj-naam" value=""></div></div>
<div class="control-group"><label for="inp-proj-plaats">Plaats:</label>
<div class="control-group"><label for="inp-proj-plaats">Plaats</label>
<div><input type="text" id="inp-proj-plaats" value=""></div></div>
<div class="control-group"><label for="inp-proj-straat">Straat:</label>
<div class="control-group"><label for="inp-proj-straat">Straat</label>
<div><input type="text" id="inp-proj-straat" value=""></div></div>
<div class="control-group"><label for="inp-proj-nummer">Projectnummer:</label>
<div class="control-group"><label for="inp-proj-nummer">Projectnummer</label>
<div><input type="text" id="inp-proj-nummer" value=""></div></div>
</div>
<div>
<div class="control-group"><label for="inp-proj-tekenaar">Tekenaar:</label>
<div class="control-group"><label for="inp-proj-tekenaar">Tekenaar</label>
<div><input type="text" id="inp-proj-tekenaar" value=""></div></div>
<div class="control-group"><label for="inp-proj-titel">Titel:</label>
<div class="control-group"><label for="inp-proj-titel">Titel</label>
<div><input type="text" id="inp-proj-titel" value="BuitenWand"></div></div>
<div class="control-group"><label for="inp-proj-element">Element nummer:</label>
<div class="control-group"><label for="inp-proj-element">Elementnummer</label>
<div><input type="text" id="inp-proj-element" value=""></div></div>
<div class="control-group"><label for="inp-proj-opmerking">Opmerking:</label>
<div class="control-group"><label for="inp-proj-opmerking">Opmerking</label>
<div><input type="text" id="inp-proj-opmerking" value=""></div></div>
</div>
</div>
@@ -338,9 +335,9 @@ function mountWallEditor(container, callbacks) {
// OPENINGEN: UI (lijst met kaarten, ankerkeuze, toevoegen/verwijderen)
// ============================================================
function anchorOffsetLabel(anchor) {
if (anchor === 'right') return 'Afstand vanaf rechts:';
if (anchor === 'middle') return 'Verschuiving t.o.v. midden:';
return 'Afstand vanaf links:';
if (anchor === 'right') return 'Afstand tot rechts';
if (anchor === 'middle') return 'Verschuiving t.o.v. midden';
return 'Afstand tot links';
}
function addOpening() {
@@ -360,16 +357,12 @@ function mountWallEditor(container, callbacks) {
}
function toggleFullscreen3D() {
const el = document.getElementById('app-container');
el.classList.remove('fullscreen-2d');
el.classList.toggle('fullscreen-3d');
UI.cycle3D(document.getElementById('app-container')); // T: standaard -> 3D groot -> alleen render
requestAnimationFrame(onWindowResize);
}
function toggleFullscreen2D() {
const el = document.getElementById('app-container');
el.classList.remove('fullscreen-3d');
el.classList.toggle('fullscreen-2d');
UI.toggle2D(document.getElementById('app-container'));
requestAnimationFrame(onWindowResize);
}
@@ -448,7 +441,7 @@ function mountWallEditor(container, callbacks) {
<div class="controls-grid">
<div>
<div class="control-group">
<label>Type:</label>
<label>Type</label>
<div>
<select data-field="type" data-id="${op.id}">
${Object.entries(WallModel.OPENING_TYPES).map(([k, t]) => `<option value="${k}" ${(op.type || 'raam') === k ? 'selected' : ''}>${t.label}</option>`).join('')}
@@ -456,21 +449,21 @@ function mountWallEditor(container, callbacks) {
</div>
</div>
<div class="control-group">
<label>Breedte:</label>
<label>Breedte</label>
<div><input type="number" data-field="w" data-id="${op.id}" value="${op.w}" step="50" min="400" max="2850"><span class="unit">mm</span></div>
</div>
<div class="control-group">
<label>Hoogte:</label>
<label>Hoogte</label>
<div><input type="number" data-field="h" data-id="${op.id}" value="${op.h}" step="50" min="400"><span class="unit">mm</span></div>
</div>
<div class="control-group">
<label>Hoogte vloer (Y):</label>
<label>Afstand tot vloer</label>
<div><input type="number" data-field="y" data-id="${op.id}" value="${op.y}" step="50" min="0"><span class="unit">mm</span></div>
</div>
</div>
<div>
<div class="control-group">
<label>Ankerpunt:</label>
<label>Ankerpunt</label>
<div>
<select data-field="anchor" data-id="${op.id}">
<option value="left" ${op.anchor === 'left' ? 'selected' : ''}>Links</option>