39038-vm/admin_shipment_edit.php
2026-03-13 10:55:45 +00:00

352 lines
17 KiB
PHP

<?php
declare(strict_types=1);
require_once __DIR__ . '/includes/layout.php';
$id = (int)($_GET['id'] ?? 0);
$isAjax = isset($_GET['ajax']) && $_GET['ajax'] === '1';
if (!$id) {
if ($isAjax) {
echo json_encode(['success' => false, 'message' => t('invalid_id')]);
exit;
}
header('Location: admin_shipments.php'); exit;
}
$errors = [];
$flash = null;
$stmt = db()->prepare("SELECT * FROM shipments WHERE id = ?");
$stmt->execute([$id]);
$shipment = $stmt->fetch();
if (!$shipment) {
if ($isAjax) {
echo json_encode(['success' => false, 'message' => t('shipment_not_found')]);
exit;
}
header('Location: admin_shipments.php'); exit;
}
// Fetch all countries for dropdowns
$countries = [];
try {
$countries = db()->query("SELECT * FROM countries ORDER BY name_en ASC")->fetchAll();
} catch (Throwable $e) {}
// Helper to find country_id by city name
function find_country_id_by_city_name($cityName) {
if (!$cityName) return null;
$stmt = db()->prepare("SELECT country_id FROM cities WHERE name_en = ? LIMIT 1");
$stmt->execute([$cityName]);
return $stmt->fetchColumn() ?: null;
}
// Pre-fetch country IDs for existing cities
$origin_country_id = find_country_id_by_city_name($shipment['origin_city']);
$destination_country_id = find_country_id_by_city_name($shipment['destination_city']);
// Fetch initial city lists for the pre-selected countries
$origin_cities_list = [];
if ($origin_country_id) {
$stmt = db()->prepare("SELECT * FROM cities WHERE country_id = ? ORDER BY name_en ASC");
$stmt->execute([$origin_country_id]);
$origin_cities_list = $stmt->fetchAll();
}
$destination_cities_list = [];
if ($destination_country_id) {
$stmt = db()->prepare("SELECT * FROM cities WHERE country_id = ? ORDER BY name_en ASC");
$stmt->execute([$destination_country_id]);
$destination_cities_list = $stmt->fetchAll();
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$shipper_name = trim($_POST['shipper_name'] ?? '');
$shipper_company = trim($_POST['shipper_company'] ?? '');
// These are now selected from dropdowns, but the value is still the city name
$origin_city = trim($_POST['origin_city'] ?? '');
$destination_city = trim($_POST['destination_city'] ?? '');
$cargo_description = trim($_POST['cargo_description'] ?? '');
$weight_tons = (float)($_POST['weight_tons'] ?? 0);
$pickup_date = trim($_POST['pickup_date'] ?? '');
$delivery_date = trim($_POST['delivery_date'] ?? '');
$payment_method = trim($_POST['payment_method'] ?? 'thawani');
$status = trim($_POST['status'] ?? 'posted');
if ($shipper_name === '') $errors[] = t('error_required');
if ($origin_city === '') $errors[] = t('error_required');
if ($destination_city === '') $errors[] = t('error_required');
if (empty($errors)) {
$updateSql = "
UPDATE shipments
SET shipper_name = ?, shipper_company = ?, origin_city = ?, destination_city = ?,
cargo_description = ?, weight_tons = ?, pickup_date = ?, delivery_date = ?,
payment_method = ?, status = ?
WHERE id = ?
";
db()->prepare($updateSql)->execute([
$shipper_name, $shipper_company, $origin_city, $destination_city,
$cargo_description, $weight_tons, $pickup_date, $delivery_date,
$payment_method, $status, $id
]);
$flash = t('shipment_updated_success');
if ($isAjax) {
header('Content-Type: application/json');
echo json_encode(['success' => true, 'message' => $flash]);
exit;
}
// Refresh data
$stmt->execute([$id]);
$shipment = $stmt->fetch();
// Re-fetch derived data for the form
$origin_country_id = find_country_id_by_city_name($shipment['origin_city']);
$destination_country_id = find_country_id_by_city_name($shipment['destination_city']);
$origin_cities_list = [];
if ($origin_country_id) {
$stmt = db()->prepare("SELECT * FROM cities WHERE country_id = ? ORDER BY name_en ASC");
$stmt->execute([$origin_country_id]);
$origin_cities_list = $stmt->fetchAll();
}
$destination_cities_list = [];
if ($destination_country_id) {
$stmt = db()->prepare("SELECT * FROM cities WHERE country_id = ? ORDER BY name_en ASC");
$stmt->execute([$destination_country_id]);
$destination_cities_list = $stmt->fetchAll();
}
}
if ($isAjax && $errors) {
header('Content-Type: application/json');
echo json_encode(['success' => false, 'message' => implode('<br>', $errors)]);
exit;
}
}
// -- OUTPUT START --
if (!$isAjax):
render_header(t('edit_shipment_tooltip'), 'admin', true);
?>
<div class="row g-0">
<div class="col-md-2 bg-white border-end min-vh-100">
<?php render_admin_sidebar('shipments'); ?>
</div>
<div class="col-md-10 p-4">
<div class="d-flex align-items-center gap-3 mb-4">
<a href="admin_shipments.php" class="btn btn-light border text-secondary" title="<?= t('back') ?>">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-left" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8z"/>
</svg>
</a>
<div>
<h1 class="section-title mb-1"><?= t('edit_shipment_title') ?><?= e((string)$shipment['id']) ?></h1>
<p class="muted mb-0"><?= t('update_shipment_details') ?></p>
</div>
</div>
<?php if ($flash): ?>
<div class="alert alert-success" data-auto-dismiss="true"><?= e($flash) ?></div>
<?php endif; ?>
<?php if ($errors): ?>
<div class="alert alert-danger">
<ul class="mb-0">
<?php foreach ($errors as $error): ?>
<li><?= e($error) ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<div class="panel">
<div class="panel-heading"><?= t('shipment_details') ?></div>
<div class="p-4">
<?php endif; // End non-ajax wrapper ?>
<form method="post" action="admin_shipment_edit.php?id=<?= $id ?><?= $isAjax ? '&ajax=1' : '' ?>" class="ajax-form">
<?php if ($isAjax): ?>
<div class="modal-header">
<h5 class="modal-title"><?= t('edit_shipment_title') ?><?= e((string)$shipment['id']) ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div id="form-errors" class="alert alert-danger d-none"></div>
<?php endif; ?>
<div class="row g-3">
<div class="col-md-6">
<label class="form-label"><?= t('shipper_name') ?></label>
<input type="text" name="shipper_name" class="form-control" value="<?= e($shipment['shipper_name']) ?>" required>
</div>
<div class="col-md-6">
<label class="form-label"><?= t('shipper_company') ?></label>
<input type="text" name="shipper_company" class="form-control" value="<?= e((string)$shipment['shipper_company']) ?>">
</div>
<!-- Origin Selection -->
<div class="col-md-6">
<label class="form-label"><?= t('origin_country') ?></label>
<select class="form-select" id="origin_country">
<option value=""><?= t('select_country_placeholder') ?></option>
<?php foreach ($countries as $c): ?>
<option value="<?= e($c['id']) ?>" <?= $c['id'] == $origin_country_id ? 'selected' : '' ?>>
<?= e($c['name_en']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-6">
<label class="form-label"><?= t('origin') ?></label>
<select class="form-select" name="origin_city" id="origin_city" required>
<option value=""><?= t('select_city_placeholder') ?></option>
<!-- If shipment has a city but we couldn't match a country, preserve the value as a fallback option -->
<?php if (!$origin_country_id && $shipment['origin_city']): ?>
<option value="<?= e($shipment['origin_city']) ?>" selected><?= e($shipment['origin_city']) ?></option>
<?php endif; ?>
<?php foreach ($origin_cities_list as $city): ?>
<option value="<?= e($city['name_en']) ?>" <?= $city['name_en'] === $shipment['origin_city'] ? 'selected' : '' ?>>
<?= e($city['name_en']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<!-- Destination Selection -->
<div class="col-md-6">
<label class="form-label"><?= t('destination_country') ?></label>
<select class="form-select" id="destination_country">
<option value=""><?= t('select_country_placeholder') ?></option>
<?php foreach ($countries as $c): ?>
<option value="<?= e($c['id']) ?>" <?= $c['id'] == $destination_country_id ? 'selected' : '' ?>>
<?= e($c['name_en']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-6">
<label class="form-label"><?= t('destination') ?></label>
<select class="form-select" name="destination_city" id="destination_city" required>
<option value=""><?= t('select_city_placeholder') ?></option>
<!-- Fallback for unmapped city -->
<?php if (!$destination_country_id && $shipment['destination_city']): ?>
<option value="<?= e($shipment['destination_city']) ?>" selected><?= e($shipment['destination_city']) ?></option>
<?php endif; ?>
<?php foreach ($destination_cities_list as $city): ?>
<option value="<?= e($city['name_en']) ?>" <?= $city['name_en'] === $shipment['destination_city'] ? 'selected' : '' ?>>
<?= e($city['name_en']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-12">
<label class="form-label"><?= t('cargo') ?></label>
<input type="text" name="cargo_description" class="form-control" value="<?= e((string)$shipment['cargo_description']) ?>">
</div>
<div class="col-md-4">
<label class="form-label"><?= t('weight') ?></label>
<input type="number" step="0.1" name="weight_tons" class="form-control" value="<?= e((string)$shipment['weight_tons']) ?>">
</div>
<div class="col-md-4">
<label class="form-label"><?= t('pickup_date') ?></label>
<input type="date" name="pickup_date" class="form-control" value="<?= e((string)$shipment['pickup_date']) ?>">
</div>
<div class="col-md-4">
<label class="form-label"><?= t('delivery_date') ?></label>
<input type="date" name="delivery_date" class="form-control" value="<?= e((string)$shipment['delivery_date']) ?>">
</div>
<div class="col-md-6">
<label class="form-label"><?= t('payment_method') ?></label>
<select name="payment_method" class="form-select">
<option value="thawani" <?= $shipment['payment_method'] === 'thawani' ? 'selected' : '' ?>><?= t('payment_thawani') ?></option>
<option value="bank_transfer" <?= $shipment['payment_method'] === 'bank_transfer' ? 'selected' : '' ?>><?= t('payment_bank') ?></option>
</select>
</div>
<div class="col-md-6">
<label class="form-label"><?= t('status') ?></label>
<select name="status" class="form-select">
<option value="posted" <?= $shipment['status'] === 'posted' ? 'selected' : '' ?>><?= t('status_posted') ?></option>
<option value="offered" <?= $shipment['status'] === 'offered' ? 'selected' : '' ?>><?= t('status_offered') ?></option>
<option value="confirmed" <?= $shipment['status'] === 'confirmed' ? 'selected' : '' ?>><?= t('status_confirmed') ?></option>
<option value="in_transit" <?= $shipment['status'] === 'in_transit' ? 'selected' : '' ?>><?= t('status_in_transit') ?></option>
<option value="delivered" <?= $shipment['status'] === 'delivered' ? 'selected' : '' ?>><?= t('status_delivered') ?></option>
</select>
</div>
</div>
<?php if ($isAjax): ?>
</div> <!-- modal-body end -->
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?= t('cancel') ?></button>
<button type="submit" class="btn btn-primary"><?= t('save_changes') ?></button>
</div>
<?php else: ?>
<div class="mt-4 pt-3 border-top d-flex justify-content-end">
<button type="submit" class="btn btn-primary"><?= t('save_changes') ?></button>
</div>
<?php endif; ?>
</form>
<?php if (!$isAjax): ?>
</div>
</div>
</div>
</div>
<?php endif; ?>
<script>
(function() {
function setupCityLoader(countrySelectId, citySelectId) {
const countrySelect = document.getElementById(countrySelectId);
const citySelect = document.getElementById(citySelectId);
if (!countrySelect || !citySelect) return;
countrySelect.addEventListener('change', function() {
const countryId = this.value;
citySelect.innerHTML = '<option value=""><?= t('loading_cities') ?></option>';
citySelect.disabled = true;
if (countryId) {
fetch('api/get_cities.php?country_id=' + countryId)
.then(response => response.json())
.then(data => {
citySelect.innerHTML = '<option value=""><?= t('select_city_placeholder') ?></option>';
data.forEach(city => {
const option = document.createElement('option');
option.value = city.name_en; // Using name as value for DB compatibility
option.textContent = city.name_en;
citySelect.appendChild(option);
});
citySelect.disabled = false;
})
.catch(error => {
console.error('Error fetching cities:', error);
citySelect.innerHTML = '<option value=""><?= t('error_loading_cities') ?></option>';
});
} else {
citySelect.innerHTML = '<option value=""><?= t('select_city_placeholder') ?></option>';
citySelect.disabled = true;
}
});
}
setupCityLoader('origin_country', 'origin_city');
setupCityLoader('destination_country', 'destination_city');
})();
</script>
<?php if (!$isAjax) render_footer(); ?>