Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!-- === КОНФИГУРАЦИЯ (редактирай САМО стойностите; без коментари вътре) === -->
- <script type="application/json" id="win-calc-config">
- {
- "MODELS": [
- {"id":"win_fixed","label":"Прозорец глух","img":"линк към снимката за дограма"},
- {"id":"win_single","label":"Прозорец еднокрил","img":"линк към снимката за дограма"},
- {"id":"win_double","label":"Прозорец двукрил","img":"линк към снимката за дограма"},
- {"id":"win_divider","label":"Прозорец с делител","img":"линк към снимката за дограма"},
- {"id":"door_balcony","label":"Балконска врата","img":"линк към снимката за дограма"},
- {"id":"door_balcony_div","label":"Балконска врата с делител","img":"линк към снимката за дограма"},
- {"id":"win_tilt","label":"Прозорец tilt & turn","img":"линк към снимката за дограма"},
- {"id":"win_panorama","label":"Панорамен прозорец","img":"линк към снимката за дограма"}
- ],
- "PRICING": {
- "eurRate": 1.95583,
- "vatRate": 0.2,
- "profilePerMeter": { "pvc":45, "alu":70, "wood":85 },
- "colorMultiplier": { "white":1, "oneSideColor":1.15, "bothSidesColor":1.25 },
- "glazingPerM2": { "double24":85, "triple36":120 },
- "glazingAddersPerM2": { "lowE":25, "fourSeasons":40, "argon":10 },
- "hardware": { "fixed":0, "single":55, "double":95, "tiltTurn":75 },
- "mosquito": 35,
- "rollerShutterPerM2": 120,
- "innerSillPerMeter": 18,
- "dripEdgePerMeter": 15,
- "uninstallPerWindow": 20,
- "installPerWindow": 45,
- "finishingPerMeter": 14,
- "transportPerKm": 1.96,
- "labels": {
- "profile": "Профили (периметър)",
- "glazing": "Стъклопакет",
- "hardware": "Обков",
- "mosquito": "Комарници",
- "rollerShutter": "Ролетна щора",
- "innerSill": "Вътрешен перваз",
- "dripEdge": "Външен водобран",
- "uninstall": "Демонтаж",
- "install": "Монтаж",
- "finishing": "Обръщане",
- "transport": "Транспорт",
- "vat": "ДДС (20%)",
- "discount": "Отстъпка"
- },
- "enabled": {
- "mosquito": false,
- "rollerShutter": true,
- "innerSill": true,
- "dripEdge": true,
- "uninstall": true,
- "install": true,
- "finishing": false,
- "transport": true
- },
- "fixedAdders": []
- }
- }
- </script>
- <div id="win-calc" class="idi-win">
- <style>
- .idi-win{--c:#0ea5e9;--bg:#0b1220;--panel:#121a2a;--muted:#8aa0bd;font-family:Inter,system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif;color:#e6eefb;border-radius:18px;}
- .idi-grid{display:grid;grid-template-columns:1.1fr .9fr;gap:18px}
- @media(max-width:980px){.idi-grid{grid-template-columns:1fr}}
- .idi-card{background:var(--panel);border:1px solid rgba(255,255,255,.08);border-radius:16px;padding:16px}
- .idi-title{font-size:22px;font-weight:800;margin:0 0 12px}
- .idi-sub{font-size:12px;color:var(--muted);margin:-4px 0 10px}
- .idi-row{display:grid;grid-template-columns:1fr auto;gap:10px;align-items:center;margin:10px 0}
- .idi-row label{font-size:14px}
- .idi-row input[type="number"],.idi-row select{width:190px;background:#0e1626;color:#e6eefb;border:1px solid rgba(255,255,255,.1);border-radius:10px;padding:8px 10px}
- .idi-check{display:flex;align-items:center;gap:10px;margin:6px 0}
- .idi-check input{transform:scale(1.15)}
- .idi-divider{height:1px;background:linear-gradient(90deg,transparent,rgba(255,255,255,.14),transparent);margin:14px 0}
- .idi-models{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}
- @media(max-width:980px){.idi-models{grid-template-columns:repeat(2,1fr)}}
- .idi-model{background:#0e1626;border:1px solid rgba(255,255,255,.08);border-radius:12px;padding:10px;cursor:pointer;text-align:center;font-size:13px;line-height:1.2}
- .idi-model:hover{border-color:rgba(255,255,255,.25)}
- .idi-model.active{outline:2px solid var(--c);box-shadow:0 0 0 2px rgba(14,165,233,.25) inset}
- .idi-model img{width:100%;max-height:90px;object-fit:contain;margin-bottom:6px;display:block}
- .idi-model.idi-img-error::before{content:"(снимката не се зареди)";display:block;font-size:11px;color:#ffb4b4;margin-bottom:6px}
- .idi-badges{display:flex;gap:8px;flex-wrap:wrap;margin:8px 0}
- .idi-badge{background:#0e1626;border:1px solid rgba(255,255,255,.08);padding:4px 8px;border-radius:999px;font-size:12px;color:#9fb2d0}
- .idi-breakdown{list-style:none;margin:8px 0 0;padding:0}
- .idi-breakdown li{display:flex;justify-content:space-between;border-bottom:1px dashed rgba(255,255,255,.1);padding:7px 0}
- .idi-total{font-size:28px;font-weight:900}
- .idi-actions{display:flex;gap:10px;flex-wrap:wrap;margin-top:12px}
- .idi-btn{background:var(--c);border:none;color:#021322;font-weight:800;padding:10px 14px;border-radius:12px;cursor:pointer}
- .idi-btn.secondary{background:#0e1626;color:#e6eefb;border:1px solid rgba(255,255,255,.15)}
- .idi-note{font-size:12px;color:#8aa0bd;margin-top:6px}
- .idi-model-preview{margin-top:10px;background:#0e1626;border:1px solid rgba(255,255,255,.08);border-radius:12px;padding:12px}
- .idi-model-preview img{max-width:100%;height:auto;display:block;margin:0 auto}
- .idi-model-caption{font-size:12px;color:#9fb2d0;text-align:center;margin-top:6px}
- </style>
- <div class="idi-grid">
- <!-- ЛЯВО: Модели + Параметри -->
- <div class="idi-card">
- <h3 class="idi-title">Калкулатор за дограма</h3>
- <p class="idi-sub">1) Изберете модел → 2) Попълнете параметрите → 3) Вижте разбивката и тотала (BGN/EUR).</p>
- <div class="idi-sub">Модел</div>
- <div class="idi-models" id="modelsWrap"></div>
- <div id="modelPreview" class="idi-model-preview" style="display:none">
- <img id="modelImg" src="" alt="Преглед на модел">
- <div id="modelCaption" class="idi-model-caption"></div>
- </div>
- <div id="formWrap" style="display:none">
- <div class="idi-divider"></div>
- <div class="idi-row"><label>Материал</label>
- <select id="material">
- <option value="" selected disabled hidden>— Изберете —</option>
- <option value="pvc">PVC</option><option value="alu">Алуминий</option><option value="wood">Дърво</option>
- </select>
- </div>
- <div class="idi-row"><label>Цвят</label>
- <select id="color">
- <option value="" selected disabled hidden>— Изберете —</option>
- <option value="white">Бял</option><option value="oneSideColor">Едностранно цветен</option><option value="bothSidesColor">Двустранно цветен</option>
- </select>
- </div>
- <div class="idi-row"><label>Ширина (см)</label><input id="width" type="number" min="30" max="350" step="1" placeholder="напр. 120"></div>
- <div class="idi-row"><label>Височина (см)</label><input id="height" type="number" min="30" max="350" step="1" placeholder="напр. 140"></div>
- <div class="idi-row"><label>Разделител (делител)</label>
- <select id="divider">
- <option value="" selected disabled hidden>— Изберете —</option>
- <option value="none">Без</option><option value="vertical">Вертикален</option><option value="horizontal">Хоризонтален</option>
- </select>
- </div>
- <div class="idi-row"><label>Стъклопакет (база)</label>
- <select id="glazingBase">
- <option value="" selected disabled hidden>— Изберете —</option>
- <option value="double24">Двоен 24 мм</option><option value="triple36">Троен 36 мм</option>
- </select>
- </div>
- <div class="idi-check"><input id="gLowE" type="checkbox"><label for="gLowE">Low-E добавка</label></div>
- <div class="idi-check"><input id="gFour" type="checkbox"><label for="gFour">4 сезона добавка</label></div>
- <div class="idi-check"><input id="gArgon" type="checkbox"><label for="gArgon">Аргон добавка</label></div>
- <div class="idi-row"><label>Отваряемост / Обков</label>
- <select id="hardware">
- <option value="" selected disabled hidden>— Изберете —</option>
- <option value="fixed">Глух</option><option value="single">Еднокрила</option><option value="double">Двукрила</option><option value="tiltTurn">Падащо-отваряема</option>
- </select>
- </div>
- <div class="idi-divider"></div>
- <div class="idi-sub">Екстри</div>
- <div class="idi-row"><label>Комарници (бр.)</label><input id="mosquitoQty" type="number" min="0" step="1" value="0"></div>
- <div class="idi-row"><label>Външна ролетна щора</label>
- <select id="shutterYes"><option value="" selected disabled hidden>— Изберете —</option><option value="no">Не</option><option value="yes">Да</option></select>
- </div>
- <div class="idi-row"><label>Вътрешен перваз</label>
- <select id="innerSillYes"><option value="" selected disabled hidden>— Изберете —</option><option value="no">Не</option><option value="yes">Да</option></select>
- </div>
- <div class="idi-row"><label>Външен водобран</label>
- <select id="dripYes"><option value="" selected disabled hidden>— Изберете —</option><option value="no">Не</option><option value="yes">Да</option></select>
- </div>
- <div class="idi-divider"></div>
- <div class="idi-sub">Услуги</div>
- <div class="idi-check"><input id="uninstallOld" type="checkbox"><label for="uninstallOld">Демонтаж на стара дограма</label></div>
- <div class="idi-check"><input id="installNew" type="checkbox"><label for="installNew">Монтаж</label></div>
- <div class="idi-check"><input id="finishing" type="checkbox"><label for="finishing">Обръщане/довършителни работи</label></div>
- <div class="idi-row"><label>Транспорт (км)</label><input id="distanceKm" type="number" min="0" step="1" value="0"></div>
- <div class="idi-divider"></div>
- <div class="idi-row"><label>Отстъпка (%)</label><input id="discount" type="number" min="0" max="100" step="1" value="0"></div>
- <div class="idi-check"><input id="vatOn" type="checkbox" checked><label for="vatOn">Включи ДДС (20%)</label></div>
- </div>
- </div>
- <!-- ДЯСНО: Обобщение -->
- <div class="idi-card">
- <h3 class="idi-title">Обобщение</h3>
- <div class="idi-badges" id="badges"></div>
- <ul class="idi-breakdown" id="breakdown"></ul>
- <div class="idi-divider"></div>
- <div class="idi-row">
- <div><div class="idi-sub">Общо (BGN)</div><div class="idi-total" id="totalBGN">—</div></div>
- <div><div class="idi-sub">Общо (EUR)</div><div class="idi-total" id="totalEUR">—</div></div>
- </div>
- <div class="idi-actions">
- <button class="idi-btn" id="copyQuote">Копирай офертата</button>
- <button class="idi-btn secondary" id="pdfExport" type="button">Експорт PDF</button>
- <button class="idi-btn secondary" id="resetForm" type="button">Нулирай</button>
- </div>
- <p class="idi-note">* Резултатът е ориентировъчен и зависи от точните размери и спецификация.</p>
- <p class="idi-note">* EUR при курс 1 EUR = 1.95583 BGN.</p>
- </div>
- </div>
- <script>
- (function(){
- // -- Четене и валидация на конфигурацията
- let CONFIG;
- try{
- CONFIG = JSON.parse(document.getElementById('win-calc-config').textContent);
- }catch(e){
- alert('Грешка в CONFIG JSON: ' + e.message);
- return;
- }
- let MODELS = CONFIG.MODELS;
- let PRICING = CONFIG.PRICING;
- // -- DOM елементи
- const $ = id => document.getElementById(id);
- const modelsWrap=$('modelsWrap'), formWrap=$('formWrap'), modelPreview=$('modelPreview'),
- modelImg=$('modelImg'), modelCaption=$('modelCaption');
- const material=$('material'), color=$('color'), width=$('width'), height=$('height');
- const divider=$('divider'), glazingBase=$('glazingBase');
- const gLowE=$('gLowE'), gFour=$('gFour'), gArgon=$('gArgon');
- const hardware=$('hardware'), mosquitoQty=$('mosquitoQty');
- const shutterYes=$('shutterYes'), innerSillYes=$('innerSillYes'), dripYes=$('dripYes');
- const uninstallOld=$('uninstallOld'), installNew=$('installNew'), finishing=$('finishing');
- const distanceKm=$('distanceKm'), discount=$('discount'), vatOn=$('vatOn');
- const badges=$('badges'), breakdown=$('breakdown'), totalBGN=$('totalBGN'), totalEUR=$('totalEUR');
- const copyBtn=$('copyQuote'), pdfBtn=$('pdfExport'), resetBtn=$('resetForm');
- // -- Помощни
- const fmtBGN = n => new Intl.NumberFormat('bg-BG',{style:'currency',currency:'BGN',maximumFractionDigits:0}).format(n);
- const fmtEUR = n => new Intl.NumberFormat('de-DE',{style:'currency',currency:'EUR',maximumFractionDigits:0}).format(n);
- const toEUR = bgn => bgn/PRICING.eurRate;
- const clamp = (v,min,max)=>Math.min(Math.max(v,min),max);
- const badge = txt => `<span class="idi-badge">${txt}</span>`;
- const m2 = (wcm,hcm)=> (wcm/100)*(hcm/100);
- const perim = (wcm,hcm)=> 2*((wcm/100)+(hcm/100));
- const L = (k, def) => (PRICING.labels && PRICING.labels[k]) || def;
- const ON = (k) => !PRICING.enabled || PRICING.enabled[k] !== false;
- // -- Рендер на моделите (с cache-buster и fallback)
- let selectedModel = '';
- function renderModels(){
- modelsWrap.innerHTML='';
- MODELS.forEach(m=>{
- const d=document.createElement('div'); d.className='idi-model'; d.dataset.id=m.id;
- const src = (m.img||'').trim();
- const imgTag = src
- ? `<img loading="lazy" src="${src}${src.includes('?')?'&':'?'}v=${Date.now()}" alt="${m.label}" onerror="this.closest('.idi-model').classList.add('idi-img-error'); this.remove();">`
- : '';
- d.innerHTML = imgTag + `<div>${m.label}</div>`;
- d.addEventListener('click',()=>{
- selectedModel=m.id;
- [...modelsWrap.children].forEach(x=>x.classList.remove('active'));
- d.classList.add('active');
- const previewSrc = src ? src + (src.includes('?')?'&':'?') + 'v='+Date.now() : '';
- modelImg.src = previewSrc;
- modelImg.alt = m.label; modelCaption.textContent = m.label;
- modelPreview.style.display = 'block';
- formWrap.style.display='block';
- calculate();
- });
- modelsWrap.appendChild(d);
- });
- }
- renderModels();
- // -- Скриване/показване на полета според PRICING.enabled
- function toggleRow(idOrEl, on) {
- const el = typeof idOrEl === 'string' ? document.getElementById(idOrEl) : idOrEl;
- if (!el) return;
- const wrap = el.closest('.idi-row') || el.closest('.idi-check');
- if (!wrap) return;
- wrap.style.display = on ? '' : 'none';
- if (!on) {
- if (el.tagName === 'SELECT') el.selectedIndex = 0;
- else if (el.type === 'checkbox') el.checked = false;
- else if (el.type === 'number') el.value = '';
- }
- }
- function applyEnabledVisibility(){
- const e = PRICING.enabled || {};
- toggleRow('mosquitoQty', e.mosquito !== false);
- toggleRow('shutterYes', e.rollerShutter !== false);
- toggleRow('innerSillYes', e.innerSill !== false);
- toggleRow('dripYes', e.dripEdge !== false);
- toggleRow('uninstallOld', e.uninstall !== false);
- toggleRow('installNew', e.install !== false);
- toggleRow('finishing', e.finishing !== false);
- toggleRow('distanceKm', e.transport !== false);
- }
- applyEnabledVisibility();
- // -- Готовност на формата
- function ready(){
- if(!selectedModel) return false;
- if(!material.value || !color.value || !glazingBase.value || !hardware.value) return false;
- const W=parseFloat(width.value||0), H=parseFloat(height.value||0);
- return (W>0 && H>0);
- }
- // -- Последна калкулация (за PDF/копиране)
- let LAST = null;
- function gatherSelections(W,H,discP){
- return {
- Модел: (MODELS.find(x=>x.id===selectedModel)?.label || ''),
- Материал: {pvc:'PVC', alu:'Алуминий', wood:'Дърво'}[material.value] || '',
- Цвят: {white:'Бял', oneSideColor:'Едностранно цветен', bothSidesColor:'Двустранно цветен'}[color.value] || '',
- Размер: `${W} × ${H} см`,
- Делител: {none:'Без', vertical:'Вертикален', horizontal:'Хоризонтален'}[divider.value||'none'] || '—',
- 'Стъклопакет (база)': {double24:'Двоен 24 мм', triple36:'Троен 36 мм'}[glazingBase.value] || '',
- 'Добавки към стъклопакет': [
- gLowE.checked?'Low-E':null,
- gFour.checked?'4 сезона':null,
- gArgon.checked?'Аргон':null
- ].filter(Boolean).join(', ') || '—',
- Обков: {fixed:'Глух', single:'Еднокрила', double:'Двукрила', tiltTurn:'Падащо-отваряема'}[hardware.value] || '',
- 'Комарници (бр.)': parseInt(mosquitoQty.value||'0',10),
- 'Ролетна щора': {yes:'Да', no:'Не'}[shutterYes.value||'no'] || '—',
- 'Вътрешен перваз': {yes:'Да', no:'Не'}[innerSillYes.value||'no'] || '—',
- 'Външен водобран': {yes:'Да', no:'Не'}[dripYes.value||'no'] || '—',
- Демонтаж: uninstallOld.checked ? 'Да' : 'Не',
- Монтаж: installNew.checked ? 'Да' : 'Не',
- 'Обръщане/довършителни': finishing.checked ? 'Да' : 'Не',
- 'Транспорт (км)': parseFloat(distanceKm.value||'0'),
- 'Отстъпка (%)': discP,
- 'ДДС включено': vatOn.checked ? 'Да' : 'Не'
- };
- }
- // -- Калкулация
- function calculate(){
- if(!ready()){
- breakdown.innerHTML='';
- badges.innerHTML = selectedModel ? badge(MODELS.find(x=>x.id===selectedModel)?.label||'') : '';
- totalBGN.textContent='—'; totalEUR.textContent='—';
- LAST=null;
- return;
- }
- const W = clamp(parseFloat(width.value),30,350);
- const H = clamp(parseFloat(height.value),30,350);
- const area = m2(W,H);
- const perimeter = perim(W,H);
- const profPrice = PRICING.profilePerMeter[material.value];
- const colorK = PRICING.colorMultiplier[color.value] || 1;
- let profileCost = perimeter * profPrice * colorK;
- if(divider.value==='vertical'){ profileCost += (H/100) * profPrice * colorK; }
- else if(divider.value==='horizontal'){ profileCost += (W/100) * profPrice * colorK; }
- let glazingCost = area * PRICING.glazingPerM2[glazingBase.value];
- if(gLowE.checked) glazingCost += area * PRICING.glazingAddersPerM2.lowE;
- if(gFour.checked) glazingCost += area * PRICING.glazingAddersPerM2.fourSeasons;
- if(gArgon.checked) glazingCost += area * PRICING.glazingAddersPerM2.argon;
- const hardwareCost = PRICING.hardware[hardware.value];
- const e = PRICING.enabled || {};
- const widthMeters = W/100;
- const mosquitoCost = (e.mosquito === false) ? 0
- : (parseInt(mosquitoQty.value||'0',10)) * PRICING.mosquito;
- const shutterCost = (e.rollerShutter === false) ? 0
- : (shutterYes.value==='yes' ? (area * PRICING.rollerShutterPerM2) : 0);
- const innerSillCost= (e.innerSill === false) ? 0
- : (innerSillYes.value==='yes' ? (widthMeters * PRICING.innerSillPerMeter) : 0);
- const dripCost = (e.dripEdge === false) ? 0
- : (dripYes.value==='yes' ? (widthMeters * PRICING.dripEdgePerMeter) : 0);
- const uninstallCost = (e.uninstall === false) ? 0
- : (uninstallOld.checked ? PRICING.uninstallPerWindow : 0);
- const installCost = (e.install === false) ? 0
- : (installNew.checked ? PRICING.installPerWindow : 0);
- const finishingCost = (e.finishing === false) ? 0
- : (finishing.checked ? (perimeter * PRICING.finishingPerMeter) : 0);
- const transportCost = (e.transport === false) ? 0
- : ((parseFloat(distanceKm.value||'0')>0) ? (parseFloat(distanceKm.value)*PRICING.transportPerKm) : 0);
- // Редове за разбивката
- const items = [];
- if (ON('profile')) items.push([L('profile','Профили (периметър)'), Math.round(profileCost)]);
- if (ON('glazing')) items.push([L('glazing','Стъклопакет'), Math.round(glazingCost)]);
- if (ON('hardware')) items.push([L('hardware','Обков'), Math.round(hardwareCost)]);
- if (mosquitoCost && ON('mosquito')) items.push([L('mosquito','Комарници'), Math.round(mosquitoCost)]);
- if (shutterCost && ON('rollerShutter')) items.push([L('rollerShutter','Ролетна щора'), Math.round(shutterCost)]);
- if (innerSillCost && ON('innerSill')) items.push([L('innerSill','Вътрешен перваз'), Math.round(innerSillCost)]);
- if (dripCost && ON('dripEdge')) items.push([L('dripEdge','Външен водобран'), Math.round(dripCost)]);
- if (uninstallCost && ON('uninstall')) items.push([L('uninstall','Демонтаж'), Math.round(uninstallCost)]);
- if (installCost && ON('install')) items.push([L('install','Монтаж'), Math.round(installCost)]);
- if (finishingCost && ON('finishing')) items.push([L('finishing','Обръщане'), Math.round(finishingCost)]);
- if (transportCost && ON('transport')) items.push([L('transport','Транспорт'), Math.round(transportCost)]);
- if (Array.isArray(PRICING.fixedAdders)) {
- for (const adder of PRICING.fixedAdders) {
- const amt = Number(adder && adder.amount);
- if (!isNaN(amt) && amt !== 0) items.push([adder.label || 'Допълнителна позиция', Math.round(amt)]);
- }
- }
- let subtotal = items.reduce((s, it)=> s + (typeof it[1]==='number' ? it[1] : 0), 0);
- const discP = clamp(parseFloat(discount.value||'0'),0,100);
- const discAmount = Math.round(subtotal * (discP/100));
- let afterDisc = subtotal - discAmount;
- const vat = vatOn.checked ? Math.round(afterDisc * PRICING.vatRate) : 0;
- const total = afterDisc + vat;
- // Баджове
- const modelObj = MODELS.find(x=>x.id===selectedModel) || {};
- const badgeList = [];
- badgeList.push(badge(modelObj.label || ''));
- badgeList.push(badge((material.value||'').toUpperCase()));
- badgeList.push(badge(color.value==='white'?'бял':(color.value==='oneSideColor'?'едностранно':'двустранно')));
- badgeList.push(badge((glazingBase.value||'').replace('double24','двоен 24').replace('triple36','троен 36')));
- if(gLowE.checked) badgeList.push(badge('Low-E'));
- if(gFour.checked) badgeList.push(badge('4 сезона'));
- if(gArgon.checked) badgeList.push(badge('аргон'));
- badgeList.push(badge({fixed:'Глух', single:'Еднокрила', double:'Двукрила', tiltTurn:'Падащо-отваряема'}[hardware.value]||''));
- badges.innerHTML = badgeList.join('');
- // Рендер на разбивката
- breakdown.innerHTML =
- items.map(([t,v])=>`<li><span>${t}</span><strong>${fmtBGN(v)}</strong></li>`).join('') +
- (discAmount? `<li><span>${L('discount','Отстъпка')} (${discP}%)</span><strong>- ${fmtBGN(discAmount)}</strong></li>`:'') +
- (vat? `<li><span>${L('vat','ДДС (20%)')}</span><strong>${fmtBGN(vat)}</strong></li>`:'');
- totalBGN.textContent = fmtBGN(total);
- totalEUR.textContent = fmtEUR(toEUR(total));
- // Копиране на офертата
- const selections = gatherSelections(W,H,discP);
- copyBtn.onclick = () => {
- const txt = makePlainText(items, discP, discAmount, vat, total, selections);
- navigator.clipboard.writeText(txt).then(()=>{
- copyBtn.textContent='Копирано!';
- setTimeout(()=>copyBtn.textContent='Копирай офертата',1200);
- });
- };
- // Запази за PDF
- LAST = {
- items, discP, discAmount, vat, total,
- eur: Math.round(total/PRICING.eurRate),
- selections,
- modelLabel: modelObj.label || '',
- modelSrc: (modelObj.img||'')
- };
- }
- function makeEmailBody(items, discP, discAmount, vat, total, selections){
- const lines = [];
- lines.push('Здравей, Красимир,','', 'Калкулация за дограма:','', 'Параметри:');
- for(const [k,v] of Object.entries(selections)){ lines.push(`• ${k}: ${v}`); }
- lines.push('', 'Разбивка:');
- for(const [t,v] of items){ lines.push(`• ${t}: ${v} лв`); }
- if(discAmount) lines.push(`• ${L('discount','Отстъпка')} (${discP}%): -${discAmount} лв`);
- if(vat) lines.push(`• ${L('vat','ДДС (20%)')}: ${vat} лв`);
- lines.push('', `ОБЩО: ${total} лв (≈ ${Math.round(total/PRICING.eurRate)} EUR)`);
- return lines.join('\n');
- }
- function makePlainText(items, discP, discAmount, vat, total, selections){
- const lines = [];
- lines.push('Ориентировъчна оферта – дограма','Параметри:');
- for(const [k,v] of Object.entries(selections)){ lines.push(`${k}: ${v}`); }
- lines.push('----------------------');
- for(const [t,v] of items){ lines.push(`${t}: ${v} лв`); }
- if(discAmount) lines.push(`${L('discount','Отстъпка')} (${discP}%): -${discAmount} лв`);
- if(vat) lines.push(`${L('vat','ДДС (20%)')}: ${vat} лв`);
- lines.push('----------------------', `ОБЩО: ${total} лв (≈ ${Math.round(total/PRICING.eurRate)} EUR)`);
- return lines.join('\n');
- }
- // -- Експорт в PDF (Print → Save as PDF) — без <script> в темплейта
- function exportPDF(){
- if(!LAST){ alert('Попълнете параметрите и генерирайте калкулацията преди експорт.'); return; }
- const now = new Date();
- const dateStr = new Intl.DateTimeFormat('bg-BG', {
- year:'numeric', month:'2-digit', day:'2-digit',
- hour:'2-digit', minute:'2-digit'
- }).format(now);
- let rowsHTML = LAST.items.map(([t,v])=>`<tr><td>${t}</td><td class="r">${v} лв</td></tr>`).join('');
- if(LAST.discAmount) rowsHTML += `<tr><td>${L('discount','Отстъпка')} (${LAST.discP}%)</td><td class="r">- ${LAST.discAmount} лв</td></tr>`;
- if(LAST.vat) rowsHTML += `<tr><td>${L('vat','ДДС (20%)')}</td><td class="r">${LAST.vat} лв</td></tr>`;
- const selHTML = Object.entries(LAST.selections)
- .map(([k,v])=>`<div class="row"><span class="k">${k}</span><span class="v">${v}</span></div>`).join('');
- const logoOrModel = LAST.modelSrc
- ? `<img class="hero" src="${LAST.modelSrc}" alt="${LAST.modelLabel}">`
- : '';
- const html = `
- <!doctype html>
- <html lang="bg">
- <head>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width,initial-scale=1">
- <title>Оферта – дограма</title>
- <style>
- *{box-sizing:border-box}
- body{font-family:Inter,system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif;margin:0;padding:24px;background:#fff;color:#111}
- .wrap{max-width:780px;margin:0 auto}
- .head{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px}
- .brand{font-weight:800;font-size:20px}
- .meta{color:#666;font-size:12px}
- .hero{display:block;max-width:260px;max-height:160px;object-fit:contain;margin:8px 0}
- h1{font-size:24px;margin:12px 0 8px}
- h2{font-size:16px;margin:18px 0 8px;color:#444}
- .grid{display:grid;grid-template-columns:1fr 1fr;gap:18px}
- .card{border:1px solid #e6e6e6;border-radius:12px;padding:16px}
- .row{display:flex;justify-content:space-between;border-bottom:1px dashed #e6e6e6;padding:6px 0}
- .row .k{color:#444}
- .row .v{font-weight:600}
- table{width:100%;border-collapse:collapse;margin-top:4px}
- td{padding:8px 6px;border-bottom:1px solid #eee}
- td.r{text-align:right}
- .total{font-size:20px;font-weight:900;margin-top:10px}
- .muted{color:#666;font-size:12px;margin-top:6px}
- .footer{margin-top:24px;font-size:12px;color:#666}
- @media print {.no-print{display:none}}
- </style>
- </head>
- <body onload="window.print()">
- <div class="wrap">
- <div class="head">
- <div>
- <div class="brand">Оферта – дограма</div>
- <div class="meta">Генерирана: ${dateStr} • ${location.host}</div>
- </div>
- ${logoOrModel}
- </div>
- <div class="grid">
- <div class="card">
- <h2>Параметри</h2>
- ${selHTML}
- </div>
- <div class="card">
- <h2>Разбивка</h2>
- <table>${rowsHTML}</table>
- <div class="total">ОБЩО: ${LAST.total} лв (≈ ${LAST.eur} EUR)</div>
- <div class="muted">Курс: 1 EUR = ${PRICING.eurRate} BGN</div>
- </div>
- </div>
- <div class="footer">
- * Офертата е ориентировъчна и подлежи на уточнение след оглед/детайлизиране.
- </div>
- <div class="no-print" style="margin-top:16px">
- <button onclick="window.print()">Печат / Запази като PDF</button>
- </div>
- </div>
- </body>
- </html>`;
- const w = window.open('', '_blank', 'width=900,height=900');
- if(!w){ alert('Моля, разрешете pop-up за този сайт, за да се отвори PDF прозорец.'); return; }
- w.document.write(html);
- w.document.close();
- w.focus();
- }
- // -- Събития
- ['change','input'].forEach(evt=>{
- document.querySelectorAll('#win-calc select,#win-calc input')
- .forEach(el=>{ el.addEventListener(evt, calculate); el.setAttribute('autocomplete','off'); });
- });
- pdfBtn.addEventListener('click', exportPDF);
- resetBtn.addEventListener('click',()=>{
- selectedModel=''; [...modelsWrap.children].forEach(x=>x.classList.remove('active'));
- formWrap.style.display='none'; modelPreview.style.display='none'; modelImg.src=''; modelCaption.textContent='';
- document.querySelectorAll('#win-calc select').forEach(s=>s.selectedIndex=0);
- document.querySelectorAll('#win-calc input[type="number"]').forEach(i=>i.value='');
- [gLowE,gFour,gArgon,uninstallOld,installNew,finishing,vatOn].forEach(c=>c.checked=false);
- applyEnabledVisibility();
- vatOn.checked=true; mosquitoQty.value='0'; distanceKm.value='0';
- breakdown.innerHTML=''; badges.innerHTML=''; totalBGN.textContent='—'; totalEUR.textContent='—';
- LAST=null;
- });
- // -- Старт
- breakdown.innerHTML=''; totalBGN.textContent='—'; totalEUR.textContent='—';
- })();
- </script>
- </div>
Advertisement
Add Comment
Please, Sign In to add comment