From 22c95fa063f692873d6ab18a61c912d442ed8c68 Mon Sep 17 00:00:00 2001 From: Claudio Date: Fri, 22 Nov 2024 11:57:39 +0100 Subject: [PATCH] added charts and fixed analysis component --- public/userarea/easyspec/analysis.php | 385 +++++++----------- public/userarea/easyspec/cancel-analysis.php | 22 +- public/userarea/easyspec/standards.php | 367 +++++------------ .../easyspec/update-component-list.php | 115 ++++-- public/userarea/importify/importfiledate.php | 18 + public/userarea/importify/updatedate.php | 30 ++ public/userarea/importify/upload_excel.php | 73 ++++ public/userarea/include/navigationbar.php | 5 +- public/userarea/statkpi/analytes_stats.php | 360 ++++++++++++++++ public/userarea/statkpi/parsedatachart.php | 76 +++- public/userarea/statkpi/statkpi.php | 159 ++++++++ public/userarea/statkpi/substance-detail.php | 301 ++++++++++++++ 12 files changed, 1355 insertions(+), 556 deletions(-) create mode 100644 public/userarea/importify/importfiledate.php create mode 100644 public/userarea/importify/updatedate.php create mode 100644 public/userarea/importify/upload_excel.php create mode 100644 public/userarea/statkpi/analytes_stats.php create mode 100644 public/userarea/statkpi/substance-detail.php diff --git a/public/userarea/easyspec/analysis.php b/public/userarea/easyspec/analysis.php index 71fdb57..ea5a19c 100644 --- a/public/userarea/easyspec/analysis.php +++ b/public/userarea/easyspec/analysis.php @@ -1,6 +1,4 @@ - @@ -9,101 +7,67 @@ + EasySpec - Reportify - - + + - - + + + + + + + + + + - + - -
-
-
-
-
- -
- -
-
- -
- +
+
@@ -117,213 +81,136 @@
- +
-
EasySpec:
- Insert Analysis Analysis Category RSL Back to the Wizard Back to Wizard

- -
- - - - - - - - - - - - - - - setQuery("SELECT * FROM `analysis` LEFT JOIN family_analysis ON family_analysis.idfamilyanalysis=analysis.family_analysis WHERE analysis.company_id='$idcompany'"); - $tablequery->execute(); - - $wa_startindex = 0; - while (!$tablequery->atEnd()) { - $wa_startindex = $tablequery->Index; - ?> - - - - - - - - - moveNext(); - } - $tablequery->moveFirst(); //return RS to first record - unset($wa_startindex); - unset($wa_repeatcount); - - ?> -
Family
getColumnVal("name_analysis")); ?>getColumnVal("description_analysis")); ?>getColumnVal("namefamily")); ?>" role="button">Update Component List - - - - - - - - -
-
- +
EasySpec
+ Insert Analysis + Analysis Category + RSL
- - - - - -
- -
- -
+
- -
- + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/userarea/easyspec/cancel-analysis.php b/public/userarea/easyspec/cancel-analysis.php index 19c6bc6..e288c24 100644 --- a/public/userarea/easyspec/cancel-analysis.php +++ b/public/userarea/easyspec/cancel-analysis.php @@ -3,14 +3,16 @@ -Action = "delete"; - $DeleteQuery->Table = "`analysis`"; - $DeleteQuery->addFilter("idanalysis", "=", "i", "" . ($_GET['idanalysis']) . ""); - $DeleteQuery->execute(); - $DeleteGoTo = "analysis.php"; - if (function_exists("rel2abs")) $DeleteGoTo = $DeleteGoTo ? rel2abs($DeleteGoTo, dirname(__FILE__)) : ""; - $DeleteQuery->redirect($DeleteGoTo); +Action = "update"; + $UpdateQuery->Table = "`analysisvocabulary`"; + $UpdateQuery->addFilter("idanalysisvocabulary", "=", "i", "" . ($_GET['idanalysis']) . ""); + $UpdateQuery->addColumn("active", "s", "N"); // Imposta il campo active a 'N' + $UpdateQuery->execute(); + $UpdateGoTo = "analysis.php"; + if (function_exists("rel2abs")) $UpdateGoTo = $UpdateGoTo ? rel2abs($UpdateGoTo, dirname(__FILE__)) : ""; + $UpdateQuery->redirect($UpdateGoTo); } -?> \ No newline at end of file +?> diff --git a/public/userarea/easyspec/standards.php b/public/userarea/easyspec/standards.php index 7a6d94c..460b234 100644 --- a/public/userarea/easyspec/standards.php +++ b/public/userarea/easyspec/standards.php @@ -1,6 +1,5 @@ - + @@ -14,13 +13,29 @@ + + + - + + + + + + + + + + + + + + - - -
-
-
-
-
- -
- - -
-
-
-
-
@@ -106,262 +79,140 @@
-
-
EasySpec: STANDARDS
- Insert new Standard RSL Category Analysis Back to Wizard - - +
EasySpec: Standards
+
+ Insert new Standard RSL Category Analysis Back to Wizard + + - -

