Revert to version f9a4687
This commit is contained in:
parent
13560e83a1
commit
aa0f100080
@ -289,3 +289,31 @@ table th {
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* --- Charts --- */
|
||||
.dashboard-charts {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
|
||||
gap: 1.5rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
background-color: var(--color-surface-light);
|
||||
padding: 1.5rem;
|
||||
border-radius: var(--border-radius);
|
||||
border: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.chart-title {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1.5rem;
|
||||
font-weight: 600;
|
||||
font-size: 1.1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
body.dark-mode .chart-container {
|
||||
background-color: var(--color-surface-light);
|
||||
border-color: var(--border-color);
|
||||
}
|
||||
|
||||
|
||||
@ -45,4 +45,83 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
if (typeof feather !== 'undefined') {
|
||||
feather.replace();
|
||||
}
|
||||
|
||||
// -- CHARTS INITIALIZATION --
|
||||
// Check if chartData is defined (it's passed from index.php)
|
||||
if (typeof chartData !== 'undefined') {
|
||||
const pieCtx = document.getElementById('loadsByStatusChart');
|
||||
const barCtx = document.getElementById('monthlyLoadsChart');
|
||||
|
||||
// Define colors that work with the theme
|
||||
const chartColors = {
|
||||
primary: 'rgba(184, 134, 11, 0.8)', // Golden
|
||||
secondary: 'rgba(169, 169, 169, 0.8)', // Gray
|
||||
accent: 'rgba(212, 175, 55, 0.8)', // Lighter Gold
|
||||
success: 'rgba(40, 167, 69, 0.8)',
|
||||
danger: 'rgba(220, 53, 69, 0.8)',
|
||||
info: 'rgba(23, 162, 184, 0.8)',
|
||||
};
|
||||
|
||||
if (pieCtx) {
|
||||
new Chart(pieCtx, {
|
||||
type: 'pie',
|
||||
data: {
|
||||
labels: chartData.loadsByStatus.labels,
|
||||
datasets: [{
|
||||
label: 'Loads',
|
||||
data: chartData.loadsByStatus.counts,
|
||||
backgroundColor: [
|
||||
chartColors.info,
|
||||
chartColors.primary,
|
||||
chartColors.success,
|
||||
chartColors.danger,
|
||||
chartColors.secondary
|
||||
],
|
||||
borderWidth: 1
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
plugins: {
|
||||
legend: {
|
||||
position: 'top',
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (barCtx) {
|
||||
new Chart(barCtx, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: chartData.monthlyLoads.labels,
|
||||
datasets: [{
|
||||
label: 'Loads Created',
|
||||
data: chartData.monthlyLoads.counts,
|
||||
backgroundColor: chartColors.primary,
|
||||
borderColor: chartColors.accent,
|
||||
borderWidth: 1
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
ticks: { // Make sure Y-axis ticks are integers
|
||||
stepSize: 1,
|
||||
callback: function(value) { if (Number.isInteger(value)) { return value; } }
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
126
drivers.php
126
drivers.php
@ -1,16 +1,132 @@
|
||||
<?php include 'includes/header.php'; ?>
|
||||
<?php
|
||||
require_once 'db/config.php';
|
||||
|
||||
$page_title = "Drivers";
|
||||
|
||||
// Handle form submission for adding a new driver
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_driver'])) {
|
||||
$name = trim($_POST['name']);
|
||||
$email = trim($_POST['email']);
|
||||
$phone = trim($_POST['phone']);
|
||||
$status = trim($_POST['status']);
|
||||
|
||||
if (!empty($name) && !empty($email) && !empty($phone) && !empty($status)) {
|
||||
try {
|
||||
$pdo = db();
|
||||
$sql = "INSERT INTO drivers (name, email, phone, status) VALUES (:name, :email, :phone, :status)";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute(['name' => $name, 'email' => $email, 'phone' => $phone, 'status' => $status]);
|
||||
// Redirect to avoid form resubmission
|
||||
header("Location: drivers.php");
|
||||
exit;
|
||||
} catch (PDOException $e) {
|
||||
$error_message = "Database error: " . $e->getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create drivers table if it doesn't exist
|
||||
try {
|
||||
$pdo = db();
|
||||
$pdo->exec("CREATE TABLE IF NOT EXISTS drivers (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
email VARCHAR(255) NOT NULL,
|
||||
phone VARCHAR(50) NOT NULL,
|
||||
status VARCHAR(50) NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)");
|
||||
} catch (PDOException $e) {
|
||||
die("Could not create table: " . $e->getMessage());
|
||||
}
|
||||
|
||||
// Fetch all drivers
|
||||
try {
|
||||
$pdo = db();
|
||||
$stmt = $pdo->query("SELECT id, name, email, phone, status, created_at FROM drivers ORDER BY created_at DESC");
|
||||
$drivers = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
} catch (PDOException $e) {
|
||||
$error_message = "Database error: " . $e->getMessage();
|
||||
}
|
||||
|
||||
include 'includes/header.php';
|
||||
?>
|
||||
|
||||
<?php include 'includes/sidebar.php'; ?>
|
||||
|
||||
<main class="main-content">
|
||||
<header class="header">
|
||||
<h1>Drivers</h1>
|
||||
<h1>Manage Drivers</h1>
|
||||
</header>
|
||||
|
||||
<section class="dashboard-cards">
|
||||
<p>Driver management content will go here.</p>
|
||||
<section class="card">
|
||||
<h2>Add New Driver</h2>
|
||||
<form action="drivers.php" method="POST" class="form-grid">
|
||||
<div class="form-group">
|
||||
<label for="name">Full Name</label>
|
||||
<input type="text" id="name" name="name" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="email">Email</label>
|
||||
<input type="email" id="email" name="email" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="phone">Phone Number</label>
|
||||
<input type="tel" id="phone" name="phone" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="status">Status</label>
|
||||
<select id="status" name="status" required>
|
||||
<option value="Available" selected>Available</option>
|
||||
<option value="On-duty">On-duty</option>
|
||||
<option value="Off-duty">Off-duty</option>
|
||||
<option value="Maintenance">Maintenance</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group form-group-full">
|
||||
<button type="submit" name="add_driver" class="button button-primary">Add Driver</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section class="card">
|
||||
<h2>All Drivers</h2>
|
||||
<?php if (isset($error_message)): ?>
|
||||
<div class="alert alert-danger"><?php echo htmlspecialchars($error_message); ?></div>
|
||||
<?php endif; ?>
|
||||
<div class="table-responsive">
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Contact</th>
|
||||
<th>Status</th>
|
||||
<th>Joined</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (empty($drivers)): ?>
|
||||
<tr>
|
||||
<td colspan="4">No drivers found.</td>
|
||||
</tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($drivers as $driver): ?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($driver['name']); ?></td>
|
||||
<td>
|
||||
<a href="mailto:<?php echo htmlspecialchars($driver['email']); ?>"><?php echo htmlspecialchars($driver['email']); ?></a><br>
|
||||
<a href="tel:<?php echo htmlspecialchars($driver['phone']); ?>"><?php echo htmlspecialchars($driver['phone']); ?></a>
|
||||
</td>
|
||||
<td><span class="status-badge status-<?php echo strtolower(htmlspecialchars($driver['status'])); ?>"><?php echo htmlspecialchars($driver['status']); ?></span></td>
|
||||
<td><?php echo date("M d, Y", strtotime($driver['created_at'])); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</main>
|
||||
|
||||
<?php include 'includes/footer.php'; ?>
|
||||
<?php include 'includes/footer.php'; ?>
|
||||
@ -1,5 +1,6 @@
|
||||
<!-- Scripts -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
|
||||
|
||||
</body>
|
||||
|
||||
100
index.php
100
index.php
@ -1,38 +1,102 @@
|
||||
<?php include 'includes/header.php'; ?>
|
||||
<?php
|
||||
require_once 'db/config.php';
|
||||
|
||||
<?php include 'includes/sidebar.php'; ?>
|
||||
// --- DATA FETCHING ---
|
||||
$pdo = db();
|
||||
|
||||
// Card metrics
|
||||
$total_loads = $pdo->query('SELECT count(*) FROM loads')->fetchColumn();
|
||||
$total_drivers = $pdo->query('SELECT count(*) FROM drivers')->fetchColumn();
|
||||
$in_transit_loads = $pdo->query('SELECT count(*) FROM loads WHERE status = "In-Transit"')->fetchColumn();
|
||||
$delivered_loads = $pdo->query('SELECT count(*) FROM loads WHERE status = "Delivered"')->fetchColumn();
|
||||
|
||||
// Pie Chart: Loads by Status
|
||||
$loads_by_status_stmt = $pdo->query('SELECT status, count(*) as count FROM loads GROUP BY status');
|
||||
$loads_by_status = $loads_by_status_stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
$status_labels = [];
|
||||
$status_counts = [];
|
||||
foreach ($loads_by_status as $row) {
|
||||
$status_labels[] = $row['status'];
|
||||
$status_counts[] = $row['count'];
|
||||
}
|
||||
|
||||
// Bar Chart: Loads per month
|
||||
// Using a default of 0 for all months of the current year
|
||||
$monthly_counts = array_fill(1, 12, 0);
|
||||
$loads_by_month_stmt = $pdo->query("
|
||||
SELECT
|
||||
CAST(strftime('%m', pickup_date) AS INTEGER) as month,
|
||||
count(*) as count
|
||||
FROM loads
|
||||
WHERE strftime('%Y', pickup_date) = strftime('%Y', 'now')
|
||||
GROUP BY month
|
||||
");
|
||||
$loads_by_month = $loads_by_month_stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
foreach ($loads_by_month as $row) {
|
||||
$monthly_counts[$row['month']] = $row['count'];
|
||||
}
|
||||
$monthly_labels = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
||||
$monthly_values = array_values($monthly_counts);
|
||||
|
||||
|
||||
include 'includes/header.php';
|
||||
include 'includes/sidebar.php';
|
||||
?>
|
||||
|
||||
<main class="main-content">
|
||||
<header class="header">
|
||||
<h1>Dashboard Overview</h1>
|
||||
<!-- Can add user profile dropdown here later -->
|
||||
<h1>Reports & Analytics</h1>
|
||||
</header>
|
||||
|
||||
<section class="dashboard-cards">
|
||||
<div class="card">
|
||||
<div class="card-title">ACTIVE LOADS</div>
|
||||
<div class="card-value">42</div>
|
||||
<div class="card-delta text-success">+2 since yesterday</div>
|
||||
<div class="card-title">TOTAL LOADS</div>
|
||||
<div class="card-value"><?php echo $total_loads; ?></div>
|
||||
<div class="card-delta text-muted">All time</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">DRIVERS ON-ROUTE</div>
|
||||
<div class="card-value">35</div>
|
||||
<div class="card-delta text-success">+5.2%</div>
|
||||
<div class="card-title">TOTAL DRIVERS</div>
|
||||
<div class="card-value"><?php echo $total_drivers; ?></div>
|
||||
<div class="card-delta text-muted">All time</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">REVENUE TODAY</div>
|
||||
<div class="card-value">$18,450</div>
|
||||
<div class="card-delta text-success">+12% vs avg.</div>
|
||||
<div class="card-title">IN-TRANSIT NOW</div>
|
||||
<div class="card-value"><?php echo $in_transit_loads; ?></div>
|
||||
<div class="card-delta text-primary"> </div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">PENDING ISSUES</div>
|
||||
<div class="card-value">3</div>
|
||||
<div class="card-delta text-danger">1 new alert</div>
|
||||
<div class="card-title">COMPLETED LOADS</div>
|
||||
<div class="card-value"><?php echo $delivered_loads; ?></div>
|
||||
<div class="card-delta text-success"> </div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- More dashboard components can be added here -->
|
||||
<section class="dashboard-charts">
|
||||
<div class="chart-container">
|
||||
<h3 class="chart-title">Loads by Status</h3>
|
||||
<canvas id="loadsByStatusChart"></canvas>
|
||||
</div>
|
||||
<div class="chart-container">
|
||||
<h3 class="chart-title">Monthly Load Volume (This Year)</h3>
|
||||
<canvas id="monthlyLoadsChart"></canvas>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</main>
|
||||
|
||||
<?php include 'includes/footer.php'; ?>
|
||||
<script>
|
||||
// Pass data to main.js
|
||||
const chartData = {
|
||||
loadsByStatus: {
|
||||
labels: <?php echo json_encode($status_labels); ?>,
|
||||
counts: <?php echo json_encode($status_counts); ?>
|
||||
},
|
||||
monthlyLoads: {
|
||||
labels: <?php echo json_encode($monthly_labels); ?>,
|
||||
counts: <?php echo json_encode($monthly_values); ?>
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<?php include 'includes/footer.php'; ?>
|
||||
Loading…
x
Reference in New Issue
Block a user