-
Booking Request Received!
-
Hey ' . htmlspecialchars($name) . ', we got your request and will confirm availability within a few hours.
-
-
Your Request Summary
-
Package: ' . htmlspecialchars($packageLabel) . '
-
Requested Date: ' . htmlspecialchars($dateFormatted) . '
+
+
Booking Request Received!
+
Hey " . htmlspecialchars($name) . ", your request is in. We'll confirm availability and reach out within a few hours.
+
+
Booking Reference
+
{$ref}
+
Package: {$pkgLabel}
+
Requested Date: {$dateLabel}
+
Total: {$amountLabel}
-
We\'ll reach out to you at ' . htmlspecialchars($email) . '' . ($phone ? ' or ' . htmlspecialchars($phone) . '' : '') . ' to confirm your ride.
-
Questions? Call or text us at (817) 555-0199.
-
Ride on,
The Parker County Slingshot Team
+
Questions? Call or text (817) 555-0199 or reply to this email.
+
Ride on,
The Parker County Slingshot Team
-
-
© ' . date('Y') . ' Parker County Slingshot Rentals — Weatherford, TX
+
+
© " . date('Y') . " Parker County Slingshot Rentals — Weatherford, TX
-
';
+
";
-function sendgridSend(string $toEmail, string $toName, string $subject, string $html): bool {
- $payload = json_encode([
- 'personalizations' => [['to' => [['email' => $toEmail, 'name' => $toName]]]],
- 'from' => ['email' => MAIL_FROM, 'name' => MAIL_FROM_NAME],
- 'subject' => $subject,
- 'content' => [['type' => 'text/html', 'value' => $html]],
- ]);
+sendEmail(ADMIN_EMAIL, 'Parker Slingshot Admin', "New Booking {$ref}: {$name} — {$pkgLabel} on {$dateLabel}", $adminHtml);
+sendEmail($email, $name, "Booking Request {$ref} — Parker County Slingshot Rentals", $confirmHtml);
- $ch = curl_init('https://api.sendgrid.com/v3/mail/send');
- curl_setopt_array($ch, [
- CURLOPT_RETURNTRANSFER => true,
- CURLOPT_POST => true,
- CURLOPT_POSTFIELDS => $payload,
- CURLOPT_HTTPHEADER => [
- 'Authorization: Bearer ' . SENDGRID_API_KEY,
- 'Content-Type: application/json',
- ],
- CURLOPT_TIMEOUT => 20,
- CURLOPT_SSL_VERIFYPEER => false,
- ]);
- $response = curl_exec($ch);
- $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
- curl_close($ch);
- return $code === 202;
-}
-
-$apiKey = SENDGRID_API_KEY;
-if ($apiKey && strpos($apiKey, 'YOUR_KEY') === false) {
- sendgridSend(ADMIN_EMAIL, 'Parker Slingshot Admin',
- "New Booking Request: {$name} — {$packageLabel} on {$dateFormatted}", $adminHtml);
- sendgridSend($email, $name,
- "Booking Request Confirmed — Parker County Slingshot", $confirmHtml);
-} else {
- error_log('[Parker Slingshot] SENDGRID_API_KEY not configured');
-}
-
-echo json_encode(['success' => true, 'message' => 'Booking request received! We\'ll be in touch shortly.']);
+echo json_encode(['success'=>true,'ref'=>$ref,'message'=>"Booking request received! Your reference is {$ref}. We'll be in touch shortly."]);
diff --git a/db.php b/db.php
new file mode 100644
index 0000000..cfddbf3
--- /dev/null
+++ b/db.php
@@ -0,0 +1,56 @@
+ ['label' => 'Half Day (4 hrs)', 'amount' => 99.00, 'days' => 0],
+ 'full-day' => ['label' => 'Full Day (8 hrs)', 'amount' => 169.00, 'days' => 0],
+ 'weekend' => ['label' => 'Weekend (48 hrs)', 'amount' => 299.00, 'days' => 1],
+]);
+
+function db(): PDO {
+ static $pdo;
+ if (!$pdo) {
+ $pdo = new PDO(
+ 'mysql:host=' . PARKER_DB_HOST . ';dbname=' . PARKER_DB_NAME . ';charset=utf8mb4',
+ PARKER_DB_USER, PARKER_DB_PASS,
+ [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]
+ );
+ }
+ return $pdo;
+}
+
+function generateRef(): string {
+ return 'PSR-' . strtoupper(substr(uniqid(), -6));
+}
+
+function sendEmail(string $to, string $toName, string $subject, string $html): bool {
+ if (!SENDGRID_API_KEY || strpos(SENDGRID_API_KEY, 'YOUR_KEY') !== false) return false;
+ $payload = json_encode([
+ 'personalizations' => [['to' => [['email' => $to, 'name' => $toName]]]],
+ 'from' => ['email' => MAIL_FROM, 'name' => MAIL_FROM_NAME],
+ 'subject' => $subject,
+ 'content' => [['type' => 'text/html', 'value' => $html]],
+ ]);
+ $ch = curl_init('https://api.sendgrid.com/v3/mail/send');
+ curl_setopt_array($ch, [
+ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true,
+ CURLOPT_POSTFIELDS => $payload,
+ CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . SENDGRID_API_KEY, 'Content-Type: application/json'],
+ CURLOPT_TIMEOUT => 15, CURLOPT_SSL_VERIFYPEER => false,
+ ]);
+ $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+ curl_exec($ch); curl_close($ch);
+ return $code === 202;
+}
diff --git a/index.html b/index.html
index 100224c..9b903a6 100644
--- a/index.html
+++ b/index.html
@@ -385,6 +385,28 @@
.form-msg.success { background: rgba(34,197,94,0.15); border: 1px solid rgba(34,197,94,0.3); color: #4ade80; display: block; }
.form-msg.error { background: rgba(239,68,68,0.15); border: 1px solid rgba(239,68,68,0.3); color: #f87171; display: block; }
+ /* AVAILABILITY CALENDAR */
+ .cal-wrap { background: rgba(255,255,255,0.04); border: 1px solid rgba(255,255,255,0.08); border-radius: 12px; padding: 1.25rem; margin-bottom: 1.25rem; }
+ .cal-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 1rem; }
+ .cal-header h3 { font-family: 'Barlow Condensed', sans-serif; font-size: 1.2rem; font-weight: 700; letter-spacing: 0.5px; }
+ .cal-nav { background: rgba(255,255,255,0.07); border: none; color: white; border-radius: 6px; width: 32px; height: 32px; cursor: pointer; font-size: 1rem; display: flex; align-items: center; justify-content: center; transition: background 0.2s; }
+ .cal-nav:hover { background: var(--orange); }
+ .cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px; }
+ .cal-day-label { text-align: center; font-size: 0.65rem; font-weight: 600; letter-spacing: 1px; color: rgba(255,255,255,0.35); padding: 0.25rem 0; text-transform: uppercase; }
+ .cal-day { text-align: center; border-radius: 6px; padding: 0.4rem 0.25rem; font-size: 0.8rem; font-weight: 500; min-height: 32px; display: flex; align-items: center; justify-content: center; transition: background 0.15s, color 0.15s; }
+ .cal-day.empty { background: transparent; }
+ .cal-day.past { color: rgba(255,255,255,0.2); cursor: default; }
+ .cal-day.booked { background: rgba(239,68,68,0.18); color: rgba(239,68,68,0.6); cursor: not-allowed; position: relative; }
+ .cal-day.booked::after { content: ''; position: absolute; bottom: 3px; left: 50%; transform: translateX(-50%); width: 4px; height: 4px; border-radius: 50%; background: rgba(239,68,68,0.5); }
+ .cal-day.available { background: rgba(255,255,255,0.05); color: rgba(255,255,255,0.85); cursor: pointer; }
+ .cal-day.available:hover { background: rgba(249,115,22,0.25); color: var(--orange); }
+ .cal-day.today { border: 1px solid rgba(249,115,22,0.5); }
+ .cal-day.selected { background: var(--orange) !important; color: white !important; font-weight: 700; }
+ .cal-legend { display: flex; gap: 1rem; margin-top: 0.75rem; flex-wrap: wrap; }
+ .cal-legend-item { display: flex; align-items: center; gap: 0.4rem; font-size: 0.72rem; color: rgba(255,255,255,0.45); }
+ .cal-legend-dot { width: 10px; height: 10px; border-radius: 3px; flex-shrink: 0; }
+ .cal-loading { text-align: center; padding: 1.5rem; color: rgba(255,255,255,0.3); font-size: 0.85rem; }
+
/* FOOTER */
footer {
background: #080808;
@@ -656,6 +678,23 @@