-
-
- -
+ +

-
- +
- - - - - - - - - + + + + + + - - + - setQuery("SELECT * FROM standards WHERE company_id='$idcompany'"); + setQuery("SELECT * FROM standards WHERE company_id='$idcompany'"); $rsllist->execute(); - $wa_startindex = 0; while (!$rsllist->atEnd()) { - $wa_startindex = $rsllist->Index; - ?> + $idstandards = $rsllist->getColumnVal("idstandards"); + $conn = new mysqli($servername, $username, $password, $database); + $query = $conn->prepare("SELECT pdffilename FROM pdfstandards WHERE idstandards = ?"); + $query->bind_param("i", $idstandards); + $query->execute(); + $result = $query->get_result(); + $pdfFiles = []; + while ($row = $result->fetch_assoc()) { + $pdfFiles[] = $row['pdffilename']; + } + $pdfCount = count($pdfFiles); + ?> + - - - - - - getColumnVal("idstandards"); - // Assumendo che $conn sia l'oggetto della connessione al database - $conn = new mysqli($servername, $username, $password, $database); - $query = $conn->prepare("SELECT pdffilename FROM pdfstandards WHERE idstandards = ?"); - $query->bind_param("i", $idstandards); - $query->execute(); - $result = $query->get_result(); - - $pdfFiles = []; - while ($row = $result->fetch_assoc()) { - $pdfFiles[] = $row['pdffilename']; - } - - ?> - - + getColumnVal("status") == "A") { ?> + + + + + + + + + + - - - - - moveNext(); + moveNext(); } - $rsllist->moveFirst(); //return RS to first record - unset($wa_startindex); - unset($wa_repeatcount); - - ?> + ?> +
Standards NameNumberYearActive FromActive toStandards NameNumberYearActive FromActive To PDFActions
- getColumnVal("status"); - if ($actstatus == "A") { ?>getColumnVal("titlestandards")); ?>getColumnVal("numberstandards")); ?>getColumnVal("yearstandards")); ?>getColumnVal("activefrom")); ?>getColumnVal("activeto")); ?>getColumnVal("titlestandards"); ?>getColumnVal("numberstandards"); ?>getColumnVal("yearstandards"); ?>getColumnVal("activefrom"); ?>getColumnVal("activeto"); ?> - Open PDF"; - } elseif ($pdfCount > 1) { - // Più PDF, link alla pagina di gestione - $updateUrl = "update-standards.php?id=" . $rsllist->getColumnVal('idstandards'); - echo "Manage PDFs"; - } else { - echo "No PDFs"; // Nessun PDF disponibile - } ?> + Open PDF + 1) { ?> + Manage PDFs + + + - " role="button" data-toggle="tooltip" title="Go"> - - " role="button" data-toggle="tooltip" title="Delete"> - + + + + + +
-
- +
- - - - - - -
-
-
- +
+
- - - - - - - + - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/userarea/easyspec/update-component-list.php b/public/userarea/easyspec/update-component-list.php index 7f8790e..c80e88f 100644 --- a/public/userarea/easyspec/update-component-list.php +++ b/public/userarea/easyspec/update-component-list.php @@ -42,12 +42,12 @@ - +
@@ -132,52 +132,75 @@ } ?> setQuery("SELECT * FROM `analysis` WHERE analysis.idanalysis='$idanalysis'"); + $tablequery->setQuery("SELECT * FROM `analysisvocabulary` WHERE analysisvocabulary.idanalysisvocabulary='$idanalysis'"); $tablequery->execute(); ?> setQuery("SELECT * FROM component WHERE component.company_id='$idcompany' ORDER BY component.name_component"); + $componentlist->setQuery("SELECT * FROM compundsvocabulary WHERE preferred='Y' ORDER BY compundsvocabulary.namecompoundsvocabulary"); $componentlist->execute(); ?> setQuery("SELECT * FROM analysis_component LEFT JOIN component ON analysis_component.idcomponent=component.idcomponent WHERE analysis_component.idanalysis=$idanalysis ORDER BY component.name_component"); + $companalysis->setQuery("SELECT * FROM analysis_component LEFT JOIN compundsvocabulary ON analysis_component.idcomponent=compundsvocabulary.idcompoundsvocabulary WHERE analysis_component.idanalysis=$idanalysis ORDER BY compundsvocabulary.namecompoundsvocabulary"); $companalysis->execute(); ?>
-
EasySpec:
+
- " role="button">Edit RSL

