js/app.js.bak-20260416-mysalary-profile

Code: DEV-AEBD3F04 Size: 8.0 KB Lines: 174 Path: /home/prodconfig.wenesthosting.com/dev.solargroup.wenest.se/js/app.js.bak-20260416-mysalary-profile

Task / Comment

Open report form
// app.js - Globals, navigation, helpers

var STAFF_API = '/api/staff.php';
var roleLabels = {systemadmin:'Systemadmin',admin:'Admin',saljchef:'Säljchef',saljare:'Säljare',installator:'Installatör',projektledare:'Projektledare',ekonomi:'Ekonomi',pending:'Pending'};
var roleColors = {systemadmin:'purple',admin:'purple',saljchef:'green',saljare:'green',installator:'blue',projektledare:'yellow',ekonomi:'gray',pending:'gray'};
// === GLOBAL VARS (must be at top to avoid TDZ) ===
var gAccessToken = sessionStorage.getItem('gAccessToken') || '';
var gTokenExpiry = parseInt(sessionStorage.getItem('gTokenExpiry') || '0');
var gStaffId = parseInt(sessionStorage.getItem('gStaffId') || '0');
var gUserEmail = sessionStorage.getItem('gUserEmail') || '';
var gUserName = sessionStorage.getItem('gUserName') || '';
var gUserAvatar = sessionStorage.getItem('gUserAvatar') || '';
var gMailSignature = localStorage.getItem('mailSignature') || '';

function showPage(p){ navigateTo(p); }
var currentPage = 'dashboard';
function navigateTo(page){
    currentPage = page;
    document.querySelectorAll('.nav-item').forEach(n=>n.classList.remove('active'));
    document.querySelectorAll('.nav-item[data-page="'+page+'"]').forEach(n=>n.classList.add('active'));
    document.querySelectorAll('.page-content').forEach(p=>p.classList.remove('active'));
    const el = document.getElementById('page-'+page);
    if(el) el.classList.add('active');
    // Update mobile nav
    document.querySelectorAll('.mobile-nav a').forEach(a=>{
        a.classList.toggle('active', a.dataset.page===page);
    });
    if(page === 'admin') initAdminPage();
    if(page === 'settings') try{loadTaxSettingsUI();}catch(e){}
    if(page === 'personal') try{loadStaff();}catch(e){}
    if(page === 'ue') try{loadUEPage();}catch(e){}
    if(page === 'faltsalj'){
        var _tryMap = function(retries){
            if(typeof google !== 'undefined' && google.maps) {
                initFaltMap();
                if(gMap) google.maps.event.trigger(gMap,'resize');
            } else if(retries > 0) {
                setTimeout(function(){ _tryMap(retries-1); }, 500);
            }
        };
        setTimeout(function(){ _tryMap(10); }, 200);
    }
    if(page === 'inkop') try{loadInkopPage();}catch(e){}
    if(page === 'leverantorer') try{loadLeverantorerPage();}catch(e){}
    if(page === 'inkorg') try{if(typeof updateAuthUI==='function') updateAuthUI(); if(gAccessToken){loadGmailLabels();loadGmailInbox();}}catch(e){}
    if(page === 'kalender') try{if(typeof updateAuthUI==='function') updateAuthUI(); if(gAccessToken){loadCalendarEvents();} setTimeout(function(){if(typeof renderCalendar==='function')renderCalendar();},50);}catch(e){}
    if(page === 'konfigurator') try{showKalkylList();}catch(e){}
    if(page === 'projekt') try{loadDeals();}catch(e){}
    if(page === 'projektering') try{loadDealPipeline();}catch(e){}
    if(page === 'kunder') try{loadCustomers();}catch(e){}
    if(page === 'oversikt') try{if(typeof loadDashboard==='function')loadDashboard();}catch(e){}
}
document.querySelectorAll('.nav-item').forEach(item=>{
    item.addEventListener('click',function(){
        navigateTo(this.dataset.page);
    });
});
document.querySelectorAll('.mobile-nav a').forEach(item=>{
    item.addEventListener('click',function(e){
        e.preventDefault();
        navigateTo(this.dataset.page);
    });
});

/* Kalkyl list/config view toggle */
function fmt(p){return p.toLocaleString('sv-SE')+' kr'}
function fmtOpt(p){return p===0?'0,00 kr':p>0?'+'+p.toLocaleString('sv-SE')+' kr':p.toLocaleString('sv-SE')+' kr'}

