<!doctype html>

<html lang="it">

<head>

  <meta charset="utf-8" />

  <meta name="viewport" content="width=device-width, initial-scale=1" />

  <title>TMS Logistica - Demo (LocalStorage)</title>

  <style>

    :root{

      --bg:#0b0f17;

      --panel:#101828;

      --panel2:#0f172a;

      --text:#e5e7eb;

      --muted:#9ca3af;

      --line:#1f2937;

      --brand:#22c55e;

      --warn:#f59e0b;

      --bad:#ef4444;

      --info:#60a5fa;

      --chip:#111827;

      --shadow: 0 10px 30px rgba(0,0,0,.35);

      --radius: 16px;

      --radius2: 12px;

    }

    *{box-sizing:border-box}

    body{

      margin:0;

      font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial, "Apple Color Emoji","Segoe UI Emoji";

      background: radial-gradient(1200px 700px at 20% -10%, rgba(34,197,94,.18), transparent 60%),

                  radial-gradient(900px 600px at 110% 10%, rgba(96,165,250,.12), transparent 50%),

                  var(--bg);

      color:var(--text);

      min-height:100vh;

    }

    a{color:inherit}

    .wrap{

      max-width: 1100px;

      margin: 0 auto;

      padding: 18px;

    }

    .topbar{

      display:flex;

      gap:12px;

      align-items:center;

      justify-content:space-between;

      position:sticky;

      top:0;

      padding: 14px 18px;

      background: rgba(11,15,23,.65);

      backdrop-filter: blur(10px);

      border-bottom:1px solid rgba(31,41,55,.6);

      z-index: 5;

    }

    .brand{

      display:flex; align-items:center; gap:10px;

      font-weight:700;

      letter-spacing:.2px;

    }

    .dot{

      width:12px;height:12px;border-radius:999px;background:var(--brand);

      box-shadow: 0 0 0 6px rgba(34,197,94,.12);

    }

    .pill{

      display:inline-flex; align-items:center; gap:8px;

      padding: 8px 10px;

      border:1px solid rgba(31,41,55,.9);

      background: rgba(16,24,40,.75);

      border-radius:999px;

      color: var(--muted);

      font-size: 13px;

    }

    .btn{

      border:1px solid rgba(31,41,55,.9);

      background: rgba(16,24,40,.85);

      color: var(--text);

      padding: 10px 12px;

      border-radius: 12px;

      cursor:pointer;

      transition: transform .06s ease, background .2s ease, border-color .2s ease;

      font-weight: 600;

      font-size: 14px;

    }

    .btn:hover{background: rgba(16,24,40,.98); border-color: rgba(55,65,81,1)}

    .btn:active{transform: translateY(1px)}

    .btn.primary{

      background: linear-gradient(180deg, rgba(34,197,94,.95), rgba(34,197,94,.75));

      border-color: rgba(34,197,94,.35);

      color:#052e16;

    }

    .btn.danger{

      background: rgba(239,68,68,.12);

      border-color: rgba(239,68,68,.35);

      color: #fecaca;

    }

    .btn.ghost{

      background: transparent;

    }

    .grid{

      display:grid;

      gap: 14px;

    }

    .cards{

      grid-template-columns: repeat(12, 1fr);

    }

    .card{

      background: rgba(16,24,40,.85);

      border: 1px solid rgba(31,41,55,.85);

      border-radius: var(--radius);

      box-shadow: var(--shadow);

      overflow:hidden;

    }

    .card .hd{

      padding: 14px 14px 10px;

      border-bottom:1px solid rgba(31,41,55,.7);

      display:flex;

      align-items:flex-start;

      justify-content:space-between;

      gap: 12px;

    }

    .card .hd h2{

      margin:0;

      font-size: 16px;

      letter-spacing:.2px;

    }

    .card .hd p{

      margin:6px 0 0;

      color: var(--muted);

      font-size: 13px;

      line-height: 1.35;

    }

    .card .bd{

      padding: 14px;

    }

    .kpis{

      display:grid;

      grid-template-columns: repeat(4, 1fr);

      gap: 12px;

    }

    .kpi{

      background: rgba(15,23,42,.8);

      border:1px solid rgba(31,41,55,.8);

      border-radius: var(--radius2);

      padding: 12px;

      min-height: 78px;

      display:flex;

      flex-direction:column;

      justify-content:space-between;

    }

    .kpi .lab{

      color: var(--muted);

      font-size: 12px;

    }

    .kpi .val{

      font-size: 22px;

      font-weight: 800;

    }

    .kpi .sub{

      color: var(--muted);

      font-size: 12px;

    }

    .row{

      display:flex;

      gap: 10px;

      flex-wrap: wrap;

      align-items:center;

    }

    .split{

      display:flex;

      gap: 14px;

      flex-wrap: wrap;

    }

    .split > *{flex: 1}

    label{

      display:block;

      font-size: 12px;

      color: var(--muted);

      margin-bottom: 6px;

    }

    input, select, textarea{

      width:100%;

      padding: 10px 11px;

      border-radius: 12px;

      border: 1px solid rgba(31,41,55,.95);

      background: rgba(3,7,18,.35);

      color: var(--text);

      outline: none;

    }

    textarea{min-height: 88px; resize: vertical}

    input:focus, select:focus, textarea:focus{

      border-color: rgba(96,165,250,.7);

      box-shadow: 0 0 0 4px rgba(96,165,250,.12);

    }

    .table{

      width:100%;

      border-collapse: collapse;

      overflow:hidden;

      border-radius: 12px;

      border: 1px solid rgba(31,41,55,.85);

    }

    .table th, .table td{

      padding: 10px 10px;

      border-bottom: 1px solid rgba(31,41,55,.65);

      text-align:left;

      font-size: 13px;

      vertical-align: top;

    }

    .table th{

      color: var(--muted);

      font-weight: 700;

      background: rgba(15,23,42,.7);

      position: sticky;

      top: 0;

      z-index: 1;

    }

    .table tr:hover td{background: rgba(15,23,42,.35)}

    .chip{

      display:inline-flex;

      align-items:center;

      gap: 6px;

      padding: 6px 10px;

      border-radius:999px;

      background: rgba(17,24,39,.9);

      border:1px solid rgba(31,41,55,.85);

      font-size: 12px;

      color: var(--muted);

      white-space:nowrap;

    }

    .chip.good{border-color: rgba(34,197,94,.35); color: rgba(187,247,208,.95); background: rgba(34,197,94,.10)}

    .chip.warn{border-color: rgba(245,158,11,.35); color: rgba(254,243,199,.95); background: rgba(245,158,11,.10)}

    .chip.bad{border-color: rgba(239,68,68,.35); color: rgba(254,202,202,.95); background: rgba(239,68,68,.10)}

    .chip.info{border-color: rgba(96,165,250,.35); color: rgba(191,219,254,.95); background: rgba(96,165,250,.10)}

    .muted{color: var(--muted)}

    .tabs{

      display:flex;

      gap: 8px;

      flex-wrap: wrap;

    }

    .tab{

      padding: 10px 12px;

      border-radius: 12px;

      border: 1px solid rgba(31,41,55,.85);

      background: rgba(16,24,40,.70);

      cursor:pointer;

      font-weight: 700;

      color: var(--muted);

      font-size: 13px;

    }

    .tab.active{

      background: rgba(34,197,94,.14);

      border-color: rgba(34,197,94,.35);

      color: rgba(187,247,208,.95);

    }

    .two{

      display:grid;

      grid-template-columns: 1.1fr .9fr;

      gap: 14px;

    }

    .hint{

      font-size: 12px;

      color: var(--muted);

      line-height: 1.35;

    }

    .hr{

      height:1px;background: rgba(31,41,55,.8); margin: 10px 0;

    }

    .toast{

      position: fixed;

      left: 50%;

      transform: translateX(-50%);

      bottom: 16px;

      padding: 10px 12px;

      border-radius: 999px;

      background: rgba(16,24,40,.92);

      border: 1px solid rgba(31,41,55,.85);

      color: var(--text);

      box-shadow: var(--shadow);

      font-size: 13px;

      display:none;

      z-index: 10;

      max-width: calc(100vw - 24px);

    }

    .modal{

      position: fixed;

      inset: 0;

      display:none;

      background: rgba(0,0,0,.55);

      z-index: 20;

      padding: 18px;

    }

    .modal .box{

      max-width: 920px;

      margin: 0 auto;

      background: rgba(16,24,40,.96);

      border:1px solid rgba(31,41,55,.9);

      border-radius: 18px;

      overflow:hidden;

      box-shadow: var(--shadow);

    }

    .modal .box .hd{

      padding: 14px 14px 10px;

      border-bottom: 1px solid rgba(31,41,55,.7);

      display:flex;

      align-items:center;

      justify-content:space-between;

      gap: 10px;

    }

    .modal .box .hd h3{margin:0; font-size: 15px}

    .modal .box .bd{padding: 14px}

    .sigbox{

      border: 1px dashed rgba(55,65,81,1);

      border-radius: 12px;

      overflow:hidden;

      background: rgba(3,7,18,.25);

    }

    canvas{display:block; width:100%; height: 180px;}

    .imgPreview{

      width:100%;

      border-radius: 12px;

      border:1px solid rgba(31,41,55,.85);

      background: rgba(3,7,18,.25);

      overflow:hidden;

    }

    .imgPreview img{display:block; width:100%; height:auto}

    .footer-note{

      margin-top: 12px;

      color: var(--muted);

      font-size: 12px;

      line-height: 1.45;

    }


    /* Responsive */

    @media (max-width: 980px){

      .two{grid-template-columns: 1fr}

      .kpis{grid-template-columns: repeat(2, 1fr)}

    }

    @media (max-width: 520px){

      .wrap{padding: 12px}

      .topbar{padding: 12px}

      .kpis{grid-template-columns: 1fr}

      .btn{width:auto}

      .table th:nth-child(3),

      .table td:nth-child(3){display:none} /* nascondi una colonna su schermi piccoli */

    }

  </style>

