From 3f5c14836f886b3defa7e187550abafe05fca553 Mon Sep 17 00:00:00 2001 From: solocla Date: Tue, 20 Oct 2026 08:59:38 +0200 Subject: [PATCH] fixed dettaglio worksheet --- .../userarea/ajax/worksheet-linked-data.php | 38 +- .../assets/js/worksheets-linked-modals.js | 582 +++++++++++------- .../include/worksheets-linked-modals.php | 184 +++++- 3 files changed, 584 insertions(+), 220 deletions(-) diff --git a/public/userarea/ajax/worksheet-linked-data.php b/public/userarea/ajax/worksheet-linked-data.php index 793a5347..59dc772c 100644 --- a/public/userarea/ajax/worksheet-linked-data.php +++ b/public/userarea/ajax/worksheet-linked-data.php @@ -167,6 +167,7 @@ try { exit; } + // Mescole del foglio $stmtMix = $pdo->prepare(" SELECT wsm.*, @@ -180,6 +181,30 @@ try { $stmtMix->execute([$worksheetId]); $mixRows = $stmtMix->fetchAll(PDO::FETCH_ASSOC); + // Imballi del foglio (come nella sezione 3 di manage-worksheet.php) + $stmtPkg = $pdo->prepare(" + SELECT + wsp.id, + wsp.package_position, + pi.category AS package_category, + pi.item_name AS package_name, + pi.item_code AS package_item_code + FROM work_sheet_packages wsp + LEFT JOIN packaging_items pi ON pi.id = wsp.package_code + WHERE wsp.worksheet_id = ? + ORDER BY wsp.package_position ASC, wsp.id ASC + "); + $stmtPkg->execute([$worksheetId]); + $packageRows = $stmtPkg->fetchAll(PDO::FETCH_ASSOC); + + // Etichette dei menu a tendina (marchiatura, frequenze controllo, lubrificazione...) + // Prese tutte, anche le disattivate, così i fogli vecchi mostrano comunque l'etichetta + $lookups = []; + $stmtLk = $pdo->query("SELECT category, value, label FROM ws_lookup_options"); + foreach ($stmtLk->fetchAll(PDO::FETCH_ASSOC) as $r) { + $lookups[$r['category']][(string)$r['value']] = $r['label']; + } + echo json_encode([ 'success' => true, 'worksheet' => [ @@ -218,6 +243,7 @@ try { 'speed_actual_m_h' => $ws['speed_actual_m_h'] ?? '', 'approved_by' => $ws['approved_by'] ?? '', 'notes' => $ws['notes'] ?? '', + 'source_xlsx_path' => $ws['source_xlsx_path'] ?? '', 'created_at' => $ws['created_at'] ?? '', 'created_at_it' => formatDateTimeIT($ws['created_at'] ?? ''), 'updated_at' => $ws['updated_at'] ?? '', @@ -235,7 +261,17 @@ try { 'lubrication_type' => $r['lubrication_type'] ?? '', 'lubrication_notes' => $r['lubrication_notes'] ?? '' ]; - }, $mixRows) + }, $mixRows), + 'package_rows' => array_map(function ($r) { + return [ + 'id' => (int)$r['id'], + 'package_position' => (int)$r['package_position'], + 'package_category' => $r['package_category'] ?? '', + 'package_name' => $r['package_name'] ?? '', + 'package_item_code' => $r['package_item_code'] ?? '' + ]; + }, $packageRows), + 'lookups' => (object)$lookups ]); exit; } diff --git a/public/userarea/assets/js/worksheets-linked-modals.js b/public/userarea/assets/js/worksheets-linked-modals.js index 88eab707..d045eccb 100644 --- a/public/userarea/assets/js/worksheets-linked-modals.js +++ b/public/userarea/assets/js/worksheets-linked-modals.js @@ -1,6 +1,6 @@ (function () { function escapeHtml(str) { - return String(str || "") + return String(str === null || str === undefined ? "" : str) .replace(/&/g, "&") .replace(//g, ">") @@ -8,16 +8,57 @@ .replace(/'/g, "'"); } - function valueOrDash(v) { - return v === null || v === undefined || String(v).trim() === "" - ? "—" - : escapeHtml(v); + function isEmpty(v) { + return v === null || v === undefined || String(v).trim() === ""; } - function renderReadonlyField(label, value) { + function valueOrDash(v) { + return isEmpty(v) ? "—" : escapeHtml(v); + } + + // Traduce il valore salvato (es. "every_2h") nell'etichetta del menu a tendina, + // usando le etichette di ws_lookup_options restituite dall'endpoint. + // Se l'etichetta non c'è, mostra il valore così com'è. + function lookupLabel(lookups, category, value) { + if (isEmpty(value)) return ""; + const map = lookups && lookups[category]; + if (map && map[String(value)] !== undefined) return map[String(value)]; + return value; + } + + // Campo in sola lettura: etichetta piccola sopra, valore in evidenza sotto + function wsdField(label, value, extraClass) { + const empty = isEmpty(value); return ` -
${escapeHtml(label)}
-
${valueOrDash(value)}
+
+
${escapeHtml(label)}
+
${valueOrDash(value)}
+
+ `; + } + + // Blocco di testo lungo (note, misure di controllo) + function wsdText(label, value, emptyText) { + const empty = isEmpty(value); + return ` +
+ ${label ? `
${escapeHtml(label)}
` : ""} +
${empty ? escapeHtml(emptyText || "—") : escapeHtml(value)}
+
+ `; + } + + function wsdSection(theme, title, badge, body, colClass) { + return ` +
+
+
+ ${title} + ${badge ? `${badge}` : ""} +
+
${body}
+
+
`; } @@ -292,10 +333,316 @@ }); } + // ================================================================ + // Dettaglio foglio di lavoro (sola lettura) + // Rispecchia le sezioni di manage-worksheet.php: + // 1 Dati principali · 2 Controlli · 3 Imballo · 4 Velocità · 5 Note · 6 Mescole + // ================================================================ + function renderWorksheetDetail(data) { + const ws = data.worksheet || {}; + const mixRows = data.mix_rows || []; + const packageRows = data.package_rows || []; + const lookups = data.lookups || {}; + + const isInactive = ws.worksheet_status === "inactive"; + const statusLabel = + ws.worksheet_status_label || (isInactive ? "Inattivo" : "Attivo"); + const statusBadge = isInactive + ? `${escapeHtml(statusLabel)}` + : `${escapeHtml(statusLabel)}`; + + const cliente = ws.customer_name || ws.matrice_cliente || ""; + + // ---------- Intestazione ---------- + const excelLink = ws.source_xlsx_path + ? ` + Excel di origine + ` + : ""; + + const headerHtml = ` +
+
+
+

