diff --git a/public/userarea/ajax_update_priority.php b/public/userarea/ajax_update_priority.php index f89efa4..482c88a 100644 --- a/public/userarea/ajax_update_priority.php +++ b/public/userarea/ajax_update_priority.php @@ -13,11 +13,12 @@ foreach ($programmati as $p) { $stmt->execute([$p["priority"], $p["id"]]); } -foreach ($daProgrammare as $id) { - $stmt = $pdo->prepare("UPDATE productiondata SET id_status=1, priority=NULL WHERE id=?"); - $stmt->execute([$id]); +foreach ($daProgrammare as $p) { + $stmt = $pdo->prepare("UPDATE productiondata SET id_status=1, priority=? WHERE id=?"); + $stmt->execute([$p["priority"], $p["id"]]); } + $pdo->commit(); echo json_encode(["success" => true]); diff --git a/public/userarea/assets/placeholder-photo.png b/public/userarea/assets/placeholder-photo.png new file mode 100644 index 0000000..d707a41 Binary files /dev/null and b/public/userarea/assets/placeholder-photo.png differ diff --git a/public/userarea/components/param_grid.php b/public/userarea/components/param_grid.php new file mode 100644 index 0000000..f136216 --- /dev/null +++ b/public/userarea/components/param_grid.php @@ -0,0 +1,43 @@ +prepare(" + SELECT param_position, filename + FROM production_photos + WHERE production_id = ? + AND photo_type = 'parametri_macchina' +"); +$stmt->execute([$r['id']]); + +foreach ($stmt->fetchAll() as $p) { + $photosSlots[(int)$p['param_position']] = $p['filename']; +} + +// Slot dinamici per la linea +$slots = $r['param_slots'] ?? []; + +if (empty($slots)) { + echo "
Nessun parametro configurato per questa linea.
"; + return; +} +?> + +
+ + +
+
+ + + + + +
+
+
+ +
\ No newline at end of file diff --git a/public/userarea/components/photo_buttons.php b/public/userarea/components/photo_buttons.php index 1264a2e..37269e7 100644 --- a/public/userarea/components/photo_buttons.php +++ b/public/userarea/components/photo_buttons.php @@ -1,4 +1,4 @@ -
+
+ +
+ + + + + + +
\ No newline at end of file diff --git a/public/userarea/components/photo_modal.php b/public/userarea/components/photo_modal.php index 9cf5401..46227de 100644 --- a/public/userarea/components/photo_modal.php +++ b/public/userarea/components/photo_modal.php @@ -20,24 +20,41 @@ ⚠️ Errore durante il caricamento.
-
- + + + +
- + +
+ + + + + + -
+

Foto già registrate per questa tipologia

@@ -46,9 +63,5 @@ style="display:flex; flex-wrap:wrap; gap:10px; max-height:220px; overflow-y:auto; padding:4px 0;"> - - - - \ No newline at end of file diff --git a/public/userarea/get_photos.php b/public/userarea/get_photos.php index 22e1e99..e1a1265 100644 --- a/public/userarea/get_photos.php +++ b/public/userarea/get_photos.php @@ -8,22 +8,39 @@ try { $production_id = isset($_GET['production_id']) ? (int)$_GET['production_id'] : 0; $photo_type = $_GET['photo_type'] ?? ''; + $slot = isset($_GET['param_position']) ? (int)$_GET['param_position'] : null; if ($production_id <= 0 || $photo_type === '') { throw new Exception("Parametri non validi"); } - $stmt = $pdo->prepare(" + // QUERY BASE + $sql = " SELECT id, filename, photo_type, created_at, elaborato FROM production_photos - WHERE production_id = :prod AND photo_type = :ptype - ORDER BY created_at DESC, id DESC - "); - $stmt->execute([ + WHERE production_id = :prod + AND photo_type = :ptype + "; + + // SE È PARAMETRO MACCHINA → FILTRO PER POSIZIONE + if ($photo_type === 'parametri_macchina') { + $sql .= " AND param_position = :slot"; + } + + $sql .= " ORDER BY created_at DESC, id DESC"; + + $stmt = $pdo->prepare($sql); + + $params = [ ':prod' => $production_id, ':ptype' => $photo_type - ]); + ]; + if ($photo_type === 'parametri_macchina') { + $params[':slot'] = $slot; + } + + $stmt->execute($params); $photos = $stmt->fetchAll(PDO::FETCH_ASSOC); echo json_encode([ diff --git a/public/userarea/manager_produzione.php b/public/userarea/manager_produzione.php index bdd604b..b8ba1c9 100644 --- a/public/userarea/manager_produzione.php +++ b/public/userarea/manager_produzione.php @@ -8,22 +8,33 @@ $linee = $pdo->query("SELECT id, line_number, name FROM production_lines ORDER B $status_list = $pdo->query("SELECT id, nome, badge_color, line_color FROM production_status ORDER BY ordinamento, nome")->fetchAll(PDO::FETCH_ASSOC); // --- CARICO TUTTE LE PRODUZIONI UNA VOLTA SOLA --- -$sql = "SELECT - p.*, - m.nome AS matrice, - ms.nome AS mescola, - l.name AS linea, - c.nome AS cliente, - s.nome AS status_nome, - COALESCE(s.badge_color, '#6c757d') AS badge_color, - COALESCE(s.line_color, '#ffffff') AS line_color - FROM productiondata p - LEFT JOIN matrice m ON p.idmatrice = m.id - LEFT JOIN mescole ms ON p.idmescola = ms.id - LEFT JOIN production_lines l ON p.id_linea = l.id - LEFT JOIN clients c ON p.id_cliente = c.id - LEFT JOIN production_status s ON p.id_status = s.id - ORDER BY p.data_produzione DESC, p.Data DESC, p.id DESC"; +$sql = " + SELECT + p.*, + m.nome AS matrice, + l.name AS linea, + c.nome AS cliente, + s.nome AS status_nome, + COALESCE(s.badge_color, '#6c757d') AS badge_color, + COALESCE(s.line_color, '#ffffff') AS line_color, + + /* 🔥 NUOVA LISTA MESCOLE MULTI */ + GROUP_CONCAT(ms.nome ORDER BY ms.nome SEPARATOR ' | ') AS mescole_list + + FROM productiondata p + LEFT JOIN matrice m ON p.idmatrice = m.id + LEFT JOIN production_lines l ON p.id_linea = l.id + LEFT JOIN clients c ON p.id_cliente = c.id + LEFT JOIN production_status s ON p.id_status = s.id + + /* NUOVA JOIN A TABELLA MESCOLE */ + LEFT JOIN productiondata_mescole pm ON p.id = pm.id_productiondata + LEFT JOIN mescole ms ON pm.id_mescola = ms.id + + GROUP BY p.id + ORDER BY p.data_produzione DESC, p.Data DESC, p.id DESC +"; + $rows = $pdo->query($sql)->fetchAll(PDO::FETCH_ASSOC); @@ -210,7 +221,24 @@ $rows_special = array_filter($rows, function ($r) { data-seconds="" style="--rowcolor: ;"> - + + + + N/A + + + + + + + @@ -307,7 +335,24 @@ $rows_special = array_filter($rows, function ($r) { data-status="" style="background-color: ;"> - + + + + N/A + + + + + + + diff --git a/public/userarea/match_matrici_foto.php b/public/userarea/match_matrici_foto.php new file mode 100644 index 0000000..dd340f3 --- /dev/null +++ b/public/userarea/match_matrici_foto.php @@ -0,0 +1,69 @@ +getConnection(); + +$folder = __DIR__ . "/photos/matrici/"; // cartella corretta +$files = scandir($folder); + +function normalize($str) +{ + $str = strtolower($str); + $str = preg_replace('/[^a-z0-9]/', '', $str); // rimuove tutto ciò che non è alfanumerico + return $str; +} + +// Carico matrici +$sql = "SELECT id, nome FROM matrice"; +$matrici = $pdo->query($sql)->fetchAll(PDO::FETCH_ASSOC); + +$matched = []; +$unmatchedPhotos = []; + +foreach ($files as $file) { + + // ignora file nascosti, . e .. + if ($file === "." || $file === "..") continue; + + $fileNoExt = pathinfo($file, PATHINFO_FILENAME); + $normFile = normalize($fileNoExt); + + $found = false; + + foreach ($matrici as $m) { + + $normNome = normalize($m['nome']); + + if ($normNome === "") continue; // evita errori su record vuoti + + // MATCHING: inizia con oppure contiene + if (strpos($normFile, $normNome) === 0 || strpos($normFile, $normNome) !== false) { + + $update = $pdo->prepare("UPDATE matrice SET photo = ? WHERE id = ?"); + $update->execute([$file, $m['id']]); + + $matched[] = [$file, $m['nome']]; + $found = true; + break; + } + } + + if (!$found) { + $unmatchedPhotos[] = $file; + } +} + +// RISULTATO: + +echo "

✔ FOTO ASSOCIATE

"; +if (empty($matched)) echo "Nessuna foto trovata"; +foreach ($matched as $m) { + echo "✔ {$m[0]} → Matrice: {$m[1]}
"; +} + +echo "

❌ FOTO NON ASSOCIATE

"; +if (empty($unmatchedPhotos)) echo "Tutte le foto hanno trovato una matrice!"; +foreach ($unmatchedPhotos as $u) { + echo "❌ $u
"; +} diff --git a/public/userarea/matrici.php b/public/userarea/matrici.php index ab941d4..2944e36 100644 --- a/public/userarea/matrici.php +++ b/public/userarea/matrici.php @@ -38,18 +38,10 @@ .back-dashboard { background-color: #b9ebc7 !important; color: #1f2d3d !important; - border: 1px solid #a1d7b4 !important; border-radius: 10px; font-weight: 600; font-size: 1rem; padding: 10px 18px; - box-shadow: 0 3px 8px rgba(0, 0, 0, 0.1); - transition: all 0.2s ease-in-out; - } - - .back-dashboard:hover { - background-color: #a1dfb1 !important; - transform: translateY(-2px); } .btn-add { @@ -57,29 +49,13 @@ color: #fff; border-radius: 8px; padding: 10px 20px; - font-weight: 500; - transition: all 0.2s ease-in-out; - } - - .btn-add:hover { - background-color: #157347; - transform: scale(1.02); } .table thead { background-color: #b9ebc7; - color: #1f2d3d; text-align: center; } - .table tbody td { - vertical-align: middle; - } - - .modal-content { - border-radius: 16px; - } - .action-btn { border: none; background: none; @@ -88,26 +64,26 @@ margin: 0 4px; } - .action-btn.edit { + .edit { color: #0d6efd; } - .action-btn.delete { + .delete { color: #dc3545; } - .action-btn.linee { + .linee { color: #198754; } - .action-btn.mescole { + .mescole { color: #ff9800; } - .dataTables_filter input { - border-radius: 8px; - padding: 6px 10px; - border: 1px solid #ced4da; + .thumb-img:hover { + transform: scale(1.05); + transition: 0.2s; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); } @@ -120,14 +96,14 @@
+
Gestione Matrici
- +
+
Elenco Completo
@@ -138,33 +114,98 @@ - - + + + + + + getConnection(); + $stmt = $pdo->query("SELECT * FROM matrice ORDER BY id DESC"); + + function formatDateIT($d) + { + if (!$d || $d == '0000-00-00') return ''; + return date("d/m/Y", strtotime($d)); + } + if ($stmt->rowCount() === 0) { - echo ""; + echo ""; } else { while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { - echo " - - - - "; + + $dataIT = formatDateIT($row['data_produzione']); + + // gestione foto + $foto = $row['photo'] ?? ''; + $pathFoto = "photos/matrici/" . $foto; + $placeholder = "assets/images/no-photo.png"; + + if ($foto && file_exists($pathFoto)) { + $thumb = $pathFoto; + $hasPhoto = true; + } else { + $thumb = $placeholder; + $hasPhoto = false; + } + + echo ""; + + // colonna FOTO + echo ""; + + // colonna NOME + echo ""; + + // colonna CLIENTE + echo ""; + + // colonna DATA + echo ""; + + // colonna AZIONI + echo ""; + + echo ""; } } + + ?> +
IDNome MatriceFotoNomeClienteData Azioni
Nessuna matrice presente
Nessuna matrice presente
{$row['id']}" . htmlspecialchars($row['nome']) . " - - - - -
+ + " . htmlspecialchars($row['nome']) . "" . htmlspecialchars($row['cliente']) . "{$dataIT} + + + + + + + +
@@ -176,82 +217,59 @@
- - +
@@ -172,48 +171,92 @@ - + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/userarea/produzione_programmazione_drag.php b/public/userarea/produzione_programmazione_drag.php index dd94468..4afec16 100644 --- a/public/userarea/produzione_programmazione_drag.php +++ b/public/userarea/produzione_programmazione_drag.php @@ -23,50 +23,105 @@ function selectOptions($arr, $sel = null, $val = 'id', $txt = 'nome') // --- SALVATAGGIO INLINE --- if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['action'])) { $action = $_POST['action']; + $data = [ - 'Data' => $_POST['Data'], - 'idmatrice' => $_POST['idmatrice'], - 'idmescola' => $_POST['idmescola'], - 'id_linea' => $_POST['id_linea'], - 'id_cliente' => $_POST['id_cliente'] ?: null, - 'data_zibo' => $_POST['data_zibo'] ?: null, - 'data_cliente' => $_POST['data_cliente'] ?: null, - 'metri' => $_POST['metri'] ?: 0, - 'kg_sp' => $_POST['kg_sp'] ?: 0, - 'kg_p' => $_POST['kg_p'] ?: 0, - 'ore_previste' => $_POST['ore_previste'] ?: 0, - 'note_extra' => $_POST['note_extra'] ?: null, - 'data_produzione' => $_POST['data_produzione'], - 'id_status' => $_POST['id_status'] ?? 1 + 'idmatrice' => $_POST['idmatrice'], + 'id_linea' => $_POST['id_linea'], + 'id_cliente' => $_POST['id_cliente'] ?: null, + 'data_zibo' => $_POST['data_zibo'] ?: null, + 'data_cliente' => $_POST['data_cliente'] ?: null, + 'metri' => $_POST['metri'] ?: 0, + 'kg_sp' => $_POST['kg_sp'] ?: 0, + 'kg_p' => $_POST['kg_p'] ?: 0, + 'ore_previste' => $_POST['ore_previste'] ?: 0, + 'note_extra' => $_POST['note_extra'] ?: null, + 'id_status' => $_POST['id_status'] ?? 1 ]; + try { + + // ============================ + // INSERT + // ============================ if ($action === 'insert') { + $sql = "INSERT INTO productiondata - (Data, idmatrice, idmescola, id_linea, id_cliente, data_zibo, data_cliente, metri, kg_sp, kg_p, ore_previste, note_extra, data_produzione, id_status) - VALUES - (:Data, :idmatrice, :idmescola, :id_linea, :id_cliente, :data_zibo, :data_cliente, :metri, :kg_sp, :kg_p, :ore_previste, :note_extra, :data_produzione, :id_status)"; - $stmt = $pdo->prepare($sql); - $stmt->execute($data); - echo json_encode(['success' => true]); - } elseif ($action === 'update' && !empty($_POST['id'])) { - $data['id'] = $_POST['id']; - $sql = "UPDATE productiondata SET - Data=:Data, idmatrice=:idmatrice, idmescola=:idmescola, id_linea=:id_linea, - id_cliente=:id_cliente, data_zibo=:data_zibo, data_cliente=:data_cliente, - metri=:metri, kg_sp=:kg_sp, kg_p=:kg_p, ore_previste=:ore_previste, - note_extra=:note_extra, data_produzione=:data_produzione, id_status=:id_status - WHERE id = :id"; + (Data, idmatrice, id_linea, id_cliente, data_zibo, data_cliente, + metri, kg_sp, kg_p, ore_previste, note_extra, data_produzione, id_status) + VALUES + (:Data, :idmatrice, :id_linea, :id_cliente, :data_zibo, :data_cliente, + :metri, :kg_sp, :kg_p, :ore_previste, :note_extra, :data_produzione, :id_status)"; + $stmt = $pdo->prepare($sql); $stmt->execute($data); + + // QUI devi prendere il nuovo ID + $idProd = $pdo->lastInsertId(); + + // cancella vecchie associazioni (non serve ma per sicurezza) + $pdo->prepare("DELETE FROM productiondata_mescole WHERE id_productiondata=?") + ->execute([$idProd]); + + // aggiungi nuove + if (!empty($_POST['mescole'])) { + $ins = $pdo->prepare("INSERT INTO productiondata_mescole (id_productiondata, id_mescola) VALUES (?, ?)"); + foreach ($_POST['mescole'] as $m) { + $ins->execute([$idProd, $m]); + } + } + echo json_encode(['success' => true]); } + + // ============================ + // UPDATE + // ============================ + elseif ($action === 'update' && !empty($_POST['id'])) { + + $data['id'] = $_POST['id']; + + $sql = "UPDATE productiondata SET + idmatrice=:idmatrice, + id_linea=:id_linea, + id_cliente=:id_cliente, + data_zibo=:data_zibo, + data_cliente=:data_cliente, + metri=:metri, + kg_sp=:kg_sp, + kg_p=:kg_p, + ore_previste=:ore_previste, + note_extra=:note_extra, + id_status=:id_status + WHERE id = :id + "; + + $stmt = $pdo->prepare($sql); + $stmt->execute($data); + + // QUI devi usare L'ID ESISTENTE ! + $idProd = $_POST['id']; + + $pdo->prepare("DELETE FROM productiondata_mescole WHERE id_productiondata=?") + ->execute([$idProd]); + + if (!empty($_POST['mescole'])) { + $ins = $pdo->prepare("INSERT INTO productiondata_mescole (id_productiondata, id_mescola) VALUES (?, ?)"); + foreach ($_POST['mescole'] as $m) { + $ins->execute([$idProd, $m]); + } + } + + echo json_encode(['success' => true]); + } + exit; } catch (Exception $e) { echo json_encode(['success' => false, 'msg' => $e->getMessage()]); exit; } } + ?> @@ -310,21 +365,25 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['action'])) { query($sql)->fetchAll(PDO::FETCH_ASSOC); ?> @@ -497,7 +556,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['action'])) { - @@ -636,7 +695,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['action'])) { // --- INLINE EDIT --- let original = {}; - $('#tabProgrammazione').on('click', '.edit-row', function() { + $('table').on('click', '.edit-row', function() { const tr = $(this).closest('tr'); original = tr.find('.view').map((i, e) => $(e).html()).get(); tr.find('.view').hide(); @@ -653,7 +712,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['action'])) { }); }); - $('#tabProgrammazione').on('click', '.cancel-row', function() { + $('table').on('click', '.cancel-row', function() { const tr = $(this).closest('tr'); tr.find('.view').show().each((i, e) => $(e).html(original[i])); tr.find('.inline-edit').hide(); @@ -662,8 +721,10 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['action'])) { tr.find('.inline-edit.select2').select2('destroy'); }); - $('#tabProgrammazione').on('click', '.save-row', function() { + $('table').on('click', '.save-row', function() { + const tr = $(this).closest('tr'); + const data = tr.find('.inline-edit').serializeArray(); data.push({ name: 'action', @@ -672,9 +733,19 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['action'])) { name: 'id', value: tr.data('id') }); - $.post('', data, r => r.success ? location.reload() : alert(r.msg || 'Errore'), 'json'); + + $.post('', data, function(r) { + if (r.success) { + location.reload(); + } else { + alert(r.msg || 'Errore salvataggio'); + } + }, 'json'); + }); + + // --- ELIMINAZIONE --- let deleteRow; $('#tabProgrammazione').on('click', '.delete-row', function(e) { @@ -755,19 +826,27 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['action'])) { function updatePriority() { + let programmati = []; let daProgrammare = []; + // → Righe nella tabella PROGRAMMATI (status deve diventare 6) $("#programmatiBlock tr").each(function(index) { programmati.push({ + id: $(this).data("id"), + priority: index + 1, + status: 6 + }); + }); + + // → Righe nella tabella DA PROGRAMMARE (status deve diventare 1) + $("#daProgrammareBlock tr").each(function(index) { + daProgrammare.push({ id: $(this).data("id"), priority: index + 1 }); }); - $("#daProgrammareBlock tr").each(function() { - daProgrammare.push($(this).data("id")); - }); $.post("ajax_update_priority.php", { programmati: JSON.stringify(programmati), @@ -776,11 +855,12 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['action'])) { if (response.success) { location.reload(); } else { - alert("Errore aggiornamento priorità"); + alert("Errore aggiornamento priorità: " + response.msg); } }, "json"); } + }); @@ -814,7 +894,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['action'])) {
- @@ -976,6 +1056,21 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['action'])) { $("#imagePreviewModal").hide(); } }); + + $(document).on("click", ".view-mescole-btn", function() { + + let names = $(this).data("names"); + let html = ""; + + names.split(",").forEach(n => { + html += `
${n.trim()}
`; + }); + + $("#mescoleList").html(html); + + let modal = new bootstrap.Modal(document.getElementById("modalMescoleView")); + modal.show(); + }); @@ -998,6 +1093,24 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['action'])) {
+ diff --git a/public/userarea/quality_grid.php b/public/userarea/quality_grid.php new file mode 100644 index 0000000..19585f8 --- /dev/null +++ b/public/userarea/quality_grid.php @@ -0,0 +1,181 @@ + + + + + + + + + + Esempio Griglia Qualità - <?= htmlspecialchars($titlewebsite, ENT_QUOTES, 'UTF-8'); ?> + + + + + + +

Esempio Griglia Controlli Qualità

+ + = $min; $v -= $step) { + $rows[] = round($v, 2); + } + + // Asse X (20 misurazioni demo) + $colonne = range(1, 20); + ?> + +
+ + + + + + + + + + + + + + + + + + + + + + + +
Valore
+
+ +
+

