39038-vm/truck_owner_dashboard.php
2026-03-14 13:13:28 +00:00

191 lines
9.9 KiB
PHP

<?php
declare(strict_types=1);
require_once __DIR__ . '/includes/layout.php'; require_role('truck_owner');
ensure_schema();
$errors = [];
// Try to prefill owner name from profile if logged in
$prefillOwnerName = '';
if (isset($_SESSION['user_id'])) {
try {
$stmt = db()->prepare("SELECT full_name FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
$prefillOwnerName = $stmt->fetchColumn() ?: '';
} catch (Throwable $e) {}
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'submit_offer') {
$shipmentId = (int) ($_POST['shipment_id'] ?? 0);
$offerOwner = trim($_POST['offer_owner'] ?? '');
$offerPrice = trim($_POST['offer_price'] ?? '');
if ($shipmentId <= 0 || $offerOwner === '' || $offerPrice === '') {
$errors[] = t('error_required');
} elseif (!is_numeric($offerPrice)) {
$errors[] = t('error_invalid');
}
if (!$errors) {
$stmt = db()->prepare(
"UPDATE shipments SET offer_owner = :offer_owner, offer_price = :offer_price, status = 'offered'
WHERE id = :id AND status IN ('posted','offered')"
);
$stmt->execute([
':offer_owner' => $offerOwner,
':offer_price' => $offerPrice,
':id' => $shipmentId,
]);
if ($stmt->rowCount() > 0) {
$_SESSION['last_offer_owner'] = $offerOwner; // Save for next time
set_flash('success', t('success_offer'));
header('Location: ' . url_with_lang('truck_owner_dashboard.php'));
exit;
} else {
$errors[] = t('error_invalid');
}
}
}
$ownerName = $_SESSION['last_offer_owner'] ?? $prefillOwnerName;
$shipments = [];
try {
$stmt = db()->query("SELECT * FROM shipments WHERE status IN ('posted','offered') ORDER BY created_at DESC LIMIT 20");
$shipments = $stmt->fetchAll();
} catch (Throwable $e) {
$shipments = [];
}
$stats = [
'available' => count($shipments),
'my_offers' => 0,
'won' => 0,
];
try {
if ($ownerName) {
$stats['my_offers'] = (int)db()->query("SELECT COUNT(*) FROM shipments WHERE offer_owner = " . db()->quote($ownerName))->fetchColumn();
$stats['won'] = (int)db()->query("SELECT COUNT(*) FROM shipments WHERE offer_owner = " . db()->quote($ownerName) . " AND status IN ('confirmed','in_transit','delivered')")->fetchColumn();
}
} catch (Throwable $e) {}
render_header(t('owner_dashboard'), 'owner');
$flash = get_flash();
?>
<div class="page-intro mb-4">
<h1 class="section-title mb-1"><?= e(t('owner_dashboard')) ?></h1>
<p class="muted mb-0"><?= e(t('welcome_back_owner') ?? 'Find loads and submit your best rate.') ?></p>
</div>
<!-- Stats Row -->
<div class="row g-3 mb-4">
<div class="col-md-4">
<div class="panel p-4 text-center h-100 shadow-sm border-0 rounded-4 position-relative overflow-hidden" style="background: linear-gradient(135deg, #ffffff, #f8f9fa);">
<div class="position-absolute opacity-10" style="inset-inline-end: 10px; top: 15px;"><i class="bi bi-search" style="font-size: 3.5rem;"></i></div>
<div class="text-primary mb-2 position-relative"><i class="bi bi-search fs-2"></i></div>
<h3 class="h2 mb-0 fw-bold position-relative"><?= $stats['available'] ?></h3>
<p class="text-muted small text-uppercase mb-0 fw-bold position-relative" style="letter-spacing: 0.5px;"><?= e(t('available_shipments')) ?></p>
</div>
</div>
<div class="col-md-4">
<div class="panel p-4 text-center h-100 shadow-sm border-0 rounded-4 position-relative overflow-hidden" style="background: linear-gradient(135deg, #ffffff, #f8f9fa);">
<div class="position-absolute opacity-10" style="inset-inline-end: 10px; top: 15px;"><i class="bi bi-tags" style="font-size: 3.5rem;"></i></div>
<div class="text-info mb-2 position-relative"><i class="bi bi-tags fs-2"></i></div>
<h3 class="h2 mb-0 fw-bold position-relative"><?= $stats['my_offers'] ?></h3>
<p class="text-muted small text-uppercase mb-0 fw-bold position-relative" style="letter-spacing: 0.5px;"><?= e(t('total_offers')) ?></p>
</div>
</div>
<div class="col-md-4">
<div class="panel p-4 text-center h-100 shadow-sm border-0 rounded-4 position-relative overflow-hidden" style="background: linear-gradient(135deg, #ffffff, #f8f9fa);">
<div class="position-absolute opacity-10" style="inset-inline-end: 10px; top: 15px;"><i class="bi bi-trophy" style="font-size: 3.5rem;"></i></div>
<div class="text-success mb-2 position-relative"><i class="bi bi-trophy fs-2"></i></div>
<h3 class="h2 mb-0 fw-bold position-relative"><?= $stats['won'] ?></h3>
<p class="text-muted small text-uppercase mb-0 fw-bold position-relative" style="letter-spacing: 0.5px;"><?= e(t('won_shipments')) ?></p>
</div>
</div>
</div>
<div class="panel p-4 shadow-sm border-0 rounded-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<h2 class="h5 mb-0 fw-bold"><i class="bi bi-truck text-muted me-2"></i><?= e(t('available_shipments')) ?></h2>
<span class="badge bg-light text-dark border"><?= e(count($shipments)) ?> <?= e(t('total_label') ?? 'total') ?></span>
</div>
<?php if ($flash): ?>
<div class="alert alert-success" data-auto-dismiss="true"><?= e($flash['message']) ?></div>
<?php endif; ?>
<?php if ($errors): ?>
<div class="alert alert-warning"><?= e(implode(' ', $errors)) ?></div>
<?php endif; ?>
<?php if (!$shipments): ?>
<div class="text-center p-5 text-muted flex-grow-1 d-flex flex-column justify-content-center">
<i class="bi bi-inbox fs-1 mb-3 d-block opacity-50"></i>
<p class="mb-0"><?= e(t('no_shipments')) ?></p>
</div>
<?php else: ?>
<div class="table-responsive">
<table class="table align-middle mb-0">
<thead>
<tr>
<th class="text-uppercase small text-muted border-top-0"><?= e(t('shipper_company')) ?></th>
<th class="text-uppercase small text-muted border-top-0"><?= e(t('route_label') ?? 'Route') ?></th>
<th class="text-uppercase small text-muted border-top-0"><?= e(t('cargo')) ?></th>
<th class="text-uppercase small text-muted border-top-0"><?= e(t('offer')) ?></th>
<th class="text-uppercase small text-muted border-top-0 text-end"><?= e(t('actions')) ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($shipments as $row): ?>
<tr>
<td>
<div class="fw-bold"><?= e($row['shipper_company']) ?></div>
<small class="text-muted"><?= e(date('M d', strtotime($row['pickup_date']))) ?></small>
</td>
<td>
<div class="d-flex align-items-center gap-2">
<span class="fw-medium"><?= e($row['origin_city']) ?></span>
<i class="bi bi-arrow-right text-muted small"></i>
<span class="fw-medium"><?= e($row['destination_city']) ?></span>
</div>
</td>
<td>
<div><?= e($row['weight_tons']) ?> Ton(s)</div>
<small class="text-muted text-truncate d-inline-block" style="max-width: 150px;"><?= e($row['cargo_description']) ?></small>
</td>
<td>
<?php if ($row['offer_price']): ?>
<div class="fw-bold text-success">$<?= e($row['offer_price']) ?></div>
<small class="text-muted"><?= e($row['offer_owner']) ?></small>
<?php else: ?>
<span class="badge bg-light text-dark border"><?= e(t('no_offers')) ?></span>
<?php endif; ?>
</td>
<td class="text-end">
<form class="d-flex align-items-center justify-content-end gap-2" method="post">
<input type="hidden" name="action" value="submit_offer">
<input type="hidden" name="shipment_id" value="<?= e($row['id']) ?>">
<input class="form-control form-control-sm border-secondary shadow-none" style="width: 120px;" name="offer_owner" placeholder="<?= e(t('offer_owner')) ?>" value="<?= e($ownerName) ?>" required>
<div class="input-group input-group-sm" style="width: 110px;">
<span class="input-group-text">$</span>
<input class="form-control border-secondary shadow-none" name="offer_price" type="number" step="0.01" min="0.1" placeholder="<?= e(t('offer_price')) ?>" required>
</div>
<button class="btn btn-sm p-1 border-0 bg-transparent text-primary" type="submit" title="Submit Offer"><i class="bi bi-send-fill"></i></button>
<a class="btn btn-sm p-1 border-0 bg-transparent text-primary ms-1" href="<?= e(url_with_lang('shipment_detail.php', ['id' => $row['id']])) ?>" title="<?= e(t('view')) ?>">
<i class="bi bi-eye"></i>
</a>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
<?php render_footer(); ?>