740 lines
29 KiB
JavaScript
740 lines
29 KiB
JavaScript
(function () {
|
|
function escapeHtml(str) {
|
|
return String(str === null || str === undefined ? "" : str)
|
|
.replace(/&/g, "&")
|
|
.replace(/</g, "<")
|
|
.replace(/>/g, ">")
|
|
.replace(/"/g, """)
|
|
.replace(/'/g, "'");
|
|
}
|
|
|
|
function isEmpty(v) {
|
|
return v === null || v === undefined || String(v).trim() === "";
|
|
}
|
|
|
|
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 `
|
|
<div class="wsd-field ${extraClass || ""}">
|
|
<div class="wsd-label">${escapeHtml(label)}</div>
|
|
<div class="wsd-value ${empty ? "wsd-empty" : ""}">${valueOrDash(value)}</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
// Blocco di testo lungo (note, misure di controllo)
|
|
function wsdText(label, value, emptyText) {
|
|
const empty = isEmpty(value);
|
|
return `
|
|
<div class="wsd-text-block">
|
|
${label ? `<div class="wsd-label mb-1">${escapeHtml(label)}</div>` : ""}
|
|
<div class="wsd-text ${empty ? "wsd-empty" : ""}">${empty ? escapeHtml(emptyText || "—") : escapeHtml(value)}</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
function wsdSection(theme, title, badge, body, colClass) {
|
|
return `
|
|
<div class="${colClass || "col-12"}">
|
|
<div class="wsd-section wsd-${theme}">
|
|
<div class="wsd-head">
|
|
<span>${title}</span>
|
|
${badge ? `<span class="wsd-head-badge">${badge}</span>` : ""}
|
|
</div>
|
|
<div class="wsd-body">${body}</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
window.loadMatriceWorksheets = function (idmatrice, matriceNome, endpoint) {
|
|
endpoint = endpoint || "ajax/worksheet-linked-data.php";
|
|
|
|
$("#wl_idmatrice").val(idmatrice);
|
|
$("#wl_matrice_name").html(
|
|
`<span class="worksheet-chip"><i class="fa-solid fa-layer-group"></i>${escapeHtml(matriceNome || "")}</span>`,
|
|
);
|
|
$("#worksheetsListContainer").html(
|
|
'<div class="text-muted">Caricamento fogli di lavoro...</div>',
|
|
);
|
|
|
|
fetch(endpoint, {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
body:
|
|
"action=get_matrice_worksheets&idmatrice=" +
|
|
encodeURIComponent(idmatrice),
|
|
})
|
|
.then(async (r) => {
|
|
const text = await r.text();
|
|
try {
|
|
return JSON.parse(text);
|
|
} catch (e) {
|
|
console.error("Risposta non JSON worksheets:", text);
|
|
throw new Error("Risposta non JSON, vedi console");
|
|
}
|
|
})
|
|
.then((data) => {
|
|
if (!data.success) {
|
|
$("#worksheetsListContainer").html(
|
|
'<div class="text-danger">Errore nel caricamento dei fogli</div>',
|
|
);
|
|
return;
|
|
}
|
|
|
|
const rows = data.worksheets || [];
|
|
|
|
if (!rows.length) {
|
|
$("#worksheetsListContainer").html(
|
|
'<div class="text-muted">Nessun foglio di lavoro collegato a questo profilo</div>',
|
|
);
|
|
return;
|
|
}
|
|
|
|
let html = `
|
|
<div class="table-responsive">
|
|
<table class="table table-striped align-middle worksheet-list-table">
|
|
<thead>
|
|
<tr>
|
|
<th style="width:110px;">Foglio</th>
|
|
<th style="width:100px;">Rev.</th>
|
|
<th style="width:110px;">Stato</th>
|
|
<th style="width:140px;">Data foglio</th>
|
|
<th>Cliente</th>
|
|
<th>Codice profilo</th>
|
|
<th style="width:110px;">Mescole</th>
|
|
<th style="width:230px;">Azioni</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
`;
|
|
|
|
rows.forEach((r) => {
|
|
const statusBadge =
|
|
r.worksheet_status === "inactive"
|
|
? `<span class="worksheet-badge-status-inactive">Inattivo</span>`
|
|
: `<span class="worksheet-badge-status-active">Attivo</span>`;
|
|
|
|
html += `
|
|
<tr>
|
|
<td><span class="worksheet-badge-fl">${escapeHtml(r.worksheet_number_label || "—")}</span></td>
|
|
<td><span class="worksheet-badge-rev">${escapeHtml(r.revision_label || "0")}</span></td>
|
|
<td>${statusBadge}</td>
|
|
<td>${escapeHtml(r.worksheet_date_it || "—")}</td>
|
|
<td title="${escapeHtml(r.customer_name || "")}">${escapeHtml(r.customer_name || "—")}</td>
|
|
<td>${escapeHtml(r.profile_type_code || "—")}</td>
|
|
<td>${escapeHtml(String(r.mix_count || 0))}</td>
|
|
<td class="text-nowrap">
|
|
<button type="button"
|
|
class="btn btn-view-worksheet open-worksheet-detail"
|
|
data-id="${r.id}"
|
|
data-endpoint="${escapeHtml(endpoint)}">
|
|
<i class="fa-solid fa-eye me-1"></i>Apri dettaglio
|
|
</button>
|
|
<a class="worksheet-open-link ms-1"
|
|
href="manage-worksheet.php?id=${r.id}"
|
|
target="_blank">
|
|
<i class="fa-solid fa-arrow-up-right-from-square"></i>Apri pagina
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
`;
|
|
});
|
|
|
|
html += `
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
`;
|
|
|
|
$("#worksheetsListContainer").html(html);
|
|
})
|
|
.catch(() => {
|
|
$("#worksheetsListContainer").html(
|
|
'<div class="text-danger">Errore nel caricamento dei fogli</div>',
|
|
);
|
|
});
|
|
};
|
|
|
|
// ================================================================
|
|
// Tab allegati della matrice: disegni tecnici, strumenti, cicli
|
|
// ================================================================
|
|
const WS_ATT_KINDS = {
|
|
disegni: {
|
|
flag: "is_disegno",
|
|
label: "Disegni tecnici",
|
|
icon: "📐",
|
|
itemLabel: "Disegno",
|
|
empty:
|
|
"Nessun disegno tecnico per questo profilo. " +
|
|
"Si possono segnare dalla gestione matrici (graffetta → pulsante compasso).",
|
|
},
|
|
strumenti: {
|
|
flag: "is_strumento",
|
|
label: "Strumenti di lavoro",
|
|
icon: "🔧",
|
|
itemLabel: "Strumento",
|
|
empty:
|
|
"Nessuno strumento di lavoro per questo profilo. " +
|
|
"Si possono segnare dalla gestione matrici (graffetta → pulsante chiave inglese).",
|
|
},
|
|
cicli: {
|
|
flag: "is_ciclo",
|
|
label: "Cicli di lavoro",
|
|
icon: "🔁",
|
|
itemLabel: "Ciclo",
|
|
empty:
|
|
"Nessun ciclo di lavoro per questo profilo. " +
|
|
"Si possono segnare dalla gestione matrici (graffetta → pulsante frecce).",
|
|
},
|
|
};
|
|
|
|
let wsAttLists = { disegni: [], strumenti: [], cicli: [] };
|
|
|
|
function wsFileExt(name) {
|
|
const p = String(name || "").split(".");
|
|
return p.length > 1 ? p.pop().toLowerCase() : "";
|
|
}
|
|
|
|
function wsIsImage(ext) {
|
|
return ["jpg", "jpeg", "png", "gif", "bmp", "webp"].includes(ext);
|
|
}
|
|
|
|
function showWorksheetAttachment(kind, index) {
|
|
const list = wsAttLists[kind] || [];
|
|
const f = list[index];
|
|
if (!f) return;
|
|
|
|
$(`.ws-disegno-item[data-kind="${kind}"]`).removeClass("active");
|
|
$(
|
|
`.ws-disegno-item[data-kind="${kind}"][data-index="${index}"]`,
|
|
).addClass("active");
|
|
|
|
const name = f.file_name || "";
|
|
const path = f.file_url || f.file_path || "";
|
|
const ext = wsFileExt(name);
|
|
|
|
let viewer;
|
|
if (ext === "pdf") {
|
|
viewer = `<iframe src="${escapeHtml(path)}#zoom=page-width"></iframe>`;
|
|
} else if (wsIsImage(ext)) {
|
|
viewer = `<div class="img-wrap"><img src="${escapeHtml(path)}" alt="${escapeHtml(name)}"></div>`;
|
|
} else {
|
|
viewer = `<div class="h-100 d-flex justify-content-center align-items-center text-muted">Anteprima non disponibile per questo formato: usa "Apri in nuova scheda"</div>`;
|
|
}
|
|
|
|
$(`#wsToolbar_${kind}`).html(`
|
|
<div>
|
|
<div class="fw-bold">${escapeHtml(name)}</div>
|
|
${f.description ? `<div class="small text-muted">${escapeHtml(f.description)}</div>` : ""}
|
|
</div>
|
|
<a href="${escapeHtml(path)}" target="_blank" class="worksheet-open-link">
|
|
<i class="fa-solid fa-arrow-up-right-from-square"></i> Apri in nuova scheda
|
|
</a>
|
|
`);
|
|
$(`#wsViewer_${kind}`).html(viewer);
|
|
}
|
|
|
|
function renderWorksheetAttachmentKind(kind) {
|
|
const cfg = WS_ATT_KINDS[kind];
|
|
const list = wsAttLists[kind];
|
|
const $c = $(`#wsContainer_${kind}`);
|
|
|
|
$(`#wsCount_${kind}`).text(list.length);
|
|
|
|
if (!list.length) {
|
|
$c.html(
|
|
`<div class="text-muted p-3">${escapeHtml(cfg.empty)}</div>`,
|
|
);
|
|
return;
|
|
}
|
|
|
|
let listHtml = "";
|
|
if (list.length > 1) {
|
|
listHtml =
|
|
'<div class="ws-disegni-list">' +
|
|
list
|
|
.map(
|
|
(f, i) =>
|
|
`<button type="button" class="ws-disegno-item" data-kind="${kind}" data-index="${i}">${cfg.icon} ${escapeHtml(f.file_name || cfg.itemLabel + " " + (i + 1))}</button>`,
|
|
)
|
|
.join("") +
|
|
"</div>";
|
|
}
|
|
|
|
$c.html(`
|
|
${listHtml}
|
|
<div class="ws-disegno-toolbar" id="wsToolbar_${kind}"></div>
|
|
<div class="ws-disegno-viewer" id="wsViewer_${kind}"></div>
|
|
`);
|
|
|
|
// Se l'utente ha già aperto il tab mentre caricava, mostro subito il primo
|
|
if ($(`.ws-tab[data-tab="${kind}"]`).hasClass("active")) {
|
|
showWorksheetAttachment(kind, 0);
|
|
}
|
|
}
|
|
|
|
function loadWorksheetAttachments(idmatrice) {
|
|
wsAttLists = { disegni: [], strumenti: [], cicli: [] };
|
|
const kinds = Object.keys(WS_ATT_KINDS);
|
|
|
|
if (!idmatrice) {
|
|
kinds.forEach((k) => {
|
|
$(`#wsCount_${k}`).text("0");
|
|
$(`#wsContainer_${k}`).html(
|
|
'<div class="text-muted">Nessun profilo collegato a questo foglio.</div>',
|
|
);
|
|
});
|
|
return;
|
|
}
|
|
|
|
fetch("get_matrice_attachments.php?id=" + encodeURIComponent(idmatrice))
|
|
.then((r) => r.json())
|
|
.then((data) => {
|
|
if (!data.success)
|
|
throw new Error(
|
|
data.message || "Errore caricamento allegati",
|
|
);
|
|
|
|
const all = data.attachments || [];
|
|
|
|
kinds.forEach((k) => {
|
|
const flag = WS_ATT_KINDS[k].flag;
|
|
wsAttLists[k] = all.filter(
|
|
(a) => parseInt(a[flag], 10) === 1,
|
|
);
|
|
renderWorksheetAttachmentKind(k);
|
|
});
|
|
})
|
|
.catch((err) => {
|
|
kinds.forEach((k) => {
|
|
$(`#wsCount_${k}`).text("!");
|
|
$(`#wsContainer_${k}`).html(
|
|
'<div class="text-danger">Errore nel caricamento degli allegati: ' +
|
|
escapeHtml(err.message || "") +
|
|
"</div>",
|
|
);
|
|
});
|
|
});
|
|
}
|
|
|
|
// ================================================================
|
|
// 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
|
|
? `<span class="worksheet-badge-status-inactive">${escapeHtml(statusLabel)}</span>`
|
|
: `<span class="worksheet-badge-status-active">${escapeHtml(statusLabel)}</span>`;
|
|
|
|
const cliente = ws.customer_name || ws.matrice_cliente || "";
|
|
|
|
// ---------- Intestazione ----------
|
|
const excelLink = ws.source_xlsx_path
|
|
? `<a href="download_worksheet_file.php?id=${encodeURIComponent(ws.id || "")}"
|
|
target="_blank" class="worksheet-open-link">
|
|
<i class="fa-solid fa-file-excel"></i> Excel di origine
|
|
</a>`
|
|
: "";
|
|
|
|
const headerHtml = `
|
|
<div class="worksheet-title-box mb-3">
|
|
<div class="d-flex justify-content-between align-items-center gap-3 flex-wrap">
|
|
<div>
|
|
<h4 class="mb-1">${escapeHtml(ws.worksheet_number_label || "—")} / Rev. ${escapeHtml(ws.revision_label || "0")}</h4>
|
|
<small>${ws.matrice_nome ? "Profilo: " + escapeHtml(ws.matrice_nome) : "Nessun profilo collegato"}</small>
|
|
</div>
|
|
<div class="d-flex gap-2 flex-wrap">
|
|
${excelLink}
|
|
<a href="manage-worksheet.php?id=${encodeURIComponent(ws.id || "")}"
|
|
target="_blank" class="worksheet-open-link">
|
|
<i class="fa-solid fa-arrow-up-right-from-square"></i> Apri foglio completo
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
// ---------- Striscia riepilogo ----------
|
|
const summaryHtml = `
|
|
<div class="wsd-summary mb-3">
|
|
<div class="wsd-sum-item">
|
|
<div class="wsd-label">Stato</div>
|
|
<div>${statusBadge}</div>
|
|
</div>
|
|
<div class="wsd-sum-item">
|
|
<div class="wsd-label">Cliente</div>
|
|
<div class="wsd-sum-value">${valueOrDash(cliente)}</div>
|
|
</div>
|
|
<div class="wsd-sum-item">
|
|
<div class="wsd-label">Codice profilo</div>
|
|
<div class="wsd-sum-value">${valueOrDash(ws.profile_type_code)}</div>
|
|
</div>
|
|
<div class="wsd-sum-item">
|
|
<div class="wsd-label">Data foglio</div>
|
|
<div class="wsd-sum-value">${valueOrDash(ws.worksheet_date_it)}</div>
|
|
</div>
|
|
<div class="wsd-sum-item">
|
|
<div class="wsd-label">Mescole / Imballi</div>
|
|
<div class="wsd-sum-value">${mixRows.length} / ${packageRows.length}</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
// ---------- 1. Dati principali ----------
|
|
const sec1 = wsdSection(
|
|
"blue",
|
|
"1. Dati principali",
|
|
"",
|
|
`
|
|
<div class="wsd-fields">
|
|
${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)}
|
|
</div>
|
|
<div class="wsd-meta">
|
|
Creato il ${valueOrDash(ws.created_at_it)} · Ultimo aggiornamento ${valueOrDash(ws.updated_at_it)}
|
|
</div>
|
|
`,
|
|
"col-lg-6",
|
|
);
|
|
|
|
// ---------- 2. Controlli di produzione ----------
|
|
const sec2 = wsdSection(
|
|
"green",
|
|
"2. Controlli di produzione",
|
|
"",
|
|
`
|
|
<div class="wsd-fields">
|
|
${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))}
|
|
</div>
|
|
${wsdText("Impostazione misure controllo produzione", ws.prod_control_measure_settings, "Nessuna indicazione")}
|
|
`,
|
|
"col-lg-6",
|
|
);
|
|
|
|
// ---------- 3. Imballo e confezionamento ----------
|
|
let packagesHtml = `<div class="wsd-empty mb-2">Nessun imballo associato</div>`;
|
|
if (packageRows.length) {
|
|
packagesHtml = `
|
|
<div class="table-responsive mb-3">
|
|
<table class="table table-sm table-striped align-middle mb-0 wsd-table">
|
|
<thead>
|
|
<tr>
|
|
<th style="width:60px;">Pos</th>
|
|
<th style="width:200px;">Categoria</th>
|
|
<th>Imballo</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
${packageRows
|
|
.map(
|
|
(p) => `
|
|
<tr>
|
|
<td>${valueOrDash(p.package_position)}</td>
|
|
<td>${valueOrDash(p.package_category)}</td>
|
|
<td>
|
|
<div class="fw-bold">${valueOrDash(p.package_name)}</div>
|
|
${p.package_item_code ? `<div class="small text-muted">${escapeHtml(p.package_item_code)}</div>` : ""}
|
|
</td>
|
|
</tr>`,
|
|
)
|
|
.join("")}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
const sec3 = wsdSection(
|
|
"orange",
|
|
"3. Imballo e confezionamento",
|
|
`${packageRows.length} imball${packageRows.length === 1 ? "o" : "i"}`,
|
|
`
|
|
<div class="row g-3">
|
|
<div class="col-lg-6">
|
|
${packagesHtml}
|
|
</div>
|
|
<div class="col-lg-6">
|
|
<div class="wsd-fields">
|
|
${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)}
|
|
</div>
|
|
${wsdText("Note metri/confezione", ws.meters_per_package_notes, "Nessuna nota")}
|
|
</div>
|
|
</div>
|
|
`,
|
|
"col-12",
|
|
);
|
|
|
|
// ---------- 4. Velocità di produzione ----------
|
|
const sec4 = wsdSection(
|
|
"purple",
|
|
"4. Velocità di produzione",
|
|
"",
|
|
`
|
|
<table class="wsd-speed">
|
|
<thead>
|
|
<tr><th></th><th>Prevista</th><th>Effettiva</th></tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<th>kg/h</th>
|
|
<td class="${isEmpty(ws.speed_expected_kg_h) ? "wsd-empty" : ""}">${valueOrDash(ws.speed_expected_kg_h)}</td>
|
|
<td class="${isEmpty(ws.speed_actual_kg_h) ? "wsd-empty" : ""}">${valueOrDash(ws.speed_actual_kg_h)}</td>
|
|
</tr>
|
|
<tr>
|
|
<th>m/h</th>
|
|
<td class="${isEmpty(ws.speed_expected_m_h) ? "wsd-empty" : ""}">${valueOrDash(ws.speed_expected_m_h)}</td>
|
|
<td class="${isEmpty(ws.speed_actual_m_h) ? "wsd-empty" : ""}">${valueOrDash(ws.speed_actual_m_h)}</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
`,
|
|
"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 = `<div class="wsd-empty">Nessuna mescola associata</div>`;
|
|
if (mixRows.length) {
|
|
mixHtml = `
|
|
<div class="table-responsive">
|
|
<table class="table table-striped align-middle mb-0 wsd-table">
|
|
<thead>
|
|
<tr>
|
|
<th style="width:60px;">Pos</th>
|
|
<th>Mescola</th>
|
|
<th style="width:120px;">Peso g/m</th>
|
|
<th style="width:150px;">Densità</th>
|
|
<th style="width:150px;">Durezza (Sh A)</th>
|
|
<th style="width:150px;">Lubrificazione</th>
|
|
<th>Note lubr.</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
${mixRows
|
|
.map(
|
|
(r) => `
|
|
<tr>
|
|
<td>${valueOrDash(r.mix_position)}</td>
|
|
<td>
|
|
<div class="fw-bold">${valueOrDash(r.mescola_nome)}</div>
|
|
${r.mescola_uscita ? `<div class="small text-muted">${escapeHtml(r.mescola_uscita)}</div>` : ""}
|
|
</td>
|
|
<td>${valueOrDash(r.mix_weight_g_m)}</td>
|
|
<td>${valueOrDash(r.required_density)}</td>
|
|
<td>${valueOrDash(r.required_hardness_shore_a)}</td>
|
|
<td>${valueOrDash(lookupLabel(lookups, "lubrication_type", r.lubrication_type))}</td>
|
|
<td>${valueOrDash(r.lubrication_notes)}</td>
|
|
</tr>`,
|
|
)
|
|
.join("")}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
const sec6 = wsdSection(
|
|
"cyan",
|
|
"6. Mescole associate al foglio",
|
|
`${mixRows.length} rig${mixRows.length === 1 ? "a" : "he"}`,
|
|
mixHtml,
|
|
"col-12",
|
|
);
|
|
|
|
const datiHtml = `
|
|
${summaryHtml}
|
|
<div class="row g-3">
|
|
${sec1}
|
|
${sec2}
|
|
${sec3}
|
|
${sec4}
|
|
${sec5}
|
|
${sec6}
|
|
</div>
|
|
`;
|
|
|
|
// ---------- Tab allegati ----------
|
|
const attTabsHtml = Object.keys(WS_ATT_KINDS)
|
|
.map((k) => {
|
|
const c = WS_ATT_KINDS[k];
|
|
return `
|
|
<button type="button" class="ws-tab" data-tab="${k}">
|
|
${c.icon} ${escapeHtml(c.label)} <span class="ws-tab-count" id="wsCount_${k}">…</span>
|
|
</button>`;
|
|
})
|
|
.join("");
|
|
|
|
const attPanesHtml = Object.keys(WS_ATT_KINDS)
|
|
.map((k) => {
|
|
const c = WS_ATT_KINDS[k];
|
|
return `
|
|
<div class="ws-tab-pane" data-pane="${k}">
|
|
<div id="wsContainer_${k}">
|
|
<div class="text-muted">Caricamento ${escapeHtml(c.label.toLowerCase())}...</div>
|
|
</div>
|
|
</div>`;
|
|
})
|
|
.join("");
|
|
|
|
return `
|
|
${headerHtml}
|
|
|
|
<div class="ws-tabs">
|
|
<button type="button" class="ws-tab active" data-tab="dati">
|
|
<i class="fa-solid fa-file-lines me-1"></i> Dati foglio
|
|
</button>
|
|
${attTabsHtml}
|
|
</div>
|
|
|
|
<div class="ws-tab-pane active" data-pane="dati">
|
|
${datiHtml}
|
|
</div>
|
|
|
|
${attPanesHtml}
|
|
`;
|
|
}
|
|
|
|
window.loadWorksheetDetail = function (worksheetId, endpoint) {
|
|
endpoint = endpoint || "ajax/worksheet-linked-data.php";
|
|
|
|
const $box = $("#worksheetDetailContainer");
|
|
$box.html(
|
|
'<div class="text-muted">Caricamento dettaglio foglio...</div>',
|
|
);
|
|
|
|
fetch(endpoint, {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
body:
|
|
"action=get_worksheet_detail&worksheet_id=" +
|
|
encodeURIComponent(worksheetId),
|
|
})
|
|
.then(async (r) => {
|
|
const text = await r.text();
|
|
try {
|
|
return JSON.parse(text);
|
|
} catch (e) {
|
|
console.error("Risposta non JSON worksheet detail:", text);
|
|
throw new Error("Risposta non JSON, vedi console");
|
|
}
|
|
})
|
|
.then((data) => {
|
|
if (!data.success) {
|
|
console.error("Errore dettaglio foglio:", data);
|
|
$box.html(
|
|
'<div class="text-danger">Errore nel caricamento del foglio: ' +
|
|
escapeHtml(
|
|
data.message || "nessun dettaglio restituito",
|
|
) +
|
|
"</div>",
|
|
);
|
|
return;
|
|
}
|
|
|
|
$box.html(renderWorksheetDetail(data));
|
|
loadWorksheetAttachments((data.worksheet || {}).idmatrice);
|
|
})
|
|
.catch((err) => {
|
|
console.error("Errore dettaglio foglio:", err);
|
|
$box.html(
|
|
'<div class="text-danger">Errore nel caricamento del foglio: ' +
|
|
escapeHtml(err.message || "errore JavaScript/fetch") +
|
|
"</div>",
|
|
);
|
|
});
|
|
};
|
|
|
|
$(document).on("click", ".worksheets, .show-worksheets", function () {
|
|
const idmatrice = $(this).data("id");
|
|
const nome = $(this).data("nome") || "";
|
|
const endpoint =
|
|
$(this).data("endpoint") || "ajax/worksheet-linked-data.php";
|
|
|
|
loadMatriceWorksheets(idmatrice, nome, endpoint);
|
|
new bootstrap.Modal(
|
|
document.getElementById("worksheetsListModal"),
|
|
).show();
|
|
});
|
|
|
|
$(document).on("click", ".ws-tab", function () {
|
|
const tab = $(this).data("tab");
|
|
|
|
$(".ws-tab").removeClass("active");
|
|
$(this).addClass("active");
|
|
|
|
$(".ws-tab-pane").removeClass("active");
|
|
$(`.ws-tab-pane[data-pane="${tab}"]`).addClass("active");
|
|
|
|
// Carico il file solo la prima volta che si apre il tab
|
|
if (
|
|
WS_ATT_KINDS[tab] &&
|
|
(wsAttLists[tab] || []).length &&
|
|
$(`#wsViewer_${tab}`).is(":empty")
|
|
) {
|
|
showWorksheetAttachment(tab, 0);
|
|
}
|
|
});
|
|
|
|
$(document).on("click", ".ws-disegno-item", function () {
|
|
showWorksheetAttachment(
|
|
$(this).data("kind"),
|
|
parseInt($(this).data("index"), 10),
|
|
);
|
|
});
|
|
|
|
$(document).on("click", ".open-worksheet-detail", function () {
|
|
const worksheetId = $(this).data("id");
|
|
const endpoint =
|
|
$(this).data("endpoint") || "ajax/worksheet-linked-data.php";
|
|
|
|
loadWorksheetDetail(worksheetId, endpoint);
|
|
new bootstrap.Modal(
|
|
document.getElementById("worksheetDetailModal"),
|
|
).show();
|
|
});
|
|
})();
|