Initial commit
This commit is contained in:
317
sales_dashboard.html
Normal file
317
sales_dashboard.html
Normal file
@@ -0,0 +1,317 @@
|
||||
|
||||
<!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>
|
||||
|
Reference in New Issue
Block a user