Light: optie price: false (of data-price="false"): geen prijs in het paneel en op het voorblad van de PDF; design().info.price blijft
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
73248a69c9
commit
4bb1548125
@@ -5,8 +5,8 @@
|
|||||||
* Zie LICENTIE.md.
|
* Zie LICENTIE.md.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// PDF van de light-versie: voorblad "Uw woningontwerp" (beeld, kerncijfers, keuzes, indicatieve prijs, contact en
|
// PDF van de light-versie: voorblad "Uw woningontwerp" (beeld, kerncijfers, keuzes, indicatieve prijs tenzij
|
||||||
// QR-code naar de modelpagina), de aanzichten en plattegrond (HousePdf, klantvariant) en een pagina over de werkwijze.
|
// d.price === false, contact en QR-code naar de modelpagina), de aanzichten en plattegrond (HousePdf, klantvariant) en een pagina over de werkwijze.
|
||||||
window.LightPdf = (() => {
|
window.LightPdf = (() => {
|
||||||
const COMPANY = {
|
const COMPANY = {
|
||||||
naam: 'Van Emous Mantelzorgwoningen',
|
naam: 'Van Emous Mantelzorgwoningen',
|
||||||
@@ -136,7 +136,8 @@ window.LightPdf = (() => {
|
|||||||
y = keyValues(doc, M, y + 6, 150, d.choices, 'Uw keuzes');
|
y = keyValues(doc, M, y + 6, 150, d.choices, 'Uw keuzes');
|
||||||
|
|
||||||
// Prijs: rustig, als de rest van de pagina; alleen het bedrag groter en vet.
|
// Prijs: rustig, als de rest van de pagina; alleen het bedrag groter en vet.
|
||||||
const py = Math.max(y + 4, 196);
|
const py = Math.max(y + 4, 196), price = d.price !== false;
|
||||||
|
if (price) {
|
||||||
doc.setDrawColor(...LINE);
|
doc.setDrawColor(...LINE);
|
||||||
doc.setLineWidth(0.3);
|
doc.setLineWidth(0.3);
|
||||||
doc.line(M, py, M + 150, py);
|
doc.line(M, py, M + 150, py);
|
||||||
@@ -152,6 +153,7 @@ window.LightPdf = (() => {
|
|||||||
doc.setFontSize(9);
|
doc.setFontSize(9);
|
||||||
doc.setTextColor(...MUTED);
|
doc.setTextColor(...MUTED);
|
||||||
doc.text('incl. btw, onder voorbehoud', M, py + 25);
|
doc.text('incl. btw, onder voorbehoud', M, py + 25);
|
||||||
|
}
|
||||||
|
|
||||||
// Beeld van de woning
|
// Beeld van de woning
|
||||||
const bx = 190, by = 18, bw = PW - M - bx, bh = 206;
|
const bx = 190, by = 18, bw = PW - M - bx, bh = 206;
|
||||||
@@ -162,7 +164,7 @@ window.LightPdf = (() => {
|
|||||||
contactBand(doc, 240, d.url, `Bekijk ${d.label} online`);
|
contactBand(doc, 240, d.url, `Bekijk ${d.label} online`);
|
||||||
doc.setFontSize(7);
|
doc.setFontSize(7);
|
||||||
doc.setTextColor(...MUTED);
|
doc.setTextColor(...MUTED);
|
||||||
doc.text('Dit ontwerp en de prijs zijn indicatief; hieraan kunnen geen rechten worden ontleend.', M, PH - 6);
|
doc.text(`Dit ontwerp${price ? ' en de prijs zijn' : ' is'} indicatief; hieraan kunnen geen rechten worden ontleend.`, M, PH - 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
function process(doc, d) {
|
function process(doc, d) {
|
||||||
|
|||||||
+11
-7
@@ -8,8 +8,9 @@
|
|||||||
// Light-versie voor de modelpagina's: één model in 3D, een paar keuzes en de kerncijfers; opslaan = PDF met
|
// Light-versie voor de modelpagina's: één model in 3D, een paar keuzes en de kerncijfers; opslaan = PDF met
|
||||||
// aanzichten en plattegrond. Alle logica in LightModel (en daarachter de gewone modellen).
|
// aanzichten en plattegrond. Alle logica in LightModel (en daarachter de gewone modellen).
|
||||||
// Inbedden: <div class="tectum-light" data-model="amstel" data-url="…"></div> (vanzelf gemount), of
|
// Inbedden: <div class="tectum-light" data-model="amstel" data-url="…"></div> (vanzelf gemount), of
|
||||||
// TectumLight.mount(el, { model, frames, url, modelViewer, save }); url = adres voor de QR-code in de PDF (standaard de
|
// TectumLight.mount(el, { model, frames, url, modelViewer, save, price }); url = adres voor de QR-code in de PDF (standaard
|
||||||
// modelpagina), modelViewer = adres van model-viewer (standaard js/vendor naast dit script).
|
// de modelpagina), modelViewer = adres van model-viewer (standaard js/vendor naast dit script), price: false (of
|
||||||
|
// data-price="false") = geen prijs in beeld en in de PDF; design().info.price blijft er wel in.
|
||||||
// save = { label, icon, onSave(ontwerp) } vervangt de PDF-knop (bijv. ontwerp aanvragen op de site); onSave krijgt
|
// save = { label, icon, onSave(ontwerp) } vervangt de PDF-knop (bijv. ontwerp aanvragen op de site); onSave krijgt
|
||||||
// { design, label, key, info, choices, url }: design = house-design-JSON zoals de configurator die opslaat, choices = de
|
// { design, label, key, info, choices, url }: design = house-design-JSON zoals de configurator die opslaat, choices = de
|
||||||
// keuzes in woorden (zoals op het voorblad van de PDF). Zonder save blijft het de PDF.
|
// keuzes in woorden (zoals op het voorblad van de PDF). Zonder save blijft het de PDF.
|
||||||
@@ -69,6 +70,7 @@ window.TectumLight = (() => {
|
|||||||
function mount(root, opts) {
|
function mount(root, opts) {
|
||||||
const o = opts || {};
|
const o = opts || {};
|
||||||
const model = LightModel.create(o.model || root.dataset.model, { frames: o.frames });
|
const model = LightModel.create(o.model || root.dataset.model, { frames: o.frames });
|
||||||
|
const showPrice = o.price !== false && root.dataset.price !== 'false';
|
||||||
let ch = clone(model.initial);
|
let ch = clone(model.initial);
|
||||||
let unitSel = model.base.units[0].id;
|
let unitSel = model.base.units[0].id;
|
||||||
let cur = null; // { st, parts, info }
|
let cur = null; // { st, parts, info }
|
||||||
@@ -502,7 +504,7 @@ window.TectumLight = (() => {
|
|||||||
const kv = (k, v) => `<div class="tl-kv"><span>${k}</span><b>${v}</b></div>`;
|
const kv = (k, v) => `<div class="tl-kv"><span>${k}</span><b>${v}</b></div>`;
|
||||||
$('.tl-facts').innerHTML = kv('Vloer bruto', `${nl(i.brutoM2, 1)} m²`) + kv('Leefbaar', `${nl(i.leefbaarM2, 1)} m²`) +
|
$('.tl-facts').innerHTML = kv('Vloer bruto', `${nl(i.brutoM2, 1)} m²`) + kv('Leefbaar', `${nl(i.leefbaarM2, 1)} m²`) +
|
||||||
kv('Inhoud', `${nl(i.inhoudM3, 0)} m³`) + kv('Gewicht', `${nl(Math.round(i.kg / 10) * 10, 0)} kg`);
|
kv('Inhoud', `${nl(i.inhoudM3, 0)} m³`) + kv('Gewicht', `${nl(Math.round(i.kg / 10) * 10, 0)} kg`);
|
||||||
$('.tl-buy').innerHTML = `<div class="tl-price"><span class="tl-price-val">${CostModel.eur(Math.round(i.price / 100) * 100)}</span><span class="tl-price-note">indicatief, incl. btw</span></div>
|
$('.tl-buy').innerHTML = `<div class="tl-price">${showPrice ? `<span class="tl-price-val">${CostModel.eur(Math.round(i.price / 100) * 100)}</span><span class="tl-price-note">indicatief, incl. btw</span>` : ''}</div>
|
||||||
<button type="button" class="tl-btn tl-icon" data-act="reset" title="Alle keuzes terug naar het model" aria-label="Terug naar het model"><i class="bi bi-arrow-counterclockwise"></i></button>
|
<button type="button" class="tl-btn tl-icon" data-act="reset" title="Alle keuzes terug naar het model" aria-label="Terug naar het model"><i class="bi bi-arrow-counterclockwise"></i></button>
|
||||||
${o.save ? `<button type="button" class="tl-btn tl-primary" data-act="save"><i class="bi bi-${esc(o.save.icon || 'send')}"></i>${esc(o.save.label || 'Opslaan')}</button>`
|
${o.save ? `<button type="button" class="tl-btn tl-primary" data-act="save"><i class="bi bi-${esc(o.save.icon || 'send')}"></i>${esc(o.save.label || 'Opslaan')}</button>`
|
||||||
: '<button type="button" class="tl-btn tl-primary" data-act="pdf"><i class="bi bi-file-earmark-pdf"></i>PDF</button>'}`;
|
: '<button type="button" class="tl-btn tl-primary" data-act="pdf"><i class="bi bi-file-earmark-pdf"></i>PDF</button>'}`;
|
||||||
@@ -632,7 +634,7 @@ window.TectumLight = (() => {
|
|||||||
try {
|
try {
|
||||||
let image = null;
|
let image = null;
|
||||||
try { image = snapshot(); } catch (err) { console.warn(err); }
|
try { image = snapshot(); } catch (err) { console.warn(err); }
|
||||||
LightPdf.generate({ st, label: model.label, info: cur.info, choices: LightModel.describe(model, ch, cur.st), url: pageUrl, image })
|
LightPdf.generate({ st, label: model.label, info: cur.info, choices: LightModel.describe(model, ch, cur.st), url: pageUrl, image, price: showPrice })
|
||||||
.save(`${model.label.replace(/[^A-Za-z0-9_-]+/g, '-')}-${new Date().toISOString().slice(0, 10)}.pdf`);
|
.save(`${model.label.replace(/[^A-Za-z0-9_-]+/g, '-')}-${new Date().toISOString().slice(0, 10)}.pdf`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
@@ -669,11 +671,13 @@ window.TectumLight = (() => {
|
|||||||
io.observe(stage);
|
io.observe(stage);
|
||||||
|
|
||||||
// GLB van het ontwerp (afgewerkte woning zoals in 3D, maaiveld onder het midden = oorsprong); één keer per ontwerp.
|
// GLB van het ontwerp (afgewerkte woning zoals in 3D, maaiveld onder het midden = oorsprong); één keer per ontwerp.
|
||||||
|
// Alles onder het maaiveld (sandwichpanelen, vloerbalken) valt weg: AR zet het laagste punt op de grond.
|
||||||
let glb = null;
|
let glb = null;
|
||||||
function makeGlb() {
|
function makeGlb() {
|
||||||
if (glb && glb.parts === cur.parts) return glb;
|
if (glb && glb.parts === cur.parts) return glb;
|
||||||
if (glb) URL.revokeObjectURL(glb.url);
|
if (glb) URL.revokeObjectURL(glb.url);
|
||||||
const out = as3d(() => GlbWriter.build(rootsOf(cur.parts), { name: model.label, origin: HouseModel.groundOrigin(cur.st, cur.parts) }));
|
const out = as3d(() => GlbWriter.build(rootsOf(cur.parts).filter(g => g !== cur.parts.sandwichGroup),
|
||||||
|
{ name: model.label, origin: HouseModel.groundOrigin(cur.st, cur.parts), clipBelow: 0 }));
|
||||||
glb = { parts: cur.parts, blob: out.blob, url: URL.createObjectURL(out.blob), stats: out.stats };
|
glb = { parts: cur.parts, blob: out.blob, url: URL.createObjectURL(out.blob), stats: out.stats };
|
||||||
return glb;
|
return glb;
|
||||||
}
|
}
|
||||||
@@ -702,7 +706,7 @@ window.TectumLight = (() => {
|
|||||||
// kader van position: fixed). De AR-knop van model-viewer verschijnt alleen als het toestel AR kan.
|
// kader van position: fixed). De AR-knop van model-viewer verschijnt alleen als het toestel AR kan.
|
||||||
const mvSrc = o.modelViewer || root.dataset.modelViewer || new URL('../vendor/model-viewer-umd.min.js', SCRIPT_SRC).href;
|
const mvSrc = o.modelViewer || root.dataset.modelViewer || new URL('../vendor/model-viewer-umd.min.js', SCRIPT_SRC).href;
|
||||||
let arView = null, arOpen = false;
|
let arView = null, arOpen = false;
|
||||||
const AR_NOTE = 'Ware grootte · met twee vingers verkleinen of draaien';
|
const AR_NOTE = 'Ware grootte · met twee vingers draaien, met één vinger verplaatsen';
|
||||||
function closeAr() {
|
function closeAr() {
|
||||||
if (!arOpen) return;
|
if (!arOpen) return;
|
||||||
arOpen = false;
|
arOpen = false;
|
||||||
@@ -718,7 +722,7 @@ window.TectumLight = (() => {
|
|||||||
arView.setAttribute('role', 'dialog');
|
arView.setAttribute('role', 'dialog');
|
||||||
arView.setAttribute('aria-modal', 'true');
|
arView.setAttribute('aria-modal', 'true');
|
||||||
arView.innerHTML = `<model-viewer camera-controls touch-action="none" interaction-prompt="none" shadow-intensity="1" environment-image="neutral"
|
arView.innerHTML = `<model-viewer camera-controls touch-action="none" interaction-prompt="none" shadow-intensity="1" environment-image="neutral"
|
||||||
ar ar-modes="webxr scene-viewer quick-look" ar-scale="auto" ar-placement="floor">
|
ar ar-modes="webxr scene-viewer quick-look" ar-scale="fixed" ar-placement="floor" xr-environment>
|
||||||
<button type="button" slot="ar-button" class="tl-ar-go"><i class="bi bi-badge-ar"></i>Bekijk in je tuin</button>
|
<button type="button" slot="ar-button" class="tl-ar-go"><i class="bi bi-badge-ar"></i>Bekijk in je tuin</button>
|
||||||
</model-viewer>
|
</model-viewer>
|
||||||
<div class="tl-ar-top"><b class="tl-ar-title"></b><button type="button" class="tl-ar-close" aria-label="Sluiten"><i class="bi bi-x-lg"></i></button></div>
|
<div class="tl-ar-top"><b class="tl-ar-title"></b><button type="button" class="tl-ar-close" aria-label="Sluiten"><i class="bi bi-x-lg"></i></button></div>
|
||||||
|
|||||||
Reference in New Issue
Block a user