</head>

<body>


  <div class="topbar">

    <div class="brand">

      <span class="dot"></span>

      <div>

        <div style="font-size:14px;">TMS Logistica</div>

        <div class="muted" style="font-size:12px;">Demo LocalStorage (Netlify-ready)</div>

      </div>

    </div>

    <div class="row" id="topRight">

      <!-- popolato via JS -->

    </div>

  </div>


  <div class="wrap" id="app"></div>


  <div class="toast" id="toast"></div>


  <!-- MODAL POD / FIRMA -->

  <div class="modal" id="modalPOD" role="dialog" aria-modal="true">

    <div class="box">

      <div class="hd">

        <div>

          <h3 id="podTitle">POD - Prova di consegna</h3>

          <div class="hint" id="podSubtitle"></div>

        </div>

        <div class="row">

          <button class="btn ghost" id="podCloseBtn">Chiudi</button>

        </div>

      </div>

      <div class="bd">

        <div class="two">

          <div>

            <div class="hint">Firma (mock): disegna nel riquadro. Poi salva.</div>

            <div class="sigbox" style="margin-top:8px;">

              <canvas id="sigCanvas" width="900" height="360"></canvas>

            </div>

            <div class="row" style="margin-top:10px;">

              <button class="btn" id="sigClearBtn">Pulisci firma</button>

              <button class="btn primary" id="sigSaveBtn">Salva firma</button>

            </div>

          </div>

          <div>

            <div class="hint">Foto POD (mock): carica un'immagine (salvata in LocalStorage).</div>

            <input type="file" id="podPhotoInput" accept="image/*" style="margin-top:8px;">

            <div class="row" style="margin-top:10px;">

              <button class="btn primary" id="podPhotoSaveBtn">Salva foto</button>

              <button class="btn danger" id="podPhotoDelBtn">Rimuovi foto</button>

            </div>

            <div style="margin-top:10px;" class="imgPreview" id="podPhotoPreview" aria-label="Anteprima foto"></div>

            <div class="footer-note">Nota: essendo una demo, firma e foto restano nel browser (LocalStorage). Se cambi dispositivo non le vedrai.</div>

          </div>

        </div>

      </div>

    </div>

  </div>


<script>

/**

 * TMS Logistica - Single File App (LocalStorage)

 * - Login mock con ruoli

 * - CRUD Clienti / Autisti / Spedizioni

 * - Vista Autista con stati + POD mock (firma+foto)

 * Nessuna dipendenza esterna.

 */


/* ------------------ Storage Keys ------------------ */

const LS = {

  DB: "tms_db_v1",

  SESSION: "tms_session_v1"

};


/* ------------------ Helpers ------------------ */

const $ = (sel, root=document) => root.querySelector(sel);

const $$ = (sel, root=document) => Array.from(root.querySelectorAll(sel));


function uid(prefix="id"){

  return prefix + "_" + Math.random().toString(16).slice(2) + "_" + Date.now().toString(16);

}


function todayISO(){

  const d = new Date();

  const y = d.getFullYear();

  const m = String(d.getMonth()+1).padStart(2,"0");

  const day = String(d.getDate()).padStart(2,"0");

  return `${y}-${m}-${day}`;

}


function formatDate(iso){

  if(!iso) return "";

  const [y,m,d] = iso.split("-");

  return `${d}/${m}/${y}`;

}


function toast(msg){

  const t = $("#toast");

  t.textContent = msg;

  t.style.display = "block";

  clearTimeout(toast._timer);

  toast._timer = setTimeout(()=> t.style.display="none", 2200);

}


function escapeHtml(s){

  return String(s ?? "")

    .replaceAll("&","&amp;")

    .replaceAll("<","&lt;")

    .replaceAll(">","&gt;")

    .replaceAll('"',"&quot;")

    .replaceAll("'","&#039;");

}


function statusChip(st){

  const map = {

    "da_caricare": ["Da caricare","warn"],

    "in_transito": ["In transito","info"],

    "consegnato": ["Consegnato","good"],

    "problema": ["Problema","bad"],

    "partito": ["Partito","info"],

    "arrivato": ["Arrivato","info"]

  };

  const [lab, cls] = map[st] || [st,""];

  return `<span class="chip ${cls}">${lab}</span>`;

}


function roleChip(role){

  const r = role === "admin" ? ["Admin/Ufficio","good"] : ["Autista","info"];

  return `<span class="chip ${r[1]}">${r[0]}</span>`;

}


/* ------------------ DB ------------------ */

