654 lines
32 KiB
PHP
654 lines
32 KiB
PHP
<?php include('../include/headscript.php'); ?>
|
|
<?php include("../class/company.php"); ?>
|
|
<?php
|
|
// Connessione al database
|
|
$conn = new mysqli($servername, $username, $password, $database);
|
|
if ($conn->connect_error) {
|
|
die("Connection failed: " . $conn->connect_error);
|
|
}
|
|
|
|
// Recupera l'ID del fornitore
|
|
$supplierId = isset($_GET['id']) ? intval($_GET['id']) : 0;
|
|
$query = "
|
|
SELECT
|
|
name,
|
|
total_products,
|
|
total_analyses,
|
|
pass_analyses,
|
|
fail_analyses,
|
|
data_analyses,
|
|
rating
|
|
FROM supplier_ratings
|
|
WHERE id = $supplierId
|
|
LIMIT 1
|
|
";
|
|
$result = $conn->query($query);
|
|
$supplier = $result->fetch_assoc();
|
|
if (!$supplier) {
|
|
die("Supplier not found.");
|
|
}
|
|
?>
|
|
|
|
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimal-ui">
|
|
<?php include('../include/seo.php'); ?>
|
|
|
|
<link rel="shortcut icon" href="../assets/images/favicon.ico">
|
|
<link href="../assets/css/bootstrap.min.css" rel="stylesheet" type="text/css">
|
|
<link href="../assets/css/icons.css" rel="stylesheet" type="text/css">
|
|
<link href="../assets/css/style.css" rel="stylesheet" type="text/css">
|
|
<script src="../assets/js/jquery.min.js"></script>
|
|
<link href="https://cdn.jsdelivr.net/npm/boxicons@2.0.7/css/boxicons.min.css" rel="stylesheet">
|
|
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
|
|
<style>
|
|
.collapsible {
|
|
background-color: green;
|
|
color: white;
|
|
padding: 5px 10px;
|
|
border: none;
|
|
border-radius: 5px;
|
|
cursor: pointer;
|
|
transition: background-color 0.3s;
|
|
}
|
|
|
|
.collapsible.active {
|
|
background-color: #d3d3d3;
|
|
}
|
|
|
|
.collapsible-content {
|
|
display: none;
|
|
overflow: hidden;
|
|
padding: 10px;
|
|
}
|
|
|
|
.btn-details {
|
|
background-color: #dc3545;
|
|
color: white;
|
|
padding: 5px 10px;
|
|
border: none;
|
|
border-radius: 5px;
|
|
cursor: pointer;
|
|
transition: background-color 0.3s;
|
|
}
|
|
|
|
.btn-details:hover {
|
|
background-color: #c82333;
|
|
}
|
|
|
|
.rating-box {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
}
|
|
|
|
.rating-score {
|
|
font-size: 1.5rem;
|
|
font-weight: bold;
|
|
color: white;
|
|
padding: 10px 20px;
|
|
border-radius: 5px;
|
|
}
|
|
|
|
.rating-high {
|
|
background-color: #28a745;
|
|
}
|
|
|
|
.rating-medium {
|
|
background-color: #ffc107;
|
|
}
|
|
|
|
.rating-low {
|
|
background-color: #dc3545;
|
|
}
|
|
|
|
.data-card {
|
|
padding: 20px;
|
|
border-radius: 10px;
|
|
margin: 10px 0;
|
|
transition: transform 0.3s, box-shadow 0.3s;
|
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.data-card:hover {
|
|
transform: scale(1.05);
|
|
box-shadow: 0 6px 10px rgba(0, 0, 0, 0.15);
|
|
}
|
|
|
|
.data-title {
|
|
font-size: 1.1rem;
|
|
font-weight: bold;
|
|
margin-top: 10px;
|
|
}
|
|
|
|
.data-value {
|
|
font-size: 1.5rem;
|
|
font-weight: bold;
|
|
margin-top: 5px;
|
|
}
|
|
|
|
.h1 {
|
|
font-size: 2.5rem;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.data-label {
|
|
font-size: 0.9rem;
|
|
color: gray;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body class="fixed-left">
|
|
<div id="wrapper">
|
|
<?php include('../include/navigationbar.php'); ?>
|
|
|
|
<div class="content-page">
|
|
<div class="content">
|
|
<?php include('../include/topbar.php'); ?>
|
|
|
|
<div class="page-content-wrapper">
|
|
<div class="container-fluid">
|
|
<div class="row">
|
|
<div class="col-sm-12">
|
|
<div class="page-title-box">
|
|
<h4 class="page-title">Supplier Details</h4>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Supplier Info Section -->
|
|
<div class="row mb-4">
|
|
<div class="col-md-12">
|
|
<div class="card p-4">
|
|
<div class="rating-box">
|
|
<h3 class="m-0">
|
|
<?php echo htmlspecialchars($supplier['name']); ?>
|
|
</h3>
|
|
<div class="rating-score
|
|
<?php echo $supplier['rating'] >= 80 ? 'rating-high' : ($supplier['rating'] >= 50 ? 'rating-medium' : 'rating-low'); ?>">
|
|
<?php echo number_format($supplier['rating'], 2); ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Supplier Stats Section -->
|
|
<div class="row text-center">
|
|
<div class="col-md-3">
|
|
<div class="data-card bg-primary text-white">
|
|
<i class="bx bx-box h1"></i>
|
|
<div class="data-title">Products</div>
|
|
<div class="data-value"><?php echo $supplier['total_products']; ?></div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="data-card bg-info text-white">
|
|
<i class="bx bx-bar-chart-alt h1"></i>
|
|
<div class="data-title">Total Analyses</div>
|
|
<div class="data-value"><?php echo $supplier['total_analyses']; ?></div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-2">
|
|
<div class="data-card bg-success text-white">
|
|
<i class="bx bx-check-circle h1"></i>
|
|
<div class="data-title">PASS</div>
|
|
<div class="data-value"><?php echo $supplier['pass_analyses']; ?></div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-2">
|
|
<div class="data-card bg-danger text-white">
|
|
<i class="bx bx-x-circle h1"></i>
|
|
<div class="data-title">FAIL</div>
|
|
<div class="data-value"><?php echo $supplier['fail_analyses']; ?></div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-2">
|
|
<div class="data-card bg-warning text-white">
|
|
<i class="bx bx-info-circle h1"></i>
|
|
<div class="data-title">DATA</div>
|
|
<div class="data-value"><?php echo $supplier['data_analyses']; ?></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row mt-4">
|
|
<!-- Pie Chart -->
|
|
<div class="col-md-6">
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Analysis Distribution</h5>
|
|
<div id="pie-chart"></div>
|
|
<button id="toggle-pie-table" class="btn btn-secondary mt-3">Toggle Table</button>
|
|
<div id="pie-table-container" style="display: none;">
|
|
<table class="table table-bordered mt-3">
|
|
<thead>
|
|
<tr>
|
|
<th>Category</th>
|
|
<th>Count</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="pie-table-body"></tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Horizontal Stacked Bar Chart -->
|
|
<div class="col-md-6">
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Analysis Summary</h5>
|
|
<div id="stacked-bar-chart"></div>
|
|
<button id="toggle-stacked-table" class="btn btn-secondary mt-3">Toggle Table</button>
|
|
<div id="stacked-table-container" style="display: none;">
|
|
<table class="table table-bordered mt-3">
|
|
<thead>
|
|
<tr>
|
|
<th>Category</th>
|
|
<th>Count</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="stacked-table-body"></tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mt-4">
|
|
<!-- Distribuzione delle Analisi -->
|
|
<div class="col-md-12">
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Total Analysis Distribution</h5>
|
|
<div id="distribution-bar-chart"></div>
|
|
<button id="toggle-distribution-table" class="btn btn-secondary mt-3">Toggle Table</button>
|
|
<div id="distribution-table-container" style="display: none;">
|
|
<table class="table table-bordered mt-3">
|
|
<thead>
|
|
<tr>
|
|
<th>Analysis Name</th>
|
|
<th>Total</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="distribution-table-body"></tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mt-4">
|
|
<!-- Analisi FAIL -->
|
|
<div class="col-md-12">
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Top FAIL Analyses</h5>
|
|
<div id="fail-bar-chart"></div>
|
|
<!-- Pulsante Toggle Table -->
|
|
<button id="toggle-fail-table" class="btn btn-secondary mt-3">Toggle Table</button>
|
|
<div id="fail-table-container" style="display: none;">
|
|
<table class="table table-bordered mt-3">
|
|
<thead>
|
|
<tr>
|
|
<th>Analysis Name</th>
|
|
<th>Fail Count</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="fail-table-body"></tbody>
|
|
</table>
|
|
</div>
|
|
<button id="view-fail-details" class="btn btn-primary mt-3">View Fail Details</button>
|
|
<div id="fail-details-container" style="display: none;">
|
|
<table class="table table-bordered mt-3">
|
|
<thead>
|
|
<tr>
|
|
<th>Analysis Name</th>
|
|
<th>Report Number</th>
|
|
<th>Ref Number</th>
|
|
<th>Product Description</th>
|
|
<th>Action</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="fail-details-table-body"></tbody>
|
|
</table>
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<script>
|
|
document.addEventListener("DOMContentLoaded", function() {
|
|
const supplierName = "<?php echo htmlspecialchars($supplier['name']); ?>";
|
|
|
|
// Pie Chart Configuration (Analysis Distribution)
|
|
const passCount = <?php echo isset($supplier['pass_analyses']) ? $supplier['pass_analyses'] : 0; ?>;
|
|
const failCount = <?php echo isset($supplier['fail_analyses']) ? $supplier['fail_analyses'] : 0; ?>;
|
|
const dataCount = <?php echo isset($supplier['data_analyses']) ? $supplier['data_analyses'] : 0; ?>;
|
|
|
|
|
|
$.getJSON(`get_fail_details.php?supplier=${supplierName}`, function(data) {
|
|
if (data.error) {
|
|
alert(data.error);
|
|
return;
|
|
}
|
|
|
|
// Configurazione del grafico
|
|
const failChartOptions = {
|
|
series: [{
|
|
data: data.failDistribution.map(item => item.fail)
|
|
}],
|
|
chart: {
|
|
type: 'bar',
|
|
height: 350,
|
|
horizontal: true
|
|
},
|
|
xaxis: {
|
|
categories: data.failDistribution.map(item => item.analysis_name),
|
|
title: {
|
|
text: 'Fail Count'
|
|
}
|
|
},
|
|
colors: ['#dc3545'],
|
|
title: {
|
|
text: 'Top FAIL Analyses',
|
|
align: 'center'
|
|
},
|
|
plotOptions: {
|
|
bar: {
|
|
horizontal: true,
|
|
barHeight: '50%'
|
|
}
|
|
}
|
|
};
|
|
|
|
const failChart = new ApexCharts(document.querySelector("#fail-bar-chart"), failChartOptions);
|
|
failChart.render();
|
|
|
|
// Popola la tabella di riepilogo delle analisi fallite
|
|
const failTableBody = document.querySelector("#fail-table-body");
|
|
data.failDistribution.forEach(row => {
|
|
failTableBody.innerHTML += `
|
|
<tr>
|
|
<td>${row.analysis_name}</td>
|
|
<td>${row.fail}</td>
|
|
</tr>`;
|
|
});
|
|
|
|
// Gestione del pulsante "View Fail Details"
|
|
|
|
|
|
const failDetailsButton = document.querySelector("#view-fail-details");
|
|
if (!failDetailsButton) {
|
|
console.error("Pulsante #view-fail-details non trovato nel DOM.");
|
|
} else {
|
|
console.log("Pulsante trovato:", failDetailsButton);
|
|
}
|
|
|
|
|
|
// Gestione del pulsante "View Fail Details"
|
|
document.querySelector("#view-fail-details").addEventListener("click", function() {
|
|
console.log("View Fail Details clicked");
|
|
const detailsContainer = document.querySelector("#fail-details-container");
|
|
|
|
if (!detailsContainer) {
|
|
console.error("The #fail-details-container was not found.");
|
|
return;
|
|
}
|
|
|
|
const detailsTableBody = document.querySelector("#fail-details-table-body");
|
|
|
|
if (!detailsTableBody) {
|
|
console.error("The #fail-details-table-body was not found.");
|
|
return;
|
|
}
|
|
|
|
// Remove the nested AJAX call and use the existing data from the first AJAX call
|
|
if (!detailsContainer.hasAttribute("data-loaded")) {
|
|
// Use the data from the first AJAX call
|
|
const details = data; // This assumes 'data' is in scope from the previous $.getJSON call
|
|
|
|
// Clear any existing content
|
|
detailsTableBody.innerHTML = '';
|
|
|
|
// Populate the table with fail details
|
|
details.failDetails.forEach(detail => {
|
|
detailsTableBody.innerHTML += `
|
|
<tr>
|
|
<td>${detail.analysis_name}</td>
|
|
<td>${detail.report_number}</td>
|
|
<td>${detail.product_refnumber}</td>
|
|
<td>${detail.product_description}</td>
|
|
<td>
|
|
<a href="../products/reportdetails.php?idreports=${detail.report_id}" target="_blank" class="btn btn-sm btn-primary">
|
|
View Details
|
|
</a>
|
|
</td>
|
|
</tr>`;
|
|
});
|
|
|
|
detailsContainer.setAttribute("data-loaded", "true");
|
|
detailsContainer.style.display = "block";
|
|
} else {
|
|
// Toggle visibility if already loaded
|
|
detailsContainer.style.display = detailsContainer.style.display === "block" ? "none" : "block";
|
|
}
|
|
});
|
|
|
|
|
|
|
|
// Toggle per la tabella Fail Summary
|
|
document.querySelector("#toggle-fail-table").addEventListener("click", function() {
|
|
const table = document.querySelector("#fail-table-container");
|
|
table.style.display = table.style.display === "block" ? "none" : "block";
|
|
});
|
|
});
|
|
|
|
|
|
|
|
const pieChartOptions = {
|
|
series: [passCount, failCount, dataCount],
|
|
chart: {
|
|
type: 'pie',
|
|
height: 350
|
|
},
|
|
labels: ['PASS', 'FAIL', 'DATA'],
|
|
colors: ['#28a745', '#dc3545', '#ffc107'],
|
|
title: {
|
|
text: 'Analysis Distribution',
|
|
align: 'center'
|
|
},
|
|
legend: {
|
|
position: 'bottom'
|
|
},
|
|
dataLabels: {
|
|
enabled: true,
|
|
formatter: function(val, opts) {
|
|
return opts.w.globals.series[opts.seriesIndex] + " (" + val.toFixed(2) + "%)";
|
|
}
|
|
}
|
|
};
|
|
|
|
const pieChart = new ApexCharts(document.querySelector("#pie-chart"), pieChartOptions);
|
|
pieChart.render();
|
|
|
|
// Stacked Bar Chart Configuration (Analysis Summary)
|
|
const stackedBarChartOptions = {
|
|
series: [{
|
|
name: 'PASS',
|
|
data: [passCount]
|
|
},
|
|
{
|
|
name: 'FAIL',
|
|
data: [failCount]
|
|
},
|
|
{
|
|
name: 'DATA',
|
|
data: [dataCount]
|
|
}
|
|
],
|
|
chart: {
|
|
type: 'bar',
|
|
height: 350,
|
|
stacked: true,
|
|
horizontal: true
|
|
},
|
|
colors: ['#28a745', '#dc3545', '#ffc107'],
|
|
xaxis: {
|
|
categories: ['Analysis'],
|
|
title: {
|
|
text: 'Count'
|
|
}
|
|
},
|
|
plotOptions: {
|
|
bar: {
|
|
horizontal: true,
|
|
barHeight: '70%'
|
|
}
|
|
},
|
|
title: {
|
|
text: 'Analysis Summary',
|
|
align: 'center'
|
|
},
|
|
legend: {
|
|
position: 'bottom'
|
|
}
|
|
};
|
|
|
|
const stackedBarChart = new ApexCharts(document.querySelector("#stacked-bar-chart"), stackedBarChartOptions);
|
|
stackedBarChart.render();
|
|
|
|
// Fetch Data for Additional Charts and Tables
|
|
$.getJSON(`get_analysis_data.php?supplier=${supplierName}`, function(data) {
|
|
if (data.error) {
|
|
alert(data.error);
|
|
return;
|
|
}
|
|
|
|
// Distribution Bar Chart (Total Analysis Distribution)
|
|
const distributionChartOptions = {
|
|
series: [{
|
|
data: data.analysisDistribution.map(item => item.total)
|
|
}],
|
|
chart: {
|
|
type: 'bar',
|
|
height: 350,
|
|
horizontal: true
|
|
},
|
|
xaxis: {
|
|
categories: data.analysisDistribution.map(item => item.analysis_name),
|
|
title: {
|
|
text: 'Total Analyses'
|
|
}
|
|
},
|
|
colors: ['#007bff'],
|
|
title: {
|
|
text: 'Total Analysis Distribution',
|
|
align: 'center'
|
|
},
|
|
plotOptions: {
|
|
bar: {
|
|
horizontal: true,
|
|
barHeight: '50%'
|
|
}
|
|
}
|
|
};
|
|
|
|
const distributionChart = new ApexCharts(document.querySelector("#distribution-bar-chart"), distributionChartOptions);
|
|
distributionChart.render();
|
|
|
|
// Populate Distribution Table
|
|
const distTableBody = document.querySelector("#distribution-table-body");
|
|
data.analysisDistribution.forEach(row => {
|
|
distTableBody.innerHTML += `
|
|
<tr>
|
|
<td>${row.analysis_name}</td>
|
|
<td>${row.total}</td>
|
|
</tr>`;
|
|
});
|
|
|
|
// Fail Analysis Chart (Top FAIL Analyses)
|
|
const failChartOptions = {
|
|
series: [{
|
|
data: data.failDistribution.map(item => item.fail)
|
|
}],
|
|
chart: {
|
|
type: 'bar',
|
|
height: 350,
|
|
horizontal: true
|
|
},
|
|
xaxis: {
|
|
categories: data.failDistribution.map(item => item.analysis_name),
|
|
title: {
|
|
text: 'Fail Count'
|
|
}
|
|
},
|
|
colors: ['#dc3545'],
|
|
title: {
|
|
text: 'Top FAIL Analyses',
|
|
align: 'center'
|
|
},
|
|
plotOptions: {
|
|
bar: {
|
|
horizontal: true,
|
|
barHeight: '50%'
|
|
}
|
|
}
|
|
};
|
|
|
|
const failChart = new ApexCharts(document.querySelector("#fail-bar-chart"), failChartOptions);
|
|
failChart.render();
|
|
|
|
// Populate Fail Table
|
|
const failTableBody = document.querySelector("#fail-table-body");
|
|
data.failDistribution.forEach(row => {
|
|
failTableBody.innerHTML += `
|
|
<tr>
|
|
<td>${row.analysis_name}</td>
|
|
<td>${row.fail}</td>
|
|
</tr>`;
|
|
});
|
|
});
|
|
|
|
// Toggle Tables
|
|
document.querySelector("#toggle-distribution-table").addEventListener("click", function() {
|
|
const table = document.querySelector("#distribution-table-container");
|
|
table.style.display = table.style.display === "block" ? "none" : "block";
|
|
});
|
|
|
|
document.querySelector("#toggle-fail-table").addEventListener("click", function() {
|
|
const table = document.querySelector("#fail-table-container");
|
|
table.style.display = table.style.display === "block" ? "none" : "block";
|
|
});
|
|
|
|
});
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php include('../include/footer.php'); ?>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
|
|
</html>
|