LYSTÉ
— Notre projet —
Quand la production trouve son rythme · Accès sécurisé

🔒 Connexion

ou
🔑 Mot de passe oublié / Réinitialiser
LYSTÉ © 2026 — Accès réservé aux employés autorisés

Nouvel événement

Nouvelle tâche — Pilote

Nouveau client

📌 Progression de production
Étape actuelle
📄 Informations
👤 Responsables par poste
💬 Notes du projet
☐ Sous-tâches

Nouvelle mission — Focus

Ajouter projet au Rythme

Nouvelle soumission

'; }).join(''):'
'+(searchQuery?'Aucun r\u00e9sultat':'Aucun \u00e9v\u00e9nement cette semaine')+'
'; } function fES(id){ var s=document.getElementById(id);var c=s.value; s.innerHTML=''+D.emps.map(function(e){return '';}).join(''); if(c)s.value=c; } function openEM(){fES('ee');if(!document.getElementById('ed').value)document.getElementById('ed').value=fd(T);document.getElementById('eovl').classList.add('on');} function closeEM(){document.getElementById('eovl').classList.remove('on');} function saveEv(){ var t=document.getElementById('et').value.trim();if(!t)return; D.events.push({id:D.nid++,title:t,type:document.getElementById('ety').value,date:document.getElementById('ed').value,time:document.getElementById('eh').value,emp:document.getElementById('ee').value}); document.getElementById('et').value='';sv();closeEM(); if(cTab==='cal')rCal();else if(cTab==='dash')rDash();else if(cTab==='rh')rRH();else if(cTab==='soumissions')rSoumissions(); } function openTM(){fES('te2');document.getElementById('td').value=fd(ad(T,3));document.getElementById('tovl').classList.add('on');} function closeTM(){document.getElementById('tovl').classList.remove('on');} function saveTk(){ var t=document.getElementById('tt').value.trim();if(!t)return; D.tasks.push({id:D.nid++,title:t,cat:document.getElementById('tc2').value,prio:document.getElementById('tp').value,emp:document.getElementById('te2').value,due:document.getElementById('td').value,done:false,subtasks:[],msgs:[]}); document.getElementById('tt').value='';sv();closeTM();rRythme(); } function addEmp(){ var n=prompt('Nom complet :');if(!n||!n.trim())return; var r=prompt('R\u00f4le / poste :'); D.emps.push({id:D.nid++,name:n.trim(),role:r||'',c:D.emps.length%ABG.length}); sv();rRH(); } // ---- SOUMISSIONS ---- var soumStatLabel={envoyee:'Envoy\u00e9e',en_attente:'En attente',acceptee:'Accept\u00e9e \u2713',refusee:'Refus\u00e9e',expiree:'Expir\u00e9e'}; var soumStatClass={envoyee:'p-blu',en_attente:'p-amb',acceptee:'p-grn',refusee:'p-red2',expiree:'b-n'}; function rSoumissions(){ fES('sresp'); var grid=document.getElementById('soum-grid'); if(!D.soumissions||!D.soumissions.length){ grid.innerHTML='
Aucune soumission \u2014 cliquez + Soumission pour commencer.
'; return; } D.soumissions.sort(function(a,b){return a.num=0?ABG[D.emps[idx].c%ABG.length]:ABG[0]; var fg=idx>=0?AFG[D.emps[idx].c%AFG.length]:AFG[0]; var sc=soumStatClass[s.statut]||'b-n'; var sl=soumStatLabel[s.statut]||s.statut; var montant=s.montant?Number(s.montant).toLocaleString('fr-CA',{style:'currency',currency:'CAD',maximumFractionDigits:0}):''; return '
'+ '
'+ '
'+ '
'+esc(s.num)+'
'+ '
'+esc(s.nom)+'
'+ '
'+ ''+sl+''+ '
'+ (s.type?'
'+esc(s.type)+'

