Create New Item
×
Item Type
File
Folder
Item Name
×
Search file in folder and subfolders...
File Manager
/
operator
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
<?php require_once '../includes/functions.php'; // Require login and operator access requireLogin(); if ($_SESSION['user_type'] !== 'operator') { redirect('/auth/login.php'); } $user = getCurrentUser(); $db = Database::getInstance(); $errors = []; $success = ''; // Check if operator has active session $currentSession = $db->fetch( "SELECT os.*, fl.name as from_location_name FROM operator_sessions os JOIN from_locations fl ON os.from_location_id = fl.id WHERE os.operator_id = ? AND os.status = 'active'", [$user['id']] ); if (!$currentSession) { redirect('index.php'); } // Handle status updates if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['update_status'])) { if (!validateCSRFToken($_POST['csrf_token'] ?? '')) { $errors[] = 'Invalid request. Please try again.'; } else { $bookingId = (int)($_POST['booking_id'] ?? 0); $newStatus = $_POST['new_status'] ?? ''; if (empty($bookingId) || empty($newStatus)) { $errors[] = 'Missing booking information.'; } else { try { $updateFields = ['status = ?']; $params = [$newStatus]; if ($newStatus === 'completed') { $updateFields[] = 'completion_time = NOW()'; } $sql = "UPDATE bookings SET " . implode(', ', $updateFields) . " WHERE id = ? AND operator_id = ?"; $params[] = $bookingId; $params[] = $user['id']; $db->query($sql, $params); $success = 'Booking status updated successfully!'; } catch (Exception $e) { $errors[] = 'Error updating booking: ' . $e->getMessage(); } } } } // Get filter parameters $statusFilter = $_GET['status'] ?? ''; $startDate = $_GET['start_date'] ?? ''; $endDate = $_GET['end_date'] ?? ''; // Build query for bookings $whereConditions = ['b.operator_id = ?', 'b.from_location_id = ?']; $params = [$user['id'], $currentSession['from_location_id']]; if ($statusFilter) { $whereConditions[] = 'b.status = ?'; $params[] = $statusFilter; } if ($startDate && $endDate) { $whereConditions[] = 'DATE(b.created_at) BETWEEN ? AND ?'; $params[] = $startDate; $params[] = $endDate; } elseif ($startDate) { $whereConditions[] = 'DATE(b.created_at) >= ?'; $params[] = $startDate; } elseif ($endDate) { $whereConditions[] = 'DATE(b.created_at) <= ?'; $params[] = $endDate; } $whereClause = implode(' AND ', $whereConditions); // Get bookings for current session only $bookings = $db->fetchAll( "SELECT b.*, p.name as passenger_name, p.phone as passenger_phone, tl.name as to_location_name, tl.city as to_city, ar.number_plate, ar.unique_local_id, ao.name as owner_name FROM bookings b JOIN passengers p ON b.passenger_id = p.id JOIN to_locations tl ON b.to_location_id = tl.id LEFT JOIN auto_rickshaws ar ON b.auto_rickshaw_id = ar.id LEFT JOIN auto_owners ao ON ar.owner_id = ao.id WHERE $whereClause ORDER BY b.created_at DESC", $params ); // Get status counts for current session only $statusCounts = $db->fetchAll( "SELECT status, COUNT(*) as count FROM bookings WHERE operator_id = ? AND from_location_id = ? GROUP BY status", [$user['id'], $currentSession['from_location_id']] ); $statusStats = []; foreach ($statusCounts as $stat) { $statusStats[$stat['status']] = $stat['count']; } $pageTitle = 'Manage Bookings'; require_once '../includes/header.php'; ?> <div class="container py-4"> <!-- Header --> <div class="row mb-4"> <div class="col-12"> <div class="card"> <div class="card-body"> <h2 class="card-title mb-2">Manage Bookings</h2> <p class="card-text text-muted"> Current Location: <?php echo htmlspecialchars($currentSession['from_location_name'] ?? 'Location not set'); ?> </p> </div> </div> </div> </div> <?php if (!empty($errors)): ?> <div class="alert alert-danger"> <ul class="mb-0"> <?php foreach ($errors as $error): ?> <li><?php echo htmlspecialchars($error); ?></li> <?php endforeach; ?> </ul> </div> <?php endif; ?> <?php if ($success): ?> <div class="alert alert-success"> <?php echo htmlspecialchars($success); ?> </div> <?php endif; ?> <!-- Status Statistics --> <div class="row mb-4"> <div class="col-md-3"> <div class="card text-center"> <div class="card-body"> <h3 class="card-title text-primary"><?php echo $statusStats['confirmed'] ?? 0; ?></h3> <p class="card-text text-muted">Confirmed</p> </div> </div> </div> <div class="col-md-3"> <div class="card text-center"> <div class="card-body"> <h3 class="card-title text-info"><?php echo $statusStats['in_progress'] ?? 0; ?></h3> <p class="card-text text-muted">In Progress</p> </div> </div> </div> <div class="col-md-3"> <div class="card text-center"> <div class="card-body"> <h3 class="card-title text-success"><?php echo $statusStats['completed'] ?? 0; ?></h3> <p class="card-text text-muted">Completed</p> </div> </div> </div> <div class="col-md-3"> <div class="card text-center"> <div class="card-body"> <h3 class="card-title text-warning"><?php echo $statusStats['cancelled'] ?? 0; ?></h3> <p class="card-text text-muted">Cancelled</p> </div> </div> </div> </div> <!-- Filters --> <div class="row mb-4"> <div class="col-12"> <div class="card"> <div class="card-body"> <form method="GET" action="" class="row g-3"> <div class="col-md-4"> <label for="status" class="form-label">Status Filter</label> <select class="form-select" id="status" name="status"> <option value="">All Statuses</option> <option value="confirmed" <?php echo $statusFilter === 'confirmed' ? 'selected' : ''; ?>>Confirmed</option> <option value="in_progress" <?php echo $statusFilter === 'in_progress' ? 'selected' : ''; ?>>In Progress</option> <option value="completed" <?php echo $statusFilter === 'completed' ? 'selected' : ''; ?>>Completed</option> <option value="cancelled" <?php echo $statusFilter === 'cancelled' ? 'selected' : ''; ?>>Cancelled</option> </select> </div> <div class="col-md-6"> <label class="form-label">Date Range</label> <div class="input-group"> <input type="date" class="form-control" id="start_date" name="start_date" value="<?php echo htmlspecialchars($startDate); ?>" placeholder="From"> <span class="input-group-text">to</span> <input type="date" class="form-control" id="end_date" name="end_date" value="<?php echo htmlspecialchars($endDate); ?>" placeholder="To"> </div> </div> <div class="col-md-2"> <label class="form-label"> </label> <div class="d-grid"> <button type="submit" class="btn btn-primary"> <i class="bi bi-funnel"></i> Apply Filters </button> </div> </div> </form> </div> </div> </div> </div> <!-- Bookings Table --> <div class="row"> <div class="col-12"> <div class="card"> <div class="card-header d-flex justify-content-between align-items-center"> <h5 class="card-title mb-0"> <i class="bi bi-list-check"></i> Bookings (<?php echo count($bookings); ?>) </h5> <a href="index.php" class="btn btn-outline-secondary btn-sm"> <i class="bi bi-arrow-left"></i> Back to Dashboard </a> </div> <div class="card-body"> <?php if (empty($bookings)): ?> <div class="text-center text-muted py-4"> <i class="bi bi-inbox" style="font-size: 3rem;"></i> <p class="mt-2">No bookings found for the selected filters.</p> </div> <?php else: ?> <div class="table-responsive"> <table class="table table-hover"> <thead> <tr> <th>Booking ID</th> <th>Passenger</th> <th>Destination</th> <th>Auto Rickshaw</th> <th>Amount</th> <th>Status</th> <th>Time</th> <th>Actions</th> </tr> </thead> <tbody> <?php foreach ($bookings as $booking): ?> <tr> <td> <strong>#<?php echo $booking['id']; ?></strong> <br><small class="text-muted"><?php echo ucfirst($booking['booking_type']); ?></small> </td> <td> <?php echo htmlspecialchars($booking['passenger_name']); ?> <br><small class="text-muted"><?php echo $booking['passenger_phone']; ?></small> </td> <td> <?php echo htmlspecialchars($booking['to_location_name']); ?> <br><small class="text-muted"><?php echo $booking['to_city']; ?></small> </td> <td> <?php if ($booking['auto_rickshaw_id']): ?> <?php echo htmlspecialchars($booking['number_plate']); ?> <br><small class="text-muted"><?php echo $booking['owner_name']; ?></small> <?php else: ?> <span class="text-muted">Not assigned</span> <?php endif; ?> </td> <td> <strong>₹<?php echo number_format($booking['total_amount'], 2); ?></strong> <br><small class="text-muted">Fare: ₹<?php echo number_format($booking['fare_amount'], 2); ?></small> </td> <td> <?php $statusClass = [ 'confirmed' => 'bg-warning', 'in_progress' => 'bg-info', 'completed' => 'bg-success', 'cancelled' => 'bg-danger' ]; $statusText = [ 'confirmed' => 'Confirmed', 'in_progress' => 'In Progress', 'completed' => 'Completed', 'cancelled' => 'Cancelled' ]; ?> <span class="badge <?php echo $statusClass[$booking['status']] ?? 'bg-secondary'; ?>"> <?php echo $statusText[$booking['status']] ?? ucfirst($booking['status']); ?> </span> </td> <td> <?php echo date('H:i', strtotime($booking['created_at'])); ?> <br><small class="text-muted"><?php echo date('M d', strtotime($booking['created_at'])); ?></small> </td> <td> <div class="btn-group btn-group-sm"> <!-- View Booking Button (Always visible) --> <button type="button" class="btn btn-outline-primary btn-sm" onclick="viewBooking(<?php echo $booking['id']; ?>)"> <i class="bi bi-eye"></i> View </button> <?php if ($booking['status'] !== 'completed' && $booking['status'] !== 'cancelled'): ?> <?php if ($booking['status'] === 'confirmed'): ?> <button type="button" class="btn btn-info btn-sm" onclick="updateStatus(<?php echo $booking['id']; ?>, 'in_progress')"> Start Trip </button> <?php elseif ($booking['status'] === 'in_progress'): ?> <button type="button" class="btn btn-success btn-sm" onclick="updateStatus(<?php echo $booking['id']; ?>, 'completed')"> Complete </button> <?php endif; ?> <button type="button" class="btn btn-danger btn-sm" onclick="updateStatus(<?php echo $booking['id']; ?>, 'cancelled')"> Cancel </button> <?php endif; ?> </div> </td> </tr> <?php endforeach; ?> </tbody> </table> </div> <?php endif; ?> </div> </div> </div> </div> </div> <!-- Status Update Form (Hidden) --> <form id="statusUpdateForm" method="POST" action="" style="display: none;"> <input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>"> <input type="hidden" name="update_status" value="1"> <input type="hidden" name="booking_id" id="updateBookingId"> <input type="hidden" name="new_status" id="updateNewStatus"> </form> <!-- View Booking Modal --> <div class="modal fade" id="viewBookingModal" tabindex="-1" aria-labelledby="viewBookingModalLabel" aria-hidden="true"> <div class="modal-dialog modal-lg"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="viewBookingModalLabel"> <i class="bi bi-eye"></i> Booking Details </h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body" id="viewBookingModalBody"> <!-- Content will be loaded here --> <div class="text-center"> <div class="spinner-border" role="status"> <span class="visually-hidden">Loading...</span> </div> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button> <!-- Print Receipt Button - Only show when status is NOT cancelled --> <button type="button" class="btn btn-primary" id="printBookingReceiptBtn" style="display: none;"> <i class="bi bi-printer"></i> Print Receipt </button> </div> </div> </div> </div> <script> function updateStatus(bookingId, newStatus) { if (confirm('Are you sure you want to update this booking status?')) { document.getElementById('updateBookingId').value = bookingId; document.getElementById('updateNewStatus').value = newStatus; document.getElementById('statusUpdateForm').submit(); } } function viewBooking(bookingId) { // Show the modal const modal = new bootstrap.Modal(document.getElementById('viewBookingModal')); modal.show(); // Load booking details via AJAX loadBookingDetails(bookingId); } function loadBookingDetails(bookingId) { const modalBody = document.getElementById('viewBookingModalBody'); const printBtn = document.getElementById('printBookingReceiptBtn'); // Show loading spinner modalBody.innerHTML = ` <div class="text-center"> <div class="spinner-border" role="status"> <span class="visually-hidden">Loading...</span> </div> </div> `; // Fetch booking details fetch(`get_booking_details.php?booking_id=${bookingId}`) .then(response => response.json()) .then(data => { if (data.success) { displayBookingDetails(data.booking); // Set print button functionality for all bookings printBtn.onclick = () => printBookingReceipt(data.booking); } else { modalBody.innerHTML = ` <div class="alert alert-danger"> <i class="bi bi-exclamation-triangle"></i> ${data.message} </div> `; } }) .catch(error => { console.error('Error:', error); modalBody.innerHTML = ` <div class="alert alert-danger"> <i class="bi bi-exclamation-triangle"></i> Error loading booking details </div> `; }); } function displayBookingDetails(booking) { const modalBody = document.getElementById('viewBookingModalBody'); const printBtn = document.getElementById('printBookingReceiptBtn'); const statusClass = { 'confirmed': 'bg-warning', 'in_progress': 'bg-info', 'completed': 'bg-success', 'cancelled': 'bg-danger' }; const statusText = { 'confirmed': 'Confirmed', 'in_progress': 'In Progress', 'completed': 'Completed', 'cancelled': 'Cancelled' }; // Show/hide print button based on status if (booking.status === 'cancelled') { printBtn.style.display = 'none'; } else { printBtn.style.display = 'inline-block'; } modalBody.innerHTML = ` <div class="row"> <div class="col-md-6"> <div class="card mb-3"> <div class="card-header"> <h6 class="card-title mb-0"> <i class="bi bi-person"></i> Passenger Information </h6> </div> <div class="card-body"> <p><strong>Name:</strong> ${booking.passenger_name}</p> <p><strong>Phone:</strong> ${booking.passenger_phone}</p> <p><strong>Booking ID:</strong> #${booking.id}</p> <p><strong>Booking Type:</strong> ${booking.booking_type}</p> <p><strong>Created:</strong> ${new Date(booking.created_at).toLocaleString()}</p> </div> </div> </div> <div class="col-md-6"> <div class="card mb-3"> <div class="card-header"> <h6 class="card-title mb-0"> <i class="bi bi-geo-alt"></i> Location Details </h6> </div> <div class="card-body"> <p><strong>From:</strong> ${booking.from_location_name || 'Not set'}</p> <p><strong>To:</strong> ${booking.to_location_name}</p> <p><strong>City:</strong> ${booking.to_city}</p> </div> </div> </div> </div> <div class="row"> <div class="col-md-6"> <div class="card mb-3"> <div class="card-header"> <h6 class="card-title mb-0"> <i class="bi bi-truck"></i> Auto Rickshaw Details </h6> </div> <div class="card-body"> ${booking.auto_rickshaw_id ? ` <p><strong>Number Plate:</strong> ${booking.number_plate}</p> <p><strong>Owner:</strong> ${booking.owner_name}</p> <p><strong>ID:</strong> ${booking.unique_local_id}</p> ` : '<p class="text-muted">Not assigned yet</p>'} </div> </div> </div> <div class="col-md-6"> <div class="card mb-3"> <div class="card-header"> <h6 class="card-title mb-0"> <i class="bi bi-currency-exchange"></i> Payment Details </h6> </div> <div class="card-body"> <p><strong>Commission Amount:</strong> ₹${parseFloat(booking.commission_amount).toFixed(2)}</p> <p><strong>Fare Amount:</strong> ₹${parseFloat(booking.fare_amount).toFixed(2)}</p> <p><strong>Total Amount:</strong> ₹${parseFloat(booking.total_amount).toFixed(2)}</p> <p><strong>Status:</strong> <span class="badge ${statusClass[booking.status]}">${statusText[booking.status]}</span> </p> </div> </div> </div> </div> ${booking.confirmation_time ? ` <div class="row"> <div class="col-12"> <div class="card mb-3"> <div class="card-header"> <h6 class="card-title mb-0"> <i class="bi bi-clock"></i> Trip Timeline </h6> </div> <div class="card-body"> <p><strong>Confirmed At:</strong> ${new Date(booking.confirmation_time).toLocaleString()}</p> ${booking.completion_time ? `<p><strong>Completed At:</strong> ${new Date(booking.completion_time).toLocaleString()}</p>` : ''} </div> </div> </div> </div> ` : ''} `; } function printBookingReceipt(booking) { // Create a new window for printing const printWindow = window.open('', '_blank'); // Define status text mapping const statusText = { 'confirmed': 'Confirmed', 'in_progress': 'In Progress', 'completed': 'Completed', 'cancelled': 'Cancelled' }; const receiptContent = ` <!DOCTYPE html> <html> <head> <title>Receipt #${booking.id}</title> <style> @media print { body { margin: 0; padding: 0; } .receipt { border: none; box-shadow: none; } } body { font-family: 'Courier New', monospace; margin: 5px; font-size: 10px; line-height: 1.2; } .receipt { max-width: 300px; margin: 0 auto; border: 1px solid #000; padding: 8px; } .header { text-align: center; border-bottom: 1px solid #000; padding-bottom: 5px; margin-bottom: 8px; } .header h3 { margin: 0 0 2px 0; font-size: 12px; font-weight: bold; } .header p { margin: 1px 0; font-size: 9px; } .row { border-bottom: 1px solid #ccc; padding: 3px 0; font-size: 9px; } .total { border-top: 1px solid #000; padding-top: 5px; margin-top: 8px; font-weight: bold; } .footer { text-align: center; margin-top: 8px; padding-top: 5px; border-top: 1px solid #ccc; font-size: 8px; } .footer p { margin: 1px 0; } </style> </head> <body> <div class="receipt"> <div class="header"> <h3>AUTO RICKSHAW SERVICE</h3> <p>Booking Receipt</p> <p>Date: ${new Date().toLocaleDateString()} ${new Date().toLocaleTimeString()}</p> </div> <div class="row"> <strong>Passenger:</strong> ${booking.passenger_name} </div> <div class="row"> <strong>From:</strong> ${booking.from_location_name || 'Not set'} </div> <div class="row"> <strong>To:</strong> ${booking.to_location_name} </div> ${booking.auto_rickshaw_id ? ` <div class="row"> <strong>Rickshaw:</strong> ${booking.number_plate} </div> <div class="row"> <strong>Driver:</strong> ${booking.owner_name} </div> ` : ''} <div class="total"> <div style="display: flex; justify-content: space-between; margin-bottom: 3px;"> <span>Commission:</span> <span>₹${parseFloat(booking.commission_amount).toFixed(2)}</span> </div> <div style="display: flex; justify-content: space-between; margin-bottom: 3px;"> <span>Fare:</span> <span>₹${parseFloat(booking.fare_amount).toFixed(2)}</span> </div> <div style="display: flex; justify-content: space-between; font-weight: bold; font-size: 16px; margin-top: 8px; padding-top: 8px; border-top: 2px solid #000;"> <span>Total:</span> <span>₹${parseFloat(booking.fare_amount).toFixed(2)}</span> </div> </div> <div class="footer"> <p>Thank you for using our service!</p> <p>Status: ${statusText[booking.status]}</p> </div> </div> </body> </html> `; printWindow.document.write(receiptContent); printWindow.document.close(); // Wait for content to load then print printWindow.onload = function() { printWindow.print(); printWindow.close(); }; } </script> <?php require_once '../includes/footer.php'; ?>