PNG IHDR x sBIT|d pHYs + tEXtSoftware www.inkscape.org< ,tEXtComment
<?php
session_start();
require_once '../config/database.php';
if (!isset($_SESSION['admin_logged_in'])) header("Location: login.php");
$db = (new Database())->getConnection();
$id = $_GET['id'] ?? 0;
$msg = '';
// 1. Fetch Data First (We need this to know the existing image before updating)
$stmt = $db->prepare("SELECT * FROM shipments WHERE id = :id");
$stmt->execute([':id' => $id]);
$shipment = $stmt->fetch(PDO::FETCH_ASSOC);
if(!$shipment) die("Shipment not found");
// Handle Updates
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if (isset($_POST['update_main'])) {
// --- IMAGE UPLOAD LOGIC START ---
$current_image_path = $shipment['image_path'];
// Check if a file was uploaded without errors
if (isset($_FILES['tracking_image']) && $_FILES['tracking_image']['error'] == 0) {
$allowed = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
$filename = $_FILES['tracking_image']['name'];
$filetype = pathinfo($filename, PATHINFO_EXTENSION);
if (in_array(strtolower($filetype), $allowed)) {
// Create unique filename: shipment_ID_TIMESTAMP.ext
$new_filename = 'shipment_' . $id . '_' . time() . '.' . $filetype;
$target_dir = "../uploads/";
// Create folder if it doesn't exist
if (!is_dir($target_dir)) {
mkdir($target_dir, 0777, true);
}
$target_file = $target_dir . $new_filename;
// Move file
if (move_uploaded_file($_FILES['tracking_image']['tmp_name'], $target_file)) {
// Remove old image if it exists to save space
if ($shipment['image_path'] && file_exists("../" . $shipment['image_path'])) {
unlink("../" . $shipment['image_path']);
}
// Save the path relative to the public folder
$current_image_path = "uploads/" . $new_filename;
}
} else {
$msg = "Error: Invalid image format. Only JPG, PNG, GIF allowed.";
}
}
// --- IMAGE UPLOAD LOGIC END ---
$sql = "UPDATE shipments SET
current_location_name = :loc, current_lat = :lat, current_lng = :lng,
current_status = :status, status_details = :details,
payment_required = :pay, payment_amount = :amt,
image_path = :img
WHERE id = :id";
$stmt = $db->prepare($sql);
$stmt->execute([
':loc' => $_POST['loc_name'], ':lat' => $_POST['lat'], ':lng' => $_POST['lng'],
':status' => $_POST['status'], ':details' => $_POST['details'],
':pay' => isset($_POST['pay_req']) ? 1 : 0, ':amt' => $_POST['pay_amt'],
':img' => $current_image_path,
':id' => $id
]);
// Refresh data to show changes immediately
$stmt = $db->prepare("SELECT * FROM shipments WHERE id = :id");
$stmt->execute([':id' => $id]);
$shipment = $stmt->fetch(PDO::FETCH_ASSOC);
$msg = "Main details & image updated successfully.";
}
if (isset($_POST['add_history'])) {
$sql = "INSERT INTO shipment_history (shipment_id, status, description, location, icon, color, date)
VALUES (:id, :st, :desc, :loc, :icon, :col, NOW())";
$stmt = $db->prepare($sql);
$stmt->execute([
':id' => $id, ':st' => $_POST['hist_status'], ':desc' => $_POST['hist_desc'],
':loc' => $_POST['hist_loc'], ':icon' => $_POST['hist_icon'], ':col' => $_POST['hist_color']
]);
$msg = "New timeline event added.";
}
}
$histStmt = $db->prepare("SELECT * FROM shipment_history WHERE shipment_id = :id ORDER BY date DESC");
$histStmt->execute([':id' => $id]);
$history = $histStmt->fetchAll(PDO::FETCH_ASSOC);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Edit Shipment | Admin Panel</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/lucide@latest"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<style>
body { font-family: 'Inter', sans-serif; }
/* Hide scrollbar for Chrome, Safari and Opera */
.no-scrollbar::-webkit-scrollbar { display: none; }
/* Hide scrollbar for IE, Edge and Firefox */
.no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
</style>
</head>
<body class="bg-gray-50 text-gray-800 flex h-screen overflow-hidden">
<aside class="w-64 bg-gray-900 text-white flex-col hidden md:flex flex-shrink-0 transition-all duration-300">
<div class="p-6 border-b border-gray-800 flex items-center gap-3">
<div class="w-8 h-8 bg-blue-600 rounded-lg flex items-center justify-center font-bold">F</div>
<span class="text-lg font-bold tracking-wide">titanwaveexpressservice</span>
</div>
<nav class="flex-1 p-4 space-y-1 overflow-y-auto">
<p class="px-4 text-xs font-semibold text-gray-500 uppercase tracking-wider mb-2 mt-2">Menu</p>
<a href="index.php" class="flex items-center gap-3 px-4 py-2.5 text-gray-400 hover:bg-gray-800 hover:text-white rounded-lg transition-colors group">
<i data-lucide="layout-dashboard" class="w-5 h-5 group-hover:text-blue-400 transition-colors"></i> Dashboard
</a>
<a href="shipments.php" class="flex items-center gap-3 px-4 py-2.5 bg-blue-600 text-white rounded-lg shadow-md">
<i data-lucide="package" class="w-5 h-5"></i> Shipments
</a>
<a href="settings.php" class="flex items-center gap-3 px-4 py-2.5 text-gray-400 hover:bg-gray-800 hover:text-white rounded-lg transition-colors group">
<i data-lucide="settings" class="w-5 h-5 group-hover:text-blue-400 transition-colors"></i> Settings
</a>
</nav>
<div class="p-4 border-t border-gray-800">
<a href="logout.php" class="flex items-center gap-3 px-4 py-2 text-red-400 hover:bg-gray-800 hover:text-red-300 rounded-lg transition-colors text-sm font-medium">
<i data-lucide="log-out" class="w-4 h-4"></i> Sign Out
</a>
</div>
</aside>
<main class="flex-1 flex flex-col h-full overflow-hidden bg-gray-50">
<header class="bg-white border-b border-gray-200 h-16 flex items-center justify-between px-4 md:px-8 shadow-sm z-10">
<div class="flex items-center gap-4">
<a href="shipments.php" class="p-2 rounded-full hover:bg-gray-100 text-gray-500 transition-colors md:hidden">
<i data-lucide="arrow-left" class="w-5 h-5"></i>
</a>
<div>
<h1 class="text-lg font-bold text-gray-900">Edit Shipment</h1>
<p class="text-xs text-gray-500 hidden md:block">Updating Tracking ID: <span class="font-mono text-blue-600"><?php echo $shipment['tracking_number']; ?></span></p>
</div>
</div>
<div class="flex items-center gap-3">
<a href="../public/tracking.php?id=<?php echo $shipment['tracking_number']; ?>" target="_blank" class="hidden sm:flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors">
<i data-lucide="external-link" class="w-4 h-4"></i> View Live
</a>
<a href="shipments.php" class="flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-gray-600 hover:text-gray-900 transition-colors">
<span class="hidden sm:inline">Back to List</span> <i data-lucide="x" class="w-5 h-5"></i>
</a>
</div>
</header>
<div class="flex-1 overflow-y-auto p-4 md:p-8">
<div class="max-w-6xl mx-auto">
<?php if($msg): ?>
<div class="mb-6 flex items-center gap-3 bg-green-50 border border-green-200 text-green-700 px-4 py-3 rounded-lg shadow-sm animate-fade-in">
<div class="bg-green-100 p-1 rounded-full"><i data-lucide="check" class="w-4 h-4"></i></div>
<p class="text-sm font-medium"><?php echo $msg; ?></p>
</div>
<?php endif; ?>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
<div class="lg:col-span-2 space-y-8">
<div class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
<div class="px-6 py-4 border-b border-gray-100 flex justify-between items-center bg-gray-50/50">
<h2 class="font-semibold text-gray-900 flex items-center gap-2">
<i data-lucide="edit-3" class="w-4 h-4 text-blue-500"></i> Status & Location
</h2>
</div>
<form method="POST" enctype="multipart/form-data" class="p-6 space-y-6">
<input type="hidden" name="update_main" value="1">
<div class="bg-gray-50 border border-gray-200 rounded-lg p-4">
<label class="block text-sm font-medium text-gray-700 mb-3">Package Image</label>
<div class="flex items-start gap-5">
<div class="w-24 h-24 rounded-lg border border-gray-300 bg-white flex items-center justify-center overflow-hidden flex-shrink-0 relative group">
<?php if(!empty($shipment['image_path'])): ?>
<img src="../<?php echo $shipment['image_path']; ?>" alt="Package" class="w-full h-full object-cover">
<?php else: ?>
<i data-lucide="image" class="w-8 h-8 text-gray-300"></i>
<?php endif; ?>
</div>
<div class="flex-1">
<input type="file" name="tracking_image" accept="image/*" class="block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-xs file:font-semibold file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100 mb-2 cursor-pointer">
<p class="text-xs text-gray-500">Upload a photo of the package to show on tracking page. Max 2MB.</p>
</div>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1.5">Current Status</label>
<div class="relative">
<select name="status" class="w-full pl-10 pr-4 py-2.5 bg-gray-50 border border-gray-200 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none appearance-none cursor-pointer">
<option value="Pending" <?php echo $shipment['current_status']=='Pending'?'selected':''; ?>>Pending</option>
<option value="Picked Up" <?php echo $shipment['current_status']=='Picked Up'?'selected':''; ?>>Picked Up</option>
<option value="In Transit" <?php echo $shipment['current_status']=='In Transit'?'selected':''; ?>>In Transit</option>
<option value="On Hold" <?php echo $shipment['current_status']=='On Hold'?'selected':''; ?>>On Hold</option>
<option value="Delivered" <?php echo $shipment['current_status']=='Delivered'?'selected':''; ?>>Delivered</option>
</select>
<i data-lucide="tag" class="w-4 h-4 text-gray-400 absolute left-3 top-3"></i>
<i data-lucide="chevron-down" class="w-4 h-4 text-gray-400 absolute right-3 top-3 pointer-events-none"></i>
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1.5">Status Description</label>
<input type="text" name="details" value="<?php echo htmlspecialchars($shipment['status_details']); ?>" class="w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 outline-none">
</div>
</div>
<div class="p-5 rounded-lg border border-blue-100 bg-blue-50/30 space-y-4">
<div class="flex items-center justify-between">
<label class="text-sm font-bold text-blue-800 flex items-center gap-2">
<i data-lucide="map-pin" class="w-4 h-4"></i> Current Location (Map)
</label>
<a href="https://www.latlong.net/" target="_blank" class="text-xs text-blue-600 hover:underline">Find Coords</a>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<div class="md:col-span-3">
<input type="text" name="loc_name" value="<?php echo htmlspecialchars($shipment['current_location_name']); ?>" class="w-full px-3 py-2 bg-white border border-blue-200 rounded-lg text-sm focus:border-blue-500 outline-none" placeholder="City, Country">
</div>
<div>
<input type="text" name="lat" value="<?php echo htmlspecialchars($shipment['current_lat']); ?>" class="w-full px-3 py-2 bg-white border border-blue-200 rounded-lg text-sm font-mono" placeholder="Latitude">
</div>
<div>
<input type="text" name="lng" value="<?php echo htmlspecialchars($shipment['current_lng']); ?>" class="w-full px-3 py-2 bg-white border border-blue-200 rounded-lg text-sm font-mono" placeholder="Longitude">
</div>
</div>
</div>
<div class="flex items-center justify-between p-4 rounded-lg border border-gray-200 bg-gray-50">
<div class="flex items-center gap-3">
<div class="p-2 bg-white border border-gray-200 rounded-md">
<i data-lucide="credit-card" class="w-5 h-5 text-gray-500"></i>
</div>
<div>
<label for="pay" class="block text-sm font-medium text-gray-900">Require Payment</label>
<p class="text-xs text-gray-500">Does the customer need to pay fees?</p>
</div>
</div>
<div class="flex items-center gap-3">
<input type="checkbox" name="pay_req" id="pay" class="w-5 h-5 text-blue-600 rounded border-gray-300 focus:ring-blue-500" <?php echo $shipment['payment_required']?'checked':''; ?>>
<input type="text" name="pay_amt" value="<?php echo htmlspecialchars($shipment['payment_amount']); ?>" class="w-24 px-2 py-1 border border-gray-300 rounded text-sm text-right" placeholder="0.00">
</div>
</div>
<div class="flex justify-end pt-2">
<button type="submit" class="bg-blue-600 text-white px-6 py-2.5 rounded-lg font-medium hover:bg-blue-700 shadow-lg shadow-blue-600/20 transition-all flex items-center gap-2">
<i data-lucide="save" class="w-4 h-4"></i> Save Changes
</button>
</div>
</form>
</div>
<div class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
<div class="px-6 py-4 border-b border-gray-100 bg-gray-50/50">
<h2 class="font-semibold text-gray-900 flex items-center gap-2">
<i data-lucide="history" class="w-4 h-4 text-gray-500"></i> Shipment History
</h2>
</div>
<div class="p-6">
<div class="space-y-0 relative">
<?php if (count($history) > 0): ?>
<div class="absolute top-2 bottom-2 left-[19px] w-0.5 bg-gray-100"></div>
<?php foreach($history as $h): ?>
<div class="relative flex gap-6 pb-8 last:pb-0 group">
<div class="relative z-10 w-10 h-10 rounded-full bg-white border-2 border-<?php echo $h['color']; ?>-100 flex items-center justify-center shrink-0 shadow-sm">
<div class="w-2.5 h-2.5 rounded-full bg-<?php echo $h['color']; ?>-500"></div>
</div>
<div class="flex-1 pt-1">
<div class="flex flex-wrap justify-between items-start gap-2 mb-1">
<h4 class="text-sm font-bold text-gray-900"><?php echo htmlspecialchars($h['status']); ?></h4>
<span class="text-xs text-gray-400 font-mono bg-gray-50 px-2 py-0.5 rounded"><?php echo date('M d, H:i', strtotime($h['date'])); ?></span>
</div>
<p class="text-sm text-gray-600 mb-2 leading-relaxed"><?php echo htmlspecialchars($h['description']); ?></p>
<div class="inline-flex items-center gap-1.5 text-xs text-gray-500 bg-gray-50 px-2 py-1 rounded border border-gray-100">
<i data-lucide="map-pin" class="w-3 h-3 text-gray-400"></i> <?php echo htmlspecialchars($h['location']); ?>
</div>
</div>
</div>
<?php endforeach; ?>
<?php else: ?>
<div class="text-center py-8 text-gray-400">
<i data-lucide="calendar-off" class="w-8 h-8 mx-auto mb-2 opacity-50"></i>
<p class="text-sm">No history events recorded yet.</p>
</div>
<?php endif; ?>
</div>
</div>
</div>
</div>
<div class="lg:col-span-1">
<div class="sticky top-6 space-y-6">
<form method="POST" class="bg-white rounded-xl shadow-lg border border-gray-200 overflow-hidden">
<input type="hidden" name="add_history" value="1">
<div class="px-5 py-4 border-b border-gray-100 bg-gray-900 text-white flex justify-between items-center">
<h2 class="font-bold text-sm">New Event</h2>
<i data-lucide="plus-circle" class="w-4 h-4 text-gray-400"></i>
</div>
<div class="p-5 space-y-4">
<div>
<label class="block text-xs font-bold text-gray-500 uppercase mb-1">Event Title</label>
<input type="text" name="hist_status" placeholder="e.g. Cleared Customs" class="w-full p-2 border border-gray-200 rounded-lg text-sm focus:border-blue-500 outline-none transition-colors" required>
</div>
<div>
<label class="block text-xs font-bold text-gray-500 uppercase mb-1">Description</label>
<textarea name="hist_desc" placeholder="Brief details..." rows="2" class="w-full p-2 border border-gray-200 rounded-lg text-sm focus:border-blue-500 outline-none transition-colors resize-none"></textarea>
</div>
<div>
<label class="block text-xs font-bold text-gray-500 uppercase mb-1">Location</label>
<div class="relative">
<input type="text" name="hist_loc" value="<?php echo htmlspecialchars($shipment['current_location_name']); ?>" class="w-full pl-8 pr-2 py-2 border border-gray-200 rounded-lg text-sm focus:border-blue-500 outline-none">
<i data-lucide="map-pin" class="w-4 h-4 text-gray-400 absolute left-2.5 top-2.5"></i>
</div>
</div>
<div class="grid grid-cols-2 gap-3">
<div>
<label class="block text-xs font-bold text-gray-500 uppercase mb-1">Icon</label>
<select name="hist_icon" class="w-full p-2 border border-gray-200 rounded-lg text-sm bg-white">
<option value="truck">Truck</option>
<option value="check">Check</option>
<option value="info">Info</option>
<option value="alert">Alert</option>
<option value="box">Box</option>
</select>
</div>
<div>
<label class="block text-xs font-bold text-gray-500 uppercase mb-1">Color</label>
<select name="hist_color" class="w-full p-2 border border-gray-200 rounded-lg text-sm bg-white">
<option value="blue">Blue</option>
<option value="green">Green</option>
<option value="yellow">Yellow</option>
<option value="red">Red</option>
</select>
</div>
</div>
<button type="submit" class="w-full bg-gray-900 text-white py-2.5 rounded-lg font-bold text-sm hover:bg-black transition-transform active:scale-[0.98] shadow-md">
Add Timeline Entry
</button>
</div>
</form>
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-5">
<p class="text-xs font-bold text-gray-400 uppercase mb-3">Quick Actions</p>
<div class="space-y-2">
<button onclick="copyLink()" class="w-full text-left text-sm text-gray-600 hover:text-blue-600 flex items-center gap-2 p-2 hover:bg-blue-50 rounded transition-colors">
<i data-lucide="link" class="w-4 h-4"></i> Copy Tracking Link
</button>
<a href="shipments.php" class="w-full text-left text-sm text-gray-600 hover:text-gray-900 flex items-center gap-2 p-2 hover:bg-gray-50 rounded transition-colors">
<i data-lucide="list" class="w-4 h-4"></i> View All Shipments
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
<script>
lucide.createIcons();
function copyLink() {
const url = window.location.origin + '/public/tracking.php?id=<?php echo $shipment['tracking_number']; ?>';
navigator.clipboard.writeText(url);
alert('Link copied to clipboard!');
}
</script>
</body>
</html>
b IDATxytVսϓ22 A@IR:hCiZ[v*E:WũZA ^dQeQ @ !jZ'>gsV仿$|?g)&x-E