backups/2026-03-28-pre-sidebar-refactor/konfigurator.js

Code: DEV-A9C67553 Size: 11.4 KB Lines: 214 Path: /home/prodconfig.wenesthosting.com/dev.solargroup.wenest.se/backups/2026-03-28-pre-sidebar-refactor/konfigurator.js

Task / Comment

Open report form
// konfigurator.js - Kalkyl list, config switching

function showKalkylConfig(){ var _cs2=document.getElementById('categorySelect');if(_cs2)_cs2.value=''; ['solarConfigView','genericConfigView','fonsterConfigView','batteriConfigView','laddboxConfigView','taktvatConfigView','varmepumpConfigView','takConfigView','isoleringConfigView'].forEach(function(v){var el=document.getElementById(v);if(el)el.style.display='none';}); if(typeof loadCfgCategories==='function')loadCfgCategories();
    document.getElementById('kalkylListView').style.display='none';
    document.getElementById('kalkylConfigView').style.display='block';
    var afv = document.getElementById('affarView');
    if(afv) afv.style.display='none';
    // Rensa produktkalkylvy om den finns
    var pqv = document.getElementById('productQuoteView'); if(pqv) pqv.remove();
    // Visa kategori-grid
    var catGrid = document.getElementById('cfgCategoryGrid'); if(catGrid) catGrid.style.display = '';
    // Visa kalkyl-header (kundinformation + prospektbilder)
    if(typeof populateKalkylFromCustomer === 'function') populateKalkylFromCustomer();
    var photosSection = document.getElementById('kalkylPhotosSection');
    if(photosSection) photosSection.style.display = '';
}
function addQuoteToProspect(pIdx, qId){
    if(pIdx < 0 || !faltProspects[pIdx]) return;
    if(!faltProspects[pIdx].quoteIds){
        faltProspects[pIdx].quoteIds = faltProspects[pIdx].quoteId ? [faltProspects[pIdx].quoteId] : [];
    }
    if(!faltProspects[pIdx].quoteIds.includes(qId)){
        faltProspects[pIdx].quoteIds.push(qId);
    }
    faltProspects[pIdx].quoteId = qId;
    localStorage.setItem('faltProspects', JSON.stringify(faltProspects));
}
function showProspectQuotes(prospectIdx){
    var p = faltProspects[prospectIdx];
    if(!p) return;
    var ids = p.quoteIds || (p.quoteId ? [p.quoteId] : []);
    if(ids.length === 0){ alert('Inga kalkyler'); return; }
    if(ids.length === 1){ kalkylOrigin = 'faltsalj'; openQuoteFromList(ids[0]); return; }
    var modal = document.createElement('div');
    modal.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:9999;display:flex;align-items:center;justify-content:center;padding:20px';
    modal.onclick = function(e){ if(e.target === modal) modal.remove(); };
    modal.innerHTML = '<div style="background:#fff;border-radius:16px;padding:24px;width:420px;max-width:95vw;box-shadow:0 20px 60px rgba(0,0,0,.2)"><div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:16px"><h3 style="font-size:17px;font-weight:700;margin:0">V\u00e4lj kalkyl</h3><button id="closeQPBtn" style="background:none;border:none;font-size:22px;cursor:pointer;color:#94a3b8">\u00d7</button></div><div style="font-size:13px;color:#64748b;margin-bottom:14px">'+(p.addr||'')+(p.city?', '+p.city:'')+'</div><div id="qpList" style="display:flex;flex-direction:column;gap:8px"><div style="text-align:center;padding:20px;color:#94a3b8">Laddar...</div></div></div>';
    document.body.appendChild(modal);
    document.getElementById('closeQPBtn').onclick = function(){ modal.remove(); };
    Promise.all(ids.map(function(id){ return fetch('/api/quotes.php?id='+id).then(function(r){return r.json();}).catch(function(){return null;}); })).then(function(results){
        var html = '';
        results.forEach(function(data){
            if(!data || !data.success || !data.quote) return;
            var q = data.quote;
            var cat = q.category || 'solceller';
            var date = q.updated_at ? new Date(q.updated_at).toLocaleDateString('sv-SE') : '';
            var price = q.total_price ? Math.round(q.total_price).toLocaleString('sv-SE') + ' kr' : '';
            var st = q.status || 'utkast';
            var sc = st === 'offert' ? '#f59e0b' : st === 'order' ? '#10b981' : '#64748b';
            html += '<div data-qid="'+q.id+'" class="qp-item" style="padding:14px 16px;border:1.5px solid #e5e7eb;border-radius:10px;cursor:pointer;display:flex;justify-content:space-between;align-items:center"><div><div style="font-weight:600;font-size:14px;color:#1a1a1a;text-transform:capitalize">'+cat+'</div><div style="font-size:12px;color:#64748b;margin-top:2px">#'+q.id+' \u2014 '+date+'</div></div><div style="text-align:right"><div style="font-weight:700;font-size:14px;color:#024550">'+price+'</div><span style="font-size:11px;font-weight:600;color:'+sc+';text-transform:uppercase">'+st+'</span></div></div>';
        });
        var list = document.getElementById('qpList');
        if(list) list.innerHTML = html || '<div style="text-align:center;padding:20px;color:#94a3b8">Inga kalkyler</div>';
        document.querySelectorAll('.qp-item').forEach(function(el){
            el.onmouseover = function(){ el.style.borderColor='#024550'; el.style.background='#f0fdfa'; };
            el.onmouseout = function(){ el.style.borderColor='#e5e7eb'; el.style.background='#fff'; };
            el.onclick = function(){ var qid = parseInt(el.getAttribute('data-qid')); modal.remove(); kalkylOrigin='faltsalj'; openQuoteFromList(qid); };
        });
    });
}
function kalkylGoBack(){
    if(kalkylOrigin === 'faltsalj'){
        kalkylOrigin = 'konfigurator';
        navigateTo('faltsalj');
    } else {
        showKalkylList();
    }
}
function showKalkylList(){
    kalkylOrigin = 'konfigurator';
    document.getElementById('kalkylConfigView').style.display='none';
    const afv = document.getElementById('affarView');
    if(afv) afv.style.display='none';
    document.getElementById('kalkylListView').style.display='block';
    kalkylImages = [];
    const kpSec = document.getElementById('kalkylPhotosSection');
    if(kpSec) kpSec.style.display = 'none';
    loadQuotesList();
}
function changeCategory(){ if(typeof renderCfgCategoryGrid==='function')renderCfgCategoryGrid();
    const cat=document.getElementById('categorySelect').value;
    const views=['solarConfigView','genericConfigView','fonsterConfigView','batteriConfigView','laddboxConfigView','taktvatConfigView','varmepumpConfigView','takConfigView','isoleringConfigView'];
    views.forEach(v=>{const el=document.getElementById(v);if(el)el.style.display='none'});
    const afv=document.getElementById('affarView');
    if(afv) afv.style.display='none';
    const map={
        'solceller':['solarConfigView','initSolarConfig'],
        'batteri':['batteriConfigView','initBatConfig'],
        'laddbox':['laddboxConfigView','initLbConfig'],
        'taktvatt':['taktvatConfigView','initTtConfig'],
        'varmepump':['varmepumpConfigView','initVpConfig'],
        'fonster':['fonsterConfigView','initFonsterConfig'],
        'tak':['takConfigView','initTakConfig'],
        'isolering':['isoleringConfigView','initIsoConfig']
    };
    if(map[cat]){
        document.getElementById(map[cat][0]).style.display='block';
        if(typeof window[map[cat][1]]==='function') window[map[cat][1]]();
    } else if(cat) {
        document.getElementById('genericConfigView').style.display='block';
    }
}

// === GEMENSAM PRISSAMMANSTÄLLNING ===
var _cfgItems = []; // {id, name, price, deductType, deductRate, laborRatio}
var _cfgOwners = 1;
var _cfgFinYears = 15;

function cfgAddItem(id, name, price, deductType, laborRatio) {
    // Remove existing with same id
    _cfgItems = _cfgItems.filter(function(item) { return item.id !== id; });
    if (price > 0) {
        _cfgItems.push({id: id, name: name, price: price, deductType: deductType || 'none', laborRatio: laborRatio || 0});
    }
    renderCfgSummary();
}

function cfgRemoveItem(id) {
    _cfgItems = _cfgItems.filter(function(item) { return item.id !== id; });
    renderCfgSummary();
}

function cfgClearItems() {
    _cfgItems = [];
    renderCfgSummary();
}

function setCfgOwners(n) {
    _cfgOwners = n;
    cfgSetBtns('owner', 'cfg-owner-btn', n);
    renderCfgSummary();
}

function setCfgFinYears(y) {
    _cfgFinYears = y;
    cfgSetBtns('fin', 'cfg-fin-btn', y);
    renderCfgSummary();
}

function renderCfgSummary() {
    var itemsEl = document.getElementById('cfgSummaryItems');
    var subtotalEl = document.getElementById('cfgSumSubtotal');
    var deductLabelEl = document.getElementById('cfgSumDeductLabel');
    var deductKrEl = document.getElementById('cfgSumDeductKr');
    var deductRowEl = document.getElementById('cfgSumDeductRow');
    var totalEl = document.getElementById('cfgSumTotal');
    var finInfoEl = document.getElementById('cfgSumFinInfo');
    var monthlyEl = document.getElementById('cfgSumMonthly');
    var finSectionEl = document.getElementById('cfgFinSection');

    if (!itemsEl) return;

    if (!_cfgItems.length) {
        itemsEl.innerHTML = '<div style="text-align:center;color:#94a3b8;font-size:13px;padding:20px 0">Välj produkter för att se pris</div>';
        if(subtotalEl) subtotalEl.textContent = '0 kr';
        if(deductKrEl) deductKrEl.textContent = '0 kr';
        if(totalEl) totalEl.textContent = '0 kr';
        if(monthlyEl) monthlyEl.textContent = '0 kr/mån';
        return;
    }

    // Render items
    var html = '';
    _cfgItems.forEach(function(item) {
        var badge = '';
        if (item.deductType === 'green') badge = '<span style="font-size:9px;background:#ecfdf5;color:#059669;padding:1px 6px;border-radius:4px;margin-left:4px">Grön teknik</span>';
        else if (item.deductType === 'rot') badge = '<span style="font-size:9px;background:#fef3c7;color:#92400e;padding:1px 6px;border-radius:4px;margin-left:4px">ROT</span>';
        html += '<div style="display:flex;justify-content:space-between;align-items:center;padding:6px 0;border-bottom:1px solid #f1f5f9">'
            + '<div><span style="font-size:13px;font-weight:500;color:#334155">' + item.name + '</span>' + badge + '</div>'
            + '<div style="display:flex;align-items:center;gap:8px">'
            + '<span style="font-size:13px;font-weight:600">' + fmt(item.price) + '</span>'
            + '<button onclick="cfgRemoveItem(\'' + item.id + '\')" style="background:none;border:none;color:#ef4444;cursor:pointer;font-size:14px;padding:0 2px">&times;</button>'
            + '</div></div>';
    });
    itemsEl.innerHTML = html;

    // Calculate totals
    var subtotal = 0;
    var totalDeduct = 0;
    _cfgItems.forEach(function(item) {
        subtotal += item.price;
        var maxPerOwner = 50000;
        var maxTotal = _cfgOwners * maxPerOwner;
        if (item.deductType === 'green') {
            totalDeduct += Math.min(Math.round(item.price * 0.20), maxTotal);
        } else if (item.deductType === 'rot') {
            totalDeduct += Math.min(Math.round(item.price * item.laborRatio * 0.30), maxTotal);
        }
    });

    var total = subtotal - totalDeduct;
    var monthly = 0;
    if (_cfgFinYears > 0) {
        var r = 0.049 / 12, n = _cfgFinYears * 12;
        monthly = Math.round(total * r * Math.pow(1+r,n) / (Math.pow(1+r,n)-1));
    }

    if(subtotalEl) subtotalEl.textContent = fmt(subtotal);
    if(deductKrEl) deductKrEl.textContent = totalDeduct ? '-' + fmt(totalDeduct) : '0 kr';
    if(deductLabelEl) deductLabelEl.textContent = totalDeduct ? 'Skattereduktion' : 'Inget avdrag';
    if(deductRowEl) deductRowEl.style.display = totalDeduct ? '' : 'none';
    if(totalEl) totalEl.textContent = fmt(total);

    if (_cfgFinYears > 0) {
        if(finInfoEl) finInfoEl.textContent = '(' + _cfgFinYears + ' år, 4.9%)';
        if(monthlyEl) monthlyEl.textContent = fmt(monthly) + '/mån';
        if(finSectionEl) finSectionEl.style.display = '';
    } else {
        if(finInfoEl) finInfoEl.textContent = '';
        if(monthlyEl) monthlyEl.textContent = 'Ej finans';
        if(finSectionEl) finSectionEl.style.display = '';
    }
}