Autosave: 20260313-070520

This commit is contained in:
Flatlogic Bot 2026-03-13 07:05:20 +00:00
parent eeb8d0977c
commit 2ee38edf60
7 changed files with 399 additions and 75 deletions

View File

@ -75,27 +75,46 @@ if ($shipperId) {
render_header(t('shippers_statements') ?: 'Shippers Statements', 'reports_shippers', true);
?>
<!-- Select2 CSS -->
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
<style>
/* Select2 Bootstrap 5 Fixes */
.select2-container .select2-selection--single { height: 38px !important; border: 1px solid #dee2e6 !important; padding: 5px 0; }
.select2-container--default .select2-selection--single .select2-selection__arrow { height: 36px !important; }
.select2-container--default .select2-selection--single .select2-selection__rendered { line-height: 26px !important; color: #212529; }
@media print {
@page { size: A4; margin: 2cm; }
@page { size: A4; margin: 1cm; }
body { background: white !important; font-family: 'Times New Roman', serif; -webkit-print-color-adjust: exact; }
.no-print, .admin-sidebar, nav, footer, .btn, form.filter-form { display: none !important; }
.col-md-2 { display: none !important; }
.col-md-10 { width: 100% !important; flex: 0 0 100% !important; max-width: 100% !important; padding: 0 !important; margin: 0 !important; }
.row { display: block !important; margin: 0 !important; }
.row { display: flex !important; flex-wrap: wrap !important; margin: 0 !important; }
.col-6 { width: 50% !important; flex: 0 0 50% !important; max-width: 50% !important; }
.panel { border: none !important; box-shadow: none !important; padding: 0 !important; }
.print-header { display: block !important; margin-bottom: 30px; border-bottom: 2px solid #000; padding-bottom: 20px; }
.print-header h1 { font-size: 24pt; font-weight: bold; margin-bottom: 5px; text-transform: uppercase; }
.print-header p { margin: 0; font-size: 10pt; color: #555; }
.statement-info { margin-bottom: 30px; display: flex; justify-content: space-between; border-bottom: 1px solid #ddd; padding-bottom: 20px; }
.statement-info div { width: 48%; }
/* Compact Header */
.print-header { display: flex !important; justify-content: space-between !important; align-items: flex-start !important; margin-bottom: 10px !important; border-bottom: 2px solid #000 !important; padding-bottom: 5px !important; }
.print-header-left { text-align: left; }
.print-header-right { text-align: right; }
.print-header h1 { font-size: 14pt; font-weight: bold; margin: 0; text-transform: uppercase; }
.print-header h2 { font-size: 12pt; margin: 0; font-weight: normal; }
.print-header p { margin: 0; font-size: 9pt; color: #555; }
/* Compact Info Section */
.statement-info { margin-bottom: 10px !important; display: flex !important; justify-content: space-between !important; border-bottom: 1px solid #ddd !important; padding-bottom: 5px !important; }
.statement-info h5 { margin: 0 0 2px 0; font-size: 9pt; color: #777; text-transform: uppercase; font-weight: bold; }
.statement-info h4 { margin: 0; font-size: 11pt; font-weight: bold; }
.statement-info .small { font-size: 9pt; margin-top: 2px; }
.table-responsive { overflow: visible !important; }
table { width: 100% !important; border-collapse: collapse !important; font-size: 10pt; }
th, td { border: 1px solid #ddd !important; padding: 8px 12px !important; text-align: left; }
th { background-color: #f8f9fa !important; font-weight: bold; text-transform: uppercase; color: #000 !important; }
table { width: 100% !important; border-collapse: collapse !important; font-size: 9pt; }
th, td { border: 1px solid #ddd !important; padding: 4px 6px !important; text-align: left; }
th { background-color: #f8f9fa !important; font-weight: bold; text-transform: uppercase; color: #000 !important; font-size: 8pt; }
.text-end { text-align: right !important; }
.total-row td { background-color: #eee !important; font-weight: bold; font-size: 12pt; border-top: 2px solid #000 !important; }
.print-footer { display: block !important; margin-top: 50px; text-align: center; font-size: 9pt; color: #777; border-top: 1px solid #ddd; padding-top: 10px; }
.total-row td { background-color: #eee !important; font-weight: bold; font-size: 10pt; border-top: 2px solid #000 !important; }
.print-footer { display: block !important; margin-top: 20px; text-align: center; font-size: 8pt; color: #777; border-top: 1px solid #ddd; padding-top: 5px; }
/* Arabic Support */
[dir="rtl"] body { font-family: 'Traditional Arabic', serif; }
@ -128,7 +147,7 @@ render_header(t('shippers_statements') ?: 'Shippers Statements', 'reports_shippe
<form method="get" class="row g-3 align-items-end">
<div class="col-md-4">
<label class="form-label small text-muted">Select Shipper</label>
<select name="shipper_id" class="form-select" onchange="this.form.submit()">
<select name="shipper_id" id="shipperSelect" class="form-select" onchange="this.form.submit()">
<option value="">-- Choose a Shipper --</option>
<?php foreach ($allShippers as $s): ?>
<option value="<?= $s['id'] ?>" <?= $shipperId == $s['id'] ? 'selected' : '' ?>>
@ -155,37 +174,43 @@ render_header(t('shippers_statements') ?: 'Shippers Statements', 'reports_shippe
<div class="alert alert-warning">Shipper not found.</div>
<?php elseif ($shipper): ?>
<div class="panel p-5 bg-white">
<!-- Print Header -->
<div class="print-header text-center">
<h1>Statement of Account</h1>
<h2 style="font-size: 18pt; margin: 0; font-weight: normal;">كشف حساب</h2>
<p class="mt-2"><?= e(get_setting('company_name', 'Logistics Platform')) ?></p>
<p><?= date('F j, Y') ?></p>
<!-- Print Header (Compact) -->
<div class="print-header">
<div class="print-header-left">
<h2 style="font-size: 14pt; margin: 0; font-weight: bold;"><?= e(get_setting('company_name', 'Logistics Platform')) ?></h2>
<p class="mt-1"><?= date('F j, Y') ?></p>
</div>
<div class="print-header-right">
<h1>Statement of Account</h1>
<h2 style="font-size: 12pt; margin: 0; font-weight: normal;">كشف حساب</h2>
</div>
</div>
<!-- Info Section -->
<div class="statement-info row mb-4">
<!-- Info Section (Compact) -->
<div class="statement-info row">
<div class="col-6">
<h5 class="fw-bold text-uppercase text-muted small mb-2">Billed To / إلى السيد</h5>
<h4 class="fw-bold mb-1"><?= e($shipper['full_name']) ?></h4>
<div class="text-muted"><?= e($shipper['company_name'] ?: '-') ?></div>
<div class="small text-muted mt-1">
<h5>Billed To / إلى السيد</h5>
<h4><?= e($shipper['full_name']) ?></h4>
<div class="small text-muted">
<?= e($shipper['company_name'] ?: '-') ?><br>
<?= e($shipper['address_line'] ?: '') ?><br>
<?= e($shipper['city'] ?: '') ?>, <?= e($shipper['country'] ?: '') ?><br>
<?= e($shipper['phone'] ?: '') ?>
</div>
</div>
<div class="col-6 text-end">
<h5 class="fw-bold text-uppercase text-muted small mb-2">Summary / ملخص</h5>
<div class="mb-1"><strong>Statement Date:</strong> <?= date('Y-m-d') ?></div>
<?php if ($startDate || $endDate): ?>
<div class="mb-1"><strong>Period:</strong> <?= e($startDate ?: 'Start') ?> to <?= e($endDate ?: 'Now') ?></div>
<?php else: ?>
<div class="mb-1"><strong>Period:</strong> All Time</div>
<?php endif; ?>
<div class="mb-1"><strong>Total Shipments:</strong> <?= count($shipments) ?></div>
<div class="fs-4 fw-bold text-primary mt-2">
<?= number_format($totalAmount, 2) ?> OMR
<h5>Summary / ملخص</h5>
<div class="small">
<div><strong>Date:</strong> <?= date('Y-m-d') ?></div>
<?php if ($startDate || $endDate): ?>
<div><strong>Period:</strong> <?= e($startDate ?: 'Start') ?> to <?= e($endDate ?: 'Now') ?></div>
<?php else: ?>
<div><strong>Period:</strong> All Time</div>
<?php endif; ?>
<div><strong>Count:</strong> <?= count($shipments) ?></div>
<div class="fs-5 fw-bold text-primary mt-1">
<?= number_format($totalAmount, 2) ?> OMR
</div>
</div>
</div>
</div>
@ -251,4 +276,17 @@ render_header(t('shippers_statements') ?: 'Shippers Statements', 'reports_shippe
</div>
</div>
<!-- jQuery and Select2 JS -->
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
<script>
$(document).ready(function() {
$('#shipperSelect').select2({
width: '100%',
placeholder: '-- Choose a Shipper --',
allowClear: true
});
});
</script>
<?php render_footer(); ?>

208
admin_reports_summary.php Normal file
View File

@ -0,0 +1,208 @@
<?php
declare(strict_types=1);
require_once __DIR__ . '/includes/layout.php';
// Helper to validate date
function validate_date($date, $format = 'Y-m-d') {
$d = DateTime::createFromFormat($format, $date);
return $d && $d->format($format) === $date;
}
// Params
$reportType = $_GET['type'] ?? 'countries_origin'; // countries_origin, countries_dest, cities_origin, cities_dest, shippers
$startDate = $_GET['start_date'] ?? date('Y-m-01'); // Default to first day of current month
$endDate = $_GET['end_date'] ?? date('Y-m-t'); // Default to last day of current month
if (!validate_date($startDate)) $startDate = date('Y-m-01');
if (!validate_date($endDate)) $endDate = date('Y-m-t');
// Build Query
$where = "s.payment_status = 'paid' AND DATE(s.created_at) BETWEEN ? AND ?";
$params = [$startDate, $endDate];
$groupBy = '';
$selectName = '';
$join = '';
$orderBy = 'total_amount DESC';
switch ($reportType) {
case 'countries_origin':
$selectName = "COALESCE(co.name_en, 'Unknown') as name";
$join = "LEFT JOIN cities c ON s.origin_city = c.name_en
LEFT JOIN countries co ON c.country_id = co.id";
$groupBy = "co.name_en";
$pageTitle = "Shipments by Origin Country";
break;
case 'countries_dest':
$selectName = "COALESCE(co.name_en, 'Unknown') as name";
$join = "LEFT JOIN cities c ON s.destination_city = c.name_en
LEFT JOIN countries co ON c.country_id = co.id";
$groupBy = "co.name_en";
$pageTitle = "Shipments by Destination Country";
break;
case 'cities_origin':
$selectName = "s.origin_city as name";
$groupBy = "s.origin_city";
$pageTitle = "Shipments by Origin City";
break;
case 'cities_dest':
$selectName = "s.destination_city as name";
$groupBy = "s.destination_city";
$pageTitle = "Shipments by Destination City";
break;
case 'shippers':
$selectName = "s.shipper_name as name"; // simplified, could join users table
$groupBy = "s.shipper_name";
$pageTitle = "Shipments by Shipper";
break;
default:
$reportType = 'countries_origin';
$selectName = "COALESCE(co.name_en, 'Unknown') as name";
$join = "LEFT JOIN cities c ON s.origin_city = c.name_en
LEFT JOIN countries co ON c.country_id = co.id";
$groupBy = "co.name_en";
$pageTitle = "Shipments by Origin Country";
break;
}
$sql = "
SELECT
$selectName,
COUNT(s.id) as shipment_count,
SUM(s.total_price) as total_amount,
SUM(s.platform_fee) as total_profit
FROM shipments s
$join
WHERE $where
GROUP BY $groupBy
ORDER BY $orderBy
";
try {
$stmt = db()->prepare($sql);
$stmt->execute($params);
$results = $stmt->fetchAll();
} catch (PDOException $e) {
$results = [];
$error = "Database error: " . $e->getMessage();
}
// Calculate totals for footer
$totalShipments = 0;
$grandTotalAmount = 0.0;
$grandTotalProfit = 0.0;
foreach ($results as $row) {
$totalShipments += $row['shipment_count'];
$grandTotalAmount += $row['total_amount'];
$grandTotalProfit += $row['total_profit'];
}
render_header('Reports Summary', 'reports_summary', true);
?>
<div class="row g-0">
<div class="col-md-2 bg-white border-end min-vh-100">
<?php render_admin_sidebar('reports_summary'); ?>
</div>
<div class="col-md-10 p-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<div>
<h1 class="section-title mb-1">Summary Reports</h1>
<p class="muted mb-0">Analyze shipment performance, revenue, and profits.</p>
</div>
<div>
<button class="btn btn-outline-secondary btn-sm" onclick="window.print()">
<i class="bi bi-printer me-2"></i>Print
</button>
</div>
</div>
<div class="panel p-4 mb-4">
<form method="get" class="row g-3 align-items-end">
<div class="col-md-3">
<label class="form-label small text-muted">Report Type</label>
<select name="type" class="form-select" onchange="this.form.submit()">
<option value="countries_origin" <?= $reportType === 'countries_origin' ? 'selected' : '' ?>>By Origin Country</option>
<option value="countries_dest" <?= $reportType === 'countries_dest' ? 'selected' : '' ?>>By Destination Country</option>
<option value="cities_origin" <?= $reportType === 'cities_origin' ? 'selected' : '' ?>>By Origin City</option>
<option value="cities_dest" <?= $reportType === 'cities_dest' ? 'selected' : '' ?>>By Destination City</option>
<option value="shippers" <?= $reportType === 'shippers' ? 'selected' : '' ?>>By Shipper</option>
</select>
</div>
<div class="col-md-3">
<label class="form-label small text-muted">Start Date</label>
<input type="date" name="start_date" class="form-control" value="<?= e($startDate) ?>">
</div>
<div class="col-md-3">
<label class="form-label small text-muted">End Date</label>
<input type="date" name="end_date" class="form-control" value="<?= e($endDate) ?>">
</div>
<div class="col-md-2">
<button type="submit" class="btn btn-primary w-100">Apply Filter</button>
</div>
</form>
</div>
<div class="panel p-0">
<div class="p-3 border-bottom bg-light d-flex justify-content-between align-items-center">
<h5 class="mb-0 fw-bold"><?= e($pageTitle) ?></h5>
<span class="badge bg-secondary"><?= e($startDate) ?> to <?= e($endDate) ?></span>
</div>
<?php if (empty($results)): ?>
<div class="p-5 text-center text-muted">
<i class="bi bi-bar-chart fs-1 mb-3 d-block"></i>
<p class="mb-0">No paid shipments found for this period.</p>
</div>
<?php else: ?>
<div class="table-responsive">
<table class="table table-hover mb-0 align-middle">
<thead class="table-light">
<tr>
<th class="ps-4">Name</th>
<th class="text-center">Shipments</th>
<th class="text-end">Total Amount</th>
<th class="text-end pe-4">Profit</th>
</tr>
</thead>
<tbody>
<?php foreach ($results as $row): ?>
<tr>
<td class="ps-4 fw-medium"><?= e($row['name']) ?></td>
<td class="text-center"><?= number_format((int)$row['shipment_count']) ?></td>
<td class="text-end text-dark">$<?= number_format((float)$row['total_amount'], 2) ?></td>
<td class="text-end pe-4 text-success fw-bold">$<?= number_format((float)$row['total_profit'], 2) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
<tfoot class="table-light fw-bold border-top">
<tr>
<td class="ps-4">TOTAL</td>
<td class="text-center"><?= number_format($totalShipments) ?></td>
<td class="text-end">$<?= number_format($grandTotalAmount, 2) ?></td>
<td class="text-end pe-4 text-success">$<?= number_format($grandTotalProfit, 2) ?></td>
</tr>
</tfoot>
</table>
</div>
<?php endif; ?>
</div>
</div>
</div>
<style>
@media print {
.admin-sidebar, .btn, form { display: none !important; }
.col-md-10 { width: 100% !important; padding: 0 !important; }
.panel { border: none !important; box-shadow: none !important; }
}
</style>
<?php render_footer(); ?>

View File

@ -75,27 +75,46 @@ if ($ownerId) {
render_header(t('truck_owners_statements') ?: 'Truck Owner Statements', 'reports_truck_owners', true);
?>
<!-- Select2 CSS -->
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
<style>
/* Select2 Bootstrap 5 Fixes */
.select2-container .select2-selection--single { height: 38px !important; border: 1px solid #dee2e6 !important; padding: 5px 0; }
.select2-container--default .select2-selection--single .select2-selection__arrow { height: 36px !important; }
.select2-container--default .select2-selection--single .select2-selection__rendered { line-height: 26px !important; color: #212529; }
@media print {
@page { size: A4; margin: 2cm; }
@page { size: A4; margin: 1cm; }
body { background: white !important; font-family: 'Times New Roman', serif; -webkit-print-color-adjust: exact; }
.no-print, .admin-sidebar, nav, footer, .btn, form.filter-form { display: none !important; }
.col-md-2 { display: none !important; }
.col-md-10 { width: 100% !important; flex: 0 0 100% !important; max-width: 100% !important; padding: 0 !important; margin: 0 !important; }
.row { display: block !important; margin: 0 !important; }
.row { display: flex !important; flex-wrap: wrap !important; margin: 0 !important; }
.col-6 { width: 50% !important; flex: 0 0 50% !important; max-width: 50% !important; }
.panel { border: none !important; box-shadow: none !important; padding: 0 !important; }
.print-header { display: block !important; margin-bottom: 30px; border-bottom: 2px solid #000; padding-bottom: 20px; }
.print-header h1 { font-size: 24pt; font-weight: bold; margin-bottom: 5px; text-transform: uppercase; }
.print-header p { margin: 0; font-size: 10pt; color: #555; }
.statement-info { margin-bottom: 30px; display: flex; justify-content: space-between; border-bottom: 1px solid #ddd; padding-bottom: 20px; }
.statement-info div { width: 48%; }
/* Compact Header */
.print-header { display: flex !important; justify-content: space-between !important; align-items: flex-start !important; margin-bottom: 10px !important; border-bottom: 2px solid #000 !important; padding-bottom: 5px !important; }
.print-header-left { text-align: left; }
.print-header-right { text-align: right; }
.print-header h1 { font-size: 14pt; font-weight: bold; margin: 0; text-transform: uppercase; }
.print-header h2 { font-size: 12pt; margin: 0; font-weight: normal; }
.print-header p { margin: 0; font-size: 9pt; color: #555; }
/* Compact Info Section */
.statement-info { margin-bottom: 10px !important; display: flex !important; justify-content: space-between !important; border-bottom: 1px solid #ddd !important; padding-bottom: 5px !important; }
.statement-info h5 { margin: 0 0 2px 0; font-size: 9pt; color: #777; text-transform: uppercase; font-weight: bold; }
.statement-info h4 { margin: 0; font-size: 11pt; font-weight: bold; }
.statement-info .small { font-size: 9pt; margin-top: 2px; }
.table-responsive { overflow: visible !important; }
table { width: 100% !important; border-collapse: collapse !important; font-size: 10pt; }
th, td { border: 1px solid #ddd !important; padding: 8px 12px !important; text-align: left; }
th { background-color: #f8f9fa !important; font-weight: bold; text-transform: uppercase; color: #000 !important; }
table { width: 100% !important; border-collapse: collapse !important; font-size: 9pt; }
th, td { border: 1px solid #ddd !important; padding: 4px 6px !important; text-align: left; }
th { background-color: #f8f9fa !important; font-weight: bold; text-transform: uppercase; color: #000 !important; font-size: 8pt; }
.text-end { text-align: right !important; }
.total-row td { background-color: #eee !important; font-weight: bold; font-size: 12pt; border-top: 2px solid #000 !important; }
.print-footer { display: block !important; margin-top: 50px; text-align: center; font-size: 9pt; color: #777; border-top: 1px solid #ddd; padding-top: 10px; }
.total-row td { background-color: #eee !important; font-weight: bold; font-size: 10pt; border-top: 2px solid #000 !important; }
.print-footer { display: block !important; margin-top: 20px; text-align: center; font-size: 8pt; color: #777; border-top: 1px solid #ddd; padding-top: 5px; }
/* Arabic Support */
[dir="rtl"] body { font-family: 'Traditional Arabic', serif; }
@ -128,7 +147,7 @@ render_header(t('truck_owners_statements') ?: 'Truck Owner Statements', 'reports
<form method="get" class="row g-3 align-items-end">
<div class="col-md-4">
<label class="form-label small text-muted">Select Truck Owner</label>
<select name="owner_id" class="form-select" onchange="this.form.submit()">
<select name="owner_id" id="ownerSelect" class="form-select" onchange="this.form.submit()">
<option value="">-- Choose a Truck Owner --</option>
<?php foreach ($allOwners as $o): ?>
<option value="<?= $o['id'] ?>" <?= $ownerId == $o['id'] ? 'selected' : '' ?>>
@ -155,37 +174,43 @@ render_header(t('truck_owners_statements') ?: 'Truck Owner Statements', 'reports
<div class="alert alert-warning">Truck Owner not found.</div>
<?php elseif ($owner): ?>
<div class="panel p-5 bg-white">
<!-- Print Header -->
<div class="print-header text-center">
<h1>Payment Statement</h1>
<h2 style="font-size: 18pt; margin: 0; font-weight: normal;">كشف مدفوعات</h2>
<p class="mt-2"><?= e(get_setting('company_name', 'Logistics Platform')) ?></p>
<p><?= date('F j, Y') ?></p>
<!-- Print Header (Compact) -->
<div class="print-header">
<div class="print-header-left">
<h2 style="font-size: 14pt; margin: 0; font-weight: bold;"><?= e(get_setting('company_name', 'Logistics Platform')) ?></h2>
<p class="mt-1"><?= date('F j, Y') ?></p>
</div>
<div class="print-header-right">
<h1>Payment Statement</h1>
<h2 style="font-size: 12pt; margin: 0; font-weight: normal;">كشف مدفوعات</h2>
</div>
</div>
<!-- Info Section -->
<div class="statement-info row mb-4">
<!-- Info Section (Compact) -->
<div class="statement-info row">
<div class="col-6">
<h5 class="fw-bold text-uppercase text-muted small mb-2">Pay To / إلى السيد</h5>
<h4 class="fw-bold mb-1"><?= e($owner['full_name']) ?></h4>
<div class="text-muted">Truck Plate: <?= e($owner['plate_no'] ?: '-') ?></div>
<div class="small text-muted mt-1">
<h5>Pay To / إلى السيد</h5>
<h4><?= e($owner['full_name']) ?></h4>
<div class="text-muted small">Truck Plate: <?= e($owner['plate_no'] ?: '-') ?></div>
<div class="small text-muted">
<?= e($owner['truck_type'] ?: '') ?><br>
<?= e($owner['city'] ?: '') ?>, <?= e($owner['country'] ?: '') ?><br>
<?= e($owner['phone'] ?: '') ?>
</div>
</div>
<div class="col-6 text-end">
<h5 class="fw-bold text-uppercase text-muted small mb-2">Summary / ملخص</h5>
<div class="mb-1"><strong>Statement Date:</strong> <?= date('Y-m-d') ?></div>
<?php if ($startDate || $endDate): ?>
<div class="mb-1"><strong>Period:</strong> <?= e($startDate ?: 'Start') ?> to <?= e($endDate ?: 'Now') ?></div>
<?php else: ?>
<div class="mb-1"><strong>Period:</strong> All Time</div>
<?php endif; ?>
<div class="mb-1"><strong>Total Trips:</strong> <?= count($shipments) ?></div>
<div class="fs-4 fw-bold text-primary mt-2">
<?= number_format($totalEarnings, 2) ?> OMR
<h5>Summary / ملخص</h5>
<div class="small">
<div><strong>Date:</strong> <?= date('Y-m-d') ?></div>
<?php if ($startDate || $endDate): ?>
<div><strong>Period:</strong> <?= e($startDate ?: 'Start') ?> to <?= e($endDate ?: 'Now') ?></div>
<?php else: ?>
<div><strong>Period:</strong> All Time</div>
<?php endif; ?>
<div><strong>Total Trips:</strong> <?= count($shipments) ?></div>
<div class="fs-5 fw-bold text-primary mt-1">
<?= number_format($totalEarnings, 2) ?> OMR
</div>
</div>
</div>
</div>
@ -251,4 +276,17 @@ render_header(t('truck_owners_statements') ?: 'Truck Owner Statements', 'reports
</div>
</div>
<!-- jQuery and Select2 JS -->
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
<script>
$(document).ready(function() {
$('#ownerSelect').select2({
width: '100%',
placeholder: '-- Choose a Truck Owner --',
allowClear: true
});
});
</script>
<?php render_footer(); ?>

View File

@ -15,6 +15,7 @@
--sidebar-bg: #000080;
--sidebar-text: #ffffff;
--sidebar-text-hover: #e2e8f0;
--sidebar-muted: rgba(255, 255, 255, 0.6);
--sidebar-active-bg: rgba(255, 255, 255, 0.15);
--sidebar-active-text: #ffffff;
--sidebar-border: rgba(255, 255, 255, 0.1);
@ -428,6 +429,11 @@ body.app-body {
margin-right: -1px; /* Overlap border if needed */
}
/* Fix text-muted in sidebar (must be light on dark bg) */
.admin-sidebar .text-muted {
color: var(--sidebar-muted) !important;
}
/* Sidebar Headings */
.admin-sidebar h2 {
color: #ffffff !important; /* Force white for headings */
@ -519,3 +525,15 @@ body.app-body {
background-color: var(--sidebar-bg); /* Keep dark on mobile too */
}
}
/* Sidebar Column Wrapper */
.sidebar-col {
width: 100%;
}
@media (min-width: 768px) {
.sidebar-col {
width: 220px;
flex-shrink: 0;
min-height: 100vh;
}
}

View File

@ -204,7 +204,9 @@ $translations = [
'user_created' => 'User created successfully.',
'user_updated' => 'User updated successfully.',
'user_deleted' => 'User deleted successfully.',
'error_email_exists' => 'Email already exists.'
'error_email_exists' => 'Email already exists.',
'shipper_shipments' => 'Shipper Shipments',
'truck_owners_statements' => 'Truck Owner Statements'
),
"ar" => array (
'app_name' => 'CargoLink',
@ -397,7 +399,9 @@ $translations = [
'user_created' => 'تم إنشاء المستخدم بنجاح.',
'user_updated' => 'تم تحديث المستخدم بنجاح.',
'user_deleted' => 'تم حذف المستخدم بنجاح.',
'error_email_exists' => 'البريد الإلكتروني موجود بالفعل.'
'error_email_exists' => 'البريد الإلكتروني موجود بالفعل.',
'shipper_shipments' => 'شحنات الشاحنين',
'truck_owners_statements' => 'كشوفات أصحاب الشاحنات'
)
];
@ -606,4 +610,4 @@ function has_permission(string $permissionSlug, ?int $userId = null): bool
} catch (Throwable $e) {
return false;
}
}
}

View File

@ -250,7 +250,7 @@ function render_admin_sidebar(string $active = 'dashboard'): void
$locationsActive = in_array($active, ['countries', 'cities']);
$usersActive = in_array($active, ['shippers', 'truck_owners', 'register', 'platform_users']);
$pagesActive = in_array($active, ['faqs', 'landing_pages']);
$reportsActive = in_array($active, ['reports_shippers', 'reports_truck_owners']);
$reportsActive = in_array($active, ['reports_shippers', 'reports_truck_owners', 'reports_summary']);
?>
<aside class="admin-sidebar d-flex flex-column h-100 py-4 px-3">
<h2 class="h5 fw-bold mb-4 px-2"><i class="bi bi-shield-lock me-2 text-primary"></i><?= e(t('nav_admin')) ?></h2>
@ -268,8 +268,11 @@ function render_admin_sidebar(string $active = 'dashboard'): void
</a>
<div class="collapse <?= $reportsActive ? 'show' : '' ?>" id="collapseReports">
<div class="nav flex-column gap-1 ms-3 border-start ps-2 border-2">
<a class="admin-nav-link <?= $active === 'reports_summary' ? 'active' : '' ?>" href="<?= e(url_with_lang('admin_reports_summary.php')) ?>">
<i class="bi bi-pie-chart-fill me-2"></i>Analytics
</a>
<a class="admin-nav-link <?= $active === 'reports_shippers' ? 'active' : '' ?>" href="<?= e(url_with_lang('admin_reports_shippers.php')) ?>">
<i class="bi bi-people me-2"></i><?= e(t('shippers_statements') ?: 'Shippers Statements') ?>
<i class="bi bi-people me-2"></i><?= e(t('shipper_shipments') ?: 'Shipper Shipments') ?>
</a>
<a class="admin-nav-link <?= $active === 'reports_truck_owners' ? 'active' : '' ?>" href="<?= e(url_with_lang('admin_reports_truck_owners.php')) ?>">
<i class="bi bi-truck me-2"></i><?= e(t('truck_owners_statements') ?: 'Truck Owner Statements') ?>

15
scan_sidebar_pattern.py Normal file
View File

@ -0,0 +1,15 @@
import glob
import re
files = glob.glob("admin_*.php")
pattern = re.compile(r'<div class="col-md-10(.*?)"')
for file in files:
with open(file, 'r') as f:
content = f.read()
match = pattern.search(content)
if match:
print(f"{file}: {match.group(1)}")
else:
if "render_admin_sidebar" in content:
print(f"{file}: NO MATCH for col-md-10")