function loadDB(){

  const raw = localStorage.getItem(LS.DB);

  if(raw){

    try { return JSON.parse(raw); } catch(e){}

  }

  // Seed iniziale

  const seed = {

    clients: [

      { id: uid("cli"), ragione_sociale:"Alfa Srl", partita_iva:"01234567890", indirizzo:"Via Roma 10", citta:"Milano", cap:"20100", referente:"Marco Bianchi", telefono:"+39 02 123456", email:"logistica@alfasrl.it", note:"Consegne mattina" },

      { id: uid("cli"), ragione_sociale:"Beta Spa", partita_iva:"09876543210", indirizzo:"Viale Europa 5", citta:"Bologna", cap:"40100", referente:"Sara Rossi", telefono:"+39 051 987654", email:"spedizioni@betaspa.it", note:"Richiede POD foto" }

    ],

    drivers: [

      { id: uid("drv"), nome:"Luca Verdi", telefono:"+39 333 111222", email:"l.verdi@trasporti.it", targa_mezzo_preferito:"AB123CD" },

      { id: uid("drv"), nome:"Gianni Neri", telefono:"+39 333 444555", email:"g.neri@trasporti.it", targa_mezzo_preferito:"EF456GH" }

    ],

    shipments: []

  };

  // Seed spedizioni

  seed.shipments.push({

    id: uid("shp"),

    cliente_id: seed.clients[0].id,

    autista_id: seed.drivers[0].id,

    data_ritiro: todayISO(),

    indirizzo_ritiro: "Via Roma 10, Milano (MI)",

    data_consegna: todayISO(),

    indirizzo_consegna: "Via Emilia 20, Bologna (BO)",

    colli: 6,

    peso_kg: 420,

    volume_mc: 1.2,

    targa_mezzo: "AB123CD",

    stato: "da_caricare",

    note: "Fragile",

    pod: { signatureDataUrl: null, photoDataUrl: null }

  });

  seed.shipments.push({

    id: uid("shp"),

    cliente_id: seed.clients[1].id,

    autista_id: seed.drivers[1].id,

    data_ritiro: todayISO(),

    indirizzo_ritiro: "Viale Europa 5, Bologna (BO)",

    data_consegna: todayISO(),

    indirizzo_consegna: "Via Garibaldi 7, Firenze (FI)",

    colli: 2,

    peso_kg: 80,

    volume_mc: null,

    targa_mezzo: "EF456GH",

    stato: "in_transito",

    note: "",

    pod: { signatureDataUrl: null, photoDataUrl: null }

  });

  saveDB(seed);

  return seed;

}


function saveDB(db){

  localStorage.setItem(LS.DB, JSON.stringify(db));

}


function getSession(){

  const raw = localStorage.getItem(LS.SESSION);

  if(!raw) return null;

  try { return JSON.parse(raw); } catch(e){ return null; }

}

function setSession(sess){

  localStorage.setItem(LS.SESSION, JSON.stringify(sess));

}

function clearSession(){

  localStorage.removeItem(LS.SESSION);

}


/* ------------------ App State ------------------ */

let db = loadDB();

let view = "dashboard"; // dashboard | clients | drivers | shipments

let editing = { clientId:null, driverId:null, shipmentId:null };

let podEditingShipmentId = null;


function currentUser(){

  return getSession();

}


/* ------------------ WordPress + Netlify “collegamento” ------------------

   Questo index.html è pensato per Netlify. Su WordPress lo "colleghi" via iframe.

-------------------------------------------------------------------------- */


/* ------------------ Render Top Right ------------------ */

function renderTopRight(){

  const u = currentUser();

  const el = $("#topRight");

  if(!u){

    el.innerHTML = `<span class="pill">Non loggato</span>`;

    return;

  }

  const name = u.role === "admin" ? "Admin/Ufficio" : (u.driverName || "Autista");

  el.innerHTML = `

    <span class="pill">${roleChip(u.role)} <span class="muted">|</span> ${escapeHtml(name)}</span>

    <button class="btn" id="btnLogout">Logout</button>

  `;

  $("#btnLogout").onclick = () => {

    clearSession();

    view = "dashboard";

    editing = { clientId:null, driverId:null, shipmentId:null };

    toast("Logout effettuato");

    render();

  };

}


/* ------------------ Login Screen ------------------ */

function renderLogin(){

  const app = $("#app");

  app.innerHTML = `

    <div class="grid" style="gap:14px;">

      <div class="card">

        <div class="hd">

          <div>

            <h2>Login (mock)</h2>

            <p>Questa è una demo: niente backend. I dati restano nel tuo browser (LocalStorage).</p>

          </div>

          <div class="pill">Suggerimento: prova <b>Admin</b> per gestire tutto, oppure <b>Autista</b> per vedere solo le spedizioni assegnate.</div>

        </div>

        <div class="bd">

          <div class="two">

            <div>

              <h3 style="margin:0 0 8px;font-size:14px;">Accesso Admin/Ufficio</h3>

              <div class="hint">Clicca per entrare come Admin (mock).</div>

              <div class="row" style="margin-top:10px;">

                <button class="btn primary" id="loginAdmin">Entra come Admin</button>

              </div>

              <div class="hr"></div>

              <h3 style="margin:0 0 8px;font-size:14px;">Accesso Autista</h3>

              <div class="hint">Seleziona un autista esistente e accedi. In vista autista vedrai solo le spedizioni assegnate.</div>

              <div style="margin-top:10px;">

                <label>Autista</label>

                <select id="loginDriverSel"></select>

              </div>

              <div class="row" style="margin-top:10px;">

                <button class="btn primary" id="loginDriver">Entra come Autista</button>

              </div>

              <div class="footer-note">

                Se vuoi cambiare “utenti”, gestisci l’elenco Autisti dalla vista Admin.

              </div>

            </div>

            <div>

              <h3 style="margin:0 0 8px;font-size:14px;">Come collegarla a WordPress</h3>

              <div class="hint">

                1) Pubblica questo file su Netlify.<br>

                2) In WordPress crea una pagina “Gestionale”.<br>

                3) Inserisci un iframe con l’URL Netlify dell’app.

              </div>

              <div class="hr"></div>

              <div class="hint"><b>Nota importante:</b> usando LocalStorage, ogni dispositivo tiene i suoi dati. Per un gestionale reale (multi-dispositivo), serve un backend + database.</div>

            </div>

          </div>

        </div>

      </div>

    </div>

  `;


  // Populate driver selector

  const sel = $("#loginDriverSel");

  sel.innerHTML = db.drivers.map(d => `<option value="${d.id}">${escapeHtml(d.nome)} (${escapeHtml(d.targa_mezzo_preferito || "—")})</option>`).join("");


  $("#loginAdmin").onclick = () => {

    setSession({ role:"admin" });

    toast("Accesso Admin effettuato");

    render();

  };


  $("#loginDriver").onclick = () => {

    const id = sel.value;

    const d = db.drivers.find(x => x.id === id);

    if(!d){ toast("Seleziona un autista"); return; }

    setSession({ role:"driver", driverId: d.id, driverName: d.nome });

    toast("Accesso Autista effettuato");

    view = "shipments";

    render();

  };

}


/* ------------------ Navigation Tabs ------------------ */

function renderTabs(){

  const u = currentUser();

  if(!u) return "";


  const isAdmin = u.role === "admin";

  const tabs = [];


  tabs.push({ key:"dashboard", label:"Dashboard" });

  if(isAdmin){

    tabs.push({ key:"clients", label:"Clienti" });

    tabs.push({ key:"drivers", label:"Autisti" });

    tabs.push({ key:"shipments", label:"Spedizioni" });

  }else{

    tabs.push({ key:"shipments", label:"Le mie spedizioni" });

  }


  return `

    <div class="card" style="margin-bottom:14px;">

      <div class="bd">

        <div class="tabs">

          ${tabs.map(t => `

            <div class="tab ${view===t.key ? "active":""}" data-tab="${t.key}">${t.label}</div>

          `).join("")}

        </div>

      </div>

    </div>

  `;

}


function bindTabs(){

  $$(".tab").forEach(t => {

    t.onclick = () => {

      view = t.getAttribute("data-tab");

      editing = { clientId:null, driverId:null, shipmentId:null };

      render();

    };

  });

}


/* ------------------ Dashboard ------------------ */

