diff --git a/public/userarea/get_macro_matrici.php b/public/userarea/get_macro_matrici.php new file mode 100644 index 0000000..33b181e --- /dev/null +++ b/public/userarea/get_macro_matrici.php @@ -0,0 +1,59 @@ +load(); +} catch (Exception $e) { + file_put_contents(__DIR__ . '/error_log.txt', date('Y-m-d H:i:s') . ' - Errore caricamento .env: ' . $e->getMessage() . PHP_EOL, FILE_APPEND); + echo json_encode(['success' => false, 'message' => 'Errore caricamento configurazione: ' . $e->getMessage()]); + exit(1); +} + +// Recupera le variabili d'ambiente +$dbHost = $_ENV['DB_HOST']; +$dbName = $_ENV['DB_DATABASE']; +$dbUser = $_ENV['DB_USERNAME']; +$dbPass = $_ENV['DB_PASSWORD']; +$dbPrefix = $_ENV['DB_PREFIX']; + +// Debug: Log database connection details (excluding password) +file_put_contents(__DIR__ . '/debug_log.txt', date('Y-m-d H:i:s') . " - DB Connection: host=$dbHost, dbname=$dbName, user=$dbUser, prefix=$dbPrefix" . PHP_EOL, FILE_APPEND); + +// Connessione al database MySQL +try { + $pdo = new PDO("mysql:host=$dbHost;dbname=$dbName;charset=utf8mb4", $dbUser, $dbPass); + $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); +} catch (PDOException $e) { + file_put_contents(__DIR__ . '/error_log.txt', date('Y-m-d H:i:s') . ' - Errore connessione DB: ' . $e->getMessage() . PHP_EOL, FILE_APPEND); + echo json_encode(['success' => false, 'message' => 'Errore connessione al database: ' . $e->getMessage()]); + exit(1); +} + +try { + // Query per recuperare i valori distinti di MacroMatrice, escludendo quelli che iniziano con '*' e ordinandoli + $query = "SELECT DISTINCT MacroMatrice FROM {$dbPrefix}matrici WHERE MacroMatrice IS NOT NULL AND MacroMatrice NOT LIKE '*%' ORDER BY MacroMatrice ASC"; + $stmt = $pdo->prepare($query); + $stmt->execute(); + $macroMatrici = $stmt->fetchAll(PDO::FETCH_COLUMN); + + // Debug: Log del numero di MacroMatrice recuperate + file_put_contents(__DIR__ . '/debug_log.txt', date('Y-m-d H:i:s') . ' - Retrieved ' . count($macroMatrici) . ' MacroMatrice from database' . PHP_EOL, FILE_APPEND); + + // Restituisci risposta JSON + echo json_encode(['success' => true, 'value' => $macroMatrici]); +} catch (PDOException $e) { + // Log errore e restituisci risposta di errore + file_put_contents(__DIR__ . '/error_log.txt', date('Y-m-d H:i:s') . ' - Errore nel recupero delle MacroMatrice: ' . $e->getMessage() . PHP_EOL, FILE_APPEND); + echo json_encode(['success' => false, 'message' => 'Errore nel recupero delle MacroMatrice: ' . $e->getMessage()]); + exit(1); +} diff --git a/public/userarea/get_matrici_db.php b/public/userarea/get_matrici_db.php index 6148e64..1052aac 100644 --- a/public/userarea/get_matrici_db.php +++ b/public/userarea/get_matrici_db.php @@ -40,19 +40,19 @@ try { } try { - // Query to fetch matrices, excluding those starting with '*' and sorting by NomeMatrice - $query = "SELECT IdMatrice, NomeMatrice FROM {$dbPrefix}matrici WHERE NomeMatrice NOT LIKE '*%' ORDER BY NomeMatrice ASC"; + // Query per recuperare le matrici, includendo MacroMatrice, escludendo quelle che iniziano con '*' e ordinandole + $query = "SELECT IdMatrice, NomeMatrice, MacroMatrice FROM {$dbPrefix}matrici WHERE NomeMatrice NOT LIKE '*%' ORDER BY NomeMatrice ASC"; $stmt = $pdo->prepare($query); $stmt->execute(); $matrici = $stmt->fetchAll(PDO::FETCH_ASSOC); - // Debug: Log the number of matrices retrieved + // Debug: Log del numero di matrici recuperate file_put_contents(__DIR__ . '/debug_log.txt', date('Y-m-d H:i:s') . ' - Retrieved ' . count($matrici) . ' matrices from database' . PHP_EOL, FILE_APPEND); - // Return JSON response + // Restituisci risposta JSON echo json_encode(['success' => true, 'value' => $matrici]); } catch (PDOException $e) { - // Log error and return error response + // Log errore e restituisci risposta di errore file_put_contents(__DIR__ . '/error_log.txt', date('Y-m-d H:i:s') . ' - Errore nel recupero delle matrici: ' . $e->getMessage() . PHP_EOL, FILE_APPEND); echo json_encode(['success' => false, 'message' => 'Errore nel recupero delle matrici: ' . $e->getMessage()]); exit(1); diff --git a/public/userarea/load_parts.php b/public/userarea/load_parts.php index ef57ed6..e0fdea7 100644 --- a/public/userarea/load_parts.php +++ b/public/userarea/load_parts.php @@ -14,9 +14,9 @@ if (!$iddatadb) { } try { - $stmt = $pdo->prepare("SELECT id, iddatadb, part_number, part_description FROM identification_parts WHERE iddatadb = :iddatadb ORDER BY part_number ASC"); + $stmt = $pdo->prepare("SELECT id, iddatadb, part_number, part_description, idmatrice, note, dateexpiry FROM identification_parts WHERE iddatadb = :iddatadb ORDER BY part_number ASC"); $stmt->execute([':iddatadb' => $iddatadb]); - $parts = $stmt->fetchAll(); + $parts = $stmt->fetchAll(PDO::FETCH_ASSOC); echo json_encode(['success' => true, 'parts' => $parts]); } catch (PDOException $e) { diff --git a/public/userarea/modal_partsTable.php b/public/userarea/modal_partsTable.php index 581f25d..460d5c5 100644 --- a/public/userarea/modal_partsTable.php +++ b/public/userarea/modal_partsTable.php @@ -8,34 +8,61 @@ + + + + + + + + \ No newline at end of file diff --git a/public/userarea/partsTable.js b/public/userarea/partsTable.js index 2efaef9..91112f6 100644 --- a/public/userarea/partsTable.js +++ b/public/userarea/partsTable.js @@ -5,6 +5,7 @@ $(document).ready(function () { let partMatrice = {}; let unsavedChanges = false; let matrici = []; + let macroMatrici = []; // =================== // VOICE RECOGNITION SETUP @@ -54,7 +55,7 @@ $(document).ready(function () { }) .get(), ); - addNewRow(maxPartNumber + 1); + addNewRow(maxPartNumber + 1, false); // Aggiunge riga normale per riconoscimento vocale const $newRow = $("#partsTableBody tr:last"); $newRow.find(".part-description").focus(); } else { @@ -82,7 +83,10 @@ $(document).ready(function () { } function toggleVoiceRecognition() { - if (!recognition) return; + if (!recognition) { + console.log("Voce non supportata dal browser"); + return; + } isVoiceActive = !isVoiceActive; const $btn = $("#toggleVoiceBtn"); if (isVoiceActive) { @@ -99,7 +103,11 @@ $(document).ready(function () { } } - $("#toggleVoiceBtn").on("click", toggleVoiceRecognition); + $(document).on("click", "#toggleVoiceBtn", function (e) { + console.log("Clicked Voce - Evento triggerato"); + e.preventDefault(); + toggleVoiceRecognition(); + }); // =================== // MODAL HANDLING @@ -113,12 +121,14 @@ $(document).ready(function () { dataType: "json", success: function (data) { matrici = data.value || []; + loadMacroMatrici(); initializeGlobalSelect2(); loadPhoto(iddatadb, idquotations); loadExistingParts(iddatadb, idquotations); }, error: function (xhr, status, error) { matrici = []; + loadMacroMatrici(); initializeGlobalSelect2(); loadPhoto(iddatadb, idquotations); loadExistingParts(iddatadb, idquotations); @@ -138,6 +148,7 @@ $(document).ready(function () { }, }); } else { + loadMacroMatrici(); initializeGlobalSelect2(); loadPhoto(iddatadb, idquotations); loadExistingParts(iddatadb, idquotations); @@ -168,7 +179,6 @@ $(document).ready(function () { partsModal.hide(); } - // Verifica se annotationsModal esiste nel DOM const annotationsModalElement = document.getElementById("annotationsModal"); if (annotationsModalElement) { @@ -177,7 +187,6 @@ $(document).ready(function () { return; } - // Carica dinamicamente modal_annotations.php se non è già presente console.log("Caricamento dinamico di modal_annotations.php..."); $.ajax({ url: "modal_annotations.php", @@ -193,7 +202,6 @@ $(document).ready(function () { ); $("#annotationsModalContainer").html(response); - // Verifica nuovamente la presenza di #annotationsModal const annotationsModalElementAfterLoad = document.getElementById("annotationsModal"); if (!annotationsModalElementAfterLoad) { @@ -252,7 +260,7 @@ $(document).ready(function () { window.initAnnotationsModal(iddatadb, idquotations, trfHeader); } else { console.error( - "initAnnotationsModal non definito. Verifica che annotationsModal.js sia caricato correttamente e definisca window.initAnnotationsModal.", + "initAnnotationsModal non definito. Verifica che annotationsModal.js sia caricato correttamente.", ); alert( "Errore: Funzione initAnnotationsModal non trovata. Controlla che annotationsModal.js sia incluso correttamente.", @@ -273,10 +281,12 @@ $(document).ready(function () { partMatrice = {}; unsavedChanges = false; matrici = []; + macroMatrici = []; $("#photoSelectorContainer").empty().hide(); $("#samplePhoto").attr("src", ""); $("#partsTableBody").empty(); $("#global-matrice").empty(); + $("#macro-matrice-filter").empty(); $(".temp-alert").remove(); $(".modal-backdrop").remove(); $("body").removeClass("modal-open").css("padding-right", ""); @@ -385,9 +395,12 @@ $(document).ready(function () { // =================== // DOWNLOAD PHOTO // =================== - $("#downloadPhotoBtn").on("click", function () { + $(document).on("click", "#downloadPhotoBtn", function (e) { + console.log("Clicked Download Photo - Evento triggerato"); + e.preventDefault(); const photoSrc = $("#samplePhoto").attr("src"); if (!photoSrc) { + console.log("Nessuna foto caricata"); const errorMsg = $( '', ); @@ -406,6 +419,7 @@ $(document).ready(function () { document.body.appendChild(link); link.click(); document.body.removeChild(link); + console.log("Download avviato per:", photoSrc); }); // =================== @@ -420,7 +434,7 @@ $(document).ready(function () { }) .get(), ); - addNewRow(maxPartNumber + 1); + addNewRow(maxPartNumber + 1, false); // Riga normale }); $(document).on("click", ".add-mix-global", function (e) { @@ -432,45 +446,10 @@ $(document).ready(function () { }) .get(), ); - addNewRow(maxPartNumber + 1, true); + addNewRow(maxPartNumber + 1, true); // Riga Mix }); - function addNewRow(nextPartNumber, isMix = false) { - const description = isMix ? "Mix" : ""; - const newRow = ` - - - - -
- - -
- - - - - - - - `; - $("#partsTableBody").append(newRow); - const $select = $("#partsTableBody tr:last .part-matrice"); - initializeSelect2($select, nextPartNumber, "", null); - updateRowButtons(); - markUnsaved(); - } - - function updateRowButtons() { - const rowCount = $("#partsTableBody tr").length; - $("#partsTableBody tr").each(function () { - $(this) - .find(".remove-row") - .toggle(rowCount > 1); - }); - } - - $(document).on("click", ".add-to-mix-row", function (e) { + $(document).on("click", ".add-mix-row", function (e) { e.preventDefault(); const $row = $(this).closest("tr"); const partDescription = $row.find(".part-description").val().trim(); @@ -487,6 +466,15 @@ $(document).ready(function () { return; } + const maxPartNumber = Math.max( + ...$("#partsTableBody tr") + .map(function () { + return parseInt($(this).find(".part-number").val()) || 0; + }) + .get(), + ); + + let mixDescription = `Mix ${partDescription}`; const $mixRow = $("#partsTableBody tr") .filter(function () { return $(this) @@ -497,54 +485,132 @@ $(document).ready(function () { }) .last(); - if ($mixRow.length === 0) { - const errorMsg = $( - '', - ); - $("#partsModal .modal-body").prepend(errorMsg); - setTimeout(function () { - errorMsg.fadeOut(500, function () { - $(this).remove(); - }); - }, 5000); - return; + if ($mixRow.length > 0) { + let currentMix = $mixRow.find(".part-description").val().trim(); + if (currentMix === "Mix") { + mixDescription = currentMix + " " + partDescription; + } else if (!currentMix.includes(partDescription)) { + mixDescription = currentMix + " + " + partDescription; + } + $mixRow + .find(".part-description") + .val(mixDescription) + .trigger("blur"); + } else { + addNewRow(maxPartNumber + 1, true); // Crea nuova riga Mix + const $newMixRow = $("#partsTableBody tr:last"); + $newMixRow + .find(".part-description") + .val(mixDescription) + .trigger("blur"); } - - let mixDescription = $mixRow.find(".part-description").val().trim(); - if (mixDescription === "Mix") { - mixDescription = `Mix ${partDescription}`; - } else if (!mixDescription.includes(partDescription)) { - mixDescription += ` + ${partDescription}`; - } - $mixRow.find(".part-description").val(mixDescription).trigger("blur"); }); - $(document).on("click", ".remove-row", function (e) { - e.preventDefault(); + function addNewRow(nextPartNumber, isMix = false) { + const description = isMix ? "Mix" : ""; + const newRow = ` + + + + +
+ + +
+ + + + + + + + + + `; + $("#partsTableBody").append(newRow); + const $select = $("#partsTableBody tr:last .part-matrice"); + const selectedMacro = $("#macro-matrice-filter").val() || ""; + initializeSelect2($select, nextPartNumber, "", null, selectedMacro); + updateRowButtons(); + markUnsaved(); + } + + // =================== + // NOTE HANDLING + // =================== + $(document).on("click", ".note-btn", function () { const $row = $(this).closest("tr"); const partId = $row.data("part-id"); - const partNumber = $row.find(".part-number").val(); + const note = $row.data("note") || ""; + const $noteModal = $("#noteModal"); + $noteModal.find(".part-note").val(note); + $noteModal.data("part-id", partId); + $noteModal.data("row", $row); + const modalInstance = new bootstrap.Modal($noteModal[0], { + backdrop: "static", + keyboard: false, + }); + modalInstance.show(); + }); + + $(document).on("click", ".save-note-btn", function () { + const $noteModal = $("#noteModal"); + const $row = $noteModal.data("row"); + const partId = $noteModal.data("part-id"); + const note = $noteModal.find(".part-note").val().trim(); const iddatadb = $("#partsModal").data("iddatadb"); const idquotations = $("#partsModal").data("idquotations"); const endpoint = idquotations - ? "delete_part_quotation.php" - : "delete_part.php"; + ? "save_parts_quotation.php" + : "save_parts.php"; + const data = idquotations + ? { idquotations: idquotations } + : { iddatadb: iddatadb }; + + // Raccogli tutti i dati della riga per evitare sovrascritture + const partNumber = $row.find(".part-number").val(); + const partDescription = $row.find(".part-description").val().trim(); + const mix = partDescription.startsWith("Mix") ? "Y" : "N"; + const idmatrice = $row.find(".part-matrice").val() || null; + const dateexpiry = $row.find(".part-dateexpiry").val() || null; if (partId && partId !== "new") { + const $saveStatus = $row.find(".save-status"); + const $saveLoading = $row.find(".save-loading"); + $saveLoading.show(); + $saveStatus.hide(); + $.ajax({ url: endpoint, method: "POST", - data: JSON.stringify({ part_id: partId }), + data: JSON.stringify({ + ...data, + parts: [ + { + id: partId, + part_number: partNumber, + part_description: partDescription, + mix: mix, + idmatrice: idmatrice, + note: note || null, + dateexpiry: dateexpiry, + }, + ], + }), contentType: "application/json", success: function (response) { + $saveLoading.hide(); if (response.success) { - $row.remove(); - delete partMatrice[partNumber]; - updateRowButtons(); - markUnsaved(); + $row.data("note", note); + $row.find(".note-btn").toggleClass("has-note", !!note); + $saveStatus.show(); + setTimeout(() => $saveStatus.hide(), 2000); + bootstrap.Modal.getInstance( + document.getElementById("noteModal"), + ).hide(); } else { const errorMsg = $( - '