// Lightbox
function openLightbox(url){
    const lb = document.getElementById('imgLightbox');
    const img = document.getElementById('imgLightboxImg');
    if(lb && img){ img.src = url; lb.style.display = 'flex'; }
}
function closeLightbox(){
    const lb = document.getElementById('imgLightbox');
    if(lb) lb.style.display = 'none';
}

// Spara kalkyl från steg 1 (konfiguratorn, utan affär)
function closeModal(){const m=document.getElementById('quoteModal');if(m)m.classList.remove('active');document.body.style.overflow=''}
function submitQuote(e){if(e)e.preventDefault();alert('Tack! Vi återkommer.\n\n(DEMO)');closeModal()}
// === HELPERS ===
function escHtml(s) { const d = document.createElement('div'); d.textContent = s || ''; return d.innerHTML; }
function formatMailDate(ts) {
    if (!ts) return '';
    const d = new Date(ts * 1000);
    const now = new Date();
    if (d.toDateString() === now.toDateString()) return d.toLocaleTimeString('sv-SE', {hour:'2-digit', minute:'2-digit'});
    if (d.getFullYear() === now.getFullYear()) return d.toLocaleDateString('sv-SE', {day:'numeric', month:'short'});
    return d.toLocaleDateString('sv-SE');
}
function formatSize(bytes) {
    if (bytes < 1024) return bytes + ' B';
    if (bytes < 1048576) return (bytes/1024).toFixed(0) + ' KB';
    return (bytes/1048576).toFixed(1) + ' MB';
}

// Auto-load on page navigation
// Mail/calendar hooks injected into existing navigateTo override below

// Init on load (deferred to ensure all scripts are loaded)
window.addEventListener('DOMContentLoaded', function() {
    // Auto-login from session
    if(gStaffId && gUserEmail) {
        enterApp(gUserEmail, sessionStorage.getItem('gUserAvatar') || '');
    }
    if(typeof updateAuthUI === 'function') updateAuthUI();
    if(typeof loadCurrencySettings === 'function') loadCurrencySettings();
    if(typeof loadCatalogFromDB === 'function') loadCatalogFromDB();
    if(typeof initDashCharts === "function") initDashCharts();
    if(typeof loadCfgCategories === "function") loadCfgCategories();
});


// === Tax settings (loaded from DB) ===
var taxSettings = {gt20: 20, gt50: 50, rot: 30, rotMax: 50000, moms: 25};
async function loadTaxSettings() {
    try {
        var r = await fetch('/api/settings.php');
        var d = await r.json();
        if(d.success && d.settings) {
            taxSettings.gt20 = parseFloat(d.settings.tax_gt20_percent) || 20;
            taxSettings.gt50 = parseFloat(d.settings.tax_gt50_percent) || 50;
            taxSettings.rot = parseFloat(d.settings.tax_rot_percent) || 30;
            taxSettings.rotMax = parseFloat(d.settings.tax_rot_max_per_person) || 50000;
            taxSettings.moms = parseFloat(d.settings.tax_moms_percent) || 25;
        }
    } catch(e){}
}

// === Skatter settings UI ===
function loadTaxSettingsUI() {
    var gt20 = document.getElementById('taxGt20');
    var gt50 = document.getElementById('taxGt50');
    var rot = document.getElementById('taxRot');
    var rotMax = document.getElementById('taxRotMax');
    var moms = document.getElementById('taxMoms');
    if(gt20) gt20.value = taxSettings.gt20;
    if(gt50) gt50.value = taxSettings.gt50;
    if(rot) rot.value = taxSettings.rot;
    if(rotMax) rotMax.value = taxSettings.rotMax;
    if(moms) moms.value = taxSettings.moms;
}

async function saveTaxSettings() {
    var data = {
        tax_gt20_percent: document.getElementById('taxGt20').value,
        tax_gt50_percent: document.getElementById('taxGt50').value,
        tax_rot_percent: document.getElementById('taxRot').value,
        tax_rot_max_per_person: document.getElementById('taxRotMax').value,
        tax_moms_percent: document.getElementById('taxMoms').value
    };
    try {
        var r = await fetch('/api/settings.php', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify(data)
        });
        var d = await r.json();
        var status = document.getElementById('taxSaveStatus');
        if(d.success) {
            if(status) { status.textContent = 'Sparat!'; status.style.color = '#059669'; }
            await loadTaxSettings();
            setTimeout(function(){ if(status) status.textContent = ''; }, 2000);
        } else {
            if(status) { status.textContent = 'Fel: ' + (d.error||''); status.style.color = '#ef4444'; }
        }
    } catch(e) {
        var status = document.getElementById('taxSaveStatus');
        if(status) { status.textContent = 'Nätverksfel'; status.style.color = '#ef4444'; }
    }
}