function computeDashboard(){

  const u = currentUser();

  const isAdmin = u?.role === "admin";

  const shipments = isAdmin

    ? db.shipments

    : db.shipments.filter(s => s.autista_id === u.driverId);


  const today = todayISO();

  const todayCount = shipments.filter(s => s.data_ritiro === today || s.data_consegna === today).length;

  const inTransit = shipments.filter(s => s.stato === "in_transito" || s.stato === "partito" || s.stato === "arrivato").length;

  const delivered = shipments.filter(s => s.stato === "consegnato").length;

  const problems = shipments.filter(s => s.stato === "problema").length;


  return { todayCount, inTransit, delivered, problems };

}


function renderDashboard(){

  const u = currentUser();

  const isAdmin = u.role === "admin";

  const k = computeDashboard();


  const shipments = isAdmin

    ? db.shipments

    : db.shipments.filter(s => s.autista_id === u.driverId);


  // Recent list (max 6)

  const recent = [...shipments].sort((a,b) => (b.data_ritiro||"").localeCompare(a.data_ritiro||"")).slice(0,6);


  const app = $("#app");

  app.innerHTML = `

    ${renderTabs()}

    <div class="grid" style="gap:14px;">

      <div class="card">

        <div class="hd">

          <div>

            <h2>Dashboard</h2>

            <p>${isAdmin ? "Riepilogo generale operatività." : "Riepilogo delle tue spedizioni assegnate."}</p>

          </div>

          <div class="row">

            ${isAdmin ? `<button class="btn primary" id="quickNewShipment">+ Nuova spedizione</button>` : ""}

          </div>

        </div>

        <div class="bd">

          <div class="kpis">

            <div class="kpi">

              <div class="lab">Spedizioni oggi</div>

              <div class="val">${k.todayCount}</div>

              <div class="sub">ritiro o consegna in data odierna</div>

            </div>

            <div class="kpi">

              <div class="lab">In transito</div>

              <div class="val">${k.inTransit}</div>

              <div class="sub">partito/arrivato/in transito</div>

            </div>

            <div class="kpi">

              <div class="lab">Consegnate</div>

              <div class="val">${k.delivered}</div>

              <div class="sub">completate</div>

            </div>

            <div class="kpi">

              <div class="lab">Problemi</div>

              <div class="val">${k.problems}</div>

              <div class="sub">da gestire</div>

            </div>

          </div>

          <div class="hr"></div>

          <div class="row" style="justify-content:space-between;">

            <div>

              <div style="font-weight:800; margin-bottom:4px;">Ultime spedizioni</div>

              <div class="hint">Clicca “Apri” per dettagli (e POD in vista autista).</div>

            </div>

            <button class="btn" id="goShipments">Vai a Spedizioni</button>

          </div>

          <div style="margin-top:10px; overflow:auto; max-height: 360px;">

            <table class="table">

              <thead>

                <tr>

                  <th>Stato</th>

                  <th>Cliente</th>

                  <th>Ritiro</th>

                  <th>Consegna</th>

                  <th>Autista</th>

                  <th></th>

                </tr>

              </thead>

              <tbody>

                ${recent.length ? recent.map(s => {

                  const c = db.clients.find(x => x.id === s.cliente_id);

                  const d = db.drivers.find(x => x.id === s.autista_id);

                  return `

                    <tr>

                      <td>${statusChip(s.stato)}</td>

                      <td>${escapeHtml(c?.ragione_sociale || "—")}</td>

                      <td>${formatDate(s.data_ritiro)}<div class="muted">${escapeHtml(s.indirizzo_ritiro||"")}</div></td>

                      <td>${formatDate(s.data_consegna)}<div class="muted">${escapeHtml(s.indirizzo_consegna||"")}</div></td>

                      <td>${escapeHtml(d?.nome || "—")}</td>

                      <td><button class="btn" data-open-shp="${s.id}">Apri</button></td>

                    </tr>

                  `;

                }).join("") : `<tr><td colspan="6" class="muted">Nessuna spedizione.</td></tr>`}

              </tbody>

            </table>

          </div>

        </div>

      </div>

    </div>

  `;


  if(isAdmin){

    $("#quickNewShipment").onclick = () => { view="shipments"; editing.shipmentId=null; render(); setTimeout(()=> $("#shpForm")?.scrollIntoView({behavior:"smooth"}), 80); };

  }

  $("#goShipments").onclick = () => { view="shipments"; render(); };


  $$("[data-open-shp]").forEach(b => b.onclick = () => {

    const id = b.getAttribute("data-open-shp");

    view="shipments"; editing.shipmentId = id;

    render();

    setTimeout(()=> $("#shpForm")?.scrollIntoView({behavior:"smooth"}), 80);

  });


  bindTabs();

}


/* ------------------ Clients ------------------ */