':'')+ (montant?'
'+montant+'
':'')+ (s.notes?'
'+esc(s.notes)+'
':'')+ '
'+ (s.exp?'Exp. '+fds(s.exp)+'':'')+ '
'+ (s.resp?'
'+ini(s.resp)+'
'+esc(s.resp)+'
':'')+ '
'; }).join(''); } function openSM(){ fES('sresp'); var d=new Date(T);d.setDate(d.getDate()+30); document.getElementById('sexp').value=fd(d); document.getElementById('sovl').classList.add('on'); } function closeSM(){document.getElementById('sovl').classList.remove('on');} function saveSoum(){ var num=document.getElementById('snum').value.trim(); var nom=document.getElementById('snom').value.trim(); if(!num||!nom)return; if(!D.soumissions)D.soumissions=[]; D.soumissions.push({ id:D.nid++,num:num,nom:nom, type:document.getElementById('stype').value, montant:parseFloat(document.getElementById('smontant').value)||0, statut:document.getElementById('sstat').value, resp:document.getElementById('sresp').value, exp:document.getElementById('sexp').value, notes:document.getElementById('snotes').value.trim() }); document.getElementById('snum').value=''; document.getElementById('snom').value=''; document.getElementById('smontant').value=''; document.getElementById('snotes').value=''; sv();closeSM();rSoumissions(); } // ── RECHERCHE GLOBALE ───────────────────────────────────────────────── var searchQuery = ''; function doSearch(q) { searchQuery = q.trim().toLowerCase(); var clearBtn = document.getElementById('search-clear'); var countLbl = document.getElementById('search-count'); clearBtn.style.display = searchQuery ? 'inline-block' : 'none'; if(!searchQuery){ countLbl.textContent=''; } // Rafraîchir l'onglet courant refreshCurrent(); } function clearSearch() { document.getElementById('global-search').value = ''; searchQuery = ''; document.getElementById('search-clear').style.display='none'; document.getElementById('search-count').textContent=''; refreshCurrent(); } function refreshCurrent() { if(cTab==='dash')rDash(); else if(cTab==='cal')rCal(); else if(cTab==='rythme')rRythme(); else if(cTab==='commandes')rClient(); else if(cTab==='soumissions')rSoumissions(); else if(cTab==='rh')rRH(); } function matchSearch(fields) { if(!searchQuery) return true; return fields.some(function(f){ return f&&String(f).toLowerCase().indexOf(searchQuery)>=0; }); } function showCount(n, total) { var lbl = document.getElementById('search-count'); if(searchQuery) lbl.textContent = n+' / '+total; else lbl.textContent = ''; } // doLogout géré par le nouveau système de connexion // ── CONNEXION ──────────────────────────────────────────────────────────── var LYSTE_USERS = { mario: 'lyste2026', karine: 'lyste2026', felix: 'lyste2026', fanny: 'lyste2026', megane: 'lyste2026', karinep: 'lyste2026', matiale: 'lyste2026', benoit: 'lyste2026', sonia: 'lyste2026' }; var LYSTE_NOMS = { mario:'Mario', karine:'Karine L.', felix:'F\u00e9lix', fanny:'Fanny', megane:'M\u00e9gane', karinep:'Karine P.', matiale:'Matiale', benoit:'Beno\u00eet', sonia:'Sonia' }; var _lCurrentUser = null; // V\u00e9rifier session existante (function(){ try { var s = localStorage.getItem('lyste_session'); if(s) { var sess = JSON.parse(s); if(sess && sess.expiry > Date.now()) { _lCurrentUser = {username: sess.username, nom: sess.nom}; ouvrirApp(sess.nom); } } } catch(e) {} })(); function lLogin() { var un = document.getElementById('lusername').value; var pw = document.getElementById('lpassword').value; var err = document.getElementById('lerr-login'); err.style.display = 'none'; if(!un) { err.textContent = 'Veuillez s\u00e9lectionner votre nom.'; err.style.display = 'block'; return; } if(!pw) { err.textContent = 'Veuillez entrer votre mot de passe.'; err.style.display = 'block'; return; } // V\u00e9rifier mot de passe (localStorage ou par d\u00e9faut) var mdpSauve = localStorage.getItem('lyste_mp_' + un); var mdpValide = mdpSauve || LYSTE_USERS[un]; if(!mdpValide || pw !== mdpValide) { err.textContent = 'Mot de passe incorrect. Essayez lyste2026'; err.style.display = 'block'; document.getElementById('lpassword').value = ''; return; } // Connexion r\u00e9ussie var nom = LYSTE_NOMS[un] || un; _lCurrentUser = {username: un, nom: nom}; // Sauvegarder session 8h localStorage.setItem('lyste_session', JSON.stringify({ username: un, nom: nom, expiry: Date.now() + (8 * 60 * 60 * 1000) })); ouvrirApp(nom); } function ouvrirApp(nom) { document.getElementById('login-screen').style.display = 'none'; document.getElementById('app').style.display = 'block'; var lbl = document.getElementById('current-user-lbl'); if(lbl) lbl.textContent = nom; rDash(); } function doLogout() { localStorage.removeItem('lyste_session'); _lCurrentUser = null; document.getElementById('login-screen').style.display = 'flex'; document.getElementById('app').style.display = 'none'; document.getElementById('lpassword').value = ''; document.getElementById('lusername').value = ''; document.getElementById('lerr-login').style.display = 'none'; } function lOuvrirReinit() { document.getElementById('lscreen-login').style.display = 'none'; document.getElementById('lscreen-reinit').style.display = 'block'; } function lRetourLogin() { document.getElementById('lscreen-reinit').style.display = 'none'; document.getElementById('lscreen-login').style.display = 'block'; } function lConfirmerReinit() { alert('Contactez votre administrateur pour r\u00e9initialiser votre mot de passe.'); lRetourLogin(); } function lCheckStrength(){} function lCheckMatch(){} function lChangerMotDePasse(){} function lCreerSession(u){ ouvrirApp(u.nom || u); } function lOuvrirApp(nom){ ouvrirApp(nom); } function showResetHint(){ lOuvrirReinit(); } function togglePwd(){ var i = document.getElementById('lpassword'); i.type = i.type === 'password' ? 'text' : 'password'; } // ── CONSTANTES PRODUCTION ───────────────────────────────────────────── var ETAPES_PROD = [ 'Document pas prêt','MEP','IMPORT','ACHAT','RÉCEPTION', 'CNC','EDGE','TRIAGE/GOUJON','TM TRAVAUX MANUELS', 'PRÉPARATION','MONTAGE','PORTE','EMBALLAGE','LIVRAISON' ]; // ── DONNÉES RYTHME PROJETS ───────────────────────────────────────────── // Projets suivis dans le board de production (liés aux commandes) if(!D.rythmeProjets) D.rythmeProjets = [ {id:'r1',projId:1,etape:'CNC',resp:'Luc Bernard',notes:'',subtasks:[]}, {id:'r2',projId:2,etape:'ACHAT',resp:'Pierre Simon',notes:'',subtasks:[]}, {id:'r3',projId:3,etape:'MONTAGE',resp:'Sophie Martin',notes:'',subtasks:[]}, {id:'r4',projId:4,etape:'EMBALLAGE',resp:'Marie Dubois',notes:'',subtasks:[]}, {id:'r5',projId:5,etape:'MEP',resp:'Emma Leroy',notes:'',subtasks:[]}, {id:'r6',projId:6,etape:'LIVRAISON',resp:'Pierre Simon',notes:'',subtasks:[]} ]; // ── DONNÉES FOCUS ────────────────────────────────────────────────────── if(!D.focusTasks||!D.focusTasks.length){D.focusTasks=[ {id:'f1',title:'Confirmer livraison 04425',from:'Mario',to:'Marie Dubois',prio:'urgent',due:fd(ad(T,2)),done:false,projId:1,cat:'perso'}, {id:'f2',title:'V\u00e9rifier commande mat\u00e9riaux',from:'Karine L',to:'',prio:'normal',due:fd(ad(T,4)),done:false,projId:2,cat:'perso'}, {id:'f3',title:'Pr\u00e9parer devis 04388',from:'',to:'Mario',prio:'urgent',due:fd(ad(T,1)),done:false,projId:4,cat:'perso'}, {id:'f4',title:'Mise \u00e0 jour plan 04220',from:'Sophie Martin',to:'',prio:'normal',due:fd(ad(T,5)),done:false,projId:3,cat:'perso'}, {id:'f5',title:'Calibrage machine CNC',from:'',to:'',prio:'urgent',due:fd(ad(T,1)),done:false,projId:null,cat:'usine'}, {id:'f6',title:'Inspection ligne de peinture',from:'Luc Bernard',to:'Pierre Simon',prio:'normal',due:fd(ad(T,3)),done:false,projId:null,cat:'usine'}, {id:'f7',title:'Maintenance presse hydraulique',from:'',to:'Luc Bernard',prio:'urgent',due:fd(ad(T,0)),done:false,projId:null,cat:'usine'}, {id:'f8',title:'Rapport mensuel RH',from:'',to:'Emma Leroy',prio:'normal',due:fd(ad(T,4)),done:false,projId:null,cat:'bureau'}, {id:'f9',title:'Proc\u00e9dures qualit\u00e9',from:'Sophie Martin',to:'',prio:'normal',due:fd(ad(T,7)),done:false,projId:null,cat:'bureau'}, {id:'f10',title:'Suivi commande 04550',from:'Marie Dubois',to:'',prio:'urgent',due:fd(ad(T,2)),done:false,projId:2,cat:'commande'} ];} // ══════════════════════════════════════════════════════════════════════ // RYTHME — Board de production // ══════════════════════════════════════════════════════════════════════ function rRythme(){ if(!D.rythmeProjets)D.rythmeProjets=[]; var PALETTE=['#c0392b','#2980b9','#27ae60','#e67e22','#8e44ad','#16a085','#d35400','#922b21','#7f8c8d','#2c3e50','#1e8449','#6c3483','#e74c3c','#1a7a54']; var sel=document.getElementById('rythme-filter'); if(sel){ var cur=sel.value; sel.innerHTML=''; D.rythmeProjets.forEach(function(rp){ var p=D.projets.find(function(x){return x.id===rp.projId;}); if(p)sel.innerHTML+=''; }); sel.value=cur||''; } var filterRId=sel?sel.value:''; var board=document.getElementById('rythme-board'); if(!board)return; board.innerHTML=''; ETAPES_PROD.forEach(function(etape,ei){ var col_color=PALETTE[ei%PALETTE.length]; var items=D.rythmeProjets.filter(function(rp){return rp.etape===etape&&(!filterRId||rp.id===filterRId);}); var stats={regulier:0,attention:0,urgence:0,retard:0}; items.forEach(function(rp){ var p=D.projets.find(function(x){return x.id===rp.projId;}); if(!p)return; if(p.due){ var diff=Math.round((new Date(p.due)-new Date())/864e5); if(diff<0)stats.retard++; else if(diff<=3)stats.urgence++; else if(diff<=7)stats.attention++; else stats.regulier++; } else stats.regulier++; }); var col=document.createElement('div'); col.className='rb-col'; // En-tête coloré var hd=document.createElement('div'); hd.className='rb-col-hd'; hd.style.background=col_color; var titleRow=document.createElement('div'); titleRow.className='rb-col-title'; titleRow.style.color='#fff'; var ts=document.createElement('span'); ts.style.cssText='overflow:hidden;text-overflow:ellipsis;white-space:nowrap'; ts.textContent=etape; var tb=document.createElement('span'); tb.className='rb-total'; tb.textContent=items.length; titleRow.appendChild(ts); titleRow.appendChild(tb); hd.appendChild(titleRow); var attr=document.createElement('div'); attr.className='rb-attr'; attr.textContent='Date livraison'; hd.appendChild(attr); var statsDiv=document.createElement('div'); statsDiv.className='rb-stats'; if(stats.regulier>0){var b=document.createElement('span');b.className='rb-stat regulier';b.textContent='R\u00e9gulier: '+stats.regulier;statsDiv.appendChild(b);} if(stats.attention>0){var b=document.createElement('span');b.className='rb-stat attention';b.textContent='Attention: '+stats.attention;statsDiv.appendChild(b);} if(stats.urgence>0){var b=document.createElement('span');b.className='rb-stat urgence';b.textContent='Urgence: '+stats.urgence;statsDiv.appendChild(b);} if(stats.retard>0){var b=document.createElement('span');b.className='rb-stat retard';b.textContent='Retard: '+stats.retard;statsDiv.appendChild(b);} hd.appendChild(statsDiv); col.appendChild(hd); // Corps blanc style LYSTÉ var body=document.createElement('div'); body.className='rb-col-body'; if(!items.length){ var empty=document.createElement('div'); empty.className='rb-empty'; empty.textContent='Aucun projet'; body.appendChild(empty); } else { items.forEach(function(rp,ci){ var p=D.projets.find(function(x){return x.id===rp.projId;}); if(!p)return; var num=(p.nom.split('\u2014')[0]||p.nom).trim(); var diffDays=null,dateClass='ok'; if(p.due){ diffDays=Math.round((new Date(p.due)-new Date())/864e5); if(diffDays<0)dateClass='late'; else if(diffDays<=7)dateClass='warn'; } var card=document.createElement('div'); card.className='rb-card'+(rp.docPret===false?' doc-pas-pret':''); var numRow=document.createElement('div'); numRow.className='rb-card-num'; var ns=document.createElement('span'); ns.textContent='#'+(ci+1)+' '+num; numRow.appendChild(ns); if(diffDays!==null){ var db=document.createElement('span'); db.className='rb-card-date '+dateClass; db.textContent=(diffDays>=0?'+':'')+diffDays+'j'; numRow.appendChild(db); } card.appendChild(numRow); var dateRow=document.createElement('div'); dateRow.style.cssText='font-size:10px;color:#a09880;margin-bottom:4px'; dateRow.textContent='Date livraison: '+(p.due?fds(p.due):'\u2014'); card.appendChild(dateRow); if(rp.docPret===false){ var db2=document.createElement('span'); db2.className='rb-badge doc'; db2.textContent='\u26a0 Doc PAS PR\u00caT'; card.appendChild(db2); } var icons=document.createElement('div'); icons.className='rb-card-icons'; var icoNote=document.createElement('div'); icoNote.className='rb-icon';icoNote.title='Notes';icoNote.textContent='\ud83d\uddd2'; var icoEdit=document.createElement('div'); icoEdit.className='rb-icon';icoEdit.title='\u00c9diter';icoEdit.textContent='\u270f'; icons.appendChild(icoNote);icons.appendChild(icoEdit); if(rp.resp){ var eo=D.emps.find(function(e){return e.name===rp.resp;}); if(eo){ var av=document.createElement('div'); av.style.cssText='width:22px;height:22px;border-radius:50%;background:'+ABG[eo.c%ABG.length]+';color:'+AFG[eo.c%AFG.length]+';display:flex;align-items:center;justify-content:center;font-size:9px;font-weight:700;margin-left:auto;flex-shrink:0'; av.title=eo.name;av.textContent=ini(eo.name); icons.appendChild(av); } } card.appendChild(icons); (function(pid,rid){card.onclick=function(){openArbo(pid,rid);};icoEdit.onclick=function(e){e.stopPropagation();openArbo(pid,rid);};})(p.id,rp.id); body.appendChild(card); }); } var addBtn=document.createElement('div'); addBtn.className='rb-add-btn'; addBtn.textContent='+ Ajouter un projet'; (function(et){addBtn.onclick=function(){openRythmeProjModalWithEtape(et);};})(etape); body.appendChild(addBtn); col.appendChild(body); board.appendChild(col); }); } function openRythmeProjModalWithEtape(etape){ openRythmeProjModal(); setTimeout(function(){ var sel=document.getElementById('rpm-step'); if(sel)sel.value=etape; },100); } // ══════════════════════════════════════════════════════════════════════ // ARBORESCENCE PROJET // ══════════════════════════════════════════════════════════════════════ var _arboRpId = null; var _arboProjId = null; function openArbo(projId, rpId){ _arboProjId=projId; _arboRpId=rpId; var p=D.projets.find(function(x){return x.id===projId;}); var rp=(D.rythmeProjets||[]).find(function(x){return x.id===rpId;}); if(!p||!rp)return; var parts=p.nom.split('\u2014'); document.getElementById('arbo-num').textContent=(parts[0]||p.nom).trim(); document.getElementById('arbo-nom').textContent=parts[1]?parts[1].trim():''; var statLbl={actif:'Actif',pause:'En pause',termine:'Termin\u00e9'}; document.getElementById('arbo-cat').textContent=(p.type||'')+(p.statut?' \u00b7 '+(statLbl[p.statut]||p.statut):''); // ── Bulles d'étapes ── var curIdx=ETAPES_PROD.indexOf(rp.etape); var stepsDiv=document.getElementById('arbo-steps'); stepsDiv.innerHTML=''; ETAPES_PROD.forEach(function(e,i){ var btn=document.createElement('div'); btn.className='arbo-step '+(i'+e+''; }).join(''); // ── Infos ── var dc=dueColor(p.due); var infoData=[ {l:'Type',v:p.type||'\u2014'}, {l:'Avanc\u00e9',v:(p.pct!=null?p.pct+'%':'\u2014')}, {l:'Responsable',v:p.resp||'\u2014'}, {l:'\u00c9ch\u00e9ance',v:p.due?fds(p.due):'\u2014'}, {l:'Statut',v:statLbl[p.statut]||'\u2014'}, {l:'\u00c9tape',v:rp.etape} ]; var infoGrid=document.getElementById('arbo-infos'); infoGrid.innerHTML=''; infoData.forEach(function(x){ var item=document.createElement('div'); item.className='arbo-info-item'; item.innerHTML='
'+x.l+'
'+esc(x.v)+'
'; infoGrid.appendChild(item); }); // ── Responsables par poste ── var respsDiv=document.getElementById('arbo-resps'); respsDiv.innerHTML=''; var grid=document.createElement('div'); grid.style.cssText='display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:6px'; (D.emps||[]).forEach(function(e){ var item=document.createElement('div'); item.style.cssText='background:#f8f4ed;border-radius:7px;padding:7px 10px;display:flex;align-items:center;gap:7px'; var av=document.createElement('div'); av.style.cssText='width:28px;height:28px;border-radius:50%;background:'+ABG[e.c%ABG.length]+';color:'+AFG[e.c%AFG.length]+';display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;flex-shrink:0'; av.textContent=ini(e.name); var info=document.createElement('div'); var nameEl=document.createElement('div'); nameEl.style.cssText='font-size:11px;font-weight:700;color:#1a1714'; nameEl.textContent=e.name.split(' ')[0]; var roleEl=document.createElement('div'); roleEl.style.cssText='font-size:10px;color:#a09880'; roleEl.textContent=e.role; info.appendChild(nameEl);info.appendChild(roleEl); item.appendChild(av);item.appendChild(info); grid.appendChild(item); }); respsDiv.appendChild(grid); // ── Notes ── document.getElementById('arbo-notes-txt').value=rp.notes||''; // ── Sous-tâches ── renderArboSubs(); document.getElementById('arbo-overlay').classList.add('on'); } function closeArbo(){document.getElementById('arbo-overlay').classList.remove('on');_arboRpId=null;_arboProjId=null;} function setArboStep(etape){ var rp=(D.rythmeProjets||[]).find(function(x){return x.id===_arboRpId;}); if(rp){rp.etape=etape;sv();openArbo(_arboProjId,_arboRpId);} } function saveArboStep(){ var rp=(D.rythmeProjets||[]).find(function(x){return x.id===_arboRpId;}); if(rp){rp.etape=document.getElementById('arbo-step-sel').value;sv(); // Refresh steps visuellement var curIdx=ETAPES_PROD.indexOf(rp.etape); document.getElementById('arbo-steps').querySelectorAll('.arbo-step').forEach(function(el,i){ el.className='arbo-step '+(i'; return; } fProj.forEach(function(p){ var idx=D.emps.map(function(e){return e.name;}).indexOf(p.resp); var bg=idx>=0?ABG[D.emps[idx].c%ABG.length]:ABG[0]; var fg=idx>=0?AFG[D.emps[idx].c%AFG.length]:AFG[0]; var pct=Math.min(100,Math.max(0,p.pct||0)); var dc=dueColor(p.due); var rp=(D.rythmeProjets||[]).find(function(x){return x.projId===p.id;}); var etape=rp?rp.etape:'\u2014'; var parts=p.nom.split('\u2014'); var num=(parts[0]||p.nom).trim(); var nom=parts[1]?parts[1].trim():''; var accent=statColor[p.statut]||'#1a7a54'; var card=document.createElement('div'); card.className='client-card'; card.style.setProperty('--card-accent',accent); card.innerHTML= '
'+ '
'+ '
'+esc(num)+'
'+ '
'+esc(nom)+'
'+ '
'+ ''+statLabel[p.statut]+''+ '
'+ (p.type?'
'+esc(p.type)+'
':'')+ '
'+ '
'+ ''+pct+'% compl\u00e9t\u00e9'+ (p.due?''+fds(p.due)+(dc.label?' \u00b7 '+dc.label:'')+'':'')+ '
'+ '
'+ (p.resp?'
'+ini(p.resp)+'
'+esc(p.resp.split(' ')[0])+'
':'')+ '
'+esc(etape)+'
'+ '
'+ (p.desc?'
'+esc(p.desc)+'
':'')+ ''; (function(pid,rid){ card.onclick=function(){openArbo(pid,rid);}; })(p.id, rp?rp.id:null); grid.appendChild(card); }); } // ══════════════════════════════════════════════════════════════════════ // FOCUS — missions assignées par/à l'utilisateur connecté // ══════════════════════════════════════════════════════════════════════ function rFocus(){ fES('fm-to'); var fmProj=document.getElementById('fm-proj'); if(fmProj){ fmProj.innerHTML=''+ D.projets.map(function(p){return '';}).join(''); } var me=_lCurrentUser?_lCurrentUser.nom:''; var all=D.focusTasks||[]; var q=searchQuery; // Filtres par catégorie var parQuelquun=all.filter(function(t){return t.to===me&&t.from&&t.from!==me&&(!t.cat||t.cat==='perso')&&matchSearch([t.title,t.from,t.to]);}); var parMoi=all.filter(function(t){return (t.cat==='perso'||!t.cat)&&(t.from===me||t.from==='')&&(!t.to||t.to===''||t.to===me)&&matchSearch([t.title,t.from,t.to]);}); var jaiAssigne=all.filter(function(t){return (t.cat==='perso'||!t.cat)&&t.from===me&&t.to&&t.to!==me&&matchSearch([t.title,t.from,t.to]);}); var usine=all.filter(function(t){return t.cat==='usine'&&matchSearch([t.title,t.from,t.to]);}); var bureau=all.filter(function(t){return t.cat==='bureau'&&matchSearch([t.title,t.from,t.to]);}); var commande=all.filter(function(t){return t.cat==='commande'&&matchSearch([t.title,t.from,t.to]);}); showCount(parQuelquun.length+parMoi.length+jaiAssigne.length+usine.length+bureau.length+commande.length, all.length); var container=document.getElementById('focus-cols'); if(!container)return; container.innerHTML=''; var cols=[ {titre:'\ud83d\udce5 Assign\u00e9es \u00e0 moi', tasks:parQuelquun, mode:'par', color:'#2980b9'}, {titre:'\u26a1 Mes missions', tasks:parMoi, mode:'auto', color:'#1a7a54'}, {titre:'\ud83d\udce4 J\'ai assign\u00e9', tasks:jaiAssigne, mode:'vers', color:'#8e44ad'}, {titre:'\ud83c\udfed Usine', tasks:usine, mode:'cat', color:'#e67e22'}, {titre:'\ud83c\udfe2 Bureau', tasks:bureau, mode:'cat', color:'#16a085'}, {titre:'\ud83d\udcbc Commande', tasks:commande, mode:'cat', color:'#c0392b'} ]; cols.forEach(function(colDef){ var col=document.createElement('div'); col.className='focus-col'; col.style.cssText='min-width:160px'; // En-tête coloré var hd=document.createElement('div'); hd.className='focus-col-hd'; hd.style.cssText='border-bottom:3px solid '+colDef.color+';padding-bottom:8px;margin-bottom:8px;display:flex;justify-content:space-between;align-items:center'; var titleEl=document.createElement('span'); titleEl.style.cssText='font-size:12px;font-weight:700;color:#1a1714'; titleEl.textContent=colDef.titre; var cntEl=document.createElement('span'); cntEl.style.cssText='font-size:10px;padding:1px 7px;border-radius:10px;font-weight:700;background:'+colDef.color+';color:#fff'; cntEl.textContent=colDef.tasks.length; hd.appendChild(titleEl); hd.appendChild(cntEl); col.appendChild(hd); if(!colDef.tasks.length){ var empty=document.createElement('div'); empty.style.cssText='font-size:11px;color:#bdb3a4;padding:8px 0;text-align:center'; empty.textContent='\u2014'; col.appendChild(empty); } else { colDef.tasks.forEach(function(t){ var dc=dueColor(t.due); var proj=t.projId?D.projets.find(function(p){return p.id===t.projId;}):null; var card=document.createElement('div'); card.className='focus-task'+(t.done?' dn':''); card.setAttribute('data-tid',t.id); card.onclick=function(){_togFT(this);}; var topRow=document.createElement('div'); topRow.style.cssText='display:flex;align-items:flex-start;gap:6px'; var cb=document.createElement('input'); cb.type='checkbox'; cb.checked=t.done; cb.style.cssText='width:13px;height:13px;accent-color:'+colDef.color+';margin-top:2px;flex-shrink:0'; cb.setAttribute('data-tid',t.id); cb.onclick=function(e){e.stopPropagation();_togFT(this);}; var titleT=document.createElement('div'); titleT.className='focus-task-t'; titleT.textContent=t.title; topRow.appendChild(cb); topRow.appendChild(titleT); card.appendChild(topRow); var meta=document.createElement('div'); meta.className='focus-meta'; var badge=document.createElement('span'); badge.className='focus-badge '+(t.prio==='urgent'?'b-u':'b-n'); badge.textContent=t.prio==='urgent'?'Urgent':'Normal'; meta.appendChild(badge); if(colDef.mode==='par'&&t.from){var s=document.createElement('span');s.textContent='De : '+t.from;meta.appendChild(s);} if(colDef.mode==='vers'&&t.to){var s=document.createElement('span');s.textContent='Pour : '+t.to;meta.appendChild(s);} if(colDef.mode==='cat'&&t.from){var s=document.createElement('span');s.textContent=t.from?'\ud83d\udc64 '+t.from:'';meta.appendChild(s);} if(t.due){ var s=document.createElement('span'); s.style.cssText='color:'+dc.fg+';font-weight:600'; s.textContent=fds(t.due)+(dc.label?' \u00b7 '+dc.label:''); meta.appendChild(s); } if(proj){var s=document.createElement('span');s.textContent='\ud83d\udd17 '+(proj.nom.split('\u2014')[0]||proj.nom).trim();meta.appendChild(s);} card.appendChild(meta); col.appendChild(card); }); } // Bouton + ajouter var addBtn=document.createElement('button'); addBtn.style.cssText='width:100%;margin-top:6px;padding:5px;border-radius:6px;border:1px dashed #ddd6c8;background:transparent;cursor:pointer;font-size:11px;color:#a09880'; addBtn.textContent='+ Mission'; (function(cat){addBtn.onclick=function(){ var catSel=document.getElementById('fm-cat'); if(catSel)catSel.value=cat; openFocusTask(); };})(colDef.mode==='par'||colDef.mode==='auto'||colDef.mode==='vers'?'perso': colDef.titre.indexOf('sine')>-1?'usine': colDef.titre.indexOf('ureau')>-1?'bureau':'commande'); col.appendChild(addBtn); container.appendChild(col); }); } function focusCol(titre, tasks, mode) { var cnt = tasks.length; var col = document.createElement('div'); col.className = 'focus-col'; col.innerHTML = '
'+esc(titre)+''+cnt+'
'; if(!tasks.length){ var empty = document.createElement('div'); empty.style.cssText = 'font-size:11px;color:#bdb3a4;padding:8px 0;text-align:center'; empty.textContent = '\u2014'; col.appendChild(empty); return col.outerHTML; } tasks.forEach(function(t){ var dc = dueColor(t.due); var proj = t.projId ? D.projets.find(function(p){return p.id===t.projId;}) : null; var card = document.createElement('div'); card.className = 'focus-task' + (t.done?' dn':''); card.setAttribute('data-tid', t.id); card.onclick = function(){ _togFT(this); }; var topRow = document.createElement('div'); topRow.style.cssText = 'display:flex;align-items:flex-start;gap:6px'; var cb = document.createElement('input'); cb.type = 'checkbox'; cb.checked = t.done; cb.style.cssText = 'width:13px;height:13px;accent-color:#1a1714;margin-top:2px;flex-shrink:0'; cb.setAttribute('data-tid', t.id); cb.onclick = function(e){ e.stopPropagation(); _togFT(this); }; var titleEl = document.createElement('div'); titleEl.className = 'focus-task-t'; titleEl.textContent = t.title; topRow.appendChild(cb); topRow.appendChild(titleEl); card.appendChild(topRow); var meta = document.createElement('div'); meta.className = 'focus-meta'; var badge = document.createElement('span'); badge.className = 'focus-badge ' + (t.prio==='urgent'?'b-u':'b-n'); badge.textContent = t.prio==='urgent'?'Urgent':'Normal'; meta.appendChild(badge); if(mode==='par'&&t.from){ var sp=document.createElement('span'); sp.textContent='De : '+t.from; meta.appendChild(sp); } if(mode==='vers'&&t.to){ var sp2=document.createElement('span'); sp2.textContent='Pour : '+t.to; meta.appendChild(sp2); } if(t.due){ var sp3=document.createElement('span'); sp3.style.cssText='color:'+dc.fg+';font-weight:600'; sp3.textContent=fds(t.due)+(dc.label?' \u00b7 '+dc.label:''); meta.appendChild(sp3); } if(proj){ var sp4=document.createElement('span'); sp4.textContent='\ud83d\udd17 '+proj.nom.split('\u2014')[0].trim(); meta.appendChild(sp4); } card.appendChild(meta); col.appendChild(card); }); return col.outerHTML; } function togFocusTask(id){ var t=(D.focusTasks||[]).find(function(x){return x.id===id;}); if(t){t.done=!t.done;sv();rFocus();} } function openFocusTask(){ fES('fm-to'); document.getElementById('fm-due').value=fd(ad(T,3)); document.getElementById('focus-modal').classList.add('on'); } function closeFocusModal(){document.getElementById('focus-modal').classList.remove('on');} function saveFocusTask(){ var title=document.getElementById('fm-title').value.trim();if(!title)return; var me=_lCurrentUser?_lCurrentUser.nom:''; if(!D.focusTasks)D.focusTasks=[]; var projId=document.getElementById('fm-proj').value; var fmCat=document.getElementById('fm-cat'); D.focusTasks.push({ id:'f'+D.nid++,title:title, from:me, to:document.getElementById('fm-to').value, prio:document.getElementById('fm-prio').value, due:document.getElementById('fm-due').value, done:false, projId:projId?parseInt(projId):null, cat:fmCat?fmCat.value:'perso' }); document.getElementById('fm-title').value=''; sv();closeFocusModal();rFocus(); } // ── Rythme modal ── function openRythmeProjModal(){ var sel=document.getElementById('rpm-proj'); sel.innerHTML=''+ D.projets.map(function(p){return '';}).join(''); var stepSel=document.getElementById('rpm-step'); stepSel.innerHTML=ETAPES_PROD.map(function(e){return '';}).join(''); fES('rpm-resp'); document.getElementById('rythme-proj-modal').classList.add('on'); } function closeRythmeProjModal(){document.getElementById('rythme-proj-modal').classList.remove('on');} function saveRythmeProj(){ var projId=parseInt(document.getElementById('rpm-proj').value); if(!projId)return; if(!D.rythmeProjets)D.rythmeProjets=[]; // Éviter doublons var exists=D.rythmeProjets.find(function(x){return x.projId===projId;}); if(exists){exists.etape=document.getElementById('rpm-step').value;exists.resp=document.getElementById('rpm-resp').value;} else{D.rythmeProjets.push({id:'r'+D.nid++,projId:projId,etape:document.getElementById('rpm-step').value,resp:document.getElementById('rpm-resp').value,notes:'',subtasks:[]});} sv();closeRythmeProjModal();rRythme(); } // openArbo avec projId null var _openArboOrig=openArbo; function _oc(el){var p=parseInt(el.getAttribute("data-pid"));var r=el.getAttribute("data-rid");openArbo(p,r||null);} function openArboFromCard(el){ var pid=parseInt(el.getAttribute('data-pid')); var rid=el.getAttribute('data-rid'); openArbo(pid, rid||null); } // Enrichir les projets rythmeProjets avec données réalistes if(D.rythmeProjets && D.rythmeProjets.length){ D.rythmeProjets.forEach(function(rp){ if(!rp.statut) rp.statut = 'regulier'; if(!rp.docPret) rp.docPret = true; }); } // Ajouter données exemples si vides if(!D.rythmeProjets || !D.rythmeProjets.length){ D.rythmeProjets = [ {id:'r1',projId:1,etape:'CNC',resp:'Luc Bernard',statut:'regulier',docPret:true,notes:'',subtasks:[]}, {id:'r2',projId:2,etape:'ACHAT',resp:'Pierre Simon',statut:'attention',docPret:false,notes:'',subtasks:[]}, {id:'r3',projId:3,etape:'MONTAGE',resp:'Sophie Martin',statut:'regulier',docPret:true,notes:'',subtasks:[]}, {id:'r4',projId:4,etape:'EMBALLAGE',resp:'Marie Dubois',statut:'urgence',docPret:true,notes:'',subtasks:[]}, {id:'r5',projId:5,etape:'MEP',resp:'Emma Leroy',statut:'retard',docPret:false,notes:'MEP en attente',subtasks:[]}, {id:'r6',projId:6,etape:'LIVRAISON',resp:'Pierre Simon',statut:'regulier',docPret:true,notes:'',subtasks:[]} ]; sv(); } rDash(); rDash();