Click su una cella per inserire una misurazione.

+

Nominale: riga verde | Tolleranze: righe gialle

+
+ + + + + + \ No newline at end of file diff --git a/public/userarea/render_production_card.php b/public/userarea/render_production_card.php index e847bae..ec5cfda 100644 --- a/public/userarea/render_production_card.php +++ b/public/userarea/render_production_card.php @@ -51,7 +51,31 @@ $statusNome = $r['status_nome'];
Linea
Matrice
-
Mescola
+ + +
+ Mescola + + + N/A + + + + + + + +
Cliente
Zibo
Data Cl.
@@ -77,6 +101,29 @@ $statusNome = $r['status_nome']; 00:00:00
+ prepare(" + SELECT param_position, filename + FROM production_photos + WHERE production_id = ? + AND photo_type = 'parametri_macchina' +"); + $stmt->execute([$r['id']]); + foreach ($stmt->fetchAll() as $p) { + $photosSlots[(int)$p['param_position']] = $p['filename']; + } + + // 👉 Include la griglia parametri con le variabili già disponibili + $paramsLinea = $r['param_slots'] ?? []; + include __DIR__ . "/components/param_grid.php"; + ?> + diff --git a/public/userarea/row_production.php b/public/userarea/row_production.php index d5bc350..8bd08b6 100644 --- a/public/userarea/row_production.php +++ b/public/userarea/row_production.php @@ -2,13 +2,18 @@ - - - '> - + + + + '> + + + + + @@ -20,13 +25,53 @@ - - + + + + + + +