function renderClients(){

  const app = $("#app");

  const q = (renderClients._q || "").toLowerCase();

  const list = db.clients.filter(c => {

    const blob = `${c.ragione_sociale} ${c.partita_iva} ${c.citta} ${c.referente} ${c.email}`.toLowerCase();

    return blob.includes(q);

  });


  const editingClient = editing.clientId ? db.clients.find(c => c.id === editing.clientId) : null;


  app.innerHTML = `

    ${renderTabs()}

    <div class="grid" style="gap:14px;">

      <div class="card">

        <div class="hd">

          <div>

            <h2>Clienti</h2>

            <p>Gestisci anagrafiche clienti. CRUD completo su LocalStorage.</p>

          </div>

          <div class="row">

            <input id="clientSearch" placeholder="Cerca per ragione sociale, P.IVA, città, referente..." value="${escapeHtml(renderClients._q||"")}" style="min-width:260px;">

            <button class="btn primary" id="newClientBtn">+ Nuovo cliente</button>

          </div>

        </div>

        <div class="bd">

          <div style="overflow:auto; max-height: 420px;">

            <table class="table">

              <thead>

                <tr>

                  <th>Ragione sociale</th>

                  <th>P.IVA</th>

                  <th>Città</th>

                  <th>Referente</th>

                  <th></th>

                </tr>

              </thead>

              <tbody>

                ${list.length ? list.map(c => `

                  <tr>

                    <td><b>${escapeHtml(c.ragione_sociale)}</b><div class="muted">${escapeHtml(c.email||"")}</div></td>

                    <td>${escapeHtml(c.partita_iva||"")}</td>

                    <td>${escapeHtml(c.citta||"")}</td>

                    <td>${escapeHtml(c.referente||"")}</td>

                    <td class="row" style="justify-content:flex-end;">

                      <button class="btn" data-edit-client="${c.id}">Modifica</button>

                      <button class="btn danger" data-del-client="${c.id}">Elimina</button>

                    </td>

                  </tr>

                `).join("") : `<tr><td colspan="5" class="muted">Nessun cliente.</td></tr>`}

              </tbody>

            </table>

          </div>


          <div class="hr"></div>


          <div id="clientFormWrap">

            <div class="row" style="justify-content:space-between;">

              <div>

                <div style="font-weight:800; margin-bottom:4px;">${editingClient ? "Modifica cliente" : "Nuovo cliente"}</div>

                <div class="hint">Compila i campi e salva.</div>

              </div>

              ${editingClient ? `<button class="btn" id="cancelEditClient">Annulla modifica</button>` : ""}

            </div>


            <form id="clientForm" style="margin-top:10px;">

              <div class="split">

                <div>

                  <label>Ragione sociale *</label>

                  <input required name="ragione_sociale" value="${escapeHtml(editingClient?.ragione_sociale||"")}">

                </div>

                <div>

                  <label>Partita IVA</label>

                  <input name="partita_iva" value="${escapeHtml(editingClient?.partita_iva||"")}">

                </div>

              </div>

              <div class="split" style="margin-top:10px;">

                <div>

                  <label>Indirizzo</label>

                  <input name="indirizzo" value="${escapeHtml(editingClient?.indirizzo||"")}">

                </div>

                <div>

                  <label>Città</label>

                  <input name="citta" value="${escapeHtml(editingClient?.citta||"")}">

                </div>

                <div>

                  <label>CAP</label>

                  <input name="cap" value="${escapeHtml(editingClient?.cap||"")}">

                </div>

              </div>

              <div class="split" style="margin-top:10px;">

                <div>

                  <label>Referente</label>

                  <input name="referente" value="${escapeHtml(editingClient?.referente||"")}">

                </div>

                <div>

                  <label>Telefono</label>

                  <input name="telefono" value="${escapeHtml(editingClient?.telefono||"")}">

                </div>

                <div>

                  <label>Email</label>

                  <input type="email" name="email" value="${escapeHtml(editingClient?.email||"")}">

                </div>

              </div>

              <div style="margin-top:10px;">

                <label>Note</label>

                <textarea name="note">${escapeHtml(editingClient?.note||"")}</textarea>

              </div>

              <div class="row" style="margin-top:10px;">

                <button class="btn primary" type="submit">${editingClient ? "Salva modifiche" : "Crea cliente"}</button>

              </div>

            </form>

          </div>

        </div>

      </div>

    </div>

  `;


  $("#clientSearch").oninput = (e) => {

    renderClients._q = e.target.value || "";

    renderClients();

  };


  $("#newClientBtn").onclick = () => {

    editing.clientId = null;

    renderClients._q = renderClients._q || "";

    renderClients();

    setTimeout(()=> $("#clientFormWrap")?.scrollIntoView({behavior:"smooth"}), 80);

  };


  if(editingClient){

    $("#cancelEditClient").onclick = () => {

      editing.clientId = null;

      renderClients();

    };

  }


  $$("[data-edit-client]").forEach(b => b.onclick = () => {

    editing.clientId = b.getAttribute("data-edit-client");

    renderClients();

    setTimeout(()=> $("#clientFormWrap")?.scrollIntoView({behavior:"smooth"}), 80);

  });


  $$("[data-del-client]").forEach(b => b.onclick = () => {

    const id = b.getAttribute("data-del-client");

    // impedisci delete se usato in spedizioni

    const used = db.shipments.some(s => s.cliente_id === id);

    if(used){

      toast("Impossibile eliminare: cliente usato in una spedizione.");

      return;

    }

    db.clients = db.clients.filter(c => c.id !== id);

    saveDB(db);

    toast("Cliente eliminato");

    if(editing.clientId === id) editing.clientId = null;

    renderClients();

  });


  $("#clientForm").onsubmit = (e) => {

    e.preventDefault();

    const fd = new FormData(e.target);

    const obj = Object.fromEntries(fd.entries());

    if(!obj.ragione_sociale.trim()){

      toast("Ragione sociale obbligatoria");

      return;

    }

    if(editingClient){

      Object.assign(editingClient, obj);

      toast("Cliente aggiornato");

    }else{

      db.clients.push({ id: uid("cli"), ...obj });

      toast("Cliente creato");

      e.target.reset();

    }

    saveDB(db);

    renderClients();

  };


  bindTabs();

}


/* ------------------ Drivers ------------------ */

function renderDrivers(){

  const app = $("#app");

  const editingDriver = editing.driverId ? db.drivers.find(d => d.id === editing.driverId) : null;


  app.innerHTML = `

    ${renderTabs()}

    <div class="grid" style="gap:14px;">

      <div class="card">

        <div class="hd">

          <div>

            <h2>Autisti</h2>

            <p>Gestisci anagrafiche autisti. Gli autisti servono anche per il login mock.</p>

          </div>

          <div class="row">

            <button class="btn primary" id="newDriverBtn">+ Nuovo autista</button>

          </div>

        </div>

        <div class="bd">

          <div style="overflow:auto; max-height: 420px;">

            <table class="table">

              <thead>

                <tr>

                  <th>Nome</th>

                  <th>Telefono</th>

                  <th>Email</th>

                  <th>Targa preferita</th>

                  <th></th>

                </tr>

              </thead>

              <tbody>

                ${db.drivers.length ? db.drivers.map(d => `

                  <tr>

                    <td><b>${escapeHtml(d.nome)}</b></td>

                    <td>${escapeHtml(d.telefono||"")}</td>

                    <td>${escapeHtml(d.email||"")}</td>

                    <td>${escapeHtml(d.targa_mezzo_preferito||"")}</td>

                    <td class="row" style="justify-content:flex-end;">

                      <button class="btn" data-edit-driver="${d.id}">Modifica</button>

                      <button class="btn danger" data-del-driver="${d.id}">Elimina</button>

                    </td>

                  </tr>

                `).join("") : `<tr><td colspan="5" class="muted">Nessun autista.</td></tr>`}

              </tbody>

            </table>

          </div>


          <div class="hr"></div>


          <div id="driverFormWrap">

            <div class="row" style="justify-content:space-between;">

              <div>

                <div style="font-weight:800; margin-bottom:4px;">${editingDriver ? "Modifica autista" : "Nuovo autista"}</div>

                <div class="hint">Compila i campi e salva.</div>

              </div>

              ${editingDriver ? `<button class="btn" id="cancelEditDriver">Annulla modifica</button>` : ""}

            </div>


            <form id="driverForm" style="margin-top:10px;">

              <div class="split">

                <div>

                  <label>Nome *</label>

                  <input required name="nome" value="${escapeHtml(editingDriver?.nome||"")}">

                </div>

                <div>

                  <label>Telefono</label>

                  <input name="telefono" value="${escapeHtml(editingDriver?.telefono||"")}">

                </div>

              </div>

              <div class="split" style="margin-top:10px;">

                <div>

                  <label>Email</label>

                  <input type="email" name="email" value="${escapeHtml(editingDriver?.email||"")}">

                </div>

                <div>

                  <label>Targa mezzo preferito (opzionale)</label>

                  <input name="targa_mezzo_preferito" value="${escapeHtml(editingDriver?.targa_mezzo_preferito||"")}">

                </div>

              </div>

              <div class="row" style="margin-top:10px;">

                <button class="btn primary" type="submit">${editingDriver ? "Salva modifiche" : "Crea autista"}</button>

              </div>

            </form>

          </div>


        </div>

      </div>

    </div>

  `;


  $("#newDriverBtn").onclick = () => {

    editing.driverId = null;

    renderDrivers();

    setTimeout(()=> $("#driverFormWrap")?.scrollIntoView({behavior:"smooth"}), 80);

  };


  if(editingDriver){

    $("#cancelEditDriver").onclick = () => {

      editing.driverId = null;

      renderDrivers();

    };

  }


  $$("[data-edit-driver]").forEach(b => b.onclick = () => {

    editing.driverId = b.getAttribute("data-edit-driver");

    renderDrivers();

    setTimeout(()=> $("#driverFormWrap")?.scrollIntoView({behavior:"smooth"}), 80);

  });


  $$("[data-del-driver]").forEach(b => b.onclick = () => {

    const id = b.getAttribute("data-del-driver");

    const used = db.shipments.some(s => s.autista_id === id);

    if(used){

      toast("Impossibile eliminare: autista usato in una spedizione.");

      return;

    }

    db.drivers = db.drivers.filter(d => d.id !== id);

    saveDB(db);

    toast("Autista eliminato");

    if(editing.driverId === id) editing.driverId = null;

    renderDrivers();

  });


  $("#driverForm").onsubmit = (e) => {

    e.preventDefault();

    const fd = new FormData(e.target);

    const obj = Object.fromEntries(fd.entries());

    if(!obj.nome.trim()){

      toast("Nome obbligatorio");

      return;

    }

    if(editingDriver){

      Object.assign(editingDriver, obj);

      toast("Autista aggiornato");

    }else{

      db.drivers.push({ id: uid("drv"), ...obj });

      toast("Autista creato");

      e.target.reset();

    }

    saveDB(db);

    renderDrivers();

  };


  bindTabs();

}


