ED64 • Admin + Decrypter (PWA · Cloudflare Pages)

🛠️ Admin — Cantieri/Clienti & Lavorazioni

📤 Aggiorna Dipendenti (un click)

Anteprima JSON

Pronto.

🔐 Decrypter .enc (Telegram)

PBKDF2‑SHA256 100.000 + AES‑GCM — password ed64admin. Formati: concat salt(16)|iv(12)|ct+tag • envelope JSON {s,iv,ct,iters} • base64→JSON.
Clicca o trascina qui il file .enc (binario o testo)
Diagnostica
Nome: — Formato: — Input len:

Risultato

Nessun risultato ancora.
`; const a=document.createElement('a'); a.href=URL.createObjectURL(new Blob([tpl],{type:'text/html'})); a.download='Dipendenti-patch.html'; a.click(); } /* ===== Dipendenti auto-import da URL hash ===== */ (function initDipFromHash(){ const u=new URL(window.location.href); if(u.pathname.endsWith('/dipendenti.html') && u.hash){ try{ const txt = decodeURIComponent(escape(atob(u.hash.replace(/^#/,'').trim()))); const obj = JSON.parse(txt); localStorage.setItem(LS_COMBINED, JSON.stringify(obj)); localStorage.setItem(LS_CANTIERI, JSON.stringify(obj.cantieri||[])); localStorage.setItem(LS_LAVORAZIONI, JSON.stringify(obj.lavorazioni||[])); document.body.innerHTML = '

Import completato ✅

'+JSON.stringify(obj,null,2)+'
'; }catch(e){ document.body.innerHTML = '

Errore import

'+e+'
'; } } })(); /* ===== Decrypter ===== */ const PWD='ed64admin', ITERS=100000; let loaded=null, lastJson=null; const u8=s=>new TextEncoder().encode(s), str=u=>new TextDecoder().decode(u); const b64toU8=b=>{try{const s=atob(b.replace(/\s+/g,'')); const a=new Uint8Array(s.length); for(let i=0;i''+k+'').join('')+''; for(const r of rows.slice(0,100)){ h+=''+keys.map(k=>''+(r?.[k]??'')+'').join('')+''; } if(rows.length>100) h+='…('+rows.length+' tot)'; return h+''; } function showDec(res){ if(!res){document.getElementById('status2').textContent='Nessun formato riconosciuto';return;} document.getElementById('resultInfo2').textContent='Trovato: '+res.mode; const pre=document.getElementById('result2'); pre.style.display='block'; document.getElementById('tablePreview').innerHTML=''; if(typeof res.data==='string'){ pre.textContent=res.data.slice(0,8000); document.getElementById('copyJson2').disabled=true; document.getElementById('saveJson2').disabled=false; document.getElementById('importApp2').disabled=true; lastJson=null; } else { pre.textContent=JSON.stringify(res.data,null,2); document.getElementById('copyJson2').disabled=false; document.getElementById('saveJson2').disabled=false; document.getElementById('importApp2').disabled=false; lastJson=res.data; if(Array.isArray(lastJson)) document.getElementById('tablePreview').innerHTML=table(lastJson); } document.getElementById('status2').textContent='DECRITTAZIONE RIUSCITA'; } function saveDecrypted(){ const content=lastJson?JSON.stringify(lastJson,null,2):document.getElementById('result2').textContent; const a=document.createElement('a'); a.href=URL.createObjectURL(new Blob([content],{type:'application/json'})); a.download='decrypted.json'; a.click(); } async function copyDecrypted(){ if(!lastJson){alert('Nessun JSON');return;} try{await navigator.clipboard.writeText(JSON.stringify(lastJson,null,2)); document.getElementById('status2').textContent='JSON copiato';}catch(e){document.getElementById('status2').textContent='Copia non riuscita';} } function importDecrypted(){ if(!lastJson){alert('Nessun JSON');return;} const rows=Array.isArray(lastJson)?lastJson:[lastJson]; const pick=(o,ks)=>{for(const k of ks) if(o&&o[k]!=null&&o[k]!=='') return o[k]; return '';}; const mapped=rows.map(x=>({ data:(''+pick(x,['data','date','giorno'])).slice(0,10)||new Date().toISOString().slice(0,10), dipendente:pick(x,['dipendente','nome','worker','operatore','name']), ore:+pick(x,['ore','hours'])||0, cantiere:pick(x,['cantiere','cliente','site']), lavorazione:pick(x,['lavorazione','task']), note:pick(x,['note','notes','descrizione','description']) })); const cur=JSON.parse(localStorage.getItem('admin.step1.rows')||'[]'); localStorage.setItem('admin.step1.rows',JSON.stringify(cur.concat(mapped))); document.getElementById('status2').textContent=`Importati ${mapped.length} record in localStorage (admin.step1.rows).`; } function browseFile(){document.getElementById('file').click();} function pasteEnc(){const t=prompt('Incolla base64/JSON o JSON in chiaro:'); if(!t)return; loaded={kind:'text',data:t,name:'(incollato)'}; document.getElementById('name2').textContent='(incollato)'; document.getElementById('len2').textContent=t.length; document.getElementById('preview2').textContent=t.slice(0,200);} function resetDec(){loaded=null;lastJson=null;['name2','len2','preview2','result2','resultInfo2','tablePreview'].forEach(id=>{const el=document.getElementById(id); if(el){ if(id==='result2'){el.style.display='none'; el.textContent='';} else if(id==='tablePreview'){el.innerHTML='';} else el.textContent='—'; }}); document.getElementById('status2').textContent='Reset';} async function startDecrypt(){ if(!loaded){ const f=document.getElementById('file').files?.[0]; if(f){ try{ const buf=await f.arrayBuffer(); loaded={kind:'u8',data:new Uint8Array(buf),name:f.name}; document.getElementById('name2').textContent=f.name; document.getElementById('len2').textContent=loaded.data.length; document.getElementById('preview2').textContent='[binario]'; } catch(e){ const t=await f.text(); loaded={kind:'text',data:t,name:f.name}; document.getElementById('name2').textContent=f.name; document.getElementById('len2').textContent=t.length; document.getElementById('preview2').textContent=t.slice(0,200); } } else { const raw=prompt('Incolla contenuto (.enc)'); if(!raw) return; loaded={kind:'text',data:raw,name:'(incollato)'}; document.getElementById('name2').textContent='(incollato)'; document.getElementById('len2').textContent=raw.length; document.getElementById('preview2').textContent=raw.slice(0,200); } } try{ const res=await tryDec(loaded); showDec(res); }catch(e){ document.getElementById('status2').textContent='Errore: '+e.message; } } /* ===== PWA bootstrap + Install ===== */ let deferredPrompt=null; (function setupPWA(){ if('serviceWorker' in navigator){ navigator.serviceWorker.register('./service-worker.js', {scope:'./'}).then(()=>{ banner('Pronta per l’installazione: usa il pulsante o il menu ••• → “Aggiungi a schermata Home”.'); document.getElementById('installCard').style.display='block'; }).catch(err=>{ banner('SW non registrato: '+err); }); } else { banner('Il dispositivo non supporta Service Worker. Puoi comunque aggiungerla alla Home.'); } window.addEventListener('beforeinstallprompt', (e)=>{ e.preventDefault(); deferredPrompt = e; const btn = document.getElementById('btnInstall'); btn.disabled = false; document.getElementById('installCard').style.display='block'; }); document.getElementById('btnInstall').addEventListener('click', async ()=>{ const btn = document.getElementById('btnInstall'); if(!deferredPrompt){ banner('Se non appare il prompt, usa il menu ••• → Aggiungi a schermata Home.'); return; } btn.disabled = true; deferredPrompt.prompt(); const { outcome } = await deferredPrompt.userChoice; if(outcome === 'accepted'){ banner('Installazione avviata. Trovi l’icona su Home.'); } else { banner('Installazione annullata. Puoi riprovare dal menu •••.'); btn.disabled = false; } deferredPrompt = null; }); })(); function banner(msg){ const el=document.getElementById('pwaBanner'); el.textContent=msg; el.style.display='block'; } /* init */ window.addEventListener('DOMContentLoaded',()=>{ loadAdmin(); });