Add availability calendar, admin portal, and booking backend

- db.php: shared config, PDO, SendGrid, package definitions
- availability.php: GET endpoint returning booked/blocked dates by month
- contact.php: booking handler with DB record, availability check, SendGrid emails
- admin/index.php: full admin portal (login, bookings table, status/notes AJAX, block dates)
- index.html: interactive availability calendar with click-to-select, wires to /contact.php
- .htaccess: block direct access to db.php

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-22 13:39:20 +00:00
parent c2ab75f97d
commit 2ecf8f04c4
6 changed files with 662 additions and 114 deletions
+56
View File
@@ -0,0 +1,56 @@
<?php
define('PARKER_DB_HOST', 'localhost');
define('PARKER_DB_NAME', 'parker_db');
define('PARKER_DB_USER', 'parker_user');
define('PARKER_DB_PASS', 'Pk4rk3r_2026!Tx');
define('ADMIN_USER', 'admin');
define('ADMIN_PASS', '$2y$12$Tz8QkXv9mNpL3wR1uE6OaOQbKjH5sYdF2cVnMxPt7lGAeWqZiBSHu'); // Parker2026!
define('ADMIN_SESSION_KEY', 'parker_admin_auth');
define('SENDGRID_API_KEY', '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');
define('MAIL_FROM', 'noreply@parkerslingshotrentals.com');
define('MAIL_FROM_NAME', 'Parker County Slingshot Rentals');
define('ADMIN_EMAIL', 'info@parkerslingshotrentals.com');
define('PACKAGES', [
'half-day' => ['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;
}