/* ------------------ Shipments ------------------ */

function renderShipments(){

  const u = currentUser();

  const isAdmin = u.role === "admin";

  const app = $("#app");


  // filters

  const f = renderShipments._f || { q:"", status:"", date:"" };


  const base = isAdmin ? db.shipments : db.shipments.filter(s => s.autista_id === u.driverId);


  const list = base.filter(s => {

    const c = db.clients.find(x => x.id === s.cliente_id);

    const d = db.drivers.find(x => x.id === s.autista_id);

    const blob = `${c?.ragione_sociale||""} ${s.indirizzo_ritiro||""} ${s.indirizzo_consegna||""} ${d?.nome||""} ${s.targa_mezzo||""}`.toLowerCase();

    const qOk = !f.q || blob.includes(f.q.toLowerCase());

    const stOk = !f.status || s.stato === f.status;

    const dateOk = !f.date || s.data_ritiro === f.date || s.data_consegna === f.date;

    return qOk && stOk && dateOk;

  });


  const editingShipment = editing.shipmentId ? db.shipments.find(s => s.id === editing.shipmentId) : null;


  app.innerHTML = `

    ${renderTabs()}

    <div class="grid" style="gap:14px;">

      <div class="card">

        <div class="hd">

          <div>

            <h2>${isAdmin ? "Spedizioni" : "Le mie spedizioni"}</h2>

            <p>${isAdmin ? "Crea e assegna carichi agli autisti." : "Aggiorna stati e allega POD (firma/foto) a consegna avvenuta."}</p>

          </div>

          <div class="row">

            <input id="shpSearch" placeholder="Cerca (cliente, indirizzi, targa, autista...)" value="${escapeHtml(f.q||"")}" style="min-width:260px;">

            <select id="shpStatusFilter" style="max-width:180px;">

              <option value="">Tutti gli stati</option>

              <option value="da_caricare" ${f.status==="da_caricare"?"selected":""}>Da caricare</option>

              <option value="in_transito" ${f.status==="in_transito"?"selected":""}>In transito</option>

              <option value="consegnato" ${f.status==="consegnato"?"selected":""}>Consegnato</option>

              <option value="problema" ${f.status==="problema"?"selected":""}>Problema</option>

              <option value="partito" ${f.status==="partito"?"selected":""}>Partito</option>

              <option value="arrivato" ${f.status==="arrivato"?"selected":""}>Arrivato</option>

            </select>

            <input id="shpDateFilter" type="date" value="${escapeHtml(f.date||"")}" style="max-width:170px;">

            ${isAdmin ? `<button class="btn primary" id="newShipmentBtn">+ Nuova spedizione</button>` : ""}

          </div>

        </div>

        <div class="bd">

          <div style="overflow:auto; max-height: 440px;">

            <table class="table">

              <thead>

                <tr>

                  <th>Stato</th>

                  <th>Cliente</th>

                  <th>Ritiro</th>

                  <th>Consegna</th>

                  <th>Autista</th>

                  <th>Azioni</th>

                </tr>

              </thead>

              <tbody>

                ${list.length ? list.map(s => {

                  const c = db.clients.find(x => x.id === s.cliente_id);

                  const d = db.drivers.find(x => x.id === s.autista_id);

                  const podOk = (s.pod?.signatureDataUrl || s.pod?.photoDataUrl) ? `<span class="chip good">POD</span>` : `<span class="chip">—</span>`;

                  return `

                    <tr>

                      <td>${statusChip(s.stato)} ${podOk}</td>

                      <td><b>${escapeHtml(c?.ragione_sociale || "—")}</b><div class="muted">${escapeHtml(s.note||"")}</div></td>

                      <td>${formatDate(s.data_ritiro)}<div class="muted">${escapeHtml(s.indirizzo_ritiro||"")}</div></td>

                      <td>${formatDate(s.data_consegna)}<div class="muted">${escapeHtml(s.indirizzo_consegna||"")}</div></td>

                      <td>${escapeHtml(d?.nome || "—")}</td>

                      <td>

                        <div class="row">

                          <button class="btn" data-open-shp="${s.id}">Apri</button>

                          ${isAdmin ? `<button class="btn danger" data-del-shp="${s.id}">Elimina</button>` : ""}

                          ${!isAdmin ? `<button class="btn primary" data-pod-shp="${s.id}">POD</button>` : ""}

                        </div>

                      </td>

                    </tr>

                  `;

                }).join("") : `<tr><td colspan="6" class="muted">Nessuna spedizione trovata.</td></tr>`}

              </tbody>

            </table>

          </div>


          <div class="hr"></div>


          <div id="shpForm">

            ${isAdmin ? renderShipmentFormAdmin(editingShipment) : renderShipmentDriverPanel(editingShipment, u.driverId)}

          </div>


        </div>

      </div>

    </div>

  `;


  // bind filters

  $("#shpSearch").oninput = (e)=>{ f.q = e.target.value || ""; renderShipments._f = f; renderShipments(); };

  $("#shpStatusFilter").onchange = (e)=>{ f.status = e.target.value || ""; renderShipments._f = f; renderShipments(); };

  $("#shpDateFilter").onchange = (e)=>{ f.date = e.target.value || ""; renderShipments._f = f; renderShipments(); };


  if(isAdmin){

    $("#newShipmentBtn").onclick = () => {

      editing.shipmentId = null;

      renderShipments();

      setTimeout(()=> $("#shpForm")?.scrollIntoView({behavior:"smooth"}), 80);

    };

  }


  $$("[data-open-shp]").forEach(b => b.onclick = () => {

    editing.shipmentId = b.getAttribute("data-open-shp");

    renderShipments();

    setTimeout(()=> $("#shpForm")?.scrollIntoView({behavior:"smooth"}), 80);

  });


  $$("[data-del-shp]").forEach(b => b.onclick = () => {

    const id = b.getAttribute("data-del-shp");

    db.shipments = db.shipments.filter(s => s.id !== id);

    saveDB(db);

    toast("Spedizione eliminata");

    if(editing.shipmentId === id) editing.shipmentId = null;

    renderShipments();

  });


  $$("[data-pod-shp]").forEach(b => b.onclick = () => {

    const id = b.getAttribute("data-pod-shp");

    openPODModal(id);

  });


  // bind admin form submit

  const form = $("#shipmentFormAdmin");

  if(form){

    form.onsubmit = (e) => {

      e.preventDefault();

      const fd = new FormData(e.target);

      const obj = Object.fromEntries(fd.entries());


      // normalize numeric

      obj.colli = obj.colli ? Number(obj.colli) : 0;

      obj.peso_kg = obj.peso_kg ? Number(obj.peso_kg) : 0;

      obj.volume_mc = obj.volume_mc ? Number(obj.volume_mc) : null;


      if(!obj.cliente_id){ toast("Seleziona un cliente"); return; }

      if(!obj.autista_id){ toast("Seleziona un autista"); return; }

      if(!obj.data_ritiro){ toast("Inserisci data ritiro"); return; }

      if(!obj.indirizzo_ritiro.trim()){ toast("Inserisci luogo ritiro"); return; }

      if(!obj.data_consegna){ toast("Inserisci data consegna"); return; }

      if(!obj.indirizzo_consegna.trim()){ toast("Inserisci luogo consegna"); return; }

      if(!obj.stato){ toast("Seleziona stato"); return; }


      if(editingShipment){

        Object.assign(editingShipment, obj);

        // garantisci pod struttura

        editingShipment.pod = editingShipment.pod || { signatureDataUrl:null, photoDataUrl:null };

        toast("Spedizione aggiornata");

      }else{

        db.shipments.push({

          id: uid("shp"),

          ...obj,

          pod: { signatureDataUrl:null, photoDataUrl:null }

        });

        toast("Spedizione creata");

        e.target.reset();

      }

      saveDB(db);

      renderShipments();

    };

  }


  // bind driver quick status buttons + pod

  const panel = $("#driverPanel");

  if(panel){

    const sid = panel.getAttribute("data-sid");

    if(sid){

      $("#btnPartito")?.addEventListener("click", ()=> driverSetStatus(sid, "partito"));

      $("#btnArrivato")?.addEventListener("click", ()=> driverSetStatus(sid, "arrivato"));

      $("#btnConsegnato")?.addEventListener("click", ()=> driverSetStatus(sid, "consegnato"));

      $("#btnProblema")?.addEventListener("click", ()=> driverSetStatus(sid, "problema"));

      $("#btnPOD")?.addEventListener("click", ()=> openPODModal(sid));

    }

  }


  bindTabs();

}


