$(document).ready(function () { console.log("parts.js caricato correttamente"); const partsButtons = document.querySelectorAll(".parts-btn"); const partsModal = document.getElementById("partsModal"); const overlay = document.querySelector(".overlay"); partsButtons.forEach((button) => { button.addEventListener("click", function () { console.log( "Pulsante Parts cliccato, iddatadb:", $(this).data("iddatadb"), ); const iddatadb = $(this).data("iddatadb"); const rowIndex = $(this).data("row"); console.log("Row index:", rowIndex); const importRef = $("table tbody tr") .eq(rowIndex) .find("td") .eq(1) .text(); console.log("ImportRef:", importRef); const description = $("table tbody tr").eq(rowIndex).find("td").eq(2).text() || "Sconosciuto"; console.log("Description:", description); $("#trfHeader").text(`${iddatadb} - ${importRef} - ${description}`); $("#partsModal").data("iddatadb", iddatadb); if (partsModal) { console.log( "Tento di aprire il modal, bootstrap:", typeof bootstrap !== "undefined" ? "definito" : "non definito", ); try { console.log("Inizio try per creare modal instance"); const modalInstance = new bootstrap.Modal(partsModal, { focus: true, }); // Forza la gestione del focus console.log("Modal instance creata"); console.log("Inizio show del modal"); modalInstance.show(); console.log("Modal mostrato"); if (overlay) overlay.style.display = "none"; // Nascondi overlay solo se esiste } catch (error) { console.error("Errore nell'apertura del modal:", error); } } else { console.error("Modal Parts non trovato"); } console.log("Prima di chiamare loadPhoto e loadExistingParts"); loadPhoto(iddatadb) .then(() => { console.log("loadPhoto completata"); loadExistingParts(iddatadb) .then(() => { console.log("loadExistingParts completata"); }) .catch((error) => { console.error( "Errore in loadExistingParts:", error, ); }); }) .catch((error) => { console.error("Errore in loadPhoto:", error); }); console.log("Dopo l'avvio delle chiamate AJAX"); }); }); // Gestione della chiusura del modal Parts if (closeBtn) { closeBtn.addEventListener("click", function () { partsModal.style.display = "none"; overlay.style.display = "none"; // Nascondi overlay document.body.style.pointerEvents = "auto"; // Riattiva la pagina }); } if (partsModal) { window.addEventListener("click", function (event) { if (event.target === partsModal) { partsModal.style.display = "none"; overlay.style.display = "none"; // Nascondi overlay document.body.style.pointerEvents = "auto"; // Riattiva la pagina } }); } function loadPhoto(iddatadb) { console.log("Inizio loadPhoto per iddatadb:", iddatadb); return $.ajax({ url: "load_photo.php", method: "GET", data: { iddatadb: iddatadb }, }) .then(function (response) { console.log("Risposta loadPhoto:", response); if (response.success && response.file_path) { const img = $("#samplePhoto"); img.attr("src", response.file_path); return new Promise((resolve) => { img.on("load", function () { const container = img.parent(); const canvas = document.getElementById("photoCanvas"); const containerWidth = container.width(); const containerHeight = container.height(); const scaleX = containerWidth / img[0].naturalWidth; const scaleY = containerHeight / img[0].naturalHeight; const scale = Math.min(scaleX, scaleY); canvas.width = img[0].naturalWidth * scale; canvas.height = img[0].naturalHeight * scale; canvas.style.width = `${containerWidth}px`; canvas.style.height = `${containerHeight}px`; const ctx = canvas.getContext("2d"); ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage( img.get(0), 0, 0, canvas.width, canvas.height, ); updateMarkers(); resolve(); }); }); } else { $("#samplePhoto").attr("src", ""); console.log( "Nessuna foto trovata:", response.message || "Nessun messaggio", ); return Promise.resolve(); // Risolvi comunque la promessa } }) .catch(function (xhr, status, error) { console.error("Errore in loadPhoto:", { status, error, response: xhr.responseText, }); $("#samplePhoto").attr("src", ""); alert("Errore nel caricamento della foto: " + error); return Promise.reject(error); // Rifiuta la promessa in caso di errore }); } function addNewRow(nextPartNumber) { const newRow = ` `; $("#partsTableBody").append(newRow); updateRowButtons(); } function updateRowButtons() { const rowCount = $("#partsTableBody tr").length; $("#partsTableBody tr").each(function (index) { const $removeBtn = $(this).find(".remove-row"); if (rowCount > 1) { $removeBtn.show(); } else { $removeBtn.hide(); } }); } $(document).on("click", ".add-row", function (e) { e.preventDefault(); console.log("Pulsante Aggiungi riga cliccato"); const maxPartNumber = Math.max( ...$("#partsTableBody tr") .map(function () { return parseInt($(this).find(".part-number").val()) || 0; }) .get(), ); addNewRow(maxPartNumber + 1); updatePartsList(); }); $(document).on("click", ".remove-row", function (e) { e.preventDefault(); console.log("Pulsante Rimuovi riga cliccato"); const $row = $(this).closest("tr"); const partId = $row.data("part-id"); console.log("ID parte da eliminare:", partId); if (partId !== "new" && partId !== undefined && partId !== null) { console.log("Procedo con la cancellazione dal database"); $.ajax({ url: "delete_part.php", method: "POST", data: JSON.stringify({ part_id: partId }), contentType: "application/json", beforeSend: function () { console.log( "Invio richiesta AJAX a delete_part.php con part_id:", partId, ); }, success: function (response) { console.log("Risposta da delete_part.php:", response); if (response.success) { $row.remove(); updateRowButtons(); updatePartsList(); clearCanvasMarkers(); } else { alert("Errore nell'eliminazione: " + response.message); } }, error: function (xhr, status, error) { console.log("Errore AJAX:", status, error); alert( "Errore nell'eliminazione: " + error + ". Stato: " + xhr.status + " - " + xhr.responseText, ); }, }); } else { console.log( 'Riga non salvata nel database (partId = "new" o non definito), rimuovo solo visivamente', ); $row.remove(); updateRowButtons(); updatePartsList(); } }); $(document).on("blur", ".part-description, .part-number", function () { const $input = $(this); const $row = $input.closest("tr"); const partNumber = $row.find(".part-number").val(); const partDescription = $row.find(".part-description").val().trim(); const $saveStatus = $row.find(".save-status"); const $saveLoading = $row.find(".save-loading"); const iddatadb = $("#partsModal").data("iddatadb"); console.log("Evento blur su input:", { partNumber, partDescription }); if (partDescription && iddatadb) { $saveLoading.show(); $saveStatus.hide(); $.ajax({ url: "save_parts.php", method: "POST", data: JSON.stringify({ iddatadb: iddatadb, parts: [ { part_number: partNumber, part_description: partDescription, }, ], }), contentType: "application/json", success: function (response) { if (response.success) { if (response.part_id) { $row.data("part-id", response.part_id); console.log( "Aggiornato partId della riga:", response.part_id, ); } $saveLoading.hide(); $saveStatus.show(); updatePartsList(); setTimeout(() => $saveStatus.hide(), 2000); } else { alert("Errore nel salvataggio: " + response.message); $saveLoading.hide(); } }, error: function (xhr, status, error) { alert("Errore nel salvataggio delle parti: " + error); $saveLoading.hide(); }, }); } }); function loadExistingParts(iddatadb) { console.log("Inizio loadExistingParts per iddatadb:", iddatadb); return $.ajax({ url: "load_parts.php", method: "GET", data: { iddatadb: iddatadb }, }) .then(function (response) { console.log("Risposta loadExistingParts:", response); if (response.success) { $("#partsTableBody").empty(); if (response.parts.length > 0) { response.parts.forEach((part) => { const newRow = ` `; $("#partsTableBody").append(newRow); }); } else { addNewRow(1); } updateRowButtons(); updatePartsList(); } else { console.log( "Errore nel caricamento delle parti:", response.message, ); addNewRow(1); } return Promise.resolve(); // Risolvi la promessa }) .catch(function (xhr, status, error) { console.error("Errore in loadExistingParts:", { status, error, response: xhr.responseText, }); alert("Errore nel caricamento delle parti: " + error); addNewRow(1); return Promise.reject(error); // Rifiuta la promessa in caso di errore }); } function updatePartsList() { $("#partsList").empty(); $("#partsTableBody tr").each(function () { const partNumber = $(this).find(".part-number").val(); const partDescription = $(this).find(".part-description").val(); if (partNumber && partDescription) { const listItem = `
  • ${partNumber} - ${partDescription}
  • `; $("#partsList").append(listItem); } }); } let selectedPartNumber = null; let markers = []; let descriptionPosition = { x: 10, y: 10 }; let hasDescriptions = false; $("#partsList").on("click", "li", function () { selectedPartNumber = $(this).data("part-number"); console.log("Part number selezionato:", selectedPartNumber); $(this).addClass("active").siblings().removeClass("active"); }); const canvas = document.getElementById("photoCanvas"); const ctx = canvas.getContext("2d"); $("#markerContainer").on("click", function (e) { console.log("Click sul markerContainer rilevato"); if (selectedPartNumber !== null) { const img = $("#samplePhoto"); const canvas = document.getElementById("photoCanvas"); const rect = canvas.getBoundingRect(); const container = img.parent(); const containerWidth = container.width(); const containerHeight = container.height(); const scaleX = containerWidth / img.get(0).naturalWidth; const scaleY = containerHeight / img.get(0).naturalHeight; const scale = Math.min(scaleX, scaleY); const x = (e.clientX - rect.left) / scale; const y = (e.clientY - rect.top) / scale; console.log("Coordinate cliccate (x, y):", x, y); const existingMarker = markers.find( (m) => m.partNumber == selectedPartNumber, ); if (existingMarker) { existingMarker.x = x; existingMarker.y = y; } else { markers.push({ partNumber: selectedPartNumber, x, y }); } console.log("Markers aggiornati:", markers); updateMarkers(); if (hasDescriptions) { drawDescriptions(descriptionPosition.x, descriptionPosition.y); } selectedPartNumber = null; $("#partsList li").removeClass("active"); } else { console.log("Nessun part number selezionato"); } }); function updateMarkers() { const img = $("#samplePhoto"); const container = img.parent(); const containerWidth = container.width(); const containerHeight = container.height(); const scaleX = containerWidth / img.get(0).naturalWidth; const scaleY = containerHeight / img.get(0).naturalHeight; const scale = Math.min(scaleX, scaleY); const markerContainer = $("#markerContainer"); markerContainer.empty(); markers.forEach((marker) => { const scaledX = marker.x * scale; const scaledY = marker.y * scale; console.log( "Aggiungo marker:", marker.partNumber, "a posizione (scaledX, scaledY):", scaledX, scaledY, ); const $marker = $( `
    ${marker.partNumber}
    `, ).css({ left: scaledX - 8 + "px", top: scaledY - 8 + "px", }); markerContainer.append($marker); makeDraggable($marker, marker, scale); }); } function makeDraggable($element, item, scale) { let isDragging = false; let currentX = parseFloat($element.css("left")) || 0; let currentY = parseFloat($element.css("top")) || 0; let initialX, initialY; $element.on("mousedown", function (e) { e.preventDefault(); isDragging = true; initialX = e.clientX - currentX; initialY = e.clientY - currentY; $element.css("z-index", 1001); }); $(document).on("mousemove", function (e) { if (isDragging) { e.preventDefault(); currentX = e.clientX - initialX; currentY = e.clientY - initialY; const container = $("#photoCanvas").parent(); const containerWidth = container.width(); const containerHeight = container.height(); const maxX = containerWidth - $element.width(); const maxY = containerHeight - $element.height(); currentX = Math.max(0, Math.min(currentX, maxX)); currentY = Math.max(0, Math.min(currentY, maxY)); $element.css({ left: currentX + "px", top: currentY + "px", }); if (item.partNumber) { item.x = (currentX + 8) / scale; item.y = (currentY + 8) / scale; } else { descriptionPosition.x = (currentX + 5) / scale; descriptionPosition.y = (currentY + 5) / scale; } } }); $(document).on("mouseup", function () { isDragging = false; $element.css("z-index", 1000); }); } function drawDescriptions(x, y) { const img = $("#samplePhoto"); const container = img.parent(); const containerWidth = container.width(); const containerHeight = container.height(); const scaleX = containerWidth / img.get(0).naturalWidth; const scaleY = containerHeight / img.get(0).naturalHeight; const scale = Math.min(scaleX, scaleY); const partsList = []; $("#partsTableBody tr").each(function () { const partNumber = $(this).find(".part-number").val(); const partDescription = $(this).find(".part-description").val(); if (partNumber && partDescription) { partsList.push(`${partNumber} ${partDescription}`); } }); const descriptionList = $("#descriptionList"); descriptionList.empty(); descriptionList.css({ display: "block", top: y * scale + "px", left: x * scale + "px", width: "200px", }); partsList.forEach((part) => { descriptionList.append(`
    ${part}
    `); }); updateMarkers(); } function clearCanvasMarkers() { markers = []; hasDescriptions = false; $("#descriptionList").css("display", "none"); $("#markerContainer").empty(); const canvas = document.getElementById("photoCanvas"); const img = $("#samplePhoto"); const ctx = canvas.getContext("2d"); const container = img.parent(); const containerWidth = container.width(); const containerHeight = container.height(); const scaleX = containerWidth / img.get(0).naturalWidth; const scaleY = containerHeight / img.get(0).naturalHeight; const scale = Math.min(scaleX, scaleY); canvas.width = img.get(0).naturalWidth * scale; canvas.height = img.get(0).naturalHeight * scale; ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage(img.get(0), 0, 0, canvas.width, canvas.height); } $("#addDescriptionsBtn").on("click", function () { hasDescriptions = true; descriptionPosition = { x: 10, y: 10 }; drawDescriptions(descriptionPosition.x, descriptionPosition.y); makeDraggable( $("#descriptionList"), descriptionPosition, Math.min( $("#photoCanvas").parent().width() / $("#samplePhoto").get(0).naturalWidth, $("#photoCanvas").parent().height() / $("#samplePhoto").get(0).naturalHeight, ), ); }); $("#removeAnnotationsBtn").on("click", function () { clearCanvasMarkers(); }); $("#savePhotoBtn").on("click", function () { const canvas = document.getElementById("photoCanvas"); const img = $("#samplePhoto"); const ctx = canvas.getContext("2d"); canvas.width = img.get(0).naturalWidth; canvas.height = img.get(0).naturalHeight; ctx.drawImage(img.get(0), 0, 0); const partsList = []; $("#partsTableBody tr").each(function () { const partNumber = $(this).find(".part-number").val(); const partDescription = $(this).find(".part-description").val(); if (partNumber && partDescription) { partsList.push(`${partNumber} ${partDescription}`); } }); if (hasDescriptions) { ctx.fillStyle = "rgba(255, 255, 255, 0.8)"; ctx.fillRect( descriptionPosition.x, descriptionPosition.y, 200, partsList.length * 12 + 10, ); ctx.fillStyle = "#000000"; ctx.font = "10px Arial"; partsList.forEach((part, index) => { ctx.fillText( part, descriptionPosition.x + 5, descriptionPosition.y + 12 + index * 12, ); }); } markers.forEach((marker) => { ctx.beginPath(); ctx.arc(marker.x, marker.y, 8, 0, 2 * Math.PI); ctx.fillStyle = "rgba(255, 0, 0, 0.5)"; ctx.fill(); ctx.strokeStyle = "#ff0000"; ctx.lineWidth = 1; ctx.stroke(); ctx.fillStyle = "#ffffff"; ctx.font = "bold 8px Arial"; ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.fillText(marker.partNumber, marker.x, marker.y); }); const dataURL = canvas.toDataURL("image/png"); const timestamp = new Date().toISOString().replace(/[:.]/g, "-"); const defaultName = `photo_${$("#partsModal").data("iddatadb")}_${timestamp}.png`; const newName = prompt( "Inserisci il nome del file (senza estensione):", defaultName.split(".png")[0], ); if (newName) { const finalName = newName + "_" + timestamp + ".png"; $.ajax({ url: "save_annotated_photo.php", method: "POST", data: { dataURL: dataURL, filename: finalName }, success: function (response) { if (response.success) { alert( "Foto salvata con successo: " + response.file_path, ); } else { alert("Errore nel salvataggio: " + response.message); } }, error: function (xhr, status, error) { alert("Errore nel salvataggio della foto: " + error); }, }); } }); $(document).on("mouseenter", "tr", function () { console.log("Mouse entrato su riga"); }); $(document).on("mouseleave", "tr", function () { console.log("Mouse uscito da riga"); }); });