${escapeHtml(ws.worksheet_number_label || "—")} / Rev. ${escapeHtml(ws.revision_label || "0")}

+ ${ws.matrice_nome ? "Profilo: " + escapeHtml(ws.matrice_nome) : "Nessun profilo collegato"} +
+
+ ${excelLink} + + Apri foglio completo + +
+
+
+ `; + + // ---------- Striscia riepilogo ---------- + const summaryHtml = ` +
+
+
Stato
+
${statusBadge}
+
+
+
Cliente
+
${valueOrDash(cliente)}
+
+
+
Codice profilo
+
${valueOrDash(ws.profile_type_code)}
+
+
+
Data foglio
+
${valueOrDash(ws.worksheet_date_it)}
+
+
+
Mescole / Imballi
+
${mixRows.length} / ${packageRows.length}
+
+
+ `; + + // ---------- 1. Dati principali ---------- + const sec1 = wsdSection( + "blue", + "1. Dati principali", + "", + ` +
+ ${wsdField("Matrice / Profilo", ws.matrice_nome)} + ${wsdField("Data foglio", ws.worksheet_date_it)} + ${wsdField("Codice profilo", ws.profile_type_code)} + ${wsdField("Cliente (override)", ws.customer_name)} + ${wsdField("Marchiatura", lookupLabel(lookups, "marking", ws.marking))} + ${wsdField("Visto / Approvazione", ws.approved_by)} +
+
+ Creato il ${valueOrDash(ws.created_at_it)} · Ultimo aggiornamento ${valueOrDash(ws.updated_at_it)} +
+ `, + "col-lg-6", + ); + + // ---------- 2. Controlli di produzione ---------- + const sec2 = wsdSection( + "green", + "2. Controlli di produzione", + "", + ` +
+ ${wsdField("Taglio", lookupLabel(lookups, "control_frequency_cut", ws.control_frequency_cut))} + ${wsdField("Disegno", lookupLabel(lookups, "control_frequency_drawing", ws.control_frequency_drawing))} + ${wsdField("Dima", lookupLabel(lookups, "control_frequency_jig", ws.control_frequency_jig))} + ${wsdField("Modalità dima", lookupLabel(lookups, "control_mode_jig", ws.control_mode_jig))} +
+ ${wsdText("Impostazione misure controllo produzione", ws.prod_control_measure_settings, "Nessuna indicazione")} + `, + "col-lg-6", + ); + + // ---------- 3. Imballo e confezionamento ---------- + let packagesHtml = `
Nessun imballo associato
`; + if (packageRows.length) { + packagesHtml = ` +
+ + + + + + + + + + ${packageRows + .map( + (p) => ` + + + + + `, + ) + .join("")} + +
PosCategoriaImballo
${valueOrDash(p.package_position)}${valueOrDash(p.package_category)} +
${valueOrDash(p.package_name)}
+ ${p.package_item_code ? `
${escapeHtml(p.package_item_code)}
` : ""} +
+
+ `; + } + + const sec3 = wsdSection( + "orange", + "3. Imballo e confezionamento", + `${packageRows.length} imball${packageRows.length === 1 ? "o" : "i"}`, + ` +
+
+ ${packagesHtml} +
+
+
+ ${wsdField("Metri per confezione", ws.meters_per_package)} + ${wsdField("Tolleranza metri/conf.", ws.meters_per_package_tolerance)} + ${wsdField("Conf./pezzi per scatola", ws.packages_or_pieces_per_box)} + ${wsdField("Metri per scatola", ws.meters_per_box)} + ${wsdField("Scatole/conf. per bancale", ws.boxes_or_packages_per_pallet)} +
+ ${wsdText("Note metri/confezione", ws.meters_per_package_notes, "Nessuna nota")} +
+
+ `, + "col-12", + ); + + // ---------- 4. Velocità di produzione ---------- + const sec4 = wsdSection( + "purple", + "4. Velocità di produzione", + "", + ` + + + + + + + + + + + + + + + + +
PrevistaEffettiva
kg/h${valueOrDash(ws.speed_expected_kg_h)}${valueOrDash(ws.speed_actual_kg_h)}
m/h${valueOrDash(ws.speed_expected_m_h)}${valueOrDash(ws.speed_actual_m_h)}
+ `, + "col-lg-6", + ); + + // ---------- 5. Note finali ---------- + const sec5 = wsdSection( + "gray", + "5. Note finali", + "", + wsdText("", ws.notes, "Nessuna nota"), + "col-lg-6", + ); + + // ---------- 6. Mescole ---------- + let mixHtml = `
Nessuna mescola associata
`; + if (mixRows.length) { + mixHtml = ` +
+ + + + + + + + + + + + + + ${mixRows + .map( + (r) => ` + + + + + + + + + `, + ) + .join("")} + +
PosMescolaPeso g/mDensitàDurezza (Sh A)LubrificazioneNote lubr.
${valueOrDash(r.mix_position)} +
${valueOrDash(r.mescola_nome)}
+ ${r.mescola_uscita ? `
${escapeHtml(r.mescola_uscita)}
` : ""} +
${valueOrDash(r.mix_weight_g_m)}${valueOrDash(r.required_density)}${valueOrDash(r.required_hardness_shore_a)}${valueOrDash(lookupLabel(lookups, "lubrication_type", r.lubrication_type))}${valueOrDash(r.lubrication_notes)}
+
+ `; + } + + const sec6 = wsdSection( + "cyan", + "6. Mescole associate al foglio", + `${mixRows.length} rig${mixRows.length === 1 ? "a" : "he"}`, + mixHtml, + "col-12", + ); + + const datiHtml = ` + ${summaryHtml} +
+ ${sec1} + ${sec2} + ${sec3} + ${sec4} + ${sec5} + ${sec6} +
+ `; + + // ---------- Tab allegati ---------- + const attTabsHtml = Object.keys(WS_ATT_KINDS) + .map((k) => { + const c = WS_ATT_KINDS[k]; + return ` + `; + }) + .join(""); + + const attPanesHtml = Object.keys(WS_ATT_KINDS) + .map((k) => { + const c = WS_ATT_KINDS[k]; + return ` +
+
+
Caricamento ${escapeHtml(c.label.toLowerCase())}...
+
+
`; + }) + .join(""); + + return ` + ${headerHtml} + +
+ + ${attTabsHtml} +
+ +
+ ${datiHtml} +
+ + ${attPanesHtml} + `; + } + window.loadWorksheetDetail = function (worksheetId, endpoint) { endpoint = endpoint || "ajax/worksheet-linked-data.php"; - $("#worksheetDetailContainer").html( + const $box = $("#worksheetDetailContainer"); + $box.html( '
Caricamento dettaglio foglio...
', ); @@ -317,10 +664,9 @@ }) .then((data) => { if (!data.success) { - console.error("Errore worksheets:", data); - - $("#worksheetsListContainer").html( - '
Errore nel caricamento dei fogli: ' + + console.error("Errore dettaglio foglio:", data); + $box.html( + '
Errore nel caricamento del foglio: ' + escapeHtml( data.message || "nessun dettaglio restituito", ) + @@ -329,213 +675,13 @@ return; } - const ws = data.worksheet || {}; - const mixRows = data.mix_rows || []; - - let mixHtml = `
Nessuna mescola associata
`; - - if (mixRows.length) { - mixHtml = ` -
- - - - - - - - - - - - - - `; - - mixRows.forEach((r) => { - const nomeMescola = r.mescola_uscita - ? `${escapeHtml(r.mescola_nome || "—")}
${escapeHtml(r.mescola_uscita)}
` - : escapeHtml(r.mescola_nome || "—"); - - mixHtml += ` - - - - - - - - - - `; - }); - - mixHtml += ` - -
PosMescolaPeso g/mDensitàDurezzaLubr.Note lubr.
${escapeHtml(String(r.mix_position || ""))}${nomeMescola}${valueOrDash(r.mix_weight_g_m)}${valueOrDash(r.required_density)}${valueOrDash(r.required_hardness_shore_a)}${valueOrDash(r.lubrication_type)}${valueOrDash(r.lubrication_notes)}
-
- `; - } - - const headerHtml = ` -
-
-
-

