Autosave: 20260308-060543
This commit is contained in:
parent
c17c11d23a
commit
29654f3470
@ -79,7 +79,7 @@ $translations = [
|
|||||||
'status_in_transit' => 'In transit',
|
'status_in_transit' => 'In transit',
|
||||||
'status_delivered' => 'Delivered',
|
'status_delivered' => 'Delivered',
|
||||||
'footer_note' => 'This is the initial MVP slice. Payments are not yet connected.',
|
'footer_note' => 'This is the initial MVP slice. Payments are not yet connected.',
|
||||||
'marketing_title_1' => 'For Shippers', 'marketing_desc_1' => 'Find the right truck for your cargo quickly and securely. Post your load and get offers instantly.', 'marketing_title_2' => 'For Truck Owners', 'marketing_desc_2' => 'Maximize your earnings and eliminate empty miles. Browse available shipments and offer your rate.', 'motivation_phrase' => 'Empowering the logistics of tomorrow.', 'why_choose_us' => 'Why Choose CargoLink?', 'feature_1_title' => 'Fast Matching', 'feature_1_desc' => 'Connect with available trucks or shipments in minutes.', 'feature_2_title' => 'Secure Payments', 'feature_2_desc' => 'Your transactions are protected with security.', 'feature_3_title' => 'Verified Users', 'feature_3_desc' => 'We verify all truck owners to ensure peace of mind.',
|
'marketing_title_1' => 'For Shippers', 'marketing_desc_1' => 'Find the right truck for your cargo quickly and securely. Post your load and get offers instantly.', 'marketing_title_2' => 'For Truck Owners', 'marketing_desc_2' => 'Maximize your earnings and eliminate empty miles. Browse available shipments and offer your rate.', 'motivation_phrase' => 'Empowering the logistics of tomorrow.', 'why_choose_us' => 'لماذا تختار كارجو لينك؟', 'feature_1_title' => 'Fast Matching', 'feature_1_desc' => 'Connect with available trucks or shipments in minutes.', 'feature_2_title' => 'Secure Payments', 'feature_2_desc' => 'Your transactions are protected with security.', 'feature_3_title' => 'Verified Users', 'feature_3_desc' => 'We verify all truck owners to ensure peace of mind.',
|
||||||
],
|
],
|
||||||
'ar' => [
|
'ar' => [
|
||||||
'app_name' => 'CargoLink',
|
'app_name' => 'CargoLink',
|
||||||
@ -202,6 +202,10 @@ SQL;
|
|||||||
try { db()->exec("ALTER TABLE users ADD COLUMN status ENUM('pending','active','rejected') NOT NULL DEFAULT 'active'"); } catch (Exception $e) {}
|
try { db()->exec("ALTER TABLE users ADD COLUMN status ENUM('pending','active','rejected') NOT NULL DEFAULT 'active'"); } catch (Exception $e) {}
|
||||||
try { db()->exec("ALTER TABLE users ADD COLUMN profile_picture VARCHAR(255) NULL AFTER full_name"); } catch (Exception $e) {}
|
try { db()->exec("ALTER TABLE users ADD COLUMN profile_picture VARCHAR(255) NULL AFTER full_name"); } catch (Exception $e) {}
|
||||||
|
|
||||||
|
// Payment fields for shipments
|
||||||
|
try { db()->exec("ALTER TABLE shipments ADD COLUMN platform_fee DECIMAL(10,2) DEFAULT 0.00 AFTER offer_price"); } catch (Exception $e) {}
|
||||||
|
try { db()->exec("ALTER TABLE shipments ADD COLUMN total_price DECIMAL(10,2) DEFAULT 0.00 AFTER platform_fee"); } catch (Exception $e) {}
|
||||||
|
try { db()->exec("ALTER TABLE shipments ADD COLUMN payment_status ENUM('unpaid', 'paid') DEFAULT 'unpaid' AFTER status"); } catch (Exception $e) {}
|
||||||
|
|
||||||
db()->exec(
|
db()->exec(
|
||||||
"CREATE TABLE IF NOT EXISTS users (
|
"CREATE TABLE IF NOT EXISTS users (
|
||||||
|
|||||||
@ -15,7 +15,20 @@ if ($shipmentId > 0) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$errors = [];
|
$errors = [];
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'submit_offer') {
|
$flash = get_flash();
|
||||||
|
$userRole = $_SESSION['user_role'] ?? '';
|
||||||
|
$isAdmin = $userRole === 'admin';
|
||||||
|
$isShipper = $userRole === 'shipper';
|
||||||
|
$isTruckOwner = $userRole === 'truck_owner';
|
||||||
|
|
||||||
|
// Platform Fee Configuration
|
||||||
|
const PLATFORM_FEE_PERCENTAGE = 0.05; // 5%
|
||||||
|
|
||||||
|
// Handle POST actions
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$action = $_POST['action'] ?? '';
|
||||||
|
|
||||||
|
if ($action === 'submit_offer') {
|
||||||
$offerOwner = trim($_POST['offer_owner'] ?? '');
|
$offerOwner = trim($_POST['offer_owner'] ?? '');
|
||||||
$offerPrice = trim($_POST['offer_price'] ?? '');
|
$offerPrice = trim($_POST['offer_price'] ?? '');
|
||||||
if ($offerOwner === '' || $offerPrice === '') {
|
if ($offerOwner === '' || $offerPrice === '') {
|
||||||
@ -36,10 +49,32 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'submi
|
|||||||
header('Location: ' . url_with_lang('shipment_detail.php', ['id' => $shipmentId]));
|
header('Location: ' . url_with_lang('shipment_detail.php', ['id' => $shipmentId]));
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
}
|
} elseif ($action === 'accept_offer' && $isShipper) {
|
||||||
|
if ($shipment && $shipment['status'] === 'offered' && $shipment['offer_price'] > 0) {
|
||||||
|
$offerPrice = (float)$shipment['offer_price'];
|
||||||
|
$platformFee = $offerPrice * PLATFORM_FEE_PERCENTAGE;
|
||||||
|
$totalPrice = $offerPrice + $platformFee;
|
||||||
|
|
||||||
$flash = get_flash();
|
$stmt = db()->prepare(
|
||||||
$isAdmin = ($_SESSION['user_role'] ?? '') === 'admin';
|
"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
|
||||||
|
]);
|
||||||
|
|
||||||
|
set_flash('success', t('Payment successful. Shipment confirmed!'));
|
||||||
|
header('Location: ' . url_with_lang('shipment_detail.php', ['id' => $shipmentId]));
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render_header(t('shipment_detail'));
|
render_header(t('shipment_detail'));
|
||||||
?>
|
?>
|
||||||
@ -50,6 +85,8 @@ render_header(t('shipment_detail'));
|
|||||||
<div class="mt-3">
|
<div class="mt-3">
|
||||||
<?php if ($isAdmin): ?>
|
<?php if ($isAdmin): ?>
|
||||||
<a href="<?= e(url_with_lang('admin_shipments.php')) ?>" class="btn btn-outline-primary">Back to Shipments</a>
|
<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: ?>
|
<?php else: ?>
|
||||||
<a href="<?= e(url_with_lang('index.php')) ?>" class="btn btn-outline-primary"><?= e(t('nav_home')) ?></a>
|
<a href="<?= e(url_with_lang('index.php')) ?>" class="btn btn-outline-primary"><?= e(t('nav_home')) ?></a>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
@ -107,6 +144,17 @@ render_header(t('shipment_detail'));
|
|||||||
<div class="small text-muted"><?= e(t('best_offer')) ?></div>
|
<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 class="fw-semibold"><?= $shipment['offer_price'] ? e($shipment['offer_price'] . ' / ' . ($shipment['offer_owner'] ?? '')) : e(t('no_offers')) ?></div>
|
||||||
</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>
|
||||||
<div class="mt-4 d-flex gap-2">
|
<div class="mt-4 d-flex gap-2">
|
||||||
<?php if ($isAdmin): ?>
|
<?php if ($isAdmin): ?>
|
||||||
@ -116,13 +164,75 @@ render_header(t('shipment_detail'));
|
|||||||
<a class="btn btn-primary" href="<?= e(url_with_lang('admin_shipment_edit.php', ['id' => $shipmentId])) ?>">
|
<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
|
<i class="bi bi-pencil me-2"></i>Edit Shipment
|
||||||
</a>
|
</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: ?>
|
<?php else: ?>
|
||||||
<a class="btn btn-outline-dark" href="<?= e(url_with_lang('truck_owner_dashboard.php')) ?>"><?= e(t('nav_owner')) ?></a>
|
<a class="btn btn-outline-dark" href="<?= e(url_with_lang('truck_owner_dashboard.php')) ?>"><?= e(t('nav_owner')) ?></a>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Right Column: Actions (Offer / Payment) -->
|
||||||
<div class="col-lg-5">
|
<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 * PLATFORM_FEE_PERCENTAGE;
|
||||||
|
$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 (5%)</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>
|
||||||
|
|
||||||
|
<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>
|
||||||
|
<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>
|
||||||
|
</form>
|
||||||
|
<?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">
|
<div class="panel p-4">
|
||||||
<h3 class="section-title"><?= e(t('submit_offer')) ?></h3>
|
<h3 class="section-title"><?= e(t('submit_offer')) ?></h3>
|
||||||
<?php if ($flash): ?>
|
<?php if ($flash): ?>
|
||||||
@ -131,19 +241,27 @@ render_header(t('shipment_detail'));
|
|||||||
<?php if ($errors): ?>
|
<?php if ($errors): ?>
|
||||||
<div class="alert alert-warning"><?= e(implode(' ', $errors)) ?></div>
|
<div class="alert alert-warning"><?= e(implode(' ', $errors)) ?></div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if ($shipment['status'] === 'posted' || $shipment['status'] === 'offered'): ?>
|
||||||
<form method="post">
|
<form method="post">
|
||||||
<input type="hidden" name="action" value="submit_offer">
|
<input type="hidden" name="action" value="submit_offer">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label"><?= e(t('offer_owner')) ?></label>
|
<label class="form-label"><?= e(t('offer_owner')) ?></label>
|
||||||
<input class="form-control" name="offer_owner" required>
|
<input class="form-control" name="offer_owner" value="<?= e($shipment['offer_owner'] ?? '') ?>" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label"><?= e(t('offer_price')) ?></label>
|
<label class="form-label"><?= e(t('offer_price')) ?></label>
|
||||||
<input class="form-control" name="offer_price" type="number" step="0.01" min="0.1" required>
|
<input class="form-control" name="offer_price" type="number" step="0.01" min="0.1" value="<?= e($shipment['offer_price'] ?? '') ?>" required>
|
||||||
</div>
|
</div>
|
||||||
<button class="btn btn-primary w-100" type="submit"><?= e(t('submit_offer')) ?></button>
|
<button class="btn btn-primary w-100" type="submit"><?= e(t('submit_offer')) ?></button>
|
||||||
</form>
|
</form>
|
||||||
|
<?php else: ?>
|
||||||
|
<div class="alert alert-info">
|
||||||
|
This shipment is already confirmed/processed.
|
||||||
</div>
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user