update mescole and photo diagram
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
<?php
|
||||
ini_set('display_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
include('include/headscript.php');
|
||||
$db = DBHandlerSelect::getInstance();
|
||||
$pdo = $db->getConnection();
|
||||
@@ -265,7 +268,12 @@ if (!empty($_GET['ajax'])) {
|
||||
$sql = "SELECT
|
||||
p.*,
|
||||
m.nome AS matrice,
|
||||
ms.nome AS mescola,
|
||||
(
|
||||
SELECT GROUP_CONCAT(m.nome ORDER BY m.nome SEPARATOR ' | ')
|
||||
FROM productiondata_mescole pm
|
||||
JOIN mescole m ON m.id = pm.id_mescola
|
||||
WHERE pm.id_productiondata = p.id
|
||||
) AS mescole_list,
|
||||
l.name AS linea,
|
||||
c.nome AS cliente,
|
||||
s.nome AS status_nome,
|
||||
@@ -274,7 +282,6 @@ if (!empty($_GET['ajax'])) {
|
||||
p.tempo_totale_produzione
|
||||
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
|
||||
@@ -287,14 +294,31 @@ if (!empty($_GET['ajax'])) {
|
||||
$records = $stmt->fetchAll();
|
||||
|
||||
foreach ($records as $r) {
|
||||
|
||||
// --- PARAMETRI LINEA (slot dinamici)
|
||||
$sqlParams = "SELECT position, short_label, icon
|
||||
FROM production_line_params
|
||||
WHERE line_id = :line
|
||||
ORDER BY position ASC";
|
||||
$stmtP = $pdo->prepare($sqlParams);
|
||||
$stmtP->execute(['line' => $r['id_linea']]);
|
||||
$paramsLinea = $stmtP->fetchAll();
|
||||
|
||||
$r['param_slots'] = $paramsLinea;
|
||||
|
||||
include __DIR__ . "/render_production_card.php";
|
||||
}
|
||||
|
||||
// --- RECORD IN STATO 6 ORDINATI PER PRIORITY
|
||||
$sql2 = "SELECT
|
||||
p.*,
|
||||
m.nome AS matrice,
|
||||
ms.nome AS mescola,
|
||||
m.nome AS matrice,
|
||||
(
|
||||
SELECT GROUP_CONCAT(m2.nome ORDER BY m2.nome SEPARATOR ' | ')
|
||||
FROM productiondata_mescole pm
|
||||
JOIN mescole m2 ON m2.id = pm.id_mescola
|
||||
WHERE pm.id_productiondata = p.id
|
||||
) AS mescole_list,
|
||||
l.name AS linea,
|
||||
c.nome AS cliente,
|
||||
s.nome AS status_nome,
|
||||
@@ -303,13 +327,13 @@ if (!empty($_GET['ajax'])) {
|
||||
p.tempo_totale_produzione
|
||||
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
|
||||
WHERE p.id_status = 6
|
||||
" . (!empty($lineArray) ? " AND p.id_linea IN (" . implode(',', array_map('intval', $lineArray)) . ")" : "") . "
|
||||
ORDER BY p.priority ASC";
|
||||
" . (!empty($lineArray) ? " AND p.id_linea IN (" . implode(',', array_map('intval', $lineArray)) . ")" : "") . "
|
||||
ORDER BY p.priority ASC
|
||||
";
|
||||
|
||||
$stmt2 = $pdo->prepare($sql2);
|
||||
$stmt2->execute();
|
||||
@@ -790,6 +814,83 @@ if (!empty($_GET['ajax'])) {
|
||||
max-width: 1200px !important;
|
||||
width: 95% !important;
|
||||
}
|
||||
|
||||
/* Mantiene stile identico ai bottoni delle foto */
|
||||
/* Stesso stile dei photo-btn */
|
||||
.qc-btn {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid #000000;
|
||||
/* bordo nero */
|
||||
background: #c8f3df;
|
||||
/* verde pastello interno */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: 0.2s ease;
|
||||
}
|
||||
|
||||
.qc-btn i {
|
||||
font-size: 1.8rem;
|
||||
color: #000000;
|
||||
/* icona nera */
|
||||
}
|
||||
|
||||
.qc-btn:hover {
|
||||
background: #b3e9d3;
|
||||
/* leggero scurimento */
|
||||
transform: scale(1.07);
|
||||
}
|
||||
|
||||
.param-grid {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.param-grid {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.param-slot {
|
||||
background: #ffffff;
|
||||
border-radius: 12px;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
border: 2px solid #e2e8f0;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.08);
|
||||
transition: 0.2s ease;
|
||||
}
|
||||
|
||||
.param-slot:hover {
|
||||
border-color: #3b82f6;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.thumb {
|
||||
width: 100%;
|
||||
height: 75px;
|
||||
background: #f1f5f9;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.thumb-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.param-label {
|
||||
margin-top: 6px;
|
||||
font-weight: 700;
|
||||
font-size: 1rem;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
@@ -952,37 +1053,6 @@ if (!empty($_GET['ajax'])) {
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||
<script>
|
||||
$(document).on("mousedown", function(e) {
|
||||
|
||||
// 🔥 Se clicco sulla X, non chiudere altri modali
|
||||
if ($(e.target).attr("id") === "previewCloseX") {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// --- Se il PREVIEW è aperto ---
|
||||
if ($("#imagePreviewModal").hasClass("active")) {
|
||||
|
||||
// click fuori → chiudi SOLO il preview
|
||||
if ($(e.target).closest("#imagePreviewModal .modal-content").length === 0) {
|
||||
$("#imagePreviewModal").removeClass("active");
|
||||
}
|
||||
|
||||
return; // 🔥 BLOCCA la chiusura del photoModal
|
||||
}
|
||||
|
||||
// --- Se è aperto solo il PHOTO MODAL ---
|
||||
if ($("#photoModal").hasClass("active")) {
|
||||
if ($(e.target).closest("#photoModal .modal-content").length === 0) {
|
||||
$("#photoModal").removeClass("active");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function showPhotoSuccess() {
|
||||
$("#photoMessageError").hide();
|
||||
$("#photoMessageSuccess").fadeIn(150);
|
||||
@@ -997,13 +1067,15 @@ if (!empty($_GET['ajax'])) {
|
||||
$("#photoMessageError").text("⚠️ " + msg).fadeIn(150);
|
||||
}
|
||||
|
||||
function loadPhotoGallery(productionId, type) {
|
||||
function loadPhotoGallery(productionId, type, slot = null) {
|
||||
$("#photoGallery").html('<div style="color:#64748b;">Caricamento foto...</div>');
|
||||
|
||||
$.getJSON("get_photos.php", {
|
||||
production_id: productionId,
|
||||
photo_type: type
|
||||
photo_type: type,
|
||||
param_position: slot
|
||||
}, function(r) {
|
||||
|
||||
if (!r.success) {
|
||||
$("#photoGallery").html(
|
||||
'<div style="color:#b91c1c;">Errore nel caricamento delle foto.</div>'
|
||||
@@ -1012,60 +1084,58 @@ if (!empty($_GET['ajax'])) {
|
||||
}
|
||||
|
||||
const photos = r.photos || [];
|
||||
|
||||
if (photos.length === 0) {
|
||||
$("#photoGallery").html(
|
||||
'<div style="color:#64748b;">Nessuna foto registrata per questa tipologia.</div>'
|
||||
'<div style="color:#64748b;">Nessuna foto per questa posizione.</div>'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let html = "";
|
||||
photos.forEach(p => {
|
||||
const aiLabel = p.ai_processed == 1 ? ' (AI✔)' : '';
|
||||
|
||||
html += `
|
||||
<div style="width:90px; text-align:center; font-size:0.7rem;">
|
||||
<div class="photo-thumb"
|
||||
data-full="photos/${p.filename}"
|
||||
style="width:90px; height:70px; border-radius:8px; overflow:hidden; border:1px solid #e2e8f0; margin-bottom:4px; cursor:pointer;">
|
||||
<img src="photos/${p.filename}"
|
||||
alt="photo"
|
||||
style="width:100%; height:100%; object-fit:cover;">
|
||||
</div>
|
||||
<div style="color:#475569; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">
|
||||
#${p.id}${aiLabel}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
<div style="width:90px; text-align:center; font-size:0.7rem;">
|
||||
<div class="photo-thumb"
|
||||
data-full="photos/${p.filename}"
|
||||
style="width:90px; height:70px; border-radius:8px; overflow:hidden; border:1px solid #e2e8f0; margin-bottom:4px; cursor:pointer;">
|
||||
<img src="photos/${p.filename}" alt="photo"
|
||||
style="width:100%; height:100%; object-fit:cover;">
|
||||
</div>
|
||||
<div style="color:#475569;">#${p.id}</div>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
|
||||
|
||||
$("#photoGallery").html(html);
|
||||
}).fail(function() {
|
||||
$("#photoGallery").html(
|
||||
'<div style="color:#b91c1c;">Errore di connessione nel caricamento delle foto.</div>'
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// APRI PREVIEW — evento CLICK (non mousedown)
|
||||
$(document).on("click", ".photo-thumb", function(e) {
|
||||
e.stopPropagation(); // evita che il click chiuda subito il modale
|
||||
|
||||
const fullImage = $(this).data("full");
|
||||
|
||||
$("#previewImage").attr("src", fullImage);
|
||||
|
||||
$("#imagePreviewModal").addClass("active");
|
||||
});
|
||||
|
||||
// chiusura preview con X
|
||||
$("#previewCloseX").on("click", function(e) {
|
||||
// 🔥 chiusura preview con X - DELEGATO
|
||||
$(document).on("click", "#previewCloseX", function(e) {
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation(); // 🔥 blocca davvero tutto
|
||||
$("#imagePreviewModal").removeClass("active");
|
||||
});
|
||||
|
||||
// opzionale: chiudi cliccando fuori dal contenuto (sull’overlay scuro)
|
||||
$(document).on("click", "#imagePreviewModal", function(e) {
|
||||
if ($(e.target).is("#imagePreviewModal")) {
|
||||
$("#imagePreviewModal").removeClass("active");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
// chiusura modale principale (upload foto)
|
||||
@@ -1172,17 +1242,50 @@ if (!empty($_GET['ajax'])) {
|
||||
$("#photoModal").addClass("active");
|
||||
});
|
||||
|
||||
// FOTO PARAMETRI MACCHINA (7 posizioni)
|
||||
$(document).on("click", ".param-slot", function(e) {
|
||||
e.stopPropagation();
|
||||
|
||||
$("#photoCancel").on("click", () => {
|
||||
$("#photoModal").removeClass("active");
|
||||
const slot = $(this).data("slot");
|
||||
const productionId = $(this).data("production");
|
||||
|
||||
$("#photoType").val("parametri_macchina");
|
||||
$("#photoProductionId").val(productionId);
|
||||
$("#photoParamPosition").val(slot);
|
||||
|
||||
$("#photoModalTitle").text("Foto Parametro P" + slot);
|
||||
$("#photoModalSubtitle").text("Produzione ID: " + productionId);
|
||||
|
||||
loadPhotoGallery(productionId, "parametri_macchina", slot);
|
||||
|
||||
$("#photoModal").addClass("active");
|
||||
});
|
||||
|
||||
|
||||
$("#photoCancel").off("click").on("click", () => {
|
||||
$("#photoModal").removeClass("active");
|
||||
// 🔥 ricarica le card (e quindi le thumbnail) via AJAX
|
||||
loadRecords();
|
||||
});
|
||||
|
||||
$("#photoModalCloseX").off("click").on("click", function() {
|
||||
$("#photoModal").removeClass("active");
|
||||
// 🔥 stessa logica: al close ricarico le card
|
||||
loadRecords();
|
||||
});
|
||||
|
||||
|
||||
// --- SUBMIT FORM FOTO ---
|
||||
$("#photoForm").off("submit").on("submit", function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
let formData = new FormData(this);
|
||||
|
||||
// 🔥 mostra loader, disabilita submit
|
||||
$("#photoMessageSuccess, #photoMessageError").hide();
|
||||
$("#photoLoading").show();
|
||||
$("#photoForm .modal-confirm").prop("disabled", true);
|
||||
|
||||
$.ajax({
|
||||
url: "upload_photo.php",
|
||||
type: "POST",
|
||||
@@ -1191,18 +1294,23 @@ if (!empty($_GET['ajax'])) {
|
||||
contentType: false,
|
||||
dataType: "json",
|
||||
success: function(r) {
|
||||
$("#photoLoading").hide();
|
||||
$("#photoForm .modal-confirm").prop("disabled", false);
|
||||
|
||||
if (r.success) {
|
||||
// conferma + refresh galleria
|
||||
showPhotoSuccess();
|
||||
loadPhotoGallery(
|
||||
$("#photoProductionId").val(),
|
||||
$("#photoType").val()
|
||||
$("#photoType").val(),
|
||||
$("#photoParamPosition").val() || null
|
||||
);
|
||||
} else {
|
||||
showPhotoError(r.message || "Errore durante il caricamento della foto.");
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
$("#photoLoading").hide();
|
||||
$("#photoForm .modal-confirm").prop("disabled", false);
|
||||
showPhotoError("Errore di comunicazione con il server.");
|
||||
}
|
||||
});
|
||||
@@ -1210,6 +1318,7 @@ if (!empty($_GET['ajax'])) {
|
||||
|
||||
|
||||
|
||||
|
||||
$('.record-card.in-production').each(function() {
|
||||
const $card = $(this);
|
||||
const $expanded = $card.find('.record-expanded');
|
||||
@@ -1550,6 +1659,34 @@ if (!empty($_GET['ajax'])) {
|
||||
|
||||
loadRecords();
|
||||
});
|
||||
|
||||
// --- MODALE MESCOLE ---
|
||||
$(document).on("click", ".showMescole", function(e) {
|
||||
e.stopPropagation();
|
||||
|
||||
// prendo la stringa grezza dall’attributo, NON .data()
|
||||
const raw = $(this).attr("data-list") || "[]";
|
||||
let list = [];
|
||||
|
||||
try {
|
||||
list = JSON.parse(raw);
|
||||
} catch (err) {
|
||||
console.error("Errore parsing mescole:", err, raw);
|
||||
list = [];
|
||||
}
|
||||
|
||||
let html = "";
|
||||
list.forEach(m => {
|
||||
html += `<li style="margin:6px 0;font-size:1.1rem;">${m}</li>`;
|
||||
});
|
||||
|
||||
$("#mescoleList").html(html || '<li style="margin:6px 0;">Nessuna mescola</li>');
|
||||
$("#mescoleModal").addClass("active");
|
||||
});
|
||||
|
||||
$(document).on("click", "#closeMescole", function() {
|
||||
$("#mescoleModal").removeClass("active");
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- MODALE PER PREVIEW IMMAGINE -->
|
||||
@@ -1588,6 +1725,42 @@ if (!empty($_GET['ajax'])) {
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- MODALE MESCOLE -->
|
||||
<div id="mescoleModal" class="modal">
|
||||
<div class="modal-content" style="max-width:400px;">
|
||||
<h3>Mescole utilizzate</h3>
|
||||
|
||||
<ul id="mescoleList" style="text-align:left; padding-left:1rem;"></ul>
|
||||
|
||||
<div class="modal-buttons">
|
||||
<button class="modal-btn modal-cancel" id="closeMescole">Chiudi</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// apre il file picker sul campo interno al form
|
||||
$(document).on("click", "#choosePhotoBtn", function(e) {
|
||||
e.stopPropagation();
|
||||
$("#photoInput").click();
|
||||
});
|
||||
|
||||
// mostra solo il nome file scelto (opzionale)
|
||||
$(document).on("change", "#photoInput", function() {
|
||||
const file = this.files[0];
|
||||
if (!file) return;
|
||||
$("#selectedPhotoName").text(file.name);
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user