317 lines
12 KiB
HTML
317 lines
12 KiB
HTML
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Sales Dashboard</title>
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
<style>
|
|
body { font-family: Arial, sans-serif; margin: 20px; background-color: #f4f4f4; color: #333; }
|
|
.container { max-width: 900px; margin: auto; background: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
|
|
h1, h2 { color: #0056b3; border-bottom: 2px solid #eee; padding-bottom: 10px; margin-bottom: 20px; }
|
|
.stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin-bottom: 30px; }
|
|
.stat-box { background: #e9f7ff; padding: 15px; border-radius: 5px; text-align: center; }
|
|
.stat-box h3 { margin: 0 0 10px 0; color: #007bff; }
|
|
.stat-box p { font-size: 1.8em; font-weight: bold; color: #333; }
|
|
.chart-container { margin-bottom: 30px; background: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
|
|
.chart-container canvas { max-width: 100%; height: auto; }
|
|
|
|
.navbar {
|
|
background-color: #333;
|
|
padding: 10px 0;
|
|
text-align: center;
|
|
margin-bottom: 20px;
|
|
border-radius: 8px;
|
|
}
|
|
.nav-list {
|
|
list-style: none;
|
|
padding: 0;
|
|
margin: 0;
|
|
display: flex;
|
|
justify-content: center;
|
|
}
|
|
.nav-item {
|
|
margin: 0 15px;
|
|
}
|
|
.nav-link {
|
|
color: white;
|
|
text-decoration: none;
|
|
font-weight: bold;
|
|
padding: 8px 15px;
|
|
border-radius: 5px;
|
|
transition: background-color 0.3s ease;
|
|
}
|
|
.nav-link:hover {
|
|
background-color: #575757;
|
|
}
|
|
|
|
/* New styles for summary boxes */
|
|
.summary-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
gap: 20px;
|
|
margin-bottom: 30px;
|
|
}
|
|
.summary-box {
|
|
background: #e0f7fa; /* Light blue */
|
|
padding: 20px;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
text-align: center;
|
|
}
|
|
.summary-box h3 {
|
|
margin-top: 0;
|
|
color: #00796b; /* Darker blue-green */
|
|
}
|
|
.summary-box p {
|
|
font-size: 2em;
|
|
font-weight: bold;
|
|
color: #004d40; /* Even darker blue-green */
|
|
}
|
|
|
|
/* Styles for the data table */
|
|
.data-table-container {
|
|
margin-top: 30px;
|
|
background: #fff;
|
|
padding: 20px;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
}
|
|
.data-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
margin-top: 15px;
|
|
}
|
|
.data-table th, .data-table td {
|
|
border: 1px solid #ddd;
|
|
padding: 8px;
|
|
text-align: left;
|
|
}
|
|
.data-table th {
|
|
background-color: #f2f2f2;
|
|
font-weight: bold;
|
|
}
|
|
.data-table tbody tr:nth-child(even) {
|
|
background-color: #f9f9f9;
|
|
}
|
|
.data-table tbody tr:hover {
|
|
background-color: #f1f1f1;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<nav class="navbar">
|
|
<ul class="nav-list">
|
|
<li class="nav-item"><a href="#" class="nav-link">Overview</a></li>
|
|
<li class="nav-item"><a href="#" class="nav-link">Product Sales</a></li>
|
|
<li class="nav-item"><a href="#" class="nav-link">Regional Sales</a></li>
|
|
<li class="nav-item"><a href="sales_records.html" class="nav-link">Sales Records</a></li>
|
|
</ul>
|
|
</nav>
|
|
<div class="dashboard-container">
|
|
<h1>Sales Dashboard</h1>
|
|
|
|
<div class="summary-grid">
|
|
<div class="summary-box">
|
|
<h3>Total Sales</h3>
|
|
<p id="totalSales">Loading...</p>
|
|
</div>
|
|
<div class="summary-box">
|
|
<h3>Total Orders</h3>
|
|
<p id="totalOrders">Loading...</p>
|
|
</div>
|
|
<div class="summary-box">
|
|
<h3>Product Categories</h3>
|
|
<p id="productCategories">Loading...</p>
|
|
</div>
|
|
<div class="summary-box">
|
|
<h3>Sales Regions</h3>
|
|
<p id="salesRegions">Loading...</p>
|
|
</div>
|
|
</div>
|
|
|
|
<h2>Sales by Product Category</h2>
|
|
<div class="chart-container">
|
|
<canvas id="categoryBarChart"></canvas>
|
|
</div>
|
|
|
|
<h2>Sales Over Time</h2>
|
|
<div class="chart-container">
|
|
<canvas id="timeLineChart"></canvas>
|
|
</div>
|
|
|
|
<h2>All Sales Data</h2>
|
|
<div class="data-table-container">
|
|
<table class="data-table" id="allSalesDataTable">
|
|
<thead>
|
|
<tr>
|
|
<!-- Headers will be dynamically generated -->
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<!-- Data will be dynamically loaded -->
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<script>
|
|
// Function to fetch and display summary data
|
|
async function fetchSummaryData() {
|
|
try {
|
|
const response = await fetch('http://127.0.0.1:5000/dashboard_summary');
|
|
const data = await response.json();
|
|
document.getElementById('totalSales').innerText = `${data.total_sales.toFixed(2)}`;
|
|
document.getElementById('totalOrders').innerText = data.total_orders;
|
|
document.getElementById('productCategories').innerText = data.product_categories;
|
|
document.getElementById('salesRegions').innerText = data.sales_regions;
|
|
} catch (error) {
|
|
console.error('Error fetching summary data:', error);
|
|
document.getElementById('totalSales').innerText = 'Error';
|
|
document.getElementById('totalOrders').innerText = 'Error';
|
|
document.getElementById('productCategories').innerText = 'Error';
|
|
document.getElementById('salesRegions').innerText = 'Error';
|
|
}
|
|
}
|
|
|
|
// Function to fetch and render charts
|
|
async function fetchChartData() {
|
|
try {
|
|
const response = await fetch('http://127.0.0.1:5000/dashboard_charts');
|
|
const data = await response.json();
|
|
|
|
// Bar Chart: Sales by Product Category
|
|
const categoryBarCtx = document.getElementById('categoryBarChart').getContext('2d');
|
|
new Chart(categoryBarCtx, {
|
|
type: 'bar',
|
|
data: {
|
|
labels: data.category_sales.labels,
|
|
datasets: [{
|
|
label: 'Sales Amount',
|
|
data: data.category_sales.data,
|
|
backgroundColor: 'rgba(75, 192, 192, 0.6)',
|
|
borderColor: 'rgba(75, 192, 192, 1)',
|
|
borderWidth: 1
|
|
}]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
scales: {
|
|
y: {
|
|
beginAtZero: true,
|
|
title: {
|
|
display: true,
|
|
text: 'Sales Amount'
|
|
}
|
|
}
|
|
},
|
|
plugins: {
|
|
title: {
|
|
display: true,
|
|
text: 'Sales by Product Category'
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// Line Chart: Sales Over Time
|
|
const timeLineCtx = document.getElementById('timeLineChart').getContext('2d');
|
|
new Chart(timeLineCtx, {
|
|
type: 'line',
|
|
data: {
|
|
labels: data.time_sales.labels,
|
|
datasets: [{
|
|
label: 'Sales Amount',
|
|
data: data.time_sales.data,
|
|
backgroundColor: 'rgba(153, 102, 255, 0.6)',
|
|
borderColor: 'rgba(153, 102, 255, 1)',
|
|
borderWidth: 1,
|
|
fill: false
|
|
}]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
scales: {
|
|
y: {
|
|
beginAtZero: true,
|
|
title: {
|
|
display: true,
|
|
text: 'Sales Amount'
|
|
}
|
|
}
|
|
},
|
|
plugins: {
|
|
title: {
|
|
display: true,
|
|
text: 'Sales Over Time'
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error('Error fetching chart data:', error);
|
|
}
|
|
}
|
|
|
|
// Function to fetch and display all sales data in a table
|
|
async function fetchAllSalesData() {
|
|
try {
|
|
const response = await fetch('http://127.0.0.1:5000/sales_data');
|
|
const data = await response.json();
|
|
const table = document.getElementById('allSalesDataTable');
|
|
const thead = table.querySelector('thead tr');
|
|
const tbody = table.querySelector('tbody');
|
|
|
|
// Clear existing content
|
|
thead.innerHTML = '';
|
|
tbody.innerHTML = '';
|
|
|
|
if (data.length > 0) {
|
|
// Create headers
|
|
const headers = Object.keys(data[0]);
|
|
headers.forEach(header => {
|
|
const th = document.createElement('th');
|
|
th.innerText = header;
|
|
thead.appendChild(th);
|
|
});
|
|
|
|
// Populate table rows
|
|
data.forEach(record => {
|
|
const tr = document.createElement('tr');
|
|
headers.forEach(header => {
|
|
const td = document.createElement('td');
|
|
td.innerText = record[header];
|
|
tr.appendChild(td);
|
|
});
|
|
tbody.appendChild(tr);
|
|
});
|
|
} else {
|
|
const tr = document.createElement('tr');
|
|
const td = document.createElement('td');
|
|
td.colSpan = 10; // Arbitrary large number to span all columns
|
|
td.innerText = 'No sales data available.';
|
|
tr.appendChild(td);
|
|
tbody.appendChild(tr);
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('Error fetching all sales data:', error);
|
|
const table = document.getElementById('allSalesDataTable');
|
|
const tbody = table.querySelector('tbody');
|
|
tbody.innerHTML = '<tr><td colspan="10">Error loading data.</td></tr>';
|
|
}
|
|
}
|
|
|
|
// Run all fetch functions on page load
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
fetchSummaryData();
|
|
fetchChartData();
|
|
fetchAllSalesData();
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|
|
|