${escapeHtml(ws.worksheet_number_label || "—")} / Rev. ${escapeHtml(ws.revision_label || "0")}

- - Stato: ${escapeHtml(ws.worksheet_status_label || "Attivo")} - ${ws.matrice_nome ? " • Profilo: " + escapeHtml(ws.matrice_nome) : ""} - ${ws.matrice_cliente ? " • Cliente matrice: " + escapeHtml(ws.matrice_cliente) : ""} - -
- -
-
- - `; - - const html = ` -
-
-
-
Dati principali
-
-
- ${renderReadonlyField("Foglio", ws.worksheet_number_label)} - ${renderReadonlyField("Revisione", ws.revision_label)} - ${renderReadonlyField("Stato", ws.worksheet_status_label)} - ${renderReadonlyField("Data foglio", ws.worksheet_date_it)} - ${renderReadonlyField("Cliente override", ws.customer_name)} - ${renderReadonlyField("Codice profilo", ws.profile_type_code)} - ${renderReadonlyField("Marchiatura", ws.marking)} - ${renderReadonlyField("Approvato da", ws.approved_by)} - ${renderReadonlyField("Creato il", ws.created_at_it)} - ${renderReadonlyField("Ultimo aggiornamento", ws.updated_at_it)} -
-
-
-
- -
-
-
Controlli produzione
-
-
- ${renderReadonlyField("Taglio", ws.control_frequency_cut)} - ${renderReadonlyField("Disegno", ws.control_frequency_drawing)} - ${renderReadonlyField("Dima", ws.control_frequency_jig)} - ${renderReadonlyField("Modalità dima", ws.control_mode_jig)} -
-
-
Impostazione misure controllo produzione
-
${valueOrDash(ws.prod_control_measure_settings)}
-
-
-
- -
-
-
Packaging / Confezionamento
-
-
- ${renderReadonlyField("Codice confezione", ws.requested_package_code)} - ${renderReadonlyField("Metri per confezione", ws.meters_per_package)} - ${renderReadonlyField("Tolleranza metri/conf.", ws.meters_per_package_tolerance)} - ${renderReadonlyField("Scatola tipo", ws.box_type)} - ${renderReadonlyField("Conf./pezzi per scatola", ws.packages_or_pieces_per_box)} - ${renderReadonlyField("Metri per scatola", ws.meters_per_box)} - ${renderReadonlyField("Bancale tipo", ws.pallet_type)} - ${renderReadonlyField("Scatole/conf. per bancale", ws.boxes_or_packages_per_pallet)} -
-
-
Note metri / confezione
-
${valueOrDash(ws.meters_per_package_notes)}
-
-
-
- -
-
-
Velocità e note
-
-
- ${renderReadonlyField("Vel. prevista kg/h", ws.speed_expected_kg_h)} - ${renderReadonlyField("Vel. effettiva kg/h", ws.speed_actual_kg_h)} - ${renderReadonlyField("Vel. prevista m/h", ws.speed_expected_m_h)} - ${renderReadonlyField("Vel. effettiva m/h", ws.speed_actual_m_h)} -
-
-
Note
-
${valueOrDash(ws.notes)}
-
-
-
- -
-
-
Mescole associate al foglio
-
- ${mixHtml} -
-
-
-
- `; - - const attTabsHtml = Object.keys(WS_ATT_KINDS) - .map((k) => { - const c = WS_ATT_KINDS[k]; - return ` - `; - }) - .join(""); - - const attPanesHtml = Object.keys(WS_ATT_KINDS) - .map((k) => { - const c = WS_ATT_KINDS[k]; - return ` -
-
-
Caricamento ${escapeHtml(c.label.toLowerCase())}...
-
-
`; - }) - .join(""); - - const fullHtml = ` - ${headerHtml} - -
- - ${attTabsHtml} -
- -
- ${html} -
- - ${attPanesHtml} - `; - - $("#worksheetDetailContainer").html(fullHtml); - loadWorksheetAttachments(ws.idmatrice); + $box.html(renderWorksheetDetail(data)); + loadWorksheetAttachments((data.worksheet || {}).idmatrice); }) .catch((err) => { - console.error("Catch loadMatriceWorksheets:", err); - - $("#worksheetsListContainer").html( - '
Errore nel caricamento dei fogli: ' + + console.error("Errore dettaglio foglio:", err); + $box.html( + '
Errore nel caricamento del foglio: ' + escapeHtml(err.message || "errore JavaScript/fetch") + "
", ); diff --git a/public/userarea/include/worksheets-linked-modals.php b/public/userarea/include/worksheets-linked-modals.php index 792c58fd..23545aab 100644 --- a/public/userarea/include/worksheets-linked-modals.php +++ b/public/userarea/include/worksheets-linked-modals.php @@ -134,6 +134,188 @@ max-height: 100%; object-fit: contain; } + + /* ================================================================ + Dettaglio foglio in sola lettura (stesse sezioni e colori + di manage-worksheet.php) + ================================================================ */ + .wsd-summary { + display: grid; + grid-template-columns: repeat(5, minmax(0, 1fr)); + gap: 10px; + } + + .wsd-sum-item { + background: #fff; + border: 1px solid #e5edf6; + border-radius: 14px; + padding: 10px 14px; + box-shadow: 0 4px 12px rgba(15, 23, 42, 0.04); + min-width: 0; + } + + .wsd-sum-value { + font-size: 1.05rem; + font-weight: 800; + color: #111827; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .wsd-section { + border: 1px solid #e7edf5; + border-radius: 16px; + background: #fff; + overflow: hidden; + height: 100%; + box-shadow: 0 4px 12px rgba(15, 23, 42, 0.03); + } + + .wsd-head { + display: flex; + justify-content: space-between; + align-items: center; + gap: 10px; + padding: 10px 16px; + font-weight: 800; + font-size: 1rem; + } + + .wsd-head-badge { + background: rgba(255, 255, 255, .7); + border-radius: 999px; + padding: 3px 10px; + font-size: .78rem; + font-weight: 700; + } + + .wsd-body { + padding: 14px 16px; + } + + .wsd-blue .wsd-head { + background: linear-gradient(135deg, #dbeafe, #bfdbfe); + color: #123b7a; + } + + .wsd-green .wsd-head { + background: linear-gradient(135deg, #dcfce7, #bbf7d0); + color: #14532d; + } + + .wsd-orange .wsd-head { + background: linear-gradient(135deg, #ffedd5, #fed7aa); + color: #9a3412; + } + + .wsd-purple .wsd-head { + background: linear-gradient(135deg, #ede9fe, #ddd6fe); + color: #5b21b6; + } + + .wsd-gray .wsd-head { + background: linear-gradient(135deg, #f3f4f6, #e5e7eb); + color: #374151; + } + + .wsd-cyan .wsd-head { + background: linear-gradient(135deg, #cffafe, #a5f3fc); + color: #155e75; + } + + .wsd-fields { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); + gap: 12px 16px; + } + + .wsd-label { + font-size: .75rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: .03em; + color: #6b7280; + margin-bottom: 2px; + } + + .wsd-value { + font-size: 1.02rem; + font-weight: 700; + color: #111827; + word-break: break-word; + } + + .wsd-empty { + color: #b6bec9 !important; + font-weight: 400 !important; + font-style: italic; + } + + .wsd-text-block { + margin-top: 14px; + } + + .wsd-text { + background: #f8fafc; + border: 1px solid #e9eef5; + border-radius: 10px; + padding: 10px 12px; + white-space: pre-wrap; + word-break: break-word; + color: #1f2937; + } + + .wsd-meta { + margin-top: 14px; + padding-top: 10px; + border-top: 1px dashed #e5e7eb; + font-size: .82rem; + color: #6b7280; + } + + .wsd-table thead th { + background: #eef4fb !important; + color: #163a63; + font-weight: 800; + font-size: .88rem; + } + + .wsd-speed { + width: 100%; + border-collapse: separate; + border-spacing: 0 6px; + } + + .wsd-speed thead th { + font-size: .75rem; + font-weight: 700; + text-transform: uppercase; + color: #6b7280; + text-align: center; + } + + .wsd-speed tbody th { + width: 70px; + color: #5b21b6; + font-weight: 800; + } + + .wsd-speed td { + text-align: center; + font-size: 1.15rem; + font-weight: 800; + color: #111827; + background: #f8f7ff; + border-radius: 10px; + padding: 8px; + } + + @media (max-width: 992px) { + .wsd-summary { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + } @@ -171,7 +353,7 @@ - Visualizzazione completa in sola lettura + Sola lettura · per modificare usa "Apri foglio completo"