'; } BC.downloadInvoice=function(id){ var acct=BC.state.acct; var inv=acct.invoices.filter(function(x){return x.id===id;})[0]; if(!inv) return; var w=window.open('','_blank'); if(!w){ BC.toast('Autorisez les pop-ups pour télécharger la facture.'); return; } w.document.write(invoiceHTML(inv,acct)); w.document.close(); setTimeout(function(){ w.focus(); w.print(); },350); BC.toast('Facture '+id+' générée. Imprimez ou enregistrez-la en PDF.'); }; BC.downloadAllInvoices=function(){ var acct=BC.state.acct; var w=window.open('','_blank'); if(!w){ BC.toast('Autorisez les pop-ups pour exporter.'); return; } var html=acct.invoices.map(function(inv){ return invoiceHTML(inv,acct).replace(/^[\s\S]*?/,'').replace('',''); }).join('
'); w.document.write('Factures'+html+''); // reuse single-invoice styles by writing a full doc per page instead: w.document.close(); var full='Factures '+acct.name+''; w.document.open(); // Simpler: stitch full styled pages var pages=acct.invoices.map(function(inv,i){ var single=invoiceHTML(inv,acct); var body=single.split('')[1].split('')[0]; var style=single.split('')[0]; return (i===0?'':'')+'
'+body+'
'; }).join(''); w.document.write('Factures'+pages+''); w.document.close(); setTimeout(function(){ w.focus(); w.print(); },400); BC.toast('Export de '+acct.invoices.length+' factures généré.'); }; /* ---- boot ---- On dessine tout de suite avec ce qu'on a (le site doit s'afficher sans attendre le réseau), puis on branche la base et on redessine dès qu'elle a répondu : session restaurée, données du client chargées, stock du locker à jour. */ /* ⚠️ La feuille de style du module réservation n'était posée qu'en ouvrant le devis. Or l'espace client s'en sert aussi — .dash-vide, .rdv-track, .cf-* … Un client qui allait droit à son tableau de bord voyait donc des blocs SANS AUCUN STYLE : l'icône seule sur une ligne, et « Pas encore de carte de fidélitéDix prestations… » collé d'un seul tenant, faute de mise en forme. Elle est posée au démarrage. Le fichier est de toute façon téléchargé et analysé : ça ne coûte qu'une insertion dans le DOM, et plus aucun écran ne dépend du chemin par lequel on y arrive. */ if(BC._injectBookingCSS) BC._injectBookingCSS(); window.addEventListener('hashchange', render); BC.rerender = render; render(); /* Ce que le site a le droit de promettre dépend de ce qui est réellement configuré côté serveur (e-mail seul, ou e-mail + SMS). On le demande une fois, et les textes s'ajustent à la réponse. */ if(BC.notifier && BC.notifier.sonder) BC.notifier.sonder(); /* Idem pour la connexion Google : c'est Supabase qui dit si le fournisseur est activé, pas un drapeau écrit à la main. */ if(BC.auth && BC.auth.sonderFournisseurs) BC.auth.sonderFournisseurs(); /* Les prix que Gabin a changés depuis son espace. Lecture publique, sans session : le site doit afficher le bon tarif à un visiteur qui n'aura jamais de compte. En cas d'échec on garde ceux de data.js — voir app/tarifs.js. */ if(BC.tarifs && BC.tarifs.charger) BC.tarifs.charger(); /* Le mode de réservation, et ce que Gabin a pu y changer. Lecture publique, sans session — et repli sur app/config.js en cas d’échec : une panne ne doit pas changer le fonctionnement du site. */ if(BC.reglages && BC.reglages.charger) BC.reglages.charger(); BC.db.demarrer().then(function(){ render(); if(BC.db.erreur) console.warn('[Better Cleaner] serveur injoignable, repli sur le navigateur :', BC.db.erreur); }); /* ---- cookies ---- Le bandeau a été retiré (voir le commentaire près du ). Le lien « Gérer les cookies » du pied de page mène désormais à la section qui les décrit : c'est la seule chose honnête à offrir quand il n'y a rien à refuser. On efface au passage le choix mémorisé par l'ancien bandeau : il ne servait à rien, il n'a pas à rester dans le navigateur des gens. */ (function(){ try{ localStorage.removeItem('bc-cookie-consent'); }catch(_){} if(window.BC) window.BC.openCookiePrefs = function(){ location.hash = '#/confidentialite'; return false; }; })(); })();