-

Analysis: getColumnVal("name_analysis")); ?>

-
-
- -
-
-
- - - - -
+ + - - ', '_blank', 'location=yes,height=720,width=1000,scrollbars=yes,status=yes');"> -

+ + + + +

+ Analysis: getColumnVal("nameanalysisvoc"); ?> +

+ +

+ + +
+
+
+ + +
+
+ + +
+
+
+ + +
+ +
+
+
@@ -185,7 +208,7 @@ - + @@ -199,13 +222,18 @@ ?> - - + + - + + moveNext(); @@ -247,6 +275,25 @@ $('[data-toggle="tooltip"]').tooltip(); }); + diff --git a/public/userarea/importify/importfiledate.php b/public/userarea/importify/importfiledate.php new file mode 100644 index 0000000..312179f --- /dev/null +++ b/public/userarea/importify/importfiledate.php @@ -0,0 +1,18 @@ + + + + + + + Upload Excel + + + + + + + + + + + \ No newline at end of file diff --git a/public/userarea/importify/updatedate.php b/public/userarea/importify/updatedate.php new file mode 100644 index 0000000..771a96e --- /dev/null +++ b/public/userarea/importify/updatedate.php @@ -0,0 +1,30 @@ +connect_error) { + die("Connection failed: " . $conn->connect_error); +} + +// Aggiorna le date in reports utilizzando i dati di reportsbydate +$updateQuery = " + UPDATE reports AS r + INNER JOIN reportsbydate AS rb + ON r.reportsNumberLab = rb.report_no + SET + r.reportDatein = IF(rb.in_date IS NOT NULL, rb.in_date, r.reportDatein), + r.reportsDateDue = IF(rb.due_date IS NOT NULL, rb.due_date, r.reportsDateDue), + r.reportsDateOut = IF(rb.out_date IS NOT NULL, rb.out_date, r.reportsDateOut) +"; + +if ($conn->query($updateQuery) === TRUE) { + echo "Reports updated successfully."; +} else { + echo "Error updating reports: " . $conn->error; +} + +$conn->close(); diff --git a/public/userarea/importify/upload_excel.php b/public/userarea/importify/upload_excel.php new file mode 100644 index 0000000..765b2b5 --- /dev/null +++ b/public/userarea/importify/upload_excel.php @@ -0,0 +1,73 @@ +connect_error) { + die("Connection failed: " . $conn->connect_error); +} + +if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_FILES['file'])) { + $fileTmpPath = $_FILES['file']['tmp_name']; + $fileName = $_FILES['file']['name']; + $fileExtension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION)); + + if ($fileExtension === 'xlsx' || $fileExtension === 'xls') { + try { + $spreadsheet = IOFactory::load($fileTmpPath); + $sheet = $spreadsheet->getActiveSheet(); + $rows = $sheet->toArray(); + + // Trova gli indici delle colonne dall'header + $header = $rows[0]; // Prima riga + $colIndex = array_flip($header); // Map header to column index + + $reportNoIndex = isset($colIndex['Report no.']) ? $colIndex['Report no.'] : 'S'; + $inDateIndex = isset($colIndex['IN Date']) ? $colIndex['IN Date'] : 'T'; + $dueDateIndex = isset($colIndex['DUE Date']) ? $colIndex['DUE Date'] : 'U'; + $outDateIndex = isset($colIndex['OUT Date']) ? $colIndex['OUT Date'] : 'V'; + + foreach ($rows as $index => $row) { + if ($index == 0) continue; // Salta l'intestazione + + // Ottieni i dati dalle colonne specificate + $reportNo = $conn->real_escape_string(trim($row[$reportNoIndex])); + $inDate = isset($row[$inDateIndex]) ? date('Y-m-d', strtotime(str_replace('/', '-', $row[$inDateIndex]))) : null; + $dueDate = isset($row[$dueDateIndex]) ? date('Y-m-d', strtotime(str_replace('/', '-', $row[$dueDateIndex]))) : null; + $outDate = isset($row[$outDateIndex]) ? date('Y-m-d', strtotime(str_replace('/', '-', $row[$outDateIndex]))) : null; + + // Controlla se il report esiste già + $checkQuery = "SELECT id FROM reportsbydate WHERE report_no = '$reportNo'"; + $result = $conn->query($checkQuery); + + if ($result->num_rows == 0 && !empty($reportNo)) { + // Inserisci solo se il report non esiste e il Report No è valido + $insertQuery = " + INSERT INTO reportsbydate (report_no, in_date, due_date, out_date) + VALUES ('$reportNo', " . + ($inDate ? "'$inDate'" : "NULL") . ", " . + ($dueDate ? "'$dueDate'" : "NULL") . ", " . + ($outDate ? "'$outDate'" : "NULL") . ")"; + $conn->query($insertQuery); + } + } + + echo "File imported successfully."; + } catch (Exception $e) { + echo "Error processing file: " . $e->getMessage(); + } + } else { + echo "Invalid file format. Please upload an Excel file."; + } +} else { + echo "No file uploaded."; +} + +$conn->close(); diff --git a/public/userarea/include/navigationbar.php b/public/userarea/include/navigationbar.php index 48c54aa..2535f62 100644 --- a/public/userarea/include/navigationbar.php +++ b/public/userarea/include/navigationbar.php @@ -7,7 +7,7 @@ @@ -41,7 +41,7 @@
  • - + Notifications @@ -121,6 +121,7 @@ StatKPI
  • diff --git a/public/userarea/statkpi/analytes_stats.php b/public/userarea/statkpi/analytes_stats.php new file mode 100644 index 0000000..6f586f1 --- /dev/null +++ b/public/userarea/statkpi/analytes_stats.php @@ -0,0 +1,360 @@ + +query($query); + +$tableData = []; // Array per la tabella + +while ($row = $result->fetch_assoc()) { + $substances[] = $row['substance_name']; + $passCounts[] = $row['pass_count']; + $failCounts[] = $row['fail_count']; + $substanceIds[] = $row['substance_id']; // Aggiungi l'ID della sostanza + + // Aggiungi dati al $tableData per la tabella + $tableData[] = [ + 'id' => $row['substance_id'], + 'name' => $row['substance_name'], + 'pass_count' => $row['pass_count'], + 'fail_count' => $row['fail_count'], + 'total' => $row['pass_count'] + $row['fail_count'] + ]; +} + +$queryDetectable = " +SELECT + cv.idcompoundsvocabulary AS substance_id, + cv.namecompoundsvocabulary AS substance_name, + cv.cascompoundvocabulary AS cas_number, + COUNT(*) AS total_results, + COUNT(CASE WHEN rp.result_Value NOT LIKE '<%' THEN 1 END) AS detectable_count, + ROUND((COUNT(CASE WHEN rp.result_Value NOT LIKE '<%' THEN 1 END) / COUNT(*)) * 100, 2) AS detectable_percentage +FROM result_project rp +LEFT JOIN analysis_project ap ON rp.idanalysis_project = ap.idAnalysis_Project +LEFT JOIN compundsvocabulary cv ON rp.result_AnalytsName = cv.idcompoundsvocabulary +WHERE cv.preferred = 'Y' AND cv.component_type = 'CH' +GROUP BY cv.idcompoundsvocabulary, cv.namecompoundsvocabulary, cv.cascompoundvocabulary +ORDER BY total_results DESC; +"; + +$resultDetectable = $conn->query($queryDetectable); + +$detectableData = []; // Array per la nuova tabella + +while ($row = $resultDetectable->fetch_assoc()) { + $detectableData[] = [ + 'id' => $row['substance_id'], + 'name' => $row['substance_name'], + 'cas_number' => $row['cas_number'], // Aggiunge il CAS number + 'total_results' => $row['total_results'], + 'detectable_count' => $row['detectable_count'], + 'detectable_percentage' => $row['detectable_percentage'] + ]; +} + + +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    +
    + + +
    +
    + +
    +
    +
    +
    + +
    +

    Substance Statistics

    +
    +
    +
    +
    + + + records + + + +
    +
    +
    +
    +
    Substances by Rating
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    Substances Data
    +
    CAS
    getColumnVal("name_component"); ?>getColumnVal("description_component"); ?>getColumnVal("namecompoundsvocabulary"); ?>getColumnVal("cascompoundvocabulary"); ?> &idanalysis=" role="button">C + + + +
    + + + + + + + + + + + + + + + + + + + +
    Substance NamePass CountFail CountTotal
    + + + +
    +
    +
    +
    +
    + + + +
    +
    +
    +
    +
    Chemical Substance Result Summary
    + + + + + + + + + + + + + + + + + + + + + +
    Substance NameCAS NumberTotal ResultsDetectable CountDetectable %
    + + + + %
    +
    +
    +
    +
    + + + + + +
    +
    + + + + + + + + + + + \ No newline at end of file diff --git a/public/userarea/statkpi/parsedatachart.php b/public/userarea/statkpi/parsedatachart.php index a688bdb..51d6acb 100644 --- a/public/userarea/statkpi/parsedatachart.php +++ b/public/userarea/statkpi/parsedatachart.php @@ -489,15 +489,21 @@ while ($row = $analysisDistributionResult->fetch_assoc()) { // fecth analytes with most fails $failedAnalytesQuery = " - SELECT c.namecompoundsvocabulary AS AnalyteName, COUNT(*) AS FailCount + SELECT + c.namecompoundsvocabulary AS AnalyteName, + COUNT(*) AS FailCount FROM result_project rp LEFT JOIN compundsvocabulary c ON rp.result_AnalytsName = c.idcompoundsvocabulary - WHERE LOWER(rp.result_AnalytsRating) IN ('f', 'fail', 'doesn\'t comply') + LEFT JOIN reports r ON rp.idreports = r.idreports + LEFT JOIN products p ON r.idproducts = p.idproducts + $filters + AND LOWER(rp.result_AnalytsRating) IN ('f', 'fail', 'doesn\'t comply') GROUP BY c.namecompoundsvocabulary ORDER BY FailCount DESC LIMIT 10; "; + $resultFailedAnalytes = mysqli_query($repnew, $failedAnalytesQuery) or die("Error in Selecting " . mysqli_error($repnew)); // Verifica se ci sono risultati @@ -510,6 +516,68 @@ while ($row = mysqli_fetch_assoc($resultFailedAnalytes)) { ]; } +// New Query: phasequery +$phaseQuery = " + SELECT + p.products_phase AS phase, + COUNT(*) AS totalProducts + FROM products p + LEFT JOIN reports r ON p.idproducts = r.idproducts + $filters + AND p.products_phase IS NOT NULL + GROUP BY p.products_phase + ORDER BY totalProducts DESC +"; + +$phaseQueryResult = $conn->query($phaseQuery); + +// Process the results +$phaseData = []; +while ($row = $phaseQueryResult->fetch_assoc()) { + $phaseData[] = [ + 'phase' => $row['phase'], + 'totalProducts' => $row['totalProducts'] + ]; +} + +// New Query: Phase ratings distribution +$phaseRatingsQuery = " + SELECT + p.products_phase AS phase, + SUM(CASE + WHEN UPPER(r.reportsRating) IN ('PASS', 'P', 'COMPLY') THEN 1 + ELSE 0 + END) AS passCount, + SUM(CASE + WHEN UPPER(r.reportsRating) IN ('FAIL', 'F', 'DOESN\'T COMPLY') THEN 1 + ELSE 0 + END) AS failCount, + SUM(CASE + WHEN UPPER(r.reportsRating) NOT IN ('PASS', 'P', 'COMPLY', 'FAIL', 'F', 'DOESN\'T COMPLY') THEN 1 + ELSE 0 + END) AS otherCount + FROM products p + LEFT JOIN reports r ON p.idproducts = r.idproducts + $filters + AND p.products_phase IS NOT NULL + GROUP BY p.products_phase + ORDER BY p.products_phase ASC +"; + +$phaseRatingsResult = $conn->query($phaseRatingsQuery); + +// Process the results +$phaseRatingsData = []; +while ($row = $phaseRatingsResult->fetch_assoc()) { + $phaseRatingsData[] = [ + 'phase' => $row['phase'], + 'passCount' => (int)$row['passCount'], + 'failCount' => (int)$row['failCount'], + 'otherCount' => (int)$row['otherCount'] + ]; +} + + // Ora controlliamo se è una richiesta AJAX if ($_SERVER['REQUEST_METHOD'] === 'POST') { // Rispondi ai dati aggiornati tramite AJAX @@ -537,7 +605,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { 'failedAnalytes' => $failedAnalytes, 'analysisDistribution' => $analysisDistribution, // Distribuzione delle analisi per il grafico a torta 'horizontalBarData' => $horizontalBarData, // Dati per il grafico a barre orizzontali - 'horizontalBarAnalysisData' => $horizontalBarAnalysisData // Nuovi dati per le analisi + 'phaseData' => $phaseData, + 'horizontalBarAnalysisData' => $horizontalBarAnalysisData, + 'phaseRatingsData' => $phaseRatingsData // Nuovi dati per il grafico delle fasi ]); exit; // Ferma l'esecuzione del resto dello script dopo aver risposto all'AJAX } diff --git a/public/userarea/statkpi/statkpi.php b/public/userarea/statkpi/statkpi.php index 5c25a2f..affe8db 100644 --- a/public/userarea/statkpi/statkpi.php +++ b/public/userarea/statkpi/statkpi.php @@ -641,6 +641,27 @@ include('parsedatachart.php'); +
    + +
    +
    +
    +
    Products Distribution by Phase
    +
    +
    +
    +
    + + +
    +
    +
    +
    Phase Rating Distribution
    +
    +
    +
    +
    +
    @@ -1273,6 +1294,144 @@ include('parsedatachart.php'); alert('Error retrieving data.'); } }); + + function renderPhasePieChart(phaseData) { + const labels = phaseData.map(item => item.phase); + const values = phaseData.map(item => parseInt(item.totalProducts, 10)); + + const options = { + series: values, + chart: { + type: 'pie', + height: 350 + }, + labels: labels, + responsive: [{ + breakpoint: 480, + options: { + chart: { + width: 300 + }, + legend: { + position: 'bottom' + } + } + }], + colors: ['#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0', '#9966FF', '#C9CB8D'], // Custom Colors + legend: { + position: 'bottom' + } + }; + + const chart = new ApexCharts(document.querySelector("#phasePieChart"), options); + chart.render(); + } + + // Funzione per il grafico a barre (Phase Ratings) + function renderPhaseBarChart(phaseRatingsData) { + const labels = phaseRatingsData.map(item => item.phase); // Etichette per le fasi + const passCounts = phaseRatingsData.map(item => parseInt(item.passCount, 10)); + const failCounts = phaseRatingsData.map(item => parseInt(item.failCount, 10)); + const otherCounts = phaseRatingsData.map(item => parseInt(item.otherCount, 10)); + + const options = { + series: [{ + name: 'Pass', + data: passCounts + }, + { + name: 'Fail', + data: failCounts + }, + { + name: 'Other', + data: otherCounts + } + ], + chart: { + type: 'bar', + height: 400, + stacked: true, // Barre impilate + horizontal: true + }, + xaxis: { + categories: labels, // Fasi come categorie + title: { + text: 'Ratings Count' // Titolo per l'asse X + } + }, + colors: ['#28A745', '#FF4D4D', '#FFA500'], // Colori per Pass, Fail e Other + plotOptions: { + bar: { + horizontal: true, + dataLabels: { + enabled: false // Disabilitiamo le etichette per ogni barra + } + } + }, + legend: { + position: 'top', // Posizioniamo la leggenda sopra il grafico + }, + tooltip: { + y: { + formatter: val => `${val} reports` // Tooltip personalizzato + } + } + }; + + $('#phaseBarChart').html(''); // Reset grafico esistente + const chart = new ApexCharts(document.querySelector("#phaseBarChart"), options); + chart.render(); + } + + + + // Chiama questa funzione dopo aver recuperato i dati tramite AJAX + $(document).ready(function() { + updateData(); // Aggiorna i dati iniziali + }); + + function updateData() { + $.ajax({ + url: 'parsedatachart.php', // Endpoint per ottenere i dati + method: 'POST', + data: { + startDate: $('#startDate').val(), + endDate: $('#endDate').val(), + supplier: $('#supplierFilter').val(), + productsRefnumber: $('#productsRefnumber').val(), + productsSeason: $('#productsSeason').val(), + ageRange: $('#ageRange').val(), + reportsLabName: $('#reportsLabName').val(), + reportsTestType: $('#reportsTestType').val(), + reportsNumberLab: $('#reportsNumberLab').val(), + }, + success: function(response) { + const data = JSON.parse(response); + + // Aggiorna il grafico della distribuzione per fase + if (data.phaseData && data.phaseData.length > 0) { + renderPhasePieChart(data.phaseData); + } else { + console.log('No phase data available.'); + } + + // Aggiorna il grafico delle valutazioni per fase (Bar Chart) + if (data.phaseRatingsData && data.phaseRatingsData.length > 0) { + renderPhaseBarChart(data.phaseRatingsData); + } else { + console.log('No phase ratings data available for Bar Chart.'); + $('#phaseBarChart').html('

    No data available

    '); + } + }, + error: function() { + console.log('Error retrieving data.'); + } + }); + } + + + } diff --git a/public/userarea/statkpi/substance-detail.php b/public/userarea/statkpi/substance-detail.php new file mode 100644 index 0000000..7b3b821 --- /dev/null +++ b/public/userarea/statkpi/substance-detail.php @@ -0,0 +1,301 @@ + +prepare($query); +$stmt->bind_param("i", $substance_id); +$stmt->execute(); +$result = $stmt->get_result(); +$substance = $result->fetch_assoc(); + +// Query per ottenere i valori della sostanza +$queryValues = " +SELECT + rp.result_Value, + rp.result_UnitofMeasure, + r.reportDateIn, + r.reportsNumberLab, + p.products_refnumber, + p.products_description, + r.idreports +FROM result_project rp +LEFT JOIN compundsvocabulary cv ON rp.result_AnalytsName = cv.idcompoundsvocabulary +LEFT JOIN reports r ON rp.idreports = r.idreports +LEFT JOIN products p ON r.idproducts = p.idproducts +WHERE cv.idcompoundsvocabulary = ? +AND (rp.result_Value REGEXP '^[0-9]+([,][0-9]+)?$' OR rp.result_Value LIKE '<%') +ORDER BY r.reportDateIn ASC; +"; + +$stmtValues = $conn->prepare($queryValues); +$stmtValues->bind_param("i", $substance_id); +$stmtValues->execute(); +$resultValues = $stmtValues->get_result(); + +$values = []; +while ($row = $resultValues->fetch_assoc()) { + $values[] = $row; +} + + + +// Query per calcolare la percentuale di valori detected +$queryDetectablePercentage = " +SELECT + ROUND( + (COUNT(CASE WHEN rp.result_Value NOT LIKE '<%' THEN 1 END) / COUNT(*)) * 100, 2 + ) AS detectable_percentage +FROM result_project rp +LEFT JOIN compundsvocabulary cv ON rp.result_AnalytsName = cv.idcompoundsvocabulary +WHERE cv.idcompoundsvocabulary = ? AND cv.component_type = 'CH'; +"; + +$stmtDetectablePercentage = $conn->prepare($queryDetectablePercentage); +$stmtDetectablePercentage->bind_param("i", $substance_id); +$stmtDetectablePercentage->execute(); +$resultDetectablePercentage = $stmtDetectablePercentage->get_result(); +$detectableData = $resultDetectablePercentage->fetch_assoc(); +$detectablePercentage = $detectableData['detectable_percentage'] ?? 0; + +// Determina la classe del badge in base alla percentuale +$badgeClass = ''; +if ($detectablePercentage < 3) { + $badgeClass = 'bg-success'; // Verde +} elseif ($detectablePercentage >= 3 && $detectablePercentage < 10) { + $badgeClass = 'bg-info'; // Azzurro +} elseif ($detectablePercentage >= 10 && $detectablePercentage < 30) { + $badgeClass = 'bg-warning'; // Arancio +} else { + $badgeClass = 'bg-danger'; // Rosso +} + +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + +
    +
    + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    + + + + % Detected + +

    +

    Comprehensive analysis and details

    +
    +
    + + ID: + + + Last Updated: + +
    +
    + + +
    +
    +
    +
    + + + +
    +
    +
    +
    +
    Distribution of Values
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    Values Table
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    DateReport NumberProduct RefValueUnit
    + + + + + ' . htmlspecialchars($rawValue) . ''; + } else { + echo '' . htmlspecialchars($rawValue) . ''; + } + ?> +
    + + +
    +
    +
    +
    + +
    +
    +
    + + +
    +
    + + + + + + \ No newline at end of file