'Session expired. Please reload and log in again.']); exit; } if ($isAjax) { header('Content-Type: application/json'); $action = $_POST['action'] ?? $_GET['action'] ?? ''; if ($action === 'update_status') { $id = (int)($_POST['id'] ?? 0); $status = $_POST['status'] ?? ''; $allowed = ['pending','confirmed','completed','cancelled']; if ($id && in_array($status, $allowed)) { db()->prepare("UPDATE bookings SET status=? WHERE id=?")->execute([$status, $id]); echo json_encode(['ok'=>true]); } else { echo json_encode(['error'=>'Invalid']); } exit; } if ($action === 'save_admin_notes') { $id = (int)($_POST['id'] ?? 0); $notes = substr(trim($_POST['notes'] ?? ''), 0, 1000); db()->prepare("UPDATE bookings SET admin_notes=? WHERE id=?")->execute([$notes, $id]); echo json_encode(['ok'=>true]); exit; } if ($action === 'toggle_requirement') { $id = (int)($_POST['id'] ?? 0); $field = $_POST['field'] ?? ''; $allowed_fields = ['insurance_verified','deposit_received','license_verified']; if ($id && in_array($field, $allowed_fields)) { $stmt = db()->prepare("SELECT `{$field}` FROM bookings WHERE id=?"); $stmt->execute([$id]); $current = (int)$stmt->fetchColumn(); $new = $current ? 0 : 1; db()->prepare("UPDATE bookings SET `{$field}`=? WHERE id=?")->execute([$new, $id]); echo json_encode(['ok'=>true,'value'=>$new]); } else { echo json_encode(['error'=>'Invalid']); } exit; } if ($action === 'send_reminder') { $id = (int)($_POST['id'] ?? 0); $keys = array_filter(explode(',', $_POST['items'] ?? '')); $stmt = db()->prepare("SELECT * FROM bookings WHERE id=?"); $stmt->execute([$id]); $b = $stmt->fetch(); if (!$b) { echo json_encode(['error'=>'Not found']); exit; } $pkg = PACKAGES[$b['package']] ?? ['label' => $b['package']]; $dateLabel = date('F j, Y', strtotime($b['rental_date'])); $ref = $b['booking_ref']; $itemDefs = [ 'waiver' => [ 'label' => 'Sign Your Rental Agreement', 'detail' => 'Your digital rental agreement still needs to be signed before your pickup. It only takes a minute and can be done on any device — no printer required.', 'cta' => "
Sign Agreement →
", ], 'insurance' => [ 'label' => 'Proof of Personal Auto Insurance', 'detail' => 'You\'ll need to bring proof of valid personal auto insurance to pickup. A photo on your phone of your insurance card is fine. This is required before we can hand over the keys.', 'cta' => '', ], 'deposit' => [ 'label' => 'Security Deposit', 'detail' => 'A refundable security deposit is required at the time of pickup. Please have it ready — cash or card accepted. It will be returned in full upon safe return of the vehicle.', 'cta' => '', ], 'license' => [ 'label' => "Valid Driver's License", 'detail' => "Please bring your valid driver's license to pickup. We're required to verify it before you take the Slingshot out. Must match the name on the booking.", 'cta' => '', ], ]; $rowsHtml = ''; $n = 1; foreach ($keys as $key) { if (!isset($itemDefs[$key])) continue; $d = $itemDefs[$key]; $rowsHtml .= " {$n} " . htmlspecialchars($d['label']) . "

" . htmlspecialchars($d['detail']) . "

{$d['cta']} "; $n++; } if (!$rowsHtml) { echo json_encode(['error'=>'No items selected']); exit; } $html = "

Parker County Slingshot Rentals

Almost Ready — A Few Things Before Pickup

Hey " . htmlspecialchars($b['name']) . ", your " . htmlspecialchars($pkg['label']) . " rental on {$dateLabel} is coming up! (Ref: {$ref})

To make sure pickup goes smoothly, here's what still needs to be taken care of:

{$rowsHtml}

Questions? Call or text (817) 555-0199 or reply to this email — we're happy to help.

Ride on,
The Parker County Slingshot Team

© " . date('Y') . " Parker County Slingshot Rentals — Weatherford, TX

"; $sent = sendEmail($b['email'], $b['name'], "Action Needed Before Your Rental — {$ref}", $html); echo json_encode(['ok'=>true]); exit; } if ($action === 'block_date') { $date = $_POST['date'] ?? ''; $reason = substr($_POST['reason'] ?? '', 0, 200); if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) { db()->prepare("INSERT IGNORE INTO blocked_dates (block_date, reason) VALUES (?,?)")->execute([$date, $reason]); echo json_encode(['ok'=>true]); } else { echo json_encode(['error'=>'Invalid date']); } exit; } if ($action === 'unblock_date') { $id = (int)($_POST['id'] ?? 0); db()->prepare("DELETE FROM blocked_dates WHERE id=?")->execute([$id]); echo json_encode(['ok'=>true]); exit; } exit; } // ── Login page ───────────────────────────────────────────────────────────────── if (!$authed) { ?> Admin Login — Parker County Slingshot Rentals

Parker Admin

Slingshot Rentals Management

quote($statusFilter) : ''; $bookings = db()->query("SELECT * FROM bookings {$where} ORDER BY rental_date ASC, created_at DESC")->fetchAll(); $blocked = db()->query("SELECT * FROM blocked_dates ORDER BY block_date ASC")->fetchAll(); $stats = db()->query(" SELECT COUNT(*) AS total, SUM(status='pending') AS pending, SUM(status='confirmed') AS confirmed, SUM(status='completed') AS completed, SUM(status='cancelled') AS cancelled, SUM(CASE WHEN status IN ('confirmed','completed') THEN amount ELSE 0 END) AS revenue, SUM(waiver_signed) AS waivers_signed, SUM(insurance_verified) AS insurance_done, SUM(deposit_received) AS deposits_done FROM bookings ")->fetch(); ?> Admin — Parker County Slingshot Rentals

Parker County Slingshot — Admin

Sign Out
Total Bookings
Pending
Confirmed
Completed
$
Revenue
Waivers Signed
Insurance OK
Deposits Rcvd
No bookings found.
$b['package']]; // Determine each step's state $stepConfirmed = in_array($b['status'], ['confirmed','completed']); $stepWaiver = (bool)$b['waiver_signed']; $stepInsurance = (bool)$b['insurance_verified']; $stepDeposit = (bool)$b['deposit_received']; $stepLicense = (bool)$b['license_verified']; // Dot colors: done=green, if cancelled skip all $cancelled = $b['status'] === 'cancelled'; $dotClass = function($done) use ($cancelled) { if ($cancelled) return 'dot-skip'; return $done ? 'dot-done' : 'dot-pending'; }; $allDone = $stepConfirmed && $stepWaiver && $stepInsurance && $stepDeposit && $stepLicense; $pendingCount = ($cancelled ? 0 : ( (!$stepConfirmed?1:0)+(!$stepWaiver?1:0)+(!$stepInsurance?1:0)+(!$stepDeposit?1:0)+(!$stepLicense?1:0) )); ?>
Customer Rental Date Package Amount Status Progress Submitted


$
pending All done ✓

Customer

Package
$
Rental Date
Customer Message
Admin Notes

Booking Flow

Booking Submitted
Booking Confirmed Confirmed — status: Cancelled Awaiting confirmation — change status above
Rental Waiver Signed Signed by on N/A Not yet signed
Proof of Insurance Received
Security Deposit Received
Driver's License Verified

Send Reminder Email

Select what the customer still needs to do, then send them a nudge email with clear instructions.

Not applicable for cancelled bookings.

Include in Reminder

Waiver Link https://parkerslingshotrentals.com/waiver.php?ref=

Block Dates

No dates blocked.