function renderShipmentFormAdmin(editingShipment){

  const cOptions = db.clients.map(c => `<option value="${c.id}" ${editingShipment?.cliente_id===c.id?"selected":""}>${escapeHtml(c.ragione_sociale)}</option>`).join("");

  const dOptions = db.drivers.map(d => `<option value="${d.id}" ${editingShipment?.autista_id===d.id?"selected":""}>${escapeHtml(d.nome)}</option>`).join("");

  return `

    <div class="row" style="justify-content:space-between;">

      <div>

        <div style="font-weight:800; margin-bottom:4px;">${editingShipment ? "Dettaglio / Modifica spedizione" : "Nuova spedizione"}</div>

        <div class="hint">Crea o aggiorna una scheda carico/spedizione.</div>

      </div>

      ${editingShipment ? `<button class="btn" id="cancelEditShipment">Annulla modifica</button>` : ""}

    </div>


    <form id="shipmentFormAdmin" style="margin-top:10px;">

      <div class="split">

        <div>

          <label>Cliente *</label>

          <select name="cliente_id" required>

            <option value="">Seleziona cliente</option>

            ${cOptions}

          </select>

        </div>

        <div>

          <label>Autista assegnato *</label>

          <select name="autista_id" required>

            <option value="">Seleziona autista</option>

            ${dOptions}

          </select>

        </div>

      </div>


      <div class="split" style="margin-top:10px;">

        <div>

          <label>Data ritiro *</label>

          <input type="date" name="data_ritiro" value="${escapeHtml(editingShipment?.data_ritiro||todayISO())}" required>

        </div>

        <div>

          <label>Luogo ritiro (indirizzo completo) *</label>

          <input name="indirizzo_ritiro" value="${escapeHtml(editingShipment?.indirizzo_ritiro||"")}" required>

        </div>

      </div>


      <div class="split" style="margin-top:10px;">

        <div>

          <label>Data consegna *</label>

          <input type="date" name="data_consegna" value="${escapeHtml(editingShipment?.data_consegna||todayISO())}" required>

        </div>

        <div>

          <label>Luogo consegna (indirizzo completo) *</label>

          <input name="indirizzo_consegna" value="${escapeHtml(editingShipment?.indirizzo_consegna||"")}" required>

        </div>

      </div>


      <div class="split" style="margin-top:10px;">

        <div>

          <label>Numero colli</label>

          <input type="number" min="0" name="colli" value="${escapeHtml(editingShipment?.colli ?? "")}">

        </div>

        <div>

          <label>Peso (kg)</label>

          <input type="number" min="0" step="0.1" name="peso_kg" value="${escapeHtml(editingShipment?.peso_kg ?? "")}">

        </div>

        <div>

          <label>Volume (mc) (opzionale)</label>

          <input type="number" min="0" step="0.01" name="volume_mc" value="${escapeHtml(editingShipment?.volume_mc ?? "")}">

        </div>

      </div>


      <div class="split" style="margin-top:10px;">

        <div>

          <label>Mezzo / Targa</label>

          <input name="targa_mezzo" value="${escapeHtml(editingShipment?.targa_mezzo||"")}">

        </div>

        <div>

          <label>Stato spedizione *</label>

          <select name="stato" required>

            <option value="da_caricare" ${editingShipment?.stato==="da_caricare"?"selected":""}>Da caricare</option>

            <option value="in_transito" ${editingShipment?.stato==="in_transito"?"selected":""}>In transito</option>

            <option value="consegnato" ${editingShipment?.stato==="consegnato"?"selected":""}>Consegnato</option>

            <option value="problema" ${editingShipment?.stato==="problema"?"selected":""}>Problema</option>

            <option value="partito" ${editingShipment?.stato==="partito"?"selected":""}>Partito</option>

            <option value="arrivato" ${editingShipment?.stato==="arrivato"?"selected":""}>Arrivato</option>

          </select>

        </div>

      </div>


      <div style="margin-top:10px;">

        <label>Note</label>

        <textarea name="note">${escapeHtml(editingShipment?.note||"")}</textarea>

      </div>


      <div class="row" style="margin-top:10px;">

        <button class="btn primary" type="submit">${editingShipment ? "Salva modifiche" : "Crea spedizione"}</button>

      </div>

    </form>

  `;

}


function renderShipmentDriverPanel(editingShipment, driverId){

  // se non c'è selezione, prendi la prima del driver

  const my = db.shipments.filter(s => s.autista_id === driverId);

  const current = editingShipment && editingShipment.autista_id === driverId ? editingShipment : (my[0] || null);


  if(!current){

    return `<div class="hint">Nessuna spedizione assegnata.</div>`;

  }


  const c = db.clients.find(x => x.id === current.cliente_id);

  const hasPOD = !!(current.pod?.signatureDataUrl || current.pod?.photoDataUrl);


  // mostra detail + quick actions

  return `

    <div id="driverPanel" data-sid="${current.id}">

      <div class="row" style="justify-content:space-between;">

        <div>

          <div style="font-weight:800; margin-bottom:4px;">Dettaglio spedizione</div>

          <div class="hint">Cliente: <b>${escapeHtml(c?.ragione_sociale||"—")}</b> — ${statusChip(current.stato)} ${hasPOD ? `<span class="chip good">POD salvato</span>` : `<span class="chip">POD mancante</span>`}</div>

        </div>

        <button class="btn primary" id="btnPOD">Apri POD</button>

      </div>


      <div class="card" style="margin-top:10px; background: rgba(15,23,42,.55); box-shadow:none;">

        <div class="bd">

          <div class="split">

            <div>

              <div class="muted" style="font-size:12px;">Ritiro</div>

              <div><b>${formatDate(current.data_ritiro)}</b></div>

              <div class="muted">${escapeHtml(current.indirizzo_ritiro||"")}</div>

            </div>

            <div>

              <div class="muted" style="font-size:12px;">Consegna</div>

              <div><b>${formatDate(current.data_consegna)}</b></div>

              <div class="muted">${escapeHtml(current.indirizzo_consegna||"")}</div>

            </div>

          </div>

          <div class="hr"></div>

          <div class="split">

            <div><span class="chip">Colli: <b>${Number(current.colli||0)}</b></span></div>

            <div><span class="chip">Peso: <b>${Number(current.peso_kg||0)}</b> kg</span></div>

            <div><span class="chip">Targa: <b>${escapeHtml(current.targa_mezzo||"—")}</b></span></div>

          </div>

          <div class="hr"></div>

          <div class="hint">${escapeHtml(current.note||"")}</div>

        </div>

      </div>


      <div class="hr"></div>

      <div>

        <div style="font-weight:800; margin-bottom:6px;">Aggiorna stato</div>

        <div class="row">

          <button class="btn" id="btnPartito">Partito</button>

          <button class="btn" id="btnArrivato">Arrivato</button>

          <button class="btn primary" id="btnConsegnato">Consegnato</button>

          <button class="btn danger" id="btnProblema">Problema</button>

        </div>

        <div class="footer-note">Consiglio: a “Consegnato” apri POD e salva almeno firma o foto.</div>

      </div>

    </div>

  `;

}


function driverSetStatus(shipmentId, newStatus){

  const s = db.shipments.find(x => x.id === shipmentId);

  if(!s) return;

  s.stato = newStatus;

  saveDB(db);

  toast("Stato aggiornato: " + newStatus.replaceAll("_"," "));

  renderShipments();

}


/* ------------------ POD Modal (Signature + Photo) ------------------ */

const modal = $("#modalPOD");

const sigCanvas = $("#sigCanvas");

const sigCtx = sigCanvas.getContext("2d");

let sigDrawing = false;

let sigHasInk = false;

let pendingPhotoDataUrl = null;


function openPODModal(shipmentId){

  podEditingShipmentId = shipmentId;

  const s = db.shipments.find(x => x.id === shipmentId);

  if(!s) return;

  const c = db.clients.find(x => x.id === s.cliente_id);


  $("#podTitle").textContent = "POD - Prova di consegna";

  $("#podSubtitle").textContent = `Spedizione: ${c?.ragione_sociale || "—"} • Stato: ${s.stato.replaceAll("_"," ")}`;


  // reset canvas & load existing signature

  clearSignature();

  if(s.pod?.signatureDataUrl){

    const img = new Image();

    img.onload = () => {

      // draw to canvas with proper scaling

      sigCtx.clearRect(0,0,sigCanvas.width,sigCanvas.height);

      sigCtx.drawImage(img, 0, 0, sigCanvas.width, sigCanvas.height);

      sigHasInk = true;

    };

    img.src = s.pod.signatureDataUrl;

  }


  // load photo preview

  pendingPhotoDataUrl = null;

  $("#podPhotoInput").value = "";

  renderPhotoPreview(s.pod?.photoDataUrl || null);


  modal.style.display = "block";

}


function closePODModal(){

  modal.style.display = "none";

  podEditingShipmentId = null;

  pendingPhotoDataUrl = null;

}


function clearSignature(){

  sigCtx.clearRect(0,0,sigCanvas.width,sigCanvas.height);

  // background subtle

  sigCtx.fillStyle = "rgba(3,7,18,.15)";

  sigCtx.fillRect(0,0,sigCanvas.width,sigCanvas.height);

  sigCtx.fillStyle = "rgba(229,231,235,1)";

  sigHasInk = false;

}


function renderPhotoPreview(dataUrl){

  const box = $("#podPhotoPreview");

  if(!dataUrl){

    box.innerHTML = `<div class="hint" style="padding:12px;">Nessuna foto salvata.</div>`;

    return;

  }

  box.innerHTML = `<img alt="Foto POD" src="${dataUrl}">`;

}


// Signature drawing (mouse + touch)

function getCanvasPos(e){

  const rect = sigCanvas.getBoundingClientRect();

  const touch = e.touches && e.touches[0];

  const clientX = touch ? touch.clientX : e.clientX;

  const clientY = touch ? touch.clientY : e.clientY;

  const x = (clientX - rect.left) * (sigCanvas.width / rect.width);

  const y = (clientY - rect.top) * (sigCanvas.height / rect.height);

  return {x,y};

}


function sigStart(e){

  e.preventDefault();

  sigDrawing = true;

  const p = getCanvasPos(e);

  sigCtx.beginPath();

  sigCtx.moveTo(p.x, p.y);

}

function sigMove(e){

  if(!sigDrawing) return;

  e.preventDefault();

  const p = getCanvasPos(e);

  sigCtx.lineWidth = 4;

  sigCtx.lineCap = "round";

  sigCtx.strokeStyle = "rgba(229,231,235,.95)";

  sigCtx.lineTo(p.x, p.y);

  sigCtx.stroke();

  sigHasInk = true;

}

function sigEnd(e){

  if(!sigDrawing) return;

  e.preventDefault();

  sigDrawing = false;

  sigCtx.closePath();

}


sigCanvas.addEventListener("mousedown", sigStart);

sigCanvas.addEventListener("mousemove", sigMove);

window.addEventListener("mouseup", sigEnd);

sigCanvas.addEventListener("touchstart", sigStart, {passive:false});

sigCanvas.addEventListener("touchmove", sigMove, {passive:false});

sigCanvas.addEventListener("touchend", sigEnd, {passive:false});


$("#podCloseBtn").onclick = closePODModal;

modal.addEventListener("click", (e)=>{ if(e.target === modal) closePODModal(); });


$("#sigClearBtn").onclick = () => {

  clearSignature();

  toast("Firma pulita");

};


$("#sigSaveBtn").onclick = () => {

  if(!podEditingShipmentId) return;

  const s = db.shipments.find(x => x.id === podEditingShipmentId);

  if(!s) return;

  if(!sigHasInk){

    toast("Disegna una firma prima di salvare");

    return;

  }

  s.pod = s.pod || { signatureDataUrl:null, photoDataUrl:null };

  s.pod.signatureDataUrl = sigCanvas.toDataURL("image/png");

  saveDB(db);

  toast("Firma POD salvata");

  // refresh table badges

  render();

};


$("#podPhotoInput").addEventListener("change", async (e)=>{

  const file = e.target.files && e.target.files[0];

  if(!file) return;

  // convert to base64 dataURL

  const reader = new FileReader();

  reader.onload = () => {

    pendingPhotoDataUrl = reader.result;

    renderPhotoPreview(pendingPhotoDataUrl);

  };

  reader.readAsDataURL(file);

});


$("#podPhotoSaveBtn").onclick = () => {

  if(!podEditingShipmentId) return;

  const s = db.shipments.find(x => x.id === podEditingShipmentId);

  if(!s) return;

  if(!pendingPhotoDataUrl){

    toast("Carica una foto prima di salvare");

    return;

  }

  s.pod = s.pod || { signatureDataUrl:null, photoDataUrl:null };

  s.pod.photoDataUrl = pendingPhotoDataUrl;

  saveDB(db);

  toast("Foto POD salvata");

  render();

};


$("#podPhotoDelBtn").onclick = () => {

  if(!podEditingShipmentId) return;

  const s = db.shipments.find(x => x.id === podEditingShipmentId);

  if(!s) return;

  s.pod = s.pod || { signatureDataUrl:null, photoDataUrl:null };

  s.pod.photoDataUrl = null;

  pendingPhotoDataUrl = null;

  saveDB(db);

  renderPhotoPreview(null);

  toast("Foto rimossa");

  render();

};


// init signature background

clearSignature();


/* ------------------ Main Render ------------------ */

function render(){

  db = loadDB(); // reload (safe)

  renderTopRight();


  const u = currentUser();

  if(!u){

    renderLogin();

    return;

  }


  // route

  if(view === "dashboard") renderDashboard();

  else if(view === "clients") renderClients();

  else if(view === "drivers") renderDrivers();

  else if(view === "shipments") renderShipments();

  else renderDashboard();


  // bind cancel buttons (admin forms)

  $("#cancelEditShipment")?.addEventListener("click", ()=>{

    editing.shipmentId = null;

    renderShipments();

  });

}


// boot

render();


</script>

</body>

</html>