ReloCare
Relocation · Genève
Espace agence
Espace client
ReloCare
Nouveau mot de passe
Clients
Clients actifs
0
CA encaissé
0
Mandats en cours
0
Crédits totaux
0
🔍
Vue d'ensemble
Mandats
Coaching
Crédits
Notes
Solde crédit
Mandats
Coaching
Informations
Sauvegarde automatique
Session coaching
00:00:00
0 min15 min30 min45 min1h00
Facturable · débit crédit client
Sessions enregistrées
Aucune session
📋
Aucun mandat
Mandats ce mois-ci
Tarifs CHF & EUR · modifiables
Coaching & Conseil
Mandats ponctuels
Payé
En attente
💶
Aucune facture
Soldes prépayés · Le timer et les mandats débitent automatiquement
🏠
Aucune annonce
ReloCare
Crédit :
Bonjour !
Solde crédit
Coaching
0h
Mandats réalisés
0
Total consommé
0
Dernières activités
Mes annonces
Suivez vos appartements favoris et échangez avec votre conseillère
🏠
Aucune annonce pour le moment
Services à la carte
Chaque prestation est débitée de votre crédit · Solde :
Coaching & Conseil (au quart d'heure)
Mandats ponctuels
Historique de mon compte
Recharger mon crédit
Paiement sécurisé via Stripe · Minimum 50 CHF/EUR
Solde actuel
Disponible immédiatement après paiement
CHF
Choisir un montant
50
CHF / EUR
100
CHF / EUR
+ 5% offert
200
CHF / EUR
+ 10% offert
Libre
Montant libre
🔒 Sécurisé
ℹ️ En cliquant, vous serez redirigé vers Stripe. Le crédit est ajouté instantanément dès réception du paiement.
Nouveau client
Nouveau mandat
⚡ Le montant sera débité automatiquement du crédit client.
Ajouter du crédit
Nouveau service
Nouvelle facture
function setTab(t){ document.getElementById('lt-a').classList.toggle('active',t==='a'); document.getElementById('lt-c').classList.toggle('active',t==='c'); document.getElementById('lf-a').style.display=t==='a'?'':'none'; document.getElementById('lf-c').style.display=t==='c'?'':'none'; } function loginA(){curU={type:'a'};document.getElementById('ls').style.display='none';document.getElementById('app').classList.add('visible');document.getElementById('av').classList.add('visible');AP('clients');} function loginC(){ var code=document.getElementById('c-code').value.trim().toUpperCase(); var c=db.clients.find(function(x){return (x.cod||'').toUpperCase()===code;}); if(!c){notify('Code introuvable');return;} curU={type:'c',cid:c.id}; document.getElementById('ls').style.display='none'; document.getElementById('app').classList.add('visible'); document.getElementById('cv').classList.add('visible'); renderCV(c.id); } function logout(){curU=null;document.getElementById('app').classList.remove('visible');document.getElementById('av').classList.remove('visible');document.getElementById('cv').classList.remove('visible');document.getElementById('ls').style.display='flex';} function openM(id){ document.getElementById(id).classList.add('open'); if(id==='mm'){fillSel('mm-c');fillMT();} if(id==='mi'){fillSel('iv-c');document.getElementById('iv-dt').value=new Date().toISOString().split('T')[0];} if(id==='mcr'){fillSel('cr-cl');} } function closeM(id){document.getElementById(id).classList.remove('open');} document.querySelectorAll('.mo').forEach(function(o){o.addEventListener('click',function(e){if(e.target===o)o.classList.remove('open');});}); function fillSel(id){var el=document.getElementById(id);if(!el)return;el.innerHTML=''+db.clients.map(function(c){return'';}).join('');} var titles={clients:'Clients',timer:'Timer coaching',mandats:'Mandats',calendrier:'Calendrier',services:'Catalogue de services',facturation:'Facturation',credits:'Crédits clients',cd:''}; var actTpl={clients:'',mandats:'',calendrier:'',facturation:'',credits:''}; var icons={clients:'👤',timer:'⏱',mandats:'📋',calendrier:'📅',services:'🗂',facturation:'💶',credits:'💳'}; function AP(name){ document.querySelectorAll('.panel').forEach(function(p){p.classList.remove('active');}); document.querySelectorAll('.ni').forEach(function(n){n.classList.remove('active');}); var el=document.getElementById('panel-'+name)||document.getElementById('panel-cd'); if(name==='cd'){document.getElementById('panel-cd').classList.add('active');} else{var p=document.getElementById('panel-'+name);if(p)p.classList.add('active');} document.getElementById('a-title').textContent=titles[name]||''; document.getElementById('a-act').innerHTML=actTpl[name]||''; document.querySelectorAll('.ni').forEach(function(n){if(n.querySelector('.nic')&&n.querySelector('.nic').textContent===icons[name])n.classList.add('active');}); if(name==='clients')renderClients(); if(name==='timer'){fillSel('tcl');renderSes();} if(name==='mandats')renderMan(); if(name==='calendrier')renderCal(); if(name==='services')renderSvcs(); if(name==='facturation')renderInv(); if(name==='credits')renderCrAdmin(); } function renderClients(f){ f=f||''; var list=db.clients.filter(function(c){return (c.p+' '+c.n+' '+(c.e||'')).toLowerCase().indexOf(f.toLowerCase())>=0;}); var el=document.getElementById('clients-list'); el.innerHTML=list.length?list.map(function(c){ var cr=c.cr||0;var nm=db.mandats.filter(function(m){return m.cid===c.id;}).length; return '
' +'
'+c.p+' '+c.n+'
' +'
'+(c.e||'—')+' · '+(c.cod||'—')+'
' +''+sL(c.st)+'' +''+c.dev+'' +'
' +'
'+cr+' '+c.dev+'
' +'
'+nm+' mandat'+(nm>1?'s':'')+'
' +'
'; }).join(''):'
👤
Aucun client
'; document.getElementById('st-a').textContent=db.clients.filter(function(c){return c.st==='active';}).length; document.getElementById('st-ca').textContent=db.invoices.filter(function(i){return i.st==='paid';}).reduce(function(s,i){return s+Number(i.a);},0).toFixed(0); document.getElementById('st-m').textContent=db.mandats.filter(function(m){return m.st==='todo';}).length; document.getElementById('st-cr').textContent=db.clients.reduce(function(s,c){return s+(c.cr||0);},0).toFixed(0); } function filterC(f){renderClients(f);} function openD(id){ curC=id;var c=cBy(id); document.getElementById('dn').textContent=c.p+' '+c.n; document.getElementById('dm').textContent=(c.e||'')+( c.tel?' · '+c.tel:'')+( c.vil?' · '+c.vil:''); var b=document.getElementById('db');b.textContent=sL(c.st);b.className='badge b-'+c.st; document.getElementById('dcr').textContent=(c.cr||0)+' '+c.dev; document.getElementById('dnm').textContent=db.mandats.filter(function(m){return m.cid===id;}).length; document.getElementById('dh').textContent=fmtD(db.sessions.filter(function(s){return s.cid===id;}).reduce(function(s,x){return s+x.sec;},0)); document.getElementById('di').innerHTML=[['Devise',c.dev],['Nationalité',c.nat||'—'],['Arrivée',c.arr||'—'],['Code',c.cod||'—']].map(function(kv){return'
'+kv[0]+'
'+kv[1]+'
';}).join(''); document.getElementById('notes').value=c.no||''; renderDM(id);renderDS(id);renderDC(id); swT(0);AP('cd');document.querySelectorAll('.ni').forEach(function(n){n.classList.remove('active');}); } function renderDM(id){var m=db.mandats.filter(function(x){return x.cid===id;});document.getElementById('det-m').innerHTML=m.length?m.map(mRow).join(''):'
📋
Aucun mandat
';} function renderDS(id){var s=db.sessions.filter(function(x){return x.cid===id;});document.getElementById('det-s').innerHTML=s.length?s.map(sRow).join(''):'
Aucune session
';} function renderDC(id){ var c=cBy(id);var h=db.crHist.filter(function(x){return x.cid===id;}); var sol='
Solde actuel'+(c.cr||0)+' '+c.dev+'
'; document.getElementById('det-c').innerHTML=sol+(h.length?h.map(function(x){return'
'+(x.t==='cr'?'💳':'⬇️')+'
'+(x.no||'—')+'
'+new Date(x.dt).toLocaleDateString('fr-FR')+(x.r?' · '+x.r:'')+'
'+(x.t==='cr'?'+':'-')+x.a+' '+x.d+'
';}).join(''):'
💳
Aucun mouvement
'); } function swT(i){document.querySelectorAll('#panel-cd .tab').forEach(function(t,j){t.classList.toggle('active',i===j);});document.querySelectorAll('.tc').forEach(function(t,j){t.classList.toggle('active',i===j);});} function saveN(){if(!curC)return;var c=cBy(curC);if(c){c.no=document.getElementById('notes').value;sv();}} function editCC(){editC(curC);} function delCC(){if(!confirm('Supprimer ce client ?'))return;db.clients=db.clients.filter(function(c){return c.id!==curC;});db.mandats=db.mandats.filter(function(m){return m.cid!==curC;});db.sessions=db.sessions.filter(function(s){return s.cid!==curC;});db.crHist=db.crHist.filter(function(h){return h.cid!==curC;});sv();AP('clients');notify('Client supprimé');} function addMF(){openM('mm');setTimeout(function(){fillSel('mm-c');fillMT();document.getElementById('mm-c').value=curC;var c=cBy(curC);if(c)document.getElementById('mm-d').value=c.dev;},10);} function timerF(){AP('timer');setTimeout(function(){fillSel('tcl');document.getElementById('tcl').value=curC;tRes();},50);} function addCrF(){openM('mcr');setTimeout(function(){document.getElementById('cr-cl').value=curC;var c=cBy(curC);if(c)document.getElementById('cr-d').value=c.dev;},10);} function saveC(){ var eid=document.getElementById('mc-id').value; var c={id:eid||uid(),p:document.getElementById('mc-p').value.trim(),n:document.getElementById('mc-n').value.trim(),e:document.getElementById('mc-e').value.trim(),tel:document.getElementById('mc-tel').value.trim(),dev:document.getElementById('mc-dev').value,st:document.getElementById('mc-st').value,nat:document.getElementById('mc-nat').value.trim(),arr:document.getElementById('mc-arr').value,vil:document.getElementById('mc-vil').value.trim(),cod:document.getElementById('mc-cod').value.trim(),cr:eid?(cBy(eid)?cBy(eid).cr:0):0,no:eid?(cBy(eid)?cBy(eid).no:''):''}; if(!c.p&&!c.n){alert('Prénom ou nom requis.');return;} if(eid){var i=db.clients.findIndex(function(x){return x.id===eid;});if(i>=0)db.clients[i]=c;}else db.clients.push(c); sv();closeM('mc');clrCF();renderClients();notify(eid?'Client modifié ✓':'Client créé ✓'); } function editC(id){var c=cBy(id);if(!c)return;document.getElementById('mc-t').textContent='Modifier le client';document.getElementById('mc-id').value=c.id;document.getElementById('mc-p').value=c.p;document.getElementById('mc-n').value=c.n;document.getElementById('mc-e').value=c.e||'';document.getElementById('mc-tel').value=c.tel||'';document.getElementById('mc-nat').value=c.nat||'';document.getElementById('mc-arr').value=c.arr||'';document.getElementById('mc-vil').value=c.vil||'';document.getElementById('mc-cod').value=c.cod||'';document.getElementById('mc-dev').value=c.dev;document.getElementById('mc-st').value=c.st;openM('mc');} function clrCF(){['mc-p','mc-n','mc-e','mc-tel','mc-nat','mc-arr','mc-vil','mc-cod'].forEach(function(id){document.getElementById(id).value='';});document.getElementById('mc-id').value='';document.getElementById('mc-t').textContent='Nouveau client';} function fillMT(){document.getElementById('mm-t').innerHTML=''+db.services.filter(function(s){return s.cat==='mandat';}).map(function(s){return'';}).join('');} function fMP(){var s=db.services.find(function(x){return x.id===document.getElementById('mm-t').value;});var c=cBy(document.getElementById('mm-c').value);if(!s)return;var d=c?c.dev:'CHF';document.getElementById('mm-p').value=d==='CHF'?s.chf:s.eur;document.getElementById('mm-d').value=d;} function saveM(){ var m={id:uid(),cid:document.getElementById('mm-c').value,sid:document.getElementById('mm-t').value,prix:Number(document.getElementById('mm-p').value),dev:document.getElementById('mm-d').value,date:document.getElementById('mm-dt').value,notes:document.getElementById('mm-no').value,st:document.getElementById('mm-st').value,cAt:new Date().toISOString()}; if(!m.cid){alert('Client requis.');return;} db.mandats.unshift(m); var c=cBy(m.cid);if(c&&m.prix>0){c.cr=Math.max(0,(c.cr||0)-m.prix);var sv2=db.services.find(function(x){return x.id===m.sid;});db.crHist.unshift({id:uid(),cid:m.cid,t:'deb',a:m.prix,d:m.dev,no:sv2?sv2.name:'Mandat',r:'AUTO-'+m.id.substr(0,6),dt:new Date().toISOString()});} sv();closeM('mm');renderMan();renderCal&&typeof renderCal==='function'&&AP('mandats')==null;notify('Mandat créé · '+m.prix+' '+m.dev+' débité'); } function mRow(m){var c=cBy(m.cid);var s=db.services.find(function(x){return x.id===m.sid;});return'
'+(s?s.icon:'📋')+'
'+(s?s.name:'Mission')+'
'+(c?c.p+' '+c.n:'—')+' · '+(m.date||'—')+'
'+(m.notes?'
'+m.notes+'
':'')+'
'+m.prix+' '+m.dev+'
'+msL(m.st)+'
';} function renderMan(){var el=document.getElementById('man-list');if(!el)return;el.innerHTML=db.mandats.length?db.mandats.map(mRow).join(''):'
📋
Aucun mandat
';} function delMan(id){if(!confirm('Supprimer ?'))return;db.mandats=db.mandats.filter(function(m){return m.id!==id;});sv();renderMan();if(document.getElementById('panel-calendrier').classList.contains('active'))renderCal();} // TIMER function togT(){if(tRun){clearInterval(tInt);tRun=false;document.getElementById('tbtn').textContent='▶ Reprendre';document.getElementById('tsave').style.display='';document.getElementById('tdisp').classList.remove('run');}else{tRun=true;document.getElementById('tbtn').textContent='⏸ Pause';document.getElementById('tsave').style.display='none';document.getElementById('tdisp').classList.add('run');tInt=setInterval(function(){tSec++;document.getElementById('tdisp').textContent=fmtT(tSec);updQP();tRes();},1000);}} function rstT(){clearInterval(tInt);tRun=false;tSec=0;document.getElementById('tdisp').textContent='00:00:00';document.getElementById('tdisp').classList.remove('run');document.getElementById('tbtn').textContent='▶ Démarrer';document.getElementById('tsave').style.display='none';updQP();tRes();} function updQP(){var qs=[0,900,1800,2700,3600];document.querySelectorAll('.qp').forEach(function(p,i){p.classList.toggle('active',tSec>=qs[i]&&(i===qs.length-1||tSec0){c.cr=Math.max(0,(c.cr||0)-amt);db.crHist.unshift({id:uid(),cid:cid,t:'deb',a:amt,d:d,no:'Coaching '+fmtD(tSec),r:'SES-'+ses.id.substr(0,6),dt:new Date().toISOString()});}sv();rstT();renderSes();notify('Session · '+amt+' '+d+' débité');} function sRow(s){var c=cBy(s.cid);return'
'+fmtT(s.sec)+' · '+s.q+' quart'+(s.q>1?'s':'')+" d'heure
"+(c?c.p+' '+c.n:'—')+' · '+new Date(s.dt).toLocaleDateString('fr-FR')+'
'+s.a+' '+s.d+'
';} function renderSes(){var el=document.getElementById('ses-list');if(!el)return;el.innerHTML=db.sessions.length?db.sessions.map(sRow).join(''):'
Aucune session
';} function delSes(id){db.sessions=db.sessions.filter(function(s){return s.id!==id;});sv();renderSes();} // SERVICES function renderSvcs(){['sv-coa','sv-man'].forEach(function(eid,i){var cat=i===0?'coaching':'mandat';var el=document.getElementById(eid);if(!el)return;var list=db.services.filter(function(s){return s.cat===cat;});el.innerHTML=list.map(function(s){return'
'+s.icon+'
'+s.name+'
'+s.desc+'
'+s.chf+' CHF '+s.unit+'
'+s.eur+' EUR
';}).join('');});} function edSv(id){var s=db.services.find(function(x){return x.id===id;});if(!s)return;var c=prompt('CHF pour "'+s.name+'":',s.chf);if(c===null)return;var e=prompt('EUR:',s.eur);if(e===null)return;s.chf=Number(c);s.eur=Number(e);sv();renderSvcs();} function delSv(id){if(!confirm('Supprimer ?'))return;db.services=db.services.filter(function(s){return s.id!==id;});sv();renderSvcs();} function saveSv(){var s={id:uid(),name:document.getElementById('sv-n').value.trim(),desc:document.getElementById('sv-d').value.trim(),icon:document.getElementById('sv-i').value||'📌',chf:Number(document.getElementById('sv-ch').value),eur:Number(document.getElementById('sv-eu').value),cat:document.getElementById('sv-c').value,unit:document.getElementById('sv-u').value};if(!s.name){alert('Nom requis.');return;}db.services.push(s);sv();closeM('ms');renderSvcs();notify('Service ajouté');} // INVOICES function saveIv(){var inv={id:uid(),num:'FAC-'+String(db.invoices.length+1).padStart(3,'0'),cid:document.getElementById('iv-c').value,desc:document.getElementById('iv-d').value,a:Number(document.getElementById('iv-a').value),dev:document.getElementById('iv-dev').value,dt:document.getElementById('iv-dt').value,st:document.getElementById('iv-st').value,cAt:new Date().toISOString()};if(!inv.cid){alert('Client requis.');return;}if(!inv.a){alert('Montant requis.');return;}db.invoices.unshift(inv);sv();closeM('mi');renderInv();notify('Facture '+inv.num+' créée');} function renderInv(){var el=document.getElementById('inv-list');if(!el)return;if(!db.invoices.length){el.innerHTML='
💶
Aucune facture
';document.getElementById('ip').textContent='0';document.getElementById('iu').textContent='0';return;}el.innerHTML=db.invoices.map(function(inv){var c=cBy(inv.cid);return'
'+inv.num+'
'+(c?c.p+' '+c.n:'—')+'
'+(inv.desc||'')+'
'+(inv.dt||'—')+'
'+inv.a+' '+inv.dev+'
'+isL(inv.st)+'
'+(inv.st!=='paid'?'':'')+'
';}).join('');document.getElementById('ip').textContent=db.invoices.filter(function(i){return i.st==='paid';}).reduce(function(s,i){return s+Number(i.a);},0).toFixed(0);document.getElementById('iu').textContent=db.invoices.filter(function(i){return i.st==='unpaid';}).reduce(function(s,i){return s+Number(i.a);},0).toFixed(0);} function mPaid(id){var i=db.invoices.find(function(x){return x.id===id;});if(i){i.st='paid';sv();renderInv();notify('Facture payée ✓');}} function delIv(id){if(!confirm('Supprimer ?'))return;db.invoices=db.invoices.filter(function(i){return i.id!==id;});sv();renderInv();} // CREDITS ADMIN function saveCr(){var cid=document.getElementById('cr-cl').value;var c=cBy(cid);if(!cid){alert('Client requis.');return;}var amt=Number(document.getElementById('cr-a').value);if(!amt||amt<1){alert('Montant invalide.');return;}var d=document.getElementById('cr-d').value;c.cr=(c.cr||0)+amt;db.crHist.unshift({id:uid(),cid:cid,t:'cr',a:amt,d:d,no:document.getElementById('cr-no').value||'Recharge crédit',r:document.getElementById('cr-r').value||'',dt:new Date().toISOString()});sv();closeM('mcr');renderCrAdmin();notify('+'+amt+' '+d+' crédité · '+c.p+' '+c.n);if(curC===cid)renderDC(cid);} function renderCrAdmin(){var el=document.getElementById('cr-list');if(!el)return;el.innerHTML=db.clients.length?db.clients.map(function(c){var cr=c.cr||0;var pct=Math.min(100,cr/500*100);return'
'+c.p+' '+c.n+'
'+(c.cod||'—')+'
'+cr+' '+c.dev+''+(cr<50?'Faible':'OK')+'
';}).join(''):'
💳
Aucun client
';} function qCr(id){openM('mcr');setTimeout(function(){document.getElementById('cr-cl').value=id;var c=cBy(id);if(c)document.getElementById('cr-d').value=c.dev;},10);} // CALENDAR function calNav(d){calM+=d;if(calM>11){calM=0;calY++;}if(calM<0){calM=11;calY--;}renderCal();} function calToday(){calY=new Date().getFullYear();calM=new Date().getMonth();renderCal();} function isTod(d){var t=new Date();return d.getDate()===t.getDate()&&d.getMonth()===t.getMonth()&&d.getFullYear()===t.getFullYear();} function renderCal(){ document.getElementById('cal-lbl').textContent=MFR[calM]+' '+calY; document.getElementById('cal-hd').innerHTML=DFR.map(function(d){return'
'+d+'
';}).join(''); var today=new Date(); var first=new Date(calY,calM,1); var startDow=(first.getDay()+6)%7; var dim=new Date(calY,calM+1,0).getDate(); var dip=new Date(calY,calM,0).getDate(); var total=Math.ceil((startDow+dim)/7)*7; var evMap={}; db.mandats.forEach(function(m){if(!m.date)return;var d=new Date(m.date);if(d.getFullYear()===calY&&d.getMonth()===calM){var k=d.getDate();if(!evMap[k])evMap[k]=[];var c=cBy(m.cid);var s=db.services.find(function(x){return x.id===m.sid;});evMap[k].push({st:m.st,lbl:(s?s.icon:'📋')+' '+(c?c.p:'')+(s?' · '+s.name:''),id:m.id});}}); db.sessions.forEach(function(s){var d=new Date(s.dt);if(d.getFullYear()===calY&&d.getMonth()===calM){var k=d.getDate();if(!evMap[k])evMap[k]=[];var c=cBy(s.cid);evMap[k].push({st:'session',lbl:'⏱ '+(c?c.p:'Coaching')+' · '+fmtD(s.sec),id:null});}}); var html=''; for(var i=0;i=startDow+dim){dn=i-(startDow+dim)+1;om=true;} else dn=i-startDow+1; var isT=!om&&isTod(new Date(calY,calM,dn)); var evs=(!om&&evMap[dn])||[]; var br=(i+1)%7===0?'border-right:none;':''; html+='
'; html+='
'+dn+'
'; evs.slice(0,3).forEach(function(ev){html+='
'+ev.lbl+'
';}); if(evs.length>3)html+='
+'+(evs.length-3)+' autre'+(evs.length-3>1?'s':'')+'
'; html+='
'; } document.getElementById('cal-grid').innerHTML=html; var mm=db.mandats.filter(function(m){if(!m.date)return false;var d=new Date(m.date);return d.getFullYear()===calY&&d.getMonth()===calM;}).sort(function(a,b){return new Date(a.date)-new Date(b.date);}); var upEl=document.getElementById('cal-up'); if(!mm.length){upEl.innerHTML='
📅
Aucun mandat ce mois-ci
';return;} upEl.innerHTML=mm.map(function(m){ var c=cBy(m.cid);var s=db.services.find(function(x){return x.id===m.sid;});var d=new Date(m.date);var isPast=d' +'
' +'
'+pad(d.getDate())+'
' +'
'+MFR[d.getMonth()].substr(0,3)+'
' +'
'+(s?s.icon:'📋')+'
' +'
'+(s?s.name:'Mission')+'
' +'
'+(c?c.p+' '+c.n:'—')+(m.notes?' · '+m.notes:'')+'
' +'
'+m.prix+' '+m.dev+'
' +''+msL(m.st)+'
' +''; }).join(''); } // CLIENT VIEW function renderCV(cid){ var c=cBy(cid);if(!c)return; var cr=c.cr||0; document.getElementById('cc-top').textContent=cr+' '+c.dev; document.getElementById('cc-big').textContent=cr+' '+c.dev; document.getElementById('wn').textContent='Bonjour, '+c.p+' !'; document.getElementById('wsub').textContent=c.cod+' · '+(c.vil||'')+' · '+c.dev; document.getElementById('rc').textContent=cr; document.getElementById('rd').textContent=c.dev; document.getElementById('cc-svc').textContent=cr+' '+c.dev; var m=db.mandats.filter(function(x){return x.cid===cid;}); document.getElementById('cs-m').textContent=m.filter(function(x){return x.st==='done'||x.st==='billed';}).length; document.getElementById('cs-h').textContent=fmtD(db.sessions.filter(function(s){return s.cid===cid;}).reduce(function(s,x){return s+x.sec;},0)); document.getElementById('cs-t').textContent=db.crHist.filter(function(x){return x.cid===cid&&x.t==='deb';}).reduce(function(s,x){return s+x.a;},0).toFixed(0)+' '+c.dev; var recent=[].concat(db.sessions.filter(function(s){return s.cid===cid;}).map(function(s){return Object.assign({},s,{_t:'s'});}),m.map(function(x){return Object.assign({},x,{_t:'m'});})).sort(function(a,b){return new Date(b.dt||b.cAt)-new Date(a.dt||a.cAt);}).slice(0,5); document.getElementById('c-rec').innerHTML=recent.length?recent.map(function(x){if(x._t==='s')return'
Coaching · '+fmtT(x.sec)+'
'+new Date(x.dt).toLocaleDateString('fr-FR')+'
-'+x.a+' '+x.d+'
';var s=db.services.find(function(sv){return sv.id===x.sid;});return'
'+(s?s.icon:'📋')+'
'+(s?s.name:'Mission')+'
'+new Date(x.date||x.cAt).toLocaleDateString('fr-FR')+'
'+msL(x.st)+'
-'+x.prix+' '+x.dev+'
';}).join(''):'
📭
Aucune activité
'; ['csv-coa','csv-man'].forEach(function(eid,i){var cat=i===0?'coaching':'mandat';var el=document.getElementById(eid);if(!el)return;var list=db.services.filter(function(s){return s.cat===cat;});el.innerHTML=list.map(function(s){var price=c.dev==='CHF'?s.chf:s.eur;var ok=(c.cr||0)>=price;return'
'+s.icon+'
'+s.name+'
'+s.desc+'
'+price+' '+c.dev+'
'+s.unit+'
'+(ok?'✓ Disponible':'✗ Insuffisant')+'
';}).join('');}); var h=db.crHist.filter(function(x){return x.cid===cid;});document.getElementById('c-hist').innerHTML=h.length?h.map(function(x){return'
'+(x.t==='cr'?'💳':'⬇️')+'
'+(x.no||'—')+'
'+new Date(x.dt).toLocaleDateString('fr-FR')+(x.r?' · '+x.r:'')+'
'+(x.t==='cr'?'+':'-')+x.a+' '+x.d+'
';}).join(''):'
📋
Aucun mouvement
'; } function CP(name){ document.querySelectorAll('.cp').forEach(function(p){p.classList.remove('active');}); document.querySelectorAll('.cni').forEach(function(n){n.classList.remove('active');}); var el=document.getElementById('cp-'+name);if(el)el.classList.add('active'); var map={dash:0,annonces:1,svcs:2,hist:3,rech:4}; var navs=document.querySelectorAll('.cni'); if(map[name]!==undefined&&navs[map[name]])navs[map[name]].classList.add('active'); if(curU){ renderCV(curU.cid); if(name==='annonces')renderClientAnnonces(curU.cid); } } // ============================================================ // PHOTOS ANNONCES (Supabase Storage) // ============================================================ async function handlePhotoUpload(annonceId,input){ var files=input.files;if(!files.length)return; showLoading(true); for(var i=0;i1?'s':'')+" ajoutée"+(files.length>1?'s':'')+' !'); } async function delPhoto(id,url){ if(!confirm('Supprimer cette photo ?'))return; var parts=url.split('/annonce-photos/'); if(parts[1]){await supa.storage.from('annonce-photos').remove([decodeURIComponent(parts[1])]);} await sbDelete('annonce_photos',id); db.photos=db.photos.filter(function(p){return p.id!==id;}); renderAnnonces(); if(curU&&curU.type==='c')renderClientAnnonces(curU.cid); } // ============================================================ // RAPPORT D'ACTIVITÉ PDF // ============================================================ function genererRapport(cid,sendEmail){ var c=cBy(cid);if(!c)return; var sessions=db.sessions.filter(function(s){return s.cid===cid;}); var mandats=db.mandats.filter(function(m){return m.cid===cid;}); var anns=db.annonces.filter(function(a){return a.client_id===cid;}); var credits=db.crHist.filter(function(h){return h.cid===cid;}); if(sendEmail){envoyerRapportEmail(c,sessions,mandats,anns,credits);return;} var doc=new window.jspdf.jsPDF({orientation:'portrait',unit:'mm',format:'a4'}); var pageW=210;var mg=18;var y=20; // Header noir doc.setFillColor(17,17,17);doc.rect(0,0,pageW,32,'F'); doc.setTextColor(255,255,255);doc.setFont('helvetica','bold');doc.setFontSize(20);doc.text('ReloCare',mg,14); doc.setFont('helvetica','normal');doc.setFontSize(9);doc.setTextColor(180,180,180);doc.text("Rapport d'activite · Geneve",mg,21); doc.setTextColor(255,255,255);doc.text('Genere le '+new Date().toLocaleDateString('fr-FR'),pageW-mg,21,{align:'right'}); y=42; // Client doc.setFillColor(240,239,237);doc.roundedRect(mg,y,pageW-mg*2,22,3,3,'F'); doc.setTextColor(17,17,17);doc.setFont('helvetica','bold');doc.setFontSize(14);doc.text(c.p+' '+c.n,mg+6,y+9); doc.setFont('helvetica','normal');doc.setFontSize(9);doc.setTextColor(120,120,120); doc.text([(c.e||''),(c.nat||''),(c.vil||''),(c.cod||'')].filter(Boolean).join(' · '),mg+6,y+16);y+=30; // Stats var totalSec=sessions.reduce(function(s,x){return s+x.sec;},0); var totalDeb=credits.filter(function(h){return h.t==='deb';}).reduce(function(s,h){return s+h.a;},0); var mdone=mandats.filter(function(m){return m.st==='done'||m.st==='billed';}).length; var stats=[['Coaching',fmtD(totalSec)],['Mandats',String(mdone)],['Annonces',String(anns.length)],['Consomme',totalDeb.toFixed(0)+' '+c.dev]]; var sw=(pageW-mg*2)/4; stats.forEach(function(s,i){var x=mg+i*sw;doc.setFillColor(255,255,255);doc.setDrawColor(220,218,214);doc.roundedRect(x,y,sw-3,18,2,2,'FD');doc.setTextColor(120,120,120);doc.setFont('helvetica','normal');doc.setFontSize(7);doc.text(s[0],x+sw/2-1.5,y+6,{align:'center'});doc.setTextColor(192,57,43);doc.setFont('helvetica','bold');doc.setFontSize(12);doc.text(s[1],x+sw/2-1.5,y+14,{align:'center'});});y+=26; // Section title helper function sec(t){y+=4;doc.setFillColor(192,57,43);doc.rect(mg,y,3,6,'F');doc.setTextColor(17,17,17);doc.setFont('helvetica','bold');doc.setFontSize(11);doc.text(t,mg+6,y+5);y+=12;} function row(cols,ws,hdr,yp){var x=mg;doc.setFillColor(hdr?240:255,hdr?239:255,hdr?237:255);doc.rect(mg,yp,pageW-mg*2,6,'F');cols.forEach(function(col,i){doc.setTextColor(hdr?17:70,hdr?17:70,hdr?17:70);doc.setFont('helvetica',hdr?'bold':'normal');doc.setFontSize(8);doc.text(String(col||'—').substr(0,Math.floor(ws[i]/2.2)),x+2,yp+4.2);x+=ws[i];});doc.setDrawColor(230,228,225);doc.line(mg,yp+6,pageW-mg,yp+6);} if(sessions.length){sec('Sessions de coaching');row(['Date','Duree','Quarts','Montant'],[35,35,35,45],true,y);y+=6;sessions.slice(0,15).forEach(function(s){if(y>265){doc.addPage();y=20;}row([new Date(s.dt).toLocaleDateString('fr-FR'),fmtD(s.sec),s.q+'x15min',s.a+' '+s.d],[35,35,35,45],false,y);y+=6;});y+=4;} if(mandats.length){if(y>230){doc.addPage();y=20;}sec('Mandats');row(['Date','Service','Statut','Montant'],[30,75,30,30],true,y);y+=6;mandats.slice(0,15).forEach(function(m){if(y>265){doc.addPage();y=20;}var sv=db.services.find(function(x){return x.id===m.sid;});row([m.date||'—',(sv?sv.name:'Mission'),(msL(m.st)),m.prix+' '+m.dev],[30,75,30,30],false,y);y+=6;});y+=4;} if(anns.length){if(y>220){doc.addPage();y=20;}sec('Annonces immobilieres suivies');row(['Titre','Adresse','Prix','Statut'],[55,55,25,35],true,y);y+=6;anns.slice(0,12).forEach(function(a){if(y>265){doc.addPage();y=20;}var stl=(annSt[a.statut]||{label:'—'}).label;row([(a.titre||'—'),(a.adresse||'—'),(a.prix||'—'),stl],[55,55,25,35],false,y);y+=6;});y+=4;} if(credits.length){if(y>220){doc.addPage();y=20;}sec('Historique credits');row(['Date','Description','Reference','Montant'],[30,70,35,30],true,y);y+=6;credits.slice(0,15).forEach(function(h){if(y>265){doc.addPage();y=20;}row([new Date(h.dt).toLocaleDateString('fr-FR'),(h.no||'—'),(h.r||'—'),(h.t==='cr'?'+':'-')+h.a+' '+h.d],[30,70,35,30],false,y);y+=6;});} // Footer var pages=doc.getNumberOfPages(); for(var pi=1;pi<=pages;pi++){doc.setPage(pi);doc.setFillColor(240,239,237);doc.rect(0,285,pageW,12,'F');doc.setTextColor(120,120,120);doc.setFont('helvetica','normal');doc.setFontSize(8);doc.text('ReloCare · Agence de relocation · Geneve · apprelocare.com',mg,292);doc.text('Page '+pi+'/'+pages,pageW-mg,292,{align:'right'});} doc.save('Rapport-ReloCare-'+c.p+'-'+c.n+'-'+new Date().toISOString().split('T')[0]+'.pdf'); notify('✓ Rapport PDF telecharge !'); } async function envoyerRapportEmail(c,sessions,mandats,anns,credits){ if(!c.e){notify("Pas d'email pour ce client");return;} var totalSec=sessions.reduce(function(s,x){return s+x.sec;},0); var totalDeb=credits.filter(function(h){return h.t==='deb';}).reduce(function(s,h){return s+h.a;},0); var mdone=mandats.filter(function(m){return m.st==='done'||m.st==='billed';}).length; showLoading(true); try{ await fetch('/.netlify/functions/send-notification',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({type:'rapport_activite',to:c.e,clientName:c.p+' '+c.n,stats:{coaching:fmtD(totalSec),mandats:String(mdone),annonces:String(anns.length),debit:totalDeb.toFixed(0)+' '+c.dev},mandats:mandats.slice(0,10).map(function(m){var sv=db.services.find(function(x){return x.id===m.sid;});return{date:m.date||'—',service:sv?sv.name:'Mission',statut:msL(m.st),montant:m.prix+' '+m.dev};}),sessions:sessions.slice(0,10).map(function(s){return{date:new Date(s.dt).toLocaleDateString('fr-FR'),duree:fmtD(s.sec),montant:s.a+' '+s.d};}),annonces_list:anns.slice(0,8).map(function(a){return{titre:a.titre||'—',adresse:a.adresse||'—',statut:(annSt[a.statut]||{label:'—'}).label};})})}); notify('✓ Rapport envoye a '+c.e+' !'); }catch(e){notify('Erreur: '+e.message);} showLoading(false); } // ============================================================ // INIT // ============================================================ checkSession();