39038-vm/shipment_detail.php
2026-03-08 10:11:07 +00:00

331 lines
17 KiB
PHP

<?php
declare(strict_types=1);
require_once __DIR__ . '/includes/layout.php';
require_once __DIR__ . '/includes/NotificationService.php';
ensure_schema();
$shipmentId = (int) ($_GET['id'] ?? 0);
$shipment = null;
if ($shipmentId > 0) {
$stmt = db()->prepare("SELECT * FROM shipments WHERE id = :id");
$stmt->execute([':id' => $shipmentId]);
$shipment = $stmt->fetch();
}
$errors = [];
$flash = get_flash();
$userRole = $_SESSION['user_role'] ?? '';
$isAdmin = $userRole === 'admin';
$isShipper = $userRole === 'shipper';
$isTruckOwner = $userRole === 'truck_owner';
// Platform Fee Configuration
$settings = get_settings();
$platformFeePercentage = (float)($settings['platform_charge_percentage'] ?? 0) / 100;
// Handle POST actions
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$action = $_POST['action'] ?? '';
if ($action === 'submit_offer') {
$offerOwner = trim($_POST['offer_owner'] ?? '');
$offerPrice = trim($_POST['offer_price'] ?? '');
if ($offerOwner === '' || $offerPrice === '') {
$errors[] = t('error_required');
} elseif (!is_numeric($offerPrice)) {
$errors[] = t('error_invalid');
} else {
$truckOwnerId = isset($_SESSION['user_id']) ? (int)$_SESSION['user_id'] : null;
$stmt = db()->prepare(
"UPDATE shipments SET offer_owner = :offer_owner, offer_price = :offer_price, status = 'offered', truck_owner_id = :truck_owner_id
WHERE id = :id"
);
$stmt->execute([
':offer_owner' => $offerOwner,
':offer_price' => $offerPrice,
':truck_owner_id' => $truckOwnerId,
':id' => $shipmentId,
]);
// Notify Shipper
if (!empty($shipment['shipper_id'])) {
$shipperUser = db()->query("SELECT * FROM users WHERE id = " . (int)$shipment['shipper_id'])->fetch();
if ($shipperUser) {
NotificationService::send('shipment_offered', $shipperUser, [
'shipment_id' => $shipmentId,
'offer_price' => $offerPrice,
'offer_owner' => $offerOwner
]);
}
}
set_flash('success', t('success_offer'));
header('Location: ' . url_with_lang('shipment_detail.php', ['id' => $shipmentId]));
exit;
}
} elseif ($action === 'accept_offer' && $isShipper) {
if ($shipment && $shipment['status'] === 'offered' && $shipment['offer_price'] > 0) {
$offerPrice = (float)$shipment['offer_price'];
$platformFee = $offerPrice * $platformFeePercentage;
$totalPrice = $offerPrice + $platformFee;
$stmt = db()->prepare(
"UPDATE shipments
SET status = 'confirmed',
payment_status = 'paid',
platform_fee = :fee,
total_price = :total
WHERE id = :id"
);
$stmt->execute([
':fee' => $platformFee,
':total' => $totalPrice,
':id' => $shipmentId
]);
// Notify Truck Owner
if (!empty($shipment['truck_owner_id'])) {
$truckOwnerUser = db()->query("SELECT * FROM users WHERE id = " . (int)$shipment['truck_owner_id'])->fetch();
if ($truckOwnerUser) {
NotificationService::send('shipment_accepted', $truckOwnerUser, [
'shipment_id' => $shipmentId
]);
}
}
set_flash('success', t('Payment successful. Shipment confirmed!'));
header('Location: ' . url_with_lang('shipment_detail.php', ['id' => $shipmentId]));
exit;
}
} elseif ($action === 'reject_offer' && $isShipper) {
if ($shipment && $shipment['status'] === 'offered') {
// Notify Truck Owner first (before clearing ID)
if (!empty($shipment['truck_owner_id'])) {
$truckOwnerUser = db()->query("SELECT * FROM users WHERE id = " . (int)$shipment['truck_owner_id'])->fetch();
if ($truckOwnerUser) {
NotificationService::send('shipment_rejected', $truckOwnerUser, [
'shipment_id' => $shipmentId
]);
}
}
$stmt = db()->prepare(
"UPDATE shipments
SET status = 'posted',
offer_price = NULL,
offer_owner = NULL,
truck_owner_id = NULL
WHERE id = :id"
);
$stmt->execute([':id' => $shipmentId]);
set_flash('success', 'Offer rejected. Shipment is now open for new offers.');
header('Location: ' . url_with_lang('shipment_detail.php', ['id' => $shipmentId]));
exit;
}
}
}
render_header(t('shipment_detail'));
?>
<?php if (!$shipment): ?>
<div class="panel p-4">
<p class="muted mb-0"><?= e(t('no_shipments')) ?></p>
<div class="mt-3">
<?php if ($isAdmin): ?>
<a href="<?= e(url_with_lang('admin_shipments.php')) ?>" class="btn btn-outline-primary">Back to Shipments</a>
<?php elseif ($isShipper): ?>
<a href="<?= e(url_with_lang('shipper_dashboard.php')) ?>" class="btn btn-outline-primary">Back to Dashboard</a>
<?php else: ?>
<a href="<?= e(url_with_lang('index.php')) ?>" class="btn btn-outline-primary"><?= e(t('nav_home')) ?></a>
<?php endif; ?>
</div>
</div>
<?php else: ?>
<div class="row g-4">
<div class="col-lg-7">
<div class="panel p-4">
<div class="d-flex justify-content-between align-items-start mb-3">
<div>
<h2 class="section-title mb-1"><?= e(t('shipment_detail')) ?> #<?= e($shipment['id']) ?></h2>
<p class="muted mb-0"><?= e(t('created_at')) ?>: <?= e($shipment['created_at']) ?></p>
</div>
<span class="badge-status <?= e($shipment['status']) ?>"><?= e(status_label($shipment['status'])) ?></span>
</div>
<div class="row g-3">
<div class="col-md-6">
<div class="small text-muted"><?= e(t('shipper_company')) ?></div>
<div class="fw-semibold"><?= e($shipment['shipper_company']) ?></div>
</div>
<div class="col-md-6">
<div class="small text-muted"><?= e(t('shipper_name')) ?></div>
<div class="fw-semibold"><?= e($shipment['shipper_name']) ?></div>
</div>
<div class="col-md-6">
<div class="small text-muted"><?= e(t('origin')) ?></div>
<div class="fw-semibold"><?= e($shipment['origin_city']) ?></div>
</div>
<div class="col-md-6">
<div class="small text-muted"><?= e(t('destination')) ?></div>
<div class="fw-semibold"><?= e($shipment['destination_city']) ?></div>
</div>
<div class="col-md-6">
<div class="small text-muted"><?= e(t('cargo')) ?></div>
<div class="fw-semibold"><?= e($shipment['cargo_description']) ?></div>
</div>
<div class="col-md-6">
<div class="small text-muted"><?= e(t('weight')) ?></div>
<div class="fw-semibold"><?= e($shipment['weight_tons']) ?></div>
</div>
<div class="col-md-6">
<div class="small text-muted"><?= e(t('pickup_date')) ?></div>
<div class="fw-semibold"><?= e($shipment['pickup_date']) ?></div>
</div>
<div class="col-md-6">
<div class="small text-muted"><?= e(t('delivery_date')) ?></div>
<div class="fw-semibold"><?= e($shipment['delivery_date']) ?></div>
</div>
<div class="col-md-6">
<div class="small text-muted"><?= e(t('payment_method')) ?></div>
<div class="fw-semibold"><?= e($shipment['payment_method'] === 'bank_transfer' ? t('payment_bank') : t('payment_thawani')) ?></div>
</div>
<div class="col-md-6">
<div class="small text-muted"><?= e(t('best_offer')) ?></div>
<div class="fw-semibold"><?= $shipment['offer_price'] ? e($shipment['offer_price'] . ' / ' . ($shipment['offer_owner'] ?? '')) : e(t('no_offers')) ?></div>
</div>
<?php if ($shipment['payment_status'] === 'paid'): ?>
<div class="col-12">
<div class="alert alert-success d-flex align-items-center mb-0">
<i class="bi bi-check-circle-fill fs-4 me-2"></i>
<div>
<strong>Payment Complete</strong><br>
Total Paid: $<?= e($shipment['total_price']) ?> (Includes $<?= e($shipment['platform_fee']) ?> platform fee)
</div>
</div>
</div>
<?php endif; ?>
</div>
<div class="mt-4 d-flex gap-2">
<?php if ($isAdmin): ?>
<a class="btn btn-outline-dark" href="<?= e(url_with_lang('admin_shipments.php')) ?>">
<i class="bi bi-arrow-left me-2"></i>Back to Shipments
</a>
<a class="btn btn-primary" href="<?= e(url_with_lang('admin_shipment_edit.php', ['id' => $shipmentId])) ?>">
<i class="bi bi-pencil me-2"></i>Edit Shipment
</a>
<?php elseif ($isShipper): ?>
<a class="btn btn-outline-dark" href="<?= e(url_with_lang('shipper_dashboard.php')) ?>"><?= e(t('shipper_dashboard')) ?></a>
<?php else: ?>
<a class="btn btn-outline-dark" href="<?= e(url_with_lang('truck_owner_dashboard.php')) ?>"><?= e(t('nav_owner')) ?></a>
<?php endif; ?>
</div>
</div>
</div>
<!-- Right Column: Actions (Offer / Payment) -->
<div class="col-lg-5">
<?php if ($isShipper): ?>
<!-- Shipper View -->
<div class="panel p-4 h-100">
<h3 class="section-title">Accept Offer</h3>
<?php if ($flash): ?>
<div class="alert alert-success" data-auto-dismiss="true"><?= e($flash['message']) ?></div>
<?php endif; ?>
<?php if ($shipment['status'] === 'offered' && $shipment['offer_price'] > 0): ?>
<?php
$offerPrice = (float)$shipment['offer_price'];
$fee = $offerPrice * $platformFeePercentage;
$total = $offerPrice + $fee;
?>
<div class="card bg-light border-0 mb-4">
<div class="card-body">
<h5 class="card-title fw-bold mb-3">Payment Breakdown</h5>
<div class="d-flex justify-content-between mb-2">
<span class="text-muted">Truck Offer</span>
<span class="fw-medium">$<?= number_format($offerPrice, 2) ?></span>
</div>
<div class="d-flex justify-content-between mb-3">
<span class="text-muted">Platform Fee (<?= e($platformFeePercentage * 100) ?>%)</span>
<span class="fw-medium">$<?= number_format($fee, 2) ?></span>
</div>
<hr>
<div class="d-flex justify-content-between align-items-center">
<span class="fw-bold fs-5">Total</span>
<span class="fw-bold fs-4 text-primary">$<?= number_format($total, 2) ?></span>
</div>
</div>
</div>
<div class="d-grid gap-2">
<form method="post">
<input type="hidden" name="action" value="accept_offer">
<button class="btn btn-success w-100 py-3 fw-bold shadow-sm" type="submit">
<i class="bi bi-credit-card-2-front me-2"></i>Accept & Pay Now
</button>
</form>
<form method="post" onsubmit="return confirm('Are you sure you want to reject this offer?');">
<input type="hidden" name="action" value="reject_offer">
<button class="btn btn-outline-danger w-100 py-2 fw-bold" type="submit">
<i class="bi bi-x-circle me-2"></i>Reject Offer
</button>
</form>
</div>
<p class="text-center text-muted small mt-3 mb-0">
<i class="bi bi-shield-lock me-1"></i> Secure payment via <?= e($shipment['payment_method'] === 'bank_transfer' ? 'Bank Transfer' : 'Thawani') ?>
</p>
<?php elseif ($shipment['status'] === 'posted'): ?>
<div class="text-center py-5">
<i class="bi bi-hourglass-split fs-1 text-muted mb-3 d-block"></i>
<p class="mb-0 text-muted">Waiting for truck owners to submit offers.</p>
</div>
<?php elseif ($shipment['status'] === 'confirmed' || $shipment['status'] === 'in_transit' || $shipment['status'] === 'delivered'): ?>
<div class="text-center py-5">
<i class="bi bi-check-circle-fill fs-1 text-success mb-3 d-block"></i>
<h4 class="h5">Offer Accepted</h4>
<p class="mb-0 text-muted">This shipment has been confirmed and paid for.</p>
</div>
<?php endif; ?>
</div>
<?php else: ?>
<!-- Truck Owner / Admin / Other View (Submit Offer) -->
<div class="panel p-4">
<h3 class="section-title"><?= e(t('submit_offer')) ?></h3>
<?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 ($shipment['status'] === 'posted' || $shipment['status'] === 'offered'): ?>
<form method="post">
<input type="hidden" name="action" value="submit_offer">
<div class="mb-3">
<label class="form-label"><?= e(t('offer_owner')) ?></label>
<input class="form-control" name="offer_owner" value="<?= e($shipment['offer_owner'] ?? '') ?>" required>
</div>
<div class="mb-3">
<label class="form-label"><?= e(t('offer_price')) ?></label>
<input class="form-control" name="offer_price" type="number" step="0.01" min="0.1" value="<?= e($shipment['offer_price'] ?? '') ?>" required>
</div>
<button class="btn btn-primary w-100" type="submit"><?= e(t('submit_offer')) ?></button>
</form>
<?php else: ?>
<div class="alert alert-info">
This shipment is already confirmed/processed.
</div>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
<?php render_footer(); ?>