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

Code: DEV-831AFC3F Size: 9.5 KB Lines: 137 Path: /home/prodconfig.wenesthosting.com/dev.solargroup.wenest.se/backups/2026-03-28-pre-sidebar-refactor/prissammanstallning.js

Task / Comment

Open report form
// prissammanstallning.js
// EN gemensam prissammanställning för ALLA kalkyler
// Design kopierad från solcellskonfiguratorn (den godkända designen)

function renderPrisSidebar(containerId, data) {
    // data = {
    //   lines: [{label, detail, value, id}],
    //   subtotal: number,
    //   deductType: 'green'|'rot'|'both'|'none',
    //   deductLabel: string,
    //   deductAmount: number,
    //   deductDetail: string,
    //   owners: 1|2,
    //   maxDeduction: number,
    //   total: number,
    //   finYears: number,
    //   monthly: number,
    //   saving: number (optional),
    //   payback: number (optional),
    //   category: string,
    //   onDeductChange: string (onclick function name),
    //   onOwnerChange: string,
    //   onFinChange: string,
    //   onSave: string,
    //   onOrder: string
    // }

    var el = document.getElementById(containerId);
    if (!el) return;

    var d = data || {};
    var lines = d.lines || [];
    var deductType = d.deductType || 'none';
    var owners = d.owners || 1;
    var finYears = d.finYears || 15;
    var onDeduct = d.onDeductChange || 'setPrisDeduction';
    var onOwner = d.onOwnerChange || 'setPrisOwners';
    var onFin = d.onFinChange || 'setPrisFinYears';
    var onSave = d.onSave || 'saveCfgQuote()';
    var onOrder = d.onOrder || 'goToCfgAffar()';
    var cat = d.category || '';

    // Prisrader
    var linesHtml = lines.map(function(l) {
        var detail = l.detail ? ' <span style="font-size:10px;color:#94a3b8">' + l.detail + '</span>' : '';
        return '<div class="price-line"><span class="price-line-label">' + l.label + detail + '</span><span class="price-line-value">' + fmt(l.value || 0) + '</span></div>';
    }).join('');
    linesHtml += '<div class="price-line subtotal"><span class="price-line-label">Totalt före avdrag</span><span class="price-line-value">' + fmt(d.subtotal || 0) + '</span></div>';

    // Skatteavdrag-knappar
    function deductBtn(type, label, sub, active) {
        var style = active
            ? 'flex:1;padding:7px 4px;border:1.5px solid #059669;border-radius:6px;font-size:11px;font-weight:600;cursor:pointer;background:#059669;color:#fff;font-family:inherit;line-height:1.2'
            : 'flex:1;padding:7px 4px;border:1.5px solid #bbf7d0;border-radius:6px;font-size:11px;font-weight:600;cursor:pointer;background:#fff;color:#059669;font-family:inherit;line-height:1.2';
        return '<button onclick="' + onDeduct + '(\'' + type + '\')" style="' + style + '">' + label + '<br><span style="font-size:9px;font-weight:400;opacity:.8">' + sub + '</span></button>';
    }

    var deductHtml = '<div style="margin-bottom:10px">'
        + '<div style="font-size:11px;color:#6b7280;margin-bottom:6px;font-weight:600">SKATTEAVDRAG</div>'
        + '<div style="display:flex;gap:4px">'
        + deductBtn('green', 'Grönt teknik', '20% av allt', deductType === 'green')
        + deductBtn('rot', 'ROT-avdrag', '30% av arbete', deductType === 'rot')
        + deductBtn('both', 'Båda', 'max av båda', deductType === 'both')
        + deductBtn('none', 'Inget', '&nbsp;', deductType === 'none')
        + '</div></div>';

    // Avdragssumma
    deductHtml += '<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px">'
        + '<span style="font-size:12px;font-weight:700;color:#059669">' + (d.deductLabel || '') + '</span>'
        + '<span style="font-size:16px;font-weight:700;color:#059669">' + (d.deductAmount ? '-' + fmt(d.deductAmount) : '0 kr') + '</span></div>';
    if (d.deductDetail) deductHtml += '<div style="font-size:11px;color:#6b7280;margin-bottom:8px">' + d.deductDetail + '</div>';

    // Antal ägare
    deductHtml += '<div style="margin-bottom:10px"><div style="font-size:11px;color:#6b7280;margin-bottom:4px">Antal ägare</div>'
        + '<div style="display:flex;gap:6px">'
        + '<button onclick="' + onOwner + '(1)" style="flex:1;padding:6px;border:1.5px solid ' + (owners === 1 ? '#059669' : '#bbf7d0') + ';border-radius:6px;font-size:12px;font-weight:600;cursor:pointer;background:' + (owners === 1 ? '#059669' : '#fff') + ';color:' + (owners === 1 ? '#fff' : '#059669') + ';font-family:inherit">1 person</button>'
        + '<button onclick="' + onOwner + '(2)" style="flex:1;padding:6px;border:1.5px solid ' + (owners === 2 ? '#059669' : '#bbf7d0') + ';border-radius:6px;font-size:12px;font-weight:600;cursor:pointer;background:' + (owners === 2 ? '#059669' : '#fff') + ';color:' + (owners === 2 ? '#fff' : '#059669') + ';font-family:inherit">2 personer</button>'
        + '</div></div>';

    // Kvarvarande avdrag slider
    var maxDed = d.maxDeduction || (owners * 50000);
    deductHtml += '<div><div style="display:flex;justify-content:space-between;font-size:11px;color:#6b7280;margin-bottom:4px">'
        + '<span>Kvarvarande avdrag</span><span style="font-weight:600;color:#059669">' + maxDed.toLocaleString('sv-SE') + ' kr</span></div>'
        + '<input type="range" min="0" max="' + maxDed + '" step="5000" value="' + maxDed + '" style="width:100%;accent-color:#059669" disabled>'
        + '<div style="display:flex;justify-content:space-between;font-size:10px;color:#94a3b8"><span>0 kr</span><span>' + maxDed.toLocaleString('sv-SE') + ' kr</span></div></div>';

    // Finansiering
    function finBtn(yr, active) {
        var style = active
            ? 'padding:4px 10px;border:1.5px solid #3b82f6;border-radius:6px;font-size:11px;font-weight:600;cursor:pointer;background:#3b82f6;color:#fff;font-family:inherit'
            : 'padding:4px 10px;border:1.5px solid #bfdbfe;border-radius:6px;font-size:11px;font-weight:600;cursor:pointer;background:#fff;color:#3b82f6;font-family:inherit';
        var label = yr === 0 ? 'Ej finans' : yr + ' år';
        return '<button onclick="' + onFin + '(' + yr + ')" style="' + style + '">' + label + '</button>';
    }

    var finHtml = '<div style="background:#f0f9ff;border-radius:10px;padding:14px;margin-bottom:12px">'
        + '<div style="font-size:11px;color:#3b82f6;font-weight:600;margin-bottom:8px">FINANSIERING</div>'
        + '<div style="display:flex;gap:6px;margin-bottom:10px;flex-wrap:wrap">'
        + finBtn(0, finYears === 0) + finBtn(5, finYears === 5) + finBtn(10, finYears === 10) + finBtn(15, finYears === 15) + finBtn(20, finYears === 20) + finBtn(25, finYears === 25)
        + '</div>';
    if (finYears > 0) {
        finHtml += '<div style="display:flex;justify-content:space-between;align-items:baseline">'
            + '<span style="font-size:13px;color:#334155">Månadskostnad <span style="font-size:10px;color:#64748b">(' + finYears + ' år, 4.9%)</span></span>'
            + '<span style="font-size:20px;font-weight:700;color:#1e40af">' + fmt(d.monthly || 0) + '/mån</span></div>';
    } else {
        finHtml += '<div style="font-size:13px;color:#64748b">Ingen finansiering vald</div>';
    }
    finHtml += '</div>';

    // Besparing (valfritt)
    var savingHtml = '';
    if (d.saving) {
        savingHtml = '<div style="background:#ecfdf5;border-radius:10px;padding:14px;margin-bottom:16px">'
            + '<div style="font-size:11px;color:#059669;font-weight:600;margin-bottom:4px">UPPSKATTAD BESPARING</div>'
            + '<div style="display:flex;justify-content:space-between;align-items:baseline"><span style="font-size:13px;color:#334155">Per år</span><span style="font-size:20px;font-weight:700;color:#166534">' + d.saving.toLocaleString('sv-SE') + ' kr/år</span></div>'
            + (d.payback ? '<div style="display:flex;justify-content:space-between;align-items:baseline;margin-top:4px"><span style="font-size:13px;color:#334155">Återbetalningstid</span><span style="font-size:16px;font-weight:700;color:#166534">' + d.payback + ' år</span></div>' : '')
            + '</div>';
    }

    // Knappar
    var btnsHtml = '<button onclick="' + onSave + '" style="width:100%;padding:12px;background:#f59e0b;color:#fff;border:none;border-radius:10px;font-size:14px;font-weight:700;cursor:pointer;font-family:inherit;display:flex;align-items:center;justify-content:center;gap:8px;margin-bottom:8px">'
        + '<svg viewBox="0 0 24 24" style="width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:2"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><polyline points="17 21 17 13 7 13 7 21"/><polyline points="7 3 7 8 15 8"/></svg>'
        + 'Spara utkast</button>'
        + '<button onclick="' + onOrder + '" style="width:100%;padding:14px;background:linear-gradient(135deg,#024550,#035e6b);color:#fff;border:none;border-radius:10px;font-size:15px;font-weight:700;cursor:pointer;font-family:inherit;display:flex;align-items:center;justify-content:center;gap:8px">'
        + '<svg viewBox="0 0 24 24" style="width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:2"><path d="M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2M9 5h6"/><path d="M9 12h6M9 16h6"/></svg>'
        + 'Lägg till order</button>';

    // Hela prissammanställningen
    el.innerHTML = '<div style="position:sticky;top:20px"><div class="price-card">'
        + '<div class="price-header">Prissammanställning</div>'
        + '<div class="price-rows">' + linesHtml + '</div>'
        + '<div class="rot-section" style="background:#ecfdf5;padding:14px 16px">' + deductHtml + '</div>'
        + '<div class="total-section"><div class="total-line"><span class="total-label">Att betala</span><span class="total-value">' + fmt(d.total || 0) + '</span></div><div class="total-vat">Inkl. moms</div></div>'
        + '<div style="padding:0 16px 16px">' + finHtml + savingHtml + btnsHtml + '</div>'
        + '</div></div>';
}