commit 0f11edc62e0baad34a283791660bd4dd01159686 Author: Myron Blair Date: Fri May 22 12:52:45 2026 +0000 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..26add4a --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*.log +.DS_Store +*.swp + +api/config.php +uploads/ diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..a05d9d0 --- /dev/null +++ b/.htaccess @@ -0,0 +1,60 @@ +### Rewrite Rules Added by CyberPanel Rewrite Rule Generator + +RewriteEngine On +RewriteCond %{HTTPS} !=on +RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L] + +### End CyberPanel Generated Rules. + +# Epic Travel & Expeditions - CyberPanel LiteSpeed Configuration +DirectoryIndex index.html index.php + + +RewriteEngine On +RewriteBase / + +# API Routes - Direct to PHP backend +RewriteCond %{REQUEST_URI} ^/api/ +RewriteRule ^api/(.*)$ api/api/$1 [L,QSA] + +# Admin setup page +RewriteRule ^setup/?$ setup_password.php [L] + +# Static files and directories - serve directly +RewriteCond %{REQUEST_FILENAME} -f [OR] +RewriteCond %{REQUEST_FILENAME} -d +RewriteRule ^ - [L] + +# React Router - All other routes to index.html +RewriteRule ^ index.html [L] + + +# Security Headers + +Header set X-Content-Type-Options "nosniff" +Header set X-Frame-Options "SAMEORIGIN" +Header set X-XSS-Protection "1; mode=block" + + +# Enable CORS for API + + Header set Access-Control-Allow-Origin "*" + Header set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" + Header set Access-Control-Allow-Headers "Content-Type, Authorization" + + +# Disable directory browsing +Options -Indexes +FollowSymLinks + +# PHP Settings + +php_value upload_max_filesize 10M +php_value post_max_size 10M +php_value memory_limit 256M +php_value max_execution_time 300 + + +# Force use of index.html + +DirectoryIndex index.html index.php + diff --git a/api/.htaccess b/api/.htaccess new file mode 100644 index 0000000..5a306c7 --- /dev/null +++ b/api/.htaccess @@ -0,0 +1,52 @@ +# Epic Travel & Expeditions - LiteSpeed .htaccess for CyberPanel +# Optimized for LiteSpeed Web Server + + + RewriteEngine On + RewriteBase /api/ + + # Route all requests to index.php + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule ^(.*)$ index.php/$1 [L,QSA] + + +# LiteSpeed Cache Control + + # Disable caching for API + CacheLookup off + + +# Security Headers + + Header set X-Content-Type-Options "nosniff" + Header set X-Frame-Options "SAMEORIGIN" + Header set X-XSS-Protection "1; mode=block" + Header set X-Powered-By "Epic Travel API" + + +# Protect sensitive files + + Require all denied + + +# PHP Settings (LiteSpeed compatible) + + php_value upload_max_filesize 10M + php_value post_max_size 10M + php_value max_execution_time 300 + php_value max_input_time 300 + php_value memory_limit 256M + + +# Compression + + AddOutputFilterByType DEFLATE application/json + AddOutputFilterByType DEFLATE text/plain + AddOutputFilterByType DEFLATE text/html + + +# Browser Caching + + ExpiresActive Off + diff --git a/api/api/auth.php b/api/api/auth.php new file mode 100644 index 0000000..293a04e --- /dev/null +++ b/api/api/auth.php @@ -0,0 +1,55 @@ +getConnection(); + +// Login endpoint +if ($method === 'POST' && $id === 'login') { + $input = getJsonInput(); + + // Validate input + $errors = validateRequired($input, ['email', 'password']); + if (!empty($errors)) { + jsonResponse(['error' => implode(', ', $errors)], 400); + } + + $email = sanitizeString($input['email']); + $password = $input['password']; + + // Find admin user + $stmt = $db->prepare("SELECT * FROM admin_users WHERE email = ?"); + $stmt->execute([$email]); + $admin = $stmt->fetch(); + + if (!$admin) { + jsonResponse(['error' => 'Invalid email or password'], 401); + } + + // Verify password + if (!password_verify($password, $admin['password_hash'])) { + jsonResponse(['error' => 'Invalid email or password'], 401); + } + + // Create token + $token = JWT::createToken($email); + + jsonResponse([ + 'access_token' => $token, + 'token_type' => 'bearer', + 'email' => $email + ]); +} + +// Verify token endpoint +if ($method === 'POST' && $id === 'verify') { + $payload = requireAuth(); + + jsonResponse([ + 'valid' => true, + 'email' => $payload['sub'] + ]); +} + +jsonResponse(['error' => 'Invalid auth endpoint'], 404); diff --git a/api/api/categories.php b/api/api/categories.php new file mode 100644 index 0000000..cf6b4bd --- /dev/null +++ b/api/api/categories.php @@ -0,0 +1,64 @@ +getConnection(); + +// GET all categories (public - needed for destination forms) +if ($method === 'GET' && !$id) { + $stmt = $db->query('SELECT id, name FROM destination_categories ORDER BY name'); + jsonResponse($stmt->fetchAll()); +} + +// POST add category (admin) +if ($method === 'POST') { + requireAuth(); + $input = getJsonInput(); + $errors = validateRequired($input, ['name']); + if (!empty($errors)) jsonResponse(['error' => implode(', ', $errors)], 400); + $name = sanitizeString($input['name']); + try { + $stmt = $db->prepare('INSERT INTO destination_categories (name) VALUES (?)'); + $stmt->execute([$name]); + $newId = $db->lastInsertId(); + jsonResponse(['id' => $newId, 'name' => $name], 201); + } catch (Exception $e) { + jsonResponse(['error' => 'Category already exists'], 409); + } +} + +// PUT rename category (admin) - also updates all destinations using it +if ($method === 'PUT' && $id) { + requireAuth(); + $input = getJsonInput(); + $errors = validateRequired($input, ['name']); + if (!empty($errors)) jsonResponse(['error' => implode(', ', $errors)], 400); + $newName = sanitizeString($input['name']); + $stmt = $db->prepare('SELECT name FROM destination_categories WHERE id = ?'); + $stmt->execute([$id]); + $old = $stmt->fetch(); + if (!$old) jsonResponse(['error' => 'Category not found'], 404); + try { + $db->prepare('UPDATE destination_categories SET name = ? WHERE id = ?')->execute([$newName, $id]); + $db->prepare('UPDATE destinations SET category = ? WHERE category = ?')->execute([$newName, $old['name']]); + jsonResponse(['id' => $id, 'name' => $newName]); + } catch (Exception $e) { + jsonResponse(['error' => 'Category name already exists'], 409); + } +} + +// DELETE category (admin) - only if no destinations use it +if ($method === 'DELETE' && $id) { + requireAuth(); + $stmt = $db->prepare('SELECT name FROM destination_categories WHERE id = ?'); + $stmt->execute([$id]); + $cat = $stmt->fetch(); + if (!$cat) jsonResponse(['error' => 'Category not found'], 404); + $stmt = $db->prepare('SELECT COUNT(*) FROM destinations WHERE category = ?'); + $stmt->execute([$cat['name']]); + if ($stmt->fetchColumn() > 0) jsonResponse(['error' => 'Cannot delete — destinations are using this category'], 400); + $db->prepare('DELETE FROM destination_categories WHERE id = ?')->execute([$id]); + jsonResponse(['message' => 'Category deleted']); +} + +jsonResponse(['error' => 'Invalid categories endpoint'], 404); diff --git a/api/api/contact.php b/api/api/contact.php new file mode 100644 index 0000000..cdbe424 --- /dev/null +++ b/api/api/contact.php @@ -0,0 +1,38 @@ +getConnection(); + +if ($method === 'POST') { + $input = getJsonInput(); + + $errors = validateRequired($input, ['name', 'email', 'message']); + if (!empty($errors)) { + jsonResponse(['error' => implode(', ', $errors)], 400); + } + + if (!isValidEmail($input['email'])) { + jsonResponse(['error' => 'Invalid email address'], 400); + } + + $name = sanitizeString($input['name']); + $email = sanitizeString($input['email']); + $message = $input['message']; + $id = generateUuid(); + + $stmt = $db->prepare(" + INSERT INTO contacts (id, name, email, message, created_at) + VALUES (?, ?, ?, ?, NOW()) + "); + $stmt->execute([$id, $name, $email, $message]); + + // Send admin alert and customer confirmation via SendGrid + sendContactAlert($name, $email, $message); + sendContactConfirmation($email, $name); + + jsonResponse(['message' => 'Contact form submitted successfully']); +} + +jsonResponse(['error' => 'Method not allowed'], 405); diff --git a/api/api/destinations.php b/api/api/destinations.php new file mode 100644 index 0000000..96c1e9c --- /dev/null +++ b/api/api/destinations.php @@ -0,0 +1,139 @@ +getConnection(); + +// GET all destinations or single destination +if ($method === 'GET') { + if ($id) { + // Get single destination + $stmt = $db->prepare("SELECT * FROM destinations WHERE id = ?"); + $stmt->execute([$id]); + $destination = $stmt->fetch(); + + if (!$destination) { + jsonResponse(['error' => 'Destination not found'], 404); + } + + jsonResponse($destination); + } else { + // Get all destinations with optional filtering + $category = isset($_GET['category']) ? sanitizeString($_GET['category']) : null; + $search = isset($_GET['search']) ? sanitizeString($_GET['search']) : null; + + $sql = "SELECT * FROM destinations WHERE 1=1"; + $params = []; + + if ($category && $category !== 'All') { + $sql .= " AND category = ?"; + $params[] = $category; + } + + if ($search) { + $sql .= " AND (name LIKE ? OR location LIKE ?)"; + $params[] = "%$search%"; + $params[] = "%$search%"; + } + + $sql .= " LIMIT 100"; + + $stmt = $db->prepare($sql); + $stmt->execute($params); + $destinations = $stmt->fetchAll(); + + jsonResponse($destinations); + } +} + +// POST create new destination (admin only) +if ($method === 'POST') { + requireAuth(); + + $input = getJsonInput(); + + $errors = validateRequired($input, ['name', 'location', 'description', 'image', 'category', 'rating', 'price']); + if (!empty($errors)) { + jsonResponse(['error' => implode(', ', $errors)], 400); + } + + $id = generateUuid(); + $stmt = $db->prepare(" + INSERT INTO destinations (id, name, location, description, image, category, rating, price, currency, created_at) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NOW()) + "); + + $stmt->execute([ + $id, + sanitizeString($input['name']), + sanitizeString($input['location']), + $input['description'], + $input['image'], + $input['category'], + $input['rating'], + $input['price'], + isset($input['currency']) ? $input['currency'] : 'USD' + ]); + + // Fetch created destination + $stmt = $db->prepare("SELECT * FROM destinations WHERE id = ?"); + $stmt->execute([$id]); + $destination = $stmt->fetch(); + + jsonResponse($destination, 201); +} + +// PUT update destination (admin only) +if ($method === 'PUT' && $id) { + requireAuth(); + + $input = getJsonInput(); + + // Build update query dynamically + $updates = []; + $params = []; + + $allowedFields = ['name', 'location', 'description', 'image', 'category', 'rating', 'price', 'currency']; + + foreach ($allowedFields as $field) { + if (isset($input[$field])) { + $updates[] = "$field = ?"; + $params[] = $field === 'description' ? $input[$field] : sanitizeString($input[$field]); + } + } + + if (empty($updates)) { + jsonResponse(['error' => 'No fields to update'], 400); + } + + $params[] = $id; + + $sql = "UPDATE destinations SET " . implode(', ', $updates) . " WHERE id = ?"; + $stmt = $db->prepare($sql); + $stmt->execute($params); + + // Fetch updated destination + $stmt = $db->prepare("SELECT * FROM destinations WHERE id = ?"); + $stmt->execute([$id]); + $destination = $stmt->fetch(); + + jsonResponse($destination); +} + +// DELETE destination (admin only) +if ($method === 'DELETE' && $id) { + requireAuth(); + + // Delete destination (cascades to specials) + $stmt = $db->prepare("DELETE FROM destinations WHERE id = ?"); + $stmt->execute([$id]); + + if ($stmt->rowCount() === 0) { + jsonResponse(['error' => 'Destination not found'], 404); + } + + jsonResponse(['message' => 'Destination deleted successfully']); +} + +jsonResponse(['error' => 'Invalid destinations endpoint'], 404); diff --git a/api/api/newsletter.php b/api/api/newsletter.php new file mode 100644 index 0000000..c34d4d7 --- /dev/null +++ b/api/api/newsletter.php @@ -0,0 +1,37 @@ +getConnection(); + +if ($method === 'POST' && $id === 'subscribe') { + $input = getJsonInput(); + + if (!isset($input['email']) || !isValidEmail($input['email'])) { + jsonResponse(['error' => 'Valid email address is required'], 400); + } + + $email = sanitizeString($input['email']); + + // Check if already subscribed + $stmt = $db->prepare("SELECT id FROM newsletter_subscribers WHERE email = ?"); + $stmt->execute([$email]); + + if ($stmt->fetch()) { + jsonResponse(['message' => 'Email already subscribed']); + } + + $id = generateUuid(); + + $stmt = $db->prepare(" + INSERT INTO newsletter_subscribers (id, email, subscribed_at) + VALUES (?, ?, NOW()) + "); + + $stmt->execute([$id, $email]); + + jsonResponse(['message' => 'Successfully subscribed to newsletter']); +} + +jsonResponse(['error' => 'Invalid newsletter endpoint'], 404); diff --git a/api/api/specials.php b/api/api/specials.php new file mode 100644 index 0000000..3ca92c1 --- /dev/null +++ b/api/api/specials.php @@ -0,0 +1,131 @@ +getConnection(); + +// GET all specials +if ($method === 'GET' && !$id) { + $stmt = $db->query("SELECT * FROM specials LIMIT 100"); + $specials = $stmt->fetchAll(); + + // Parse JSON highlights + foreach ($specials as &$special) { + $special['highlights'] = json_decode($special['highlights'], true); + } + + jsonResponse($specials); +} + +// POST create special (admin only) +if ($method === 'POST') { + requireAuth(); + + $input = getJsonInput(); + + $errors = validateRequired($input, ['destination_id', 'discount', 'end_date', 'highlights']); + if (!empty($errors)) { + jsonResponse(['error' => implode(', ', $errors)], 400); + } + + // Check if destination exists + $stmt = $db->prepare("SELECT id FROM destinations WHERE id = ?"); + $stmt->execute([$input['destination_id']]); + if (!$stmt->fetch()) { + jsonResponse(['error' => 'Destination not found'], 404); + } + + // Check if special already exists for this destination + $stmt = $db->prepare("SELECT id FROM specials WHERE destination_id = ?"); + $stmt->execute([$input['destination_id']]); + if ($stmt->fetch()) { + jsonResponse(['error' => 'Special already exists for this destination'], 400); + } + + $id = generateUuid(); + $highlights = json_encode($input['highlights']); + + $stmt = $db->prepare(" + INSERT INTO specials (id, destination_id, discount, end_date, highlights, image_path, created_at) + VALUES (?, ?, ?, ?, ?, ?, NOW()) + "); + + $stmt->execute([ + $id, + $input['destination_id'], + $input['discount'], + $input['end_date'], + $highlights, + isset($input['image_path']) ? $input['image_path'] : null + ]); + + // Fetch created special + $stmt = $db->prepare("SELECT * FROM specials WHERE id = ?"); + $stmt->execute([$id]); + $special = $stmt->fetch(); + $special['highlights'] = json_decode($special['highlights'], true); + + jsonResponse($special, 201); +} + +// PUT update special (admin only) +if ($method === 'PUT' && $id) { + requireAuth(); + + $input = getJsonInput(); + + $updates = []; + $params = []; + + if (isset($input['discount'])) { + $updates[] = "discount = ?"; + $params[] = $input['discount']; + } + + if (isset($input['end_date'])) { + $updates[] = "end_date = ?"; + $params[] = $input['end_date']; + } + + if (isset($input['highlights'])) { + $updates[] = "highlights = ?"; + $params[] = json_encode($input['highlights']); + } + + if (empty($updates)) { + jsonResponse(['error' => 'No fields to update'], 400); + } + + $params[] = $id; + + $sql = "UPDATE specials SET " . implode(', ', $updates) . " WHERE id = ?"; + $stmt = $db->prepare($sql); + $stmt->execute($params); + + // Fetch updated special + $stmt = $db->prepare("SELECT * FROM specials WHERE id = ?"); + $stmt->execute([$id]); + $special = $stmt->fetch(); + $special['highlights'] = json_decode($special['highlights'], true); + + jsonResponse($special); +} + +// DELETE special by destination_id (admin only) +if ($method === 'DELETE' && isset($pathParts[1]) && $pathParts[1] === 'destination' && isset($pathParts[2])) { + requireAuth(); + + $destinationId = $pathParts[2]; + + $stmt = $db->prepare("DELETE FROM specials WHERE destination_id = ?"); + $stmt->execute([$destinationId]); + + if ($stmt->rowCount() === 0) { + jsonResponse(['error' => 'Special not found for this destination'], 404); + } + + jsonResponse(['message' => 'Special removed successfully']); +} + +jsonResponse(['error' => 'Invalid specials endpoint'], 404); diff --git a/api/api/testimonials.php b/api/api/testimonials.php new file mode 100644 index 0000000..991d3b3 --- /dev/null +++ b/api/api/testimonials.php @@ -0,0 +1,95 @@ +getConnection(); + +// GET approved testimonials (public) +if ($method === 'GET' && !$id) { + $stmt = $db->query("SELECT id, full_name, location, message, image_path, created_at FROM testimonials WHERE status = 'approved' ORDER BY created_at DESC"); + jsonResponse($stmt->fetchAll()); +} + +// GET all testimonials (admin) +if ($method === 'GET' && $id === 'all') { + requireAuth(); + $stmt = $db->query("SELECT * FROM testimonials ORDER BY created_at DESC"); + jsonResponse($stmt->fetchAll()); +} + +// POST submit testimonial (public) +if ($method === 'POST' && !$id) { + $input = getJsonInput(); + $errors = validateRequired($input, ['full_name', 'location', 'message']); + if (!empty($errors)) { + jsonResponse(['error' => implode(', ', $errors)], 400); + } + + $testimonialId = generateUuid(); + $stmt = $db->prepare("INSERT INTO testimonials (id, full_name, location, message, image_path, status, created_at) VALUES (?, ?, ?, ?, ?, 'pending', NOW())"); + $stmt->execute([ + $testimonialId, + sanitizeString($input['full_name']), + sanitizeString($input['location']), + sanitizeString($input['message']), + isset($input['image_path']) ? $input['image_path'] : null + ]); + jsonResponse(['message' => 'Testimonial submitted successfully', 'id' => $testimonialId], 201); +} + +// PUT approve/deny/edit testimonial (admin) +if ($method === 'PUT' && $id) { + requireAuth(); + $input = getJsonInput(); + $updates = []; + $params = []; + + if (isset($input['status']) && in_array($input['status'], ['pending', 'approved', 'denied'])) { + $updates[] = 'status = ?'; + $params[] = $input['status']; + } + if (isset($input['full_name'])) { $updates[] = 'full_name = ?'; $params[] = sanitizeString($input['full_name']); } + if (isset($input['location'])) { $updates[] = 'location = ?'; $params[] = sanitizeString($input['location']); } + if (isset($input['message'])) { $updates[] = 'message = ?'; $params[] = sanitizeString($input['message']); } + + if (empty($updates)) jsonResponse(['error' => 'No fields to update'], 400); + + $params[] = $id; + $stmt = $db->prepare('UPDATE testimonials SET ' . implode(', ', $updates) . ' WHERE id = ?'); + $stmt->execute($params); + + $stmt = $db->prepare('SELECT * FROM testimonials WHERE id = ?'); + $stmt->execute([$id]); + jsonResponse($stmt->fetch()); +} + +// DELETE testimonial (admin) +if ($method === 'DELETE' && $id) { + requireAuth(); + $stmt = $db->prepare('DELETE FROM testimonials WHERE id = ?'); + $stmt->execute([$id]); + if ($stmt->rowCount() === 0) jsonResponse(['error' => 'Testimonial not found'], 404); + jsonResponse(['message' => 'Testimonial deleted']); +} + + +// POST upload testimonial image (public) +if ($method === "POST" && $id === "upload") { + if (!isset($_FILES["file"])) jsonResponse(["error" => "No file uploaded"], 400); + $file = $_FILES["file"]; + if ($file["error"] !== UPLOAD_ERR_OK) jsonResponse(["error" => "Upload error"], 400); + if ($file["size"] > MAX_UPLOAD_SIZE) jsonResponse(["error" => "File too large (max 5MB)"], 400); + $finfo = finfo_open(FILEINFO_MIME_TYPE); + $mime = finfo_file($finfo, $file["tmp_name"]); + finfo_close($finfo); + $allowed = ["image/jpeg","image/jpg","image/png","image/webp"]; + if (!in_array($mime, $allowed)) jsonResponse(["error" => "Invalid file type"], 400); + $ext = strtolower(pathinfo($file["name"], PATHINFO_EXTENSION)); + $name = generateUuid() . "." . $ext; + $dest = UPLOAD_DIR . $name; + if (!move_uploaded_file($file["tmp_name"], $dest)) jsonResponse(["error" => "Failed to save"], 500); + jsonResponse(["url" => "/api/uploads/" . $name]); +} + +jsonResponse(['error' => 'Invalid testimonials endpoint'], 404); diff --git a/api/api/upload.php b/api/api/upload.php new file mode 100644 index 0000000..38d6f08 --- /dev/null +++ b/api/api/upload.php @@ -0,0 +1,72 @@ + 'No file uploaded'], 400); + } + + $file = $_FILES['file']; + + // Validate file + if ($file['error'] !== UPLOAD_ERR_OK) { + jsonResponse(['error' => 'File upload failed'], 400); + } + + // Check file size + if ($file['size'] > MAX_UPLOAD_SIZE) { + jsonResponse(['error' => 'File too large. Maximum size is 5MB'], 400); + } + + // Check file type + $allowedTypes = ['image/jpeg', 'image/jpg', 'image/png', 'image/webp']; + $finfo = finfo_open(FILEINFO_MIME_TYPE); + $mimeType = finfo_file($finfo, $file['tmp_name']); + finfo_close($finfo); + + if (!in_array($mimeType, $allowedTypes)) { + jsonResponse(['error' => 'Invalid file type. Only JPG, PNG, and WebP allowed'], 400); + } + + // Generate unique filename + $extension = pathinfo($file['name'], PATHINFO_EXTENSION); + $filename = generateUuid() . '.' . $extension; + $filepath = UPLOAD_DIR . $filename; + + // Move uploaded file + if (!move_uploaded_file($file['tmp_name'], $filepath)) { + jsonResponse(['error' => 'Failed to save file'], 500); + } + + $fileUrl = '/api/uploads/' . $filename; + + jsonResponse([ + 'url' => $fileUrl, + 'filename' => $filename + ]); +} + +// Serve uploaded images +if ($method === 'GET' && isset($pathParts[1]) && $pathParts[1] === 'uploads' && isset($pathParts[2])) { + $filename = basename($pathParts[2]); + $filepath = UPLOAD_DIR . $filename; + + if (!file_exists($filepath)) { + jsonResponse(['error' => 'Image not found'], 404); + } + + $finfo = finfo_open(FILEINFO_MIME_TYPE); + $mimeType = finfo_file($finfo, $filepath); + finfo_close($finfo); + + header('Content-Type: ' . $mimeType); + header('Content-Length: ' . filesize($filepath)); + readfile($filepath); + exit; +} + +jsonResponse(['error' => 'Invalid upload endpoint'], 404); diff --git a/api/includes/database.php b/api/includes/database.php new file mode 100644 index 0000000..4c6b7cf --- /dev/null +++ b/api/includes/database.php @@ -0,0 +1,52 @@ + PDO::ERRMODE_EXCEPTION, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + PDO::ATTR_EMULATE_PREPARES => false, + ]; + + $this->conn = new PDO($dsn, DB_USER, DB_PASS, $options); + } catch (PDOException $e) { + $this->handleError($e->getMessage()); + } + } + + public static function getInstance() { + if (self::$instance === null) { + self::$instance = new self(); + } + return self::$instance; + } + + public function getConnection() { + return $this->conn; + } + + private function handleError($message) { + if (DEBUG_MODE) { + die(json_encode(['error' => 'Database Error: ' . $message])); + } else { + die(json_encode(['error' => 'Database connection failed'])); + } + } + + // Prevent cloning + private function __clone() {} + + // Prevent unserialization + public function __wakeup() { + throw new Exception("Cannot unserialize singleton"); + } +} diff --git a/api/includes/functions.php b/api/includes/functions.php new file mode 100644 index 0000000..307c504 --- /dev/null +++ b/api/includes/functions.php @@ -0,0 +1,87 @@ + 'JWT', 'alg' => 'HS256']); + $payload = json_encode($payload); + + $base64UrlHeader = self::base64UrlEncode($header); + $base64UrlPayload = self::base64UrlEncode($payload); + + $signature = hash_hmac('sha256', $base64UrlHeader . "." . $base64UrlPayload, $secret, true); + $base64UrlSignature = self::base64UrlEncode($signature); + + return $base64UrlHeader . "." . $base64UrlPayload . "." . $base64UrlSignature; + } + + /** + * Decode and verify a JWT token + */ + public static function decode($jwt, $secret) { + $parts = explode('.', $jwt); + + if (count($parts) !== 3) { + return false; + } + + list($base64UrlHeader, $base64UrlPayload, $base64UrlSignature) = $parts; + + $signature = self::base64UrlDecode($base64UrlSignature); + $expectedSignature = hash_hmac('sha256', $base64UrlHeader . "." . $base64UrlPayload, $secret, true); + + if (!hash_equals($signature, $expectedSignature)) { + return false; + } + + $payload = json_decode(self::base64UrlDecode($base64UrlPayload), true); + + // Check expiration + if (isset($payload['exp']) && $payload['exp'] < time()) { + return false; + } + + return $payload; + } + + /** + * Create authentication token + */ + public static function createToken($email) { + $payload = [ + 'sub' => $email, + 'iat' => time(), + 'exp' => time() + JWT_EXPIRY + ]; + + return self::encode($payload, JWT_SECRET_KEY); + } + + /** + * Verify token from Authorization header + */ + public static function verifyToken() { + $headers = getallheaders(); + + if (!isset($headers['Authorization'])) { + return false; + } + + $authHeader = $headers['Authorization']; + + if (!preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches)) { + return false; + } + + $token = $matches[1]; + $payload = self::decode($token, JWT_SECRET_KEY); + + return $payload; + } + + /** + * Base64 URL encode + */ + private static function base64UrlEncode($data) { + return str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($data)); + } + + /** + * Base64 URL decode + */ + private static function base64UrlDecode($data) { + return base64_decode(str_replace(['-', '_'], ['+', '/'], $data)); + } +} + +/** + * Require authentication middleware + */ +function requireAuth() { + $payload = JWT::verifyToken(); + + if (!$payload) { + http_response_code(401); + echo json_encode(['error' => 'Unauthorized']); + exit; + } + + return $payload; +} diff --git a/api/includes/mailer.php b/api/includes/mailer.php new file mode 100644 index 0000000..6840eae --- /dev/null +++ b/api/includes/mailer.php @@ -0,0 +1,101 @@ + [['to' => [['email' => $toEmail, 'name' => $toName]]]], + 'from' => [ + 'email' => defined('MAIL_FROM') ? MAIL_FROM : 'noreply@epictravelexpeditions.com', + 'name' => defined('MAIL_FROM_NAME') ? MAIL_FROM_NAME : 'Epic Travel Expeditions', + ], + 'subject' => $subject, + 'content' => array_values(array_filter([ + $textBody ? ['type' => 'text/plain', 'value' => $textBody] : null, + ['type' => 'text/html', 'value' => $htmlBody], + ])), + ]); + + $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 ' . $apiKey, + 'Content-Type: application/json', + ], + CURLOPT_TIMEOUT => 20, + CURLOPT_SSL_VERIFYPEER => false, + ]); + + $response = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + if ($httpCode === 202) return true; + error_log('[EpicTravel mailer] SendGrid HTTP ' . $httpCode . ' — ' . $response); + return false; +} + +function sendContactAlert(string $name, string $email, string $message): bool { + $adminEmail = defined('ADMIN_EMAIL') ? ADMIN_EMAIL : 'admin@epictravelexpeditions.com'; + $subject = "New Contact Form Submission from {$name}"; + $html = ' +
+
+

Epic Travel Expeditions

+

New Contact Form Message

+
+
+ + + + + +
Name' . htmlspecialchars($name) . '
Email' . htmlspecialchars($email) . '
+
+

' . nl2br(htmlspecialchars($message)) . '

+
+

Submitted ' . date('F j, Y \a\t g:i A T') . '

+
+
+

© ' . date('Y') . ' Epic Travel Expeditions

+
+
'; + + return sendgridSend($adminEmail, 'Epic Travel Admin', $subject, $html, + "New contact from {$name} ({$email}):\n\n{$message}"); +} + +function sendContactConfirmation(string $toEmail, string $toName): bool { + $subject = "We received your message — Epic Travel Expeditions"; + $html = ' +
+
+

Epic Travel Expeditions

+
+
+

Thanks for reaching out, ' . htmlspecialchars($toName) . '!

+

We received your message and our team will get back to you within 1–2 business days.

+

In the meantime, feel free to browse our destinations and current travel specials:

+
+ Explore Destinations +
+

Adventure awaits,
The Epic Travel Team

+
+
+

© ' . date('Y') . ' Epic Travel Expeditions

+
+
'; + + return sendgridSend($toEmail, $toName, $subject, $html, + "Hi {$toName},\n\nThanks for contacting Epic Travel Expeditions! We'll get back to you within 1-2 business days.\n\nAdventure awaits,\nThe Epic Travel Team"); +} diff --git a/api/index.php b/api/index.php new file mode 100644 index 0000000..de2d080 --- /dev/null +++ b/api/index.php @@ -0,0 +1,83 @@ + 'Epic Travel API is running', + 'status' => 'healthy' + ]); +} + +// Route to appropriate handler +try { + switch ($resource) { + case 'auth': + require __DIR__ . '/api/auth.php'; + break; + + case 'destinations': + require __DIR__ . '/api/destinations.php'; + break; + + case 'specials': + require __DIR__ . '/api/specials.php'; + break; + + case 'contact': + require __DIR__ . '/api/contact.php'; + break; + + case 'newsletter': + require __DIR__ . '/api/newsletter.php'; + break; + + case 'upload': + require __DIR__ . '/api/upload.php'; + break; + + case 'download': + require __DIR__ . '/api/download.php'; + break; + + case 'testimonials': + require __DIR__ . '/api/testimonials.php'; + break; + + case 'categories': + require __DIR__ . '/api/categories.php'; + break; + + default: + jsonResponse(['error' => 'Endpoint not found'], 404); + } +} catch (Exception $e) { + if (DEBUG_MODE) { + jsonResponse(['error' => $e->getMessage()], 500); + } else { + jsonResponse(['error' => 'Internal server error'], 500); + } +} diff --git a/api/phpinfo.php b/api/phpinfo.php new file mode 100644 index 0000000..43eed3d --- /dev/null +++ b/api/phpinfo.php @@ -0,0 +1,6 @@ + diff --git a/api/setup_password.php b/api/setup_password.php new file mode 100644 index 0000000..e65a5e4 --- /dev/null +++ b/api/setup_password.php @@ -0,0 +1,116 @@ + PDO::ERRMODE_EXCEPTION] + ); + + $hash = password_hash($password, PASSWORD_BCRYPT); + + // Check if user exists + $check = $pdo->prepare("SELECT COUNT(*) FROM admin_users WHERE email = ?"); + $check->execute([$email]); + + if ($check->fetchColumn() > 0) { + // Update existing + $s = $pdo->prepare("UPDATE admin_users SET password_hash = ? WHERE email = ?"); + $s->execute([$hash, $email]); + $message = 'Password updated successfully!'; + } else { + // Create new + $s = $pdo->prepare("INSERT INTO admin_users (id, email, password_hash, created_at) VALUES (?, ?, ?, NOW())"); + $s->execute(['admin-1', $email, $hash]); + $message = 'Admin account created successfully!'; + } + + // Verify + if (password_verify($password, $hash)) { + $success = true; + } else { + $message = 'Error: Password verification failed.'; + } + + } catch (Exception $e) { + $message = 'Database error: ' . $e->getMessage(); + } + } +} +?> + + + + + +Admin Setup — Epic Travel + + + +
+

Epic Travel Admin Setup

+
Set your admin email and password
+ + +
+ +
+ + + +

+ You can now login to the admin panel.

+ ⚠ Delete this file immediately!
+ Run in SSH: rm /home/epictravelexpeditions.com/public_html/api/setup_password.php +

+ +
+ + + + + + + +
+
⚠ Delete this file after use. It provides direct DB access.
+ +
+ + diff --git a/asset-manifest.json b/asset-manifest.json new file mode 100644 index 0000000..c2c6425 --- /dev/null +++ b/asset-manifest.json @@ -0,0 +1,13 @@ +{ + "files": { + "main.css": "/static/css/main.7791f349.css", + "main.js": "/static/js/main.b20df6de.js", + "index.html": "/index.html", + "main.7791f349.css.map": "/static/css/main.7791f349.css.map", + "main.b20df6de.js.map": "/static/js/main.b20df6de.js.map" + }, + "entrypoints": [ + "static/css/main.7791f349.css", + "static/js/main.b20df6de.js" + ] +} \ No newline at end of file diff --git a/assets/og-image.jpg b/assets/og-image.jpg new file mode 100644 index 0000000..2ed2b32 --- /dev/null +++ b/assets/og-image.jpg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + 🌎 + Epic Travel Expeditions + Adventure Awaits • Curated World Expeditions + Exclusive Destinations • Guided Tours • Unforgettable Journeys + + epictravelexpeditions.com + diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..72d8e3f --- /dev/null +++ b/composer.json @@ -0,0 +1,14 @@ +{ + "name": "epic-travel/expeditions", + "description": "Epic Travel & Expeditions Website", + "type": "project", + "require": { + "php": ">=7.4.0" + }, + "config": { + "platform": { + "php": "8.0" + }, + "optimize-autoloader": true + } +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..0f8c102 --- /dev/null +++ b/index.html @@ -0,0 +1,18 @@ +Epic Travel Expeditions | Adventure Awaits + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/robots.txt b/robots.txt new file mode 100644 index 0000000..7014030 --- /dev/null +++ b/robots.txt @@ -0,0 +1,6 @@ +User-agent: * +Allow: / +Disallow: /admin +Disallow: /api/ + +Sitemap: https://epictravelexpeditions.com/sitemap.xml diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 0000000..e8c09b2 --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,30 @@ + + + + https://epictravelexpeditions.com/ + 2026-05-19 + weekly + 1.0 + + + https://epictravelexpeditions.com/destinations + 2026-05-19 + weekly + 0.9 + + + https://epictravelexpeditions.com/specials + 2026-05-19 + daily + 0.8 + + + https://epictravelexpeditions.com/contact + 2026-05-19 + monthly + 0.6 + + diff --git a/static/css/main.7791f349.css b/static/css/main.7791f349.css new file mode 100644 index 0000000..ec56952 --- /dev/null +++ b/static/css/main.7791f349.css @@ -0,0 +1,4 @@ +*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/* +! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com +*/*,:after,:before{border:0 solid #e5e7eb;box-sizing:border-box}:after,:before{--tw-content:""}:host,html{-webkit-text-size-adjust:100%;font-feature-settings:normal;-webkit-tap-highlight-color:transparent;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-variation-settings:normal;line-height:1.5;tab-size:4}body{line-height:inherit}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-feature-settings:normal;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em;font-variation-settings:normal}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{font-feature-settings:inherit;color:inherit;font-family:inherit;font-size:100%;font-variation-settings:inherit;font-weight:inherit;letter-spacing:inherit;line-height:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::placeholder,textarea::placeholder{color:#9ca3af;opacity:1}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}[hidden]:where(:not([hidden=until-found])){display:none}:root{--background:0 0% 100%;--foreground:0 0% 3.9%;--card:0 0% 100%;--card-foreground:0 0% 3.9%;--popover:0 0% 100%;--popover-foreground:0 0% 3.9%;--primary:0 0% 9%;--primary-foreground:0 0% 98%;--secondary:0 0% 96.1%;--secondary-foreground:0 0% 9%;--muted:0 0% 96.1%;--muted-foreground:0 0% 45.1%;--accent:0 0% 96.1%;--accent-foreground:0 0% 9%;--destructive:0 84.2% 60.2%;--destructive-foreground:0 0% 98%;--border:0 0% 89.8%;--input:0 0% 89.8%;--ring:0 0% 3.9%;--chart-1:12 76% 61%;--chart-2:173 58% 39%;--chart-3:197 37% 24%;--chart-4:43 74% 66%;--chart-5:27 87% 67%;--radius:0.5rem}*{border-color:#e5e5e5;border-color:hsl(var(--border))}body{background-color:#fff;background-color:hsl(var(--background));color:#0a0a0a;color:hsl(var(--foreground))}[data-debug-wrapper=true]{display:contents!important}[data-debug-wrapper=true]>*{border:inherit;column-gap:inherit;gap:inherit;margin:inherit;padding:inherit;row-gap:inherit}.sr-only{clip:rect(0,0,0,0);border-width:0;height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.visible{visibility:visible}.invisible{visibility:hidden}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.inset-x-0{left:0;right:0}.inset-y-0{bottom:0;top:0}.-bottom-12{bottom:-3rem}.-left-12{left:-3rem}.-right-12{right:-3rem}.-top-12{top:-3rem}.bottom-0{bottom:0}.bottom-4{bottom:1rem}.left-0{left:0}.left-1{left:.25rem}.left-1\/2{left:50%}.left-2{left:.5rem}.left-3{left:.75rem}.left-4{left:1rem}.left-\[50\%\]{left:50%}.right-0{right:0}.right-1{right:.25rem}.right-2{right:.5rem}.right-4{right:1rem}.top-0{top:0}.top-1{top:.25rem}.top-1\/2{top:50%}.top-2{top:.5rem}.top-4{top:1rem}.top-\[1px\]{top:1px}.top-\[50\%\]{top:50%}.top-\[60\%\]{top:60%}.top-full{top:100%}.z-0{z-index:0}.z-10{z-index:10}.z-50{z-index:50}.z-\[100\]{z-index:100}.z-\[1\]{z-index:1}.-mx-1{margin-left:-.25rem;margin-right:-.25rem}.mx-auto{margin-left:auto;margin-right:auto}.my-1{margin-bottom:.25rem;margin-top:.25rem}.-ml-4{margin-left:-1rem}.-mt-4{margin-top:-1rem}.mb-1{margin-bottom:.25rem}.mb-12{margin-bottom:3rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mr-2{margin-right:.5rem}.mr-4{margin-right:1rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-1\.5{margin-top:.375rem}.mt-2{margin-top:.5rem}.mt-24{margin-top:6rem}.mt-4{margin-top:1rem}.mt-8{margin-top:2rem}.mt-auto{margin-top:auto}.line-clamp-2{-webkit-line-clamp:2}.line-clamp-2,.line-clamp-3{-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-3{-webkit-line-clamp:3}.block{display:block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.aspect-square{aspect-ratio:1/1}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-16{height:4rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-32{height:8rem}.h-4{height:1rem}.h-48{height:12rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-64{height:16rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-\[1px\]{height:1px}.h-\[var\(--radix-navigation-menu-viewport-height\)\]{height:var(--radix-navigation-menu-viewport-height)}.h-\[var\(--radix-select-trigger-height\)\]{height:var(--radix-select-trigger-height)}.h-auto{height:auto}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.max-h-\[--radix-context-menu-content-available-height\]{max-height:var(--radix-context-menu-content-available-height)}.max-h-\[--radix-select-content-available-height\]{max-height:var(--radix-select-content-available-height)}.max-h-\[300px\]{max-height:300px}.max-h-\[90vh\]{max-height:90vh}.max-h-\[var\(--radix-dropdown-menu-content-available-height\)\]{max-height:var(--radix-dropdown-menu-content-available-height)}.max-h-screen{max-height:100vh}.min-h-\[60px\]{min-height:60px}.min-h-screen{min-height:100vh}.w-10{width:2.5rem}.w-16{width:4rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-3\/4{width:75%}.w-32{width:8rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-7{width:1.75rem}.w-72{width:18rem}.w-8{width:2rem}.w-9{width:2.25rem}.w-\[100px\]{width:100px}.w-\[1px\]{width:1px}.w-full{width:100%}.w-max{width:-webkit-max-content;width:max-content}.w-px{width:1px}.min-w-0{min-width:0}.min-w-10{min-width:2.5rem}.min-w-8{min-width:2rem}.min-w-9{min-width:2.25rem}.min-w-\[12rem\]{min-width:12rem}.min-w-\[8rem\]{min-width:8rem}.min-w-\[var\(--radix-select-trigger-width\)\]{min-width:var(--radix-select-trigger-width)}.max-w-2xl{max-width:42rem}.max-w-4xl{max-width:56rem}.max-w-7xl{max-width:80rem}.max-w-lg{max-width:32rem}.max-w-max{max-width:-webkit-max-content;max-width:max-content}.max-w-md{max-width:28rem}.flex-1{flex:1 1}.flex-shrink-0,.shrink-0{flex-shrink:0}.grow{flex-grow:1}.grow-0{flex-grow:0}.basis-full{flex-basis:100%}.caption-bottom{caption-side:bottom}.border-collapse{border-collapse:collapse}.origin-\[--radix-context-menu-content-transform-origin\]{transform-origin:var(--radix-context-menu-content-transform-origin)}.origin-\[--radix-dropdown-menu-content-transform-origin\]{transform-origin:var(--radix-dropdown-menu-content-transform-origin)}.origin-\[--radix-hover-card-content-transform-origin\]{transform-origin:var(--radix-hover-card-content-transform-origin)}.origin-\[--radix-menubar-content-transform-origin\]{transform-origin:var(--radix-menubar-content-transform-origin)}.origin-\[--radix-popover-content-transform-origin\]{transform-origin:var(--radix-popover-content-transform-origin)}.origin-\[--radix-select-content-transform-origin\]{transform-origin:var(--radix-select-content-transform-origin)}.origin-\[--radix-tooltip-content-transform-origin\]{transform-origin:var(--radix-tooltip-content-transform-origin)}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-y-1\/2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y:-50%}.translate-x-\[-50\%\]{--tw-translate-x:-50%}.translate-x-\[-50\%\],.translate-y-\[-50\%\]{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-\[-50\%\]{--tw-translate-y:-50%}.rotate-45{--tw-rotate:45deg}.rotate-45,.rotate-90{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-90{--tw-rotate:90deg}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.select-none{-webkit-user-select:none;user-select:none}.list-none{list-style-type:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-12{gap:3rem}.gap-2{gap:.5rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.gap-8{gap:2rem}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.25rem*var(--tw-space-x-reverse))}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.5rem*var(--tw-space-x-reverse))}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.75rem*var(--tw-space-x-reverse))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1rem*var(--tw-space-x-reverse))}.space-x-8>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(2rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(2rem*var(--tw-space-x-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.25rem*var(--tw-space-y-reverse));margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.375rem*var(--tw-space-y-reverse));margin-top:calc(.375rem*(1 - var(--tw-space-y-reverse)))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.5rem*var(--tw-space-y-reverse));margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.75rem*var(--tw-space-y-reverse));margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1rem*var(--tw-space-y-reverse));margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1.5rem*var(--tw-space-y-reverse));margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.overflow-x-hidden{overflow-x:hidden}.whitespace-nowrap{white-space:nowrap}.break-words{overflow-wrap:break-word}.rounded-2xl{border-radius:1rem}.rounded-\[inherit\]{border-radius:inherit}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem;border-radius:var(--radius)}.rounded-md{border-radius:calc(.5rem - 2px);border-radius:calc(var(--radius) - 2px)}.rounded-sm{border-radius:calc(.5rem - 4px);border-radius:calc(var(--radius) - 4px)}.rounded-xl{border-radius:.75rem}.rounded-t-\[10px\]{border-top-left-radius:10px;border-top-right-radius:10px}.rounded-tl-sm{border-top-left-radius:calc(.5rem - 4px);border-top-left-radius:calc(var(--radius) - 4px)}.border{border-width:1px}.border-2{border-width:2px}.border-y{border-top-width:1px}.border-b,.border-y{border-bottom-width:1px}.border-l{border-left-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-destructive{border-color:#ef4444;border-color:hsl(var(--destructive))}.border-destructive\/50{border-color:#ef444480;border-color:hsl(var(--destructive)/.5)}.border-gray-700{--tw-border-opacity:1;border-color:#374151;border-color:rgb(55 65 81/var(--tw-border-opacity,1))}.border-input{border-color:#e5e5e5;border-color:hsl(var(--input))}.border-primary{border-color:#171717;border-color:hsl(var(--primary))}.border-primary\/50{border-color:#17171780;border-color:hsl(var(--primary)/.5)}.border-red-200{--tw-border-opacity:1;border-color:#fecaca;border-color:rgb(254 202 202/var(--tw-border-opacity,1))}.border-red-500{--tw-border-opacity:1;border-color:#ef4444;border-color:rgb(239 68 68/var(--tw-border-opacity,1))}.border-transparent{border-color:#0000}.border-white{--tw-border-opacity:1;border-color:#fff;border-color:rgb(255 255 255/var(--tw-border-opacity,1))}.border-white\/30{border-color:#ffffff4d}.border-l-transparent{border-left-color:#0000}.border-t-transparent{border-top-color:#0000}.bg-accent{background-color:#f5f5f5;background-color:hsl(var(--accent))}.bg-background{background-color:#fff;background-color:hsl(var(--background))}.bg-black\/80{background-color:#000c}.bg-border{background-color:#e5e5e5;background-color:hsl(var(--border))}.bg-card{background-color:#fff;background-color:hsl(var(--card))}.bg-cyan-600{--tw-bg-opacity:1;background-color:#0891b2;background-color:rgb(8 145 178/var(--tw-bg-opacity,1))}.bg-destructive{background-color:#ef4444;background-color:hsl(var(--destructive))}.bg-foreground{background-color:#0a0a0a;background-color:hsl(var(--foreground))}.bg-gray-50{--tw-bg-opacity:1;background-color:#f9fafb;background-color:rgb(249 250 251/var(--tw-bg-opacity,1))}.bg-gray-700{--tw-bg-opacity:1;background-color:#374151;background-color:rgb(55 65 81/var(--tw-bg-opacity,1))}.bg-muted{background-color:#f5f5f5;background-color:hsl(var(--muted))}.bg-muted\/50{background-color:#f5f5f580;background-color:hsl(var(--muted)/.5)}.bg-popover{background-color:#fff;background-color:hsl(var(--popover))}.bg-primary{background-color:#171717;background-color:hsl(var(--primary))}.bg-primary\/10{background-color:#1717171a;background-color:hsl(var(--primary)/.1)}.bg-primary\/20{background-color:#17171733;background-color:hsl(var(--primary)/.2)}.bg-red-500{--tw-bg-opacity:1;background-color:#ef4444;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.bg-secondary{background-color:#f5f5f5;background-color:hsl(var(--secondary))}.bg-transparent{background-color:initial}.bg-white{--tw-bg-opacity:1;background-color:#fff;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.bg-white\/20{background-color:#fff3}.bg-white\/95{background-color:#fffffff2}.bg-gradient-to-br{background-image:linear-gradient(to bottom right,var(--tw-gradient-stops))}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.from-blue-50{--tw-gradient-from:#eff6ff var(--tw-gradient-from-position);--tw-gradient-to:#eff6ff00 var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-cyan-50{--tw-gradient-from:#ecfeff var(--tw-gradient-from-position);--tw-gradient-to:#ecfeff00 var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-cyan-500{--tw-gradient-from:#06b6d4 var(--tw-gradient-from-position);--tw-gradient-to:#06b6d400 var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-cyan-600{--tw-gradient-from:#0891b2 var(--tw-gradient-from-position);--tw-gradient-to:#0891b200 var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-cyan-900\/80{--tw-gradient-from:#164e63cc var(--tw-gradient-from-position);--tw-gradient-to:#164e6300 var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-gray-900{--tw-gradient-from:#111827 var(--tw-gradient-from-position);--tw-gradient-to:#11182700 var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.to-blue-100{--tw-gradient-to:#dbeafe var(--tw-gradient-to-position)}.to-blue-50{--tw-gradient-to:#eff6ff var(--tw-gradient-to-position)}.to-blue-600{--tw-gradient-to:#2563eb var(--tw-gradient-to-position)}.to-blue-700{--tw-gradient-to:#1d4ed8 var(--tw-gradient-to-position)}.to-blue-900\/70{--tw-gradient-to:#1e3a8ab3 var(--tw-gradient-to-position)}.to-cyan-50{--tw-gradient-to:#ecfeff var(--tw-gradient-to-position)}.to-gray-800{--tw-gradient-to:#1f2937 var(--tw-gradient-to-position)}.bg-clip-text{-webkit-background-clip:text;background-clip:text}.fill-current{fill:currentColor}.fill-primary{fill:#171717;fill:hsl(var(--primary))}.fill-yellow-400{fill:#facc15}.object-cover{object-fit:cover}.p-0{padding:0}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.p-\[1px\]{padding:1px}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-8{padding-left:2rem;padding-right:2rem}.py-0\.5{padding-bottom:.125rem;padding-top:.125rem}.py-1{padding-bottom:.25rem;padding-top:.25rem}.py-1\.5{padding-bottom:.375rem;padding-top:.375rem}.py-12{padding-bottom:3rem;padding-top:3rem}.py-2{padding-bottom:.5rem;padding-top:.5rem}.py-20{padding-bottom:5rem;padding-top:5rem}.py-3{padding-bottom:.75rem;padding-top:.75rem}.py-4{padding-bottom:1rem;padding-top:1rem}.py-6{padding-bottom:1.5rem;padding-top:1.5rem}.py-8{padding-bottom:2rem;padding-top:2rem}.pb-4{padding-bottom:1rem}.pl-10{padding-left:2.5rem}.pl-2{padding-left:.5rem}.pl-2\.5{padding-left:.625rem}.pl-4{padding-left:1rem}.pl-8{padding-left:2rem}.pr-2{padding-right:.5rem}.pr-2\.5{padding-right:.625rem}.pr-6{padding-right:1.5rem}.pr-8{padding-right:2rem}.pt-0{padding-top:0}.pt-1{padding-top:.25rem}.pt-4{padding-top:1rem}.pt-6{padding-top:1.5rem}.pt-8{padding-top:2rem}.text-left{text-align:left}.text-center{text-align:center}.align-middle{vertical-align:middle}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-5xl{font-size:3rem;line-height:1}.text-\[0\.8rem\]{font-size:.8rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.italic{font-style:italic}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.tracking-tight{letter-spacing:-.025em}.tracking-widest{letter-spacing:.1em}.text-accent-foreground{color:#171717;color:hsl(var(--accent-foreground))}.text-card-foreground{color:#0a0a0a;color:hsl(var(--card-foreground))}.text-current{color:currentColor}.text-cyan-100{--tw-text-opacity:1;color:#cffafe;color:rgb(207 250 254/var(--tw-text-opacity,1))}.text-cyan-400{--tw-text-opacity:1;color:#22d3ee;color:rgb(34 211 238/var(--tw-text-opacity,1))}.text-cyan-50{--tw-text-opacity:1;color:#ecfeff;color:rgb(236 254 255/var(--tw-text-opacity,1))}.text-cyan-600{--tw-text-opacity:1;color:#0891b2;color:rgb(8 145 178/var(--tw-text-opacity,1))}.text-destructive{color:#ef4444;color:hsl(var(--destructive))}.text-destructive-foreground{color:#fafafa;color:hsl(var(--destructive-foreground))}.text-foreground{color:#0a0a0a;color:hsl(var(--foreground))}.text-foreground\/50{color:#0a0a0a80;color:hsl(var(--foreground)/.5)}.text-gray-300{--tw-text-opacity:1;color:#d1d5db;color:rgb(209 213 219/var(--tw-text-opacity,1))}.text-gray-400{--tw-text-opacity:1;color:#9ca3af;color:rgb(156 163 175/var(--tw-text-opacity,1))}.text-gray-500{--tw-text-opacity:1;color:#6b7280;color:rgb(107 114 128/var(--tw-text-opacity,1))}.text-gray-600{--tw-text-opacity:1;color:#4b5563;color:rgb(75 85 99/var(--tw-text-opacity,1))}.text-gray-700{--tw-text-opacity:1;color:#374151;color:rgb(55 65 81/var(--tw-text-opacity,1))}.text-gray-900{--tw-text-opacity:1;color:#111827;color:rgb(17 24 39/var(--tw-text-opacity,1))}.text-muted-foreground{color:#737373;color:hsl(var(--muted-foreground))}.text-popover-foreground{color:#0a0a0a;color:hsl(var(--popover-foreground))}.text-primary{color:#171717;color:hsl(var(--primary))}.text-primary-foreground{color:#fafafa;color:hsl(var(--primary-foreground))}.text-red-500{--tw-text-opacity:1;color:#ef4444;color:rgb(239 68 68/var(--tw-text-opacity,1))}.text-red-600{--tw-text-opacity:1;color:#dc2626;color:rgb(220 38 38/var(--tw-text-opacity,1))}.text-secondary-foreground{color:#171717;color:hsl(var(--secondary-foreground))}.text-transparent{color:#0000}.text-white{--tw-text-opacity:1;color:#fff;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-yellow-400{--tw-text-opacity:1;color:#facc15;color:rgb(250 204 21/var(--tw-text-opacity,1))}.line-through{-webkit-text-decoration-line:line-through;text-decoration-line:line-through}.underline-offset-4{text-underline-offset:4px}.opacity-0{opacity:0}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-90{opacity:.9}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-lg{box-shadow:0 0 #0000,0 0 #0000,var(--tw-shadow);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-md{--tw-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a;--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.shadow-md,.shadow-sm{box-shadow:0 0 #0000,0 0 #0000,var(--tw-shadow);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 2px 0 #0000000d;--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)}.outline-none{outline:2px solid #0000;outline-offset:2px}.outline{outline-style:solid}.ring-0{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring-0,.ring-1{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),0 0 #0000;box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring-ring{--tw-ring-color:hsl(var(--ring))}.ring-offset-background{--tw-ring-offset-color:hsl(var(--background))}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-md{--tw-backdrop-blur:blur(12px)}.backdrop-blur-md,.backdrop-blur-sm{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-sm{--tw-backdrop-blur:blur(4px)}.transition{transition-duration:.15s;transition-property:color,background-color,border-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-text-decoration-color,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-text-decoration-color,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-all{transition-duration:.15s;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-colors{transition-duration:.15s;transition-property:color,background-color,border-color,fill,stroke,-webkit-text-decoration-color;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,-webkit-text-decoration-color;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-opacity{transition-duration:.15s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-shadow{transition-duration:.15s;transition-property:box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-transform{transition-duration:.15s;transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.delay-100{transition-delay:.1s}.delay-200{transition-delay:.2s}.duration-1000{transition-duration:1s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.duration-700{transition-duration:.7s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}@keyframes enter{0%{opacity:1;opacity:var(--tw-enter-opacity,1);transform:translateZ(0) scaleX(1) rotate(0);transform:translate3d(var(--tw-enter-translate-x,0),var(--tw-enter-translate-y,0),0) scale3d(var(--tw-enter-scale,1),var(--tw-enter-scale,1),var(--tw-enter-scale,1)) rotate(var(--tw-enter-rotate,0))}}@keyframes exit{to{opacity:1;opacity:var(--tw-exit-opacity,1);transform:translateZ(0) scaleX(1) rotate(0);transform:translate3d(var(--tw-exit-translate-x,0),var(--tw-exit-translate-y,0),0) scale3d(var(--tw-exit-scale,1),var(--tw-exit-scale,1),var(--tw-exit-scale,1)) rotate(var(--tw-exit-rotate,0))}}.animate-in{--tw-enter-opacity:initial;--tw-enter-scale:initial;--tw-enter-rotate:initial;--tw-enter-translate-x:initial;--tw-enter-translate-y:initial;animation-duration:.15s;animation-name:enter}.fade-in,.fade-in-0{--tw-enter-opacity:0}.zoom-in-95{--tw-enter-scale:.95}.slide-in-from-bottom{--tw-enter-translate-y:100%}.slide-in-from-top{--tw-enter-translate-y:-100%}.duration-1000{animation-duration:1s}.duration-200{animation-duration:.2s}.duration-300{animation-duration:.3s}.duration-500{animation-duration:.5s}.duration-700{animation-duration:.7s}.delay-100{animation-delay:.1s}.delay-200{animation-delay:.2s}.ease-in-out{animation-timing-function:cubic-bezier(.4,0,.2,1)}.running{animation-play-state:running}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;margin:0}code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}.file\:border-0::-webkit-file-upload-button{border-width:0}.file\:border-0::file-selector-button{border-width:0}.file\:bg-transparent::-webkit-file-upload-button{background-color:initial}.file\:bg-transparent::file-selector-button{background-color:initial}.file\:text-sm::-webkit-file-upload-button{font-size:.875rem;line-height:1.25rem}.file\:text-sm::file-selector-button{font-size:.875rem;line-height:1.25rem}.file\:font-medium::-webkit-file-upload-button{font-weight:500}.file\:font-medium::file-selector-button{font-weight:500}.file\:text-foreground::-webkit-file-upload-button{color:#0a0a0a;color:hsl(var(--foreground))}.file\:text-foreground::file-selector-button{color:#0a0a0a;color:hsl(var(--foreground))}.placeholder\:text-cyan-100::placeholder{--tw-text-opacity:1;color:#cffafe;color:rgb(207 250 254/var(--tw-text-opacity,1))}.placeholder\:text-muted-foreground::placeholder{color:#737373;color:hsl(var(--muted-foreground))}.after\:absolute:after{content:var(--tw-content);position:absolute}.after\:inset-y-0:after{bottom:0;content:var(--tw-content);top:0}.after\:left-1\/2:after{content:var(--tw-content);left:50%}.after\:w-1:after{content:var(--tw-content);width:.25rem}.after\:-translate-x-1\/2:after{--tw-translate-x:-50%;content:var(--tw-content);transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.first\:rounded-l-md:first-child{border-bottom-left-radius:calc(.5rem - 2px);border-bottom-left-radius:calc(var(--radius) - 2px);border-top-left-radius:calc(.5rem - 2px);border-top-left-radius:calc(var(--radius) - 2px)}.first\:border-l:first-child{border-left-width:1px}.last\:rounded-r-md:last-child{border-bottom-right-radius:calc(.5rem - 2px);border-bottom-right-radius:calc(var(--radius) - 2px);border-top-right-radius:calc(.5rem - 2px);border-top-right-radius:calc(var(--radius) - 2px)}.focus-within\:relative:focus-within{position:relative}.focus-within\:z-20:focus-within{z-index:20}.hover\:bg-accent:hover{background-color:#f5f5f5;background-color:hsl(var(--accent))}.hover\:bg-cyan-50:hover{--tw-bg-opacity:1;background-color:#ecfeff;background-color:rgb(236 254 255/var(--tw-bg-opacity,1))}.hover\:bg-cyan-600:hover{--tw-bg-opacity:1;background-color:#0891b2;background-color:rgb(8 145 178/var(--tw-bg-opacity,1))}.hover\:bg-cyan-700:hover{--tw-bg-opacity:1;background-color:#0e7490;background-color:rgb(14 116 144/var(--tw-bg-opacity,1))}.hover\:bg-destructive\/80:hover{background-color:#ef4444cc;background-color:hsl(var(--destructive)/.8)}.hover\:bg-destructive\/90:hover{background-color:#ef4444e6;background-color:hsl(var(--destructive)/.9)}.hover\:bg-muted:hover{background-color:#f5f5f5;background-color:hsl(var(--muted))}.hover\:bg-muted\/50:hover{background-color:#f5f5f580;background-color:hsl(var(--muted)/.5)}.hover\:bg-primary:hover{background-color:#171717;background-color:hsl(var(--primary))}.hover\:bg-primary\/80:hover{background-color:#171717cc;background-color:hsl(var(--primary)/.8)}.hover\:bg-primary\/90:hover{background-color:#171717e6;background-color:hsl(var(--primary)/.9)}.hover\:bg-red-50:hover{--tw-bg-opacity:1;background-color:#fef2f2;background-color:rgb(254 242 242/var(--tw-bg-opacity,1))}.hover\:bg-secondary:hover{background-color:#f5f5f5;background-color:hsl(var(--secondary))}.hover\:bg-secondary\/80:hover{background-color:#f5f5f5cc;background-color:hsl(var(--secondary)/.8)}.hover\:bg-white:hover{--tw-bg-opacity:1;background-color:#fff;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.hover\:text-accent-foreground:hover{color:#171717;color:hsl(var(--accent-foreground))}.hover\:text-cyan-400:hover{--tw-text-opacity:1;color:#22d3ee;color:rgb(34 211 238/var(--tw-text-opacity,1))}.hover\:text-cyan-600:hover{--tw-text-opacity:1;color:#0891b2;color:rgb(8 145 178/var(--tw-text-opacity,1))}.hover\:text-foreground:hover{color:#0a0a0a;color:hsl(var(--foreground))}.hover\:text-muted-foreground:hover{color:#737373;color:hsl(var(--muted-foreground))}.hover\:text-primary-foreground:hover{color:#fafafa;color:hsl(var(--primary-foreground))}.hover\:underline:hover{-webkit-text-decoration-line:underline;text-decoration-line:underline}.hover\:opacity-100:hover{opacity:1}.hover\:shadow-2xl:hover{--tw-shadow:0 25px 50px -12px #00000040;--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.hover\:shadow-2xl:hover,.hover\:shadow-xl:hover{box-shadow:0 0 #0000,0 0 #0000,var(--tw-shadow);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hover\:shadow-xl:hover{--tw-shadow:0 20px 25px -5px #0000001a,0 8px 10px -6px #0000001a;--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px var(--tw-shadow-color)}.focus\:bg-accent:focus{background-color:#f5f5f5;background-color:hsl(var(--accent))}.focus\:bg-primary:focus{background-color:#171717;background-color:hsl(var(--primary))}.focus\:text-accent-foreground:focus{color:#171717;color:hsl(var(--accent-foreground))}.focus\:text-primary-foreground:focus{color:#fafafa;color:hsl(var(--primary-foreground))}.focus\:opacity-100:focus{opacity:1}.focus\:outline-none:focus{outline:2px solid #0000;outline-offset:2px}.focus\:ring-1:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-1:focus,.focus\:ring-2:focus{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),0 0 #0000;box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-ring:focus{--tw-ring-color:hsl(var(--ring))}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px}.focus-visible\:outline-none:focus-visible{outline:2px solid #0000;outline-offset:2px}.focus-visible\:ring-1:focus-visible{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),0 0 #0000;box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus-visible\:ring-2:focus-visible{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),0 0 #0000;box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus-visible\:ring-ring:focus-visible{--tw-ring-color:hsl(var(--ring))}.focus-visible\:ring-offset-1:focus-visible{--tw-ring-offset-width:1px}.focus-visible\:ring-offset-2:focus-visible{--tw-ring-offset-width:2px}.focus-visible\:ring-offset-background:focus-visible{--tw-ring-offset-color:hsl(var(--background))}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.group:hover .group-hover\:scale-110{--tw-scale-x:1.1;--tw-scale-y:1.1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:hover .group-hover\:opacity-100{opacity:1}.group.destructive .group-\[\.destructive\]\:border-muted\/40{border-color:#f5f5f566;border-color:hsl(var(--muted)/.4)}.group.toaster .group-\[\.toaster\]\:border-border{border-color:#e5e5e5;border-color:hsl(var(--border))}.group.toast .group-\[\.toast\]\:bg-muted{background-color:#f5f5f5;background-color:hsl(var(--muted))}.group.toast .group-\[\.toast\]\:bg-primary{background-color:#171717;background-color:hsl(var(--primary))}.group.toaster .group-\[\.toaster\]\:bg-background{background-color:#fff;background-color:hsl(var(--background))}.group.destructive .group-\[\.destructive\]\:text-red-300{--tw-text-opacity:1;color:#fca5a5;color:rgb(252 165 165/var(--tw-text-opacity,1))}.group.toast .group-\[\.toast\]\:text-muted-foreground{color:#737373;color:hsl(var(--muted-foreground))}.group.toast .group-\[\.toast\]\:text-primary-foreground{color:#fafafa;color:hsl(var(--primary-foreground))}.group.toaster .group-\[\.toaster\]\:text-foreground{color:#0a0a0a;color:hsl(var(--foreground))}.group.toaster .group-\[\.toaster\]\:shadow-lg{--tw-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color);box-shadow:0 0 #0000,0 0 #0000,var(--tw-shadow);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.group.destructive .group-\[\.destructive\]\:hover\:border-destructive\/30:hover{border-color:#ef44444d;border-color:hsl(var(--destructive)/.3)}.group.destructive .group-\[\.destructive\]\:hover\:bg-destructive:hover{background-color:#ef4444;background-color:hsl(var(--destructive))}.group.destructive .group-\[\.destructive\]\:hover\:text-destructive-foreground:hover{color:#fafafa;color:hsl(var(--destructive-foreground))}.group.destructive .group-\[\.destructive\]\:hover\:text-red-50:hover{--tw-text-opacity:1;color:#fef2f2;color:rgb(254 242 242/var(--tw-text-opacity,1))}.group.destructive .group-\[\.destructive\]\:focus\:ring-destructive:focus{--tw-ring-color:hsl(var(--destructive))}.group.destructive .group-\[\.destructive\]\:focus\:ring-red-400:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(248 113 113/var(--tw-ring-opacity,1))}.group.destructive .group-\[\.destructive\]\:focus\:ring-offset-red-600:focus{--tw-ring-offset-color:#dc2626}.peer:disabled~.peer-disabled\:cursor-not-allowed{cursor:not-allowed}.peer:disabled~.peer-disabled\:opacity-70{opacity:.7}.has-\[\:disabled\]\:opacity-50:has(:disabled){opacity:.5}.aria-selected\:bg-accent[aria-selected=true]{background-color:#f5f5f5;background-color:hsl(var(--accent))}.aria-selected\:bg-accent\/50[aria-selected=true]{background-color:#f5f5f580;background-color:hsl(var(--accent)/.5)}.aria-selected\:text-accent-foreground[aria-selected=true]{color:#171717;color:hsl(var(--accent-foreground))}.aria-selected\:text-muted-foreground[aria-selected=true]{color:#737373;color:hsl(var(--muted-foreground))}.aria-selected\:opacity-100[aria-selected=true]{opacity:1}.data-\[disabled\=true\]\:pointer-events-none[data-disabled=true],.data-\[disabled\]\:pointer-events-none[data-disabled]{pointer-events:none}.data-\[panel-group-direction\=vertical\]\:h-px[data-panel-group-direction=vertical]{height:1px}.data-\[panel-group-direction\=vertical\]\:w-full[data-panel-group-direction=vertical]{width:100%}.data-\[side\=bottom\]\:translate-y-1[data-side=bottom]{--tw-translate-y:0.25rem}.data-\[side\=bottom\]\:translate-y-1[data-side=bottom],.data-\[side\=left\]\:-translate-x-1[data-side=left]{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.data-\[side\=left\]\:-translate-x-1[data-side=left]{--tw-translate-x:-0.25rem}.data-\[side\=right\]\:translate-x-1[data-side=right]{--tw-translate-x:0.25rem}.data-\[side\=right\]\:translate-x-1[data-side=right],.data-\[side\=top\]\:-translate-y-1[data-side=top]{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.data-\[side\=top\]\:-translate-y-1[data-side=top]{--tw-translate-y:-0.25rem}.data-\[state\=checked\]\:translate-x-4[data-state=checked]{--tw-translate-x:1rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.data-\[state\=unchecked\]\:translate-x-0[data-state=unchecked],.data-\[swipe\=cancel\]\:translate-x-0[data-swipe=cancel]{--tw-translate-x:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.data-\[swipe\=end\]\:translate-x-\[var\(--radix-toast-swipe-end-x\)\][data-swipe=end]{--tw-translate-x:var(--radix-toast-swipe-end-x)}.data-\[swipe\=end\]\:translate-x-\[var\(--radix-toast-swipe-end-x\)\][data-swipe=end],.data-\[swipe\=move\]\:translate-x-\[var\(--radix-toast-swipe-move-x\)\][data-swipe=move]{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.data-\[swipe\=move\]\:translate-x-\[var\(--radix-toast-swipe-move-x\)\][data-swipe=move]{--tw-translate-x:var(--radix-toast-swipe-move-x)}@keyframes accordion-up{0%{height:var(--radix-accordion-content-height)}to{height:0}}.data-\[state\=closed\]\:animate-accordion-up[data-state=closed]{animation:accordion-up .2s ease-out}@keyframes accordion-down{0%{height:0}to{height:var(--radix-accordion-content-height)}}.data-\[state\=open\]\:animate-accordion-down[data-state=open]{animation:accordion-down .2s ease-out}.data-\[panel-group-direction\=vertical\]\:flex-col[data-panel-group-direction=vertical]{flex-direction:column}.data-\[selected\=true\]\:bg-accent[data-selected=true]{background-color:#f5f5f5;background-color:hsl(var(--accent))}.data-\[state\=active\]\:bg-background[data-state=active]{background-color:#fff;background-color:hsl(var(--background))}.data-\[state\=checked\]\:bg-primary[data-state=checked]{background-color:#171717;background-color:hsl(var(--primary))}.data-\[state\=on\]\:bg-accent[data-state=on],.data-\[state\=open\]\:bg-accent[data-state=open]{background-color:#f5f5f5;background-color:hsl(var(--accent))}.data-\[state\=open\]\:bg-accent\/50[data-state=open]{background-color:#f5f5f580;background-color:hsl(var(--accent)/.5)}.data-\[state\=open\]\:bg-secondary[data-state=open]{background-color:#f5f5f5;background-color:hsl(var(--secondary))}.data-\[state\=selected\]\:bg-muted[data-state=selected]{background-color:#f5f5f5;background-color:hsl(var(--muted))}.data-\[state\=unchecked\]\:bg-input[data-state=unchecked]{background-color:#e5e5e5;background-color:hsl(var(--input))}.data-\[placeholder\]\:text-muted-foreground[data-placeholder]{color:#737373;color:hsl(var(--muted-foreground))}.data-\[selected\=true\]\:text-accent-foreground[data-selected=true]{color:#171717;color:hsl(var(--accent-foreground))}.data-\[state\=active\]\:text-foreground[data-state=active]{color:#0a0a0a;color:hsl(var(--foreground))}.data-\[state\=checked\]\:text-primary-foreground[data-state=checked]{color:#fafafa;color:hsl(var(--primary-foreground))}.data-\[state\=on\]\:text-accent-foreground[data-state=on],.data-\[state\=open\]\:text-accent-foreground[data-state=open]{color:#171717;color:hsl(var(--accent-foreground))}.data-\[state\=open\]\:text-muted-foreground[data-state=open]{color:#737373;color:hsl(var(--muted-foreground))}.data-\[disabled\=true\]\:opacity-50[data-disabled=true],.data-\[disabled\]\:opacity-50[data-disabled]{opacity:.5}.data-\[state\=active\]\:shadow[data-state=active]{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color);box-shadow:0 0 #0000,0 0 #0000,var(--tw-shadow);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.data-\[swipe\=move\]\:transition-none[data-swipe=move]{transition-property:none}.data-\[state\=closed\]\:duration-300[data-state=closed]{transition-duration:.3s}.data-\[state\=open\]\:duration-500[data-state=open]{transition-duration:.5s}.data-\[motion\^\=from-\]\:animate-in[data-motion^=from-],.data-\[state\=open\]\:animate-in[data-state=open],.data-\[state\=visible\]\:animate-in[data-state=visible]{--tw-enter-opacity:initial;--tw-enter-scale:initial;--tw-enter-rotate:initial;--tw-enter-translate-x:initial;--tw-enter-translate-y:initial;animation-duration:.15s;animation-name:enter}.data-\[motion\^\=to-\]\:animate-out[data-motion^=to-],.data-\[state\=closed\]\:animate-out[data-state=closed],.data-\[state\=hidden\]\:animate-out[data-state=hidden],.data-\[swipe\=end\]\:animate-out[data-swipe=end]{--tw-exit-opacity:initial;--tw-exit-scale:initial;--tw-exit-rotate:initial;--tw-exit-translate-x:initial;--tw-exit-translate-y:initial;animation-duration:.15s;animation-name:exit}.data-\[motion\^\=from-\]\:fade-in[data-motion^=from-]{--tw-enter-opacity:0}.data-\[motion\^\=to-\]\:fade-out[data-motion^=to-],.data-\[state\=closed\]\:fade-out-0[data-state=closed]{--tw-exit-opacity:0}.data-\[state\=closed\]\:fade-out-80[data-state=closed]{--tw-exit-opacity:0.8}.data-\[state\=hidden\]\:fade-out[data-state=hidden]{--tw-exit-opacity:0}.data-\[state\=open\]\:fade-in-0[data-state=open],.data-\[state\=visible\]\:fade-in[data-state=visible]{--tw-enter-opacity:0}.data-\[state\=closed\]\:zoom-out-95[data-state=closed]{--tw-exit-scale:.95}.data-\[state\=open\]\:zoom-in-90[data-state=open]{--tw-enter-scale:.9}.data-\[state\=open\]\:zoom-in-95[data-state=open]{--tw-enter-scale:.95}.data-\[motion\=from-end\]\:slide-in-from-right-52[data-motion=from-end]{--tw-enter-translate-x:13rem}.data-\[motion\=from-start\]\:slide-in-from-left-52[data-motion=from-start]{--tw-enter-translate-x:-13rem}.data-\[motion\=to-end\]\:slide-out-to-right-52[data-motion=to-end]{--tw-exit-translate-x:13rem}.data-\[motion\=to-start\]\:slide-out-to-left-52[data-motion=to-start]{--tw-exit-translate-x:-13rem}.data-\[side\=bottom\]\:slide-in-from-top-2[data-side=bottom]{--tw-enter-translate-y:-0.5rem}.data-\[side\=left\]\:slide-in-from-right-2[data-side=left]{--tw-enter-translate-x:0.5rem}.data-\[side\=right\]\:slide-in-from-left-2[data-side=right]{--tw-enter-translate-x:-0.5rem}.data-\[side\=top\]\:slide-in-from-bottom-2[data-side=top]{--tw-enter-translate-y:0.5rem}.data-\[state\=closed\]\:slide-out-to-bottom[data-state=closed]{--tw-exit-translate-y:100%}.data-\[state\=closed\]\:slide-out-to-left[data-state=closed]{--tw-exit-translate-x:-100%}.data-\[state\=closed\]\:slide-out-to-left-1\/2[data-state=closed]{--tw-exit-translate-x:-50%}.data-\[state\=closed\]\:slide-out-to-right-full[data-state=closed],.data-\[state\=closed\]\:slide-out-to-right[data-state=closed]{--tw-exit-translate-x:100%}.data-\[state\=closed\]\:slide-out-to-top[data-state=closed]{--tw-exit-translate-y:-100%}.data-\[state\=closed\]\:slide-out-to-top-\[48\%\][data-state=closed]{--tw-exit-translate-y:-48%}.data-\[state\=open\]\:slide-in-from-bottom[data-state=open]{--tw-enter-translate-y:100%}.data-\[state\=open\]\:slide-in-from-left[data-state=open]{--tw-enter-translate-x:-100%}.data-\[state\=open\]\:slide-in-from-left-1\/2[data-state=open]{--tw-enter-translate-x:-50%}.data-\[state\=open\]\:slide-in-from-right[data-state=open]{--tw-enter-translate-x:100%}.data-\[state\=open\]\:slide-in-from-top[data-state=open]{--tw-enter-translate-y:-100%}.data-\[state\=open\]\:slide-in-from-top-\[48\%\][data-state=open]{--tw-enter-translate-y:-48%}.data-\[state\=open\]\:slide-in-from-top-full[data-state=open]{--tw-enter-translate-y:-100%}.data-\[state\=closed\]\:duration-300[data-state=closed]{animation-duration:.3s}.data-\[state\=open\]\:duration-500[data-state=open]{animation-duration:.5s}.data-\[panel-group-direction\=vertical\]\:after\:left-0[data-panel-group-direction=vertical]:after{content:var(--tw-content);left:0}.data-\[panel-group-direction\=vertical\]\:after\:h-1[data-panel-group-direction=vertical]:after{content:var(--tw-content);height:.25rem}.data-\[panel-group-direction\=vertical\]\:after\:w-full[data-panel-group-direction=vertical]:after{content:var(--tw-content);width:100%}.data-\[panel-group-direction\=vertical\]\:after\:-translate-y-1\/2[data-panel-group-direction=vertical]:after{--tw-translate-y:-50%;content:var(--tw-content);transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.data-\[panel-group-direction\=vertical\]\:after\:translate-x-0[data-panel-group-direction=vertical]:after{--tw-translate-x:0px;content:var(--tw-content);transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.data-\[state\=open\]\:focus\:bg-accent:focus[data-state=open],.data-\[state\=open\]\:hover\:bg-accent:hover[data-state=open]{background-color:#f5f5f5;background-color:hsl(var(--accent))}.group[data-state=open] .group-data-\[state\=open\]\:rotate-180{--tw-rotate:180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.dark\:border-destructive:is(.dark *){border-color:#ef4444;border-color:hsl(var(--destructive))}@media (min-width:640px){.sm\:bottom-0{bottom:0}.sm\:right-0{right:0}.sm\:top-auto{top:auto}.sm\:mt-0{margin-top:0}.sm\:max-w-sm{max-width:24rem}.sm\:flex-row{flex-direction:row}.sm\:flex-col{flex-direction:column}.sm\:justify-end{justify-content:flex-end}.sm\:gap-2\.5{gap:.625rem}.sm\:space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.5rem*var(--tw-space-x-reverse))}.sm\:space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1rem*var(--tw-space-x-reverse))}.sm\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(0px*var(--tw-space-y-reverse));margin-top:calc(0px*(1 - var(--tw-space-y-reverse)))}.sm\:rounded-lg{border-radius:.5rem;border-radius:var(--radius)}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:text-left{text-align:left}.data-\[state\=open\]\:sm\:slide-in-from-bottom-full[data-state=open]{--tw-enter-translate-y:100%}}@media (min-width:768px){.md\:absolute{position:absolute}.md\:flex{display:flex}.md\:hidden{display:none}.md\:w-96{width:24rem}.md\:w-\[var\(--radix-navigation-menu-viewport-width\)\]{width:var(--radix-navigation-menu-viewport-width)}.md\:w-auto{width:auto}.md\:max-w-\[420px\]{max-width:420px}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:flex-row{flex-direction:row}.md\:p-12{padding:3rem}.md\:text-2xl{font-size:1.5rem;line-height:2rem}.md\:text-4xl{font-size:2.25rem;line-height:2.5rem}.md\:text-5xl{font-size:3rem;line-height:1}.md\:text-7xl{font-size:4.5rem;line-height:1}.md\:text-sm{font-size:.875rem;line-height:1.25rem}}@media (min-width:1024px){.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:px-8{padding-left:2rem;padding-right:2rem}}.\[\&\+div\]\:text-xs+div{font-size:.75rem;line-height:1rem}.\[\&\:has\(\>\.day-range-end\)\]\:rounded-r-md:has(>.day-range-end){border-bottom-right-radius:calc(.5rem - 2px);border-bottom-right-radius:calc(var(--radius) - 2px);border-top-right-radius:calc(.5rem - 2px);border-top-right-radius:calc(var(--radius) - 2px)}.\[\&\:has\(\>\.day-range-start\)\]\:rounded-l-md:has(>.day-range-start){border-bottom-left-radius:calc(.5rem - 2px);border-bottom-left-radius:calc(var(--radius) - 2px);border-top-left-radius:calc(.5rem - 2px);border-top-left-radius:calc(var(--radius) - 2px)}.\[\&\:has\(\[aria-selected\]\)\]\:rounded-md:has([aria-selected]){border-radius:calc(.5rem - 2px);border-radius:calc(var(--radius) - 2px)}.\[\&\:has\(\[aria-selected\]\)\]\:bg-accent:has([aria-selected]){background-color:#f5f5f5;background-color:hsl(var(--accent))}.first\:\[\&\:has\(\[aria-selected\]\)\]\:rounded-l-md:has([aria-selected]):first-child{border-bottom-left-radius:calc(.5rem - 2px);border-bottom-left-radius:calc(var(--radius) - 2px);border-top-left-radius:calc(.5rem - 2px);border-top-left-radius:calc(var(--radius) - 2px)}.last\:\[\&\:has\(\[aria-selected\]\)\]\:rounded-r-md:has([aria-selected]):last-child{border-bottom-right-radius:calc(.5rem - 2px);border-bottom-right-radius:calc(var(--radius) - 2px);border-top-right-radius:calc(.5rem - 2px);border-top-right-radius:calc(var(--radius) - 2px)}.\[\&\:has\(\[aria-selected\]\.day-outside\)\]\:bg-accent\/50:has([aria-selected].day-outside){background-color:#f5f5f580;background-color:hsl(var(--accent)/.5)}.\[\&\:has\(\[aria-selected\]\.day-range-end\)\]\:rounded-r-md:has([aria-selected].day-range-end){border-bottom-right-radius:calc(.5rem - 2px);border-bottom-right-radius:calc(var(--radius) - 2px);border-top-right-radius:calc(.5rem - 2px);border-top-right-radius:calc(var(--radius) - 2px)}.\[\&\:has\(\[role\=checkbox\]\)\]\:pr-0:has([role=checkbox]){padding-right:0}.\[\&\>\[role\=checkbox\]\]\:translate-y-\[2px\]>[role=checkbox]{--tw-translate-y:2px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.\[\&\>span\]\:line-clamp-1>span{-webkit-box-orient:vertical;-webkit-line-clamp:1;display:-webkit-box;overflow:hidden}.\[\&\>svg\+div\]\:translate-y-\[-3px\]>svg+div{--tw-translate-y:-3px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.\[\&\>svg\]\:absolute>svg{position:absolute}.\[\&\>svg\]\:left-4>svg{left:1rem}.\[\&\>svg\]\:top-4>svg{top:1rem}.\[\&\>svg\]\:size-4>svg{height:1rem;width:1rem}.\[\&\>svg\]\:h-3\.5>svg{height:.875rem}.\[\&\>svg\]\:w-3\.5>svg{width:.875rem}.\[\&\>svg\]\:shrink-0>svg{flex-shrink:0}.\[\&\>svg\]\:text-destructive>svg{color:#ef4444;color:hsl(var(--destructive))}.\[\&\>svg\]\:text-foreground>svg{color:#0a0a0a;color:hsl(var(--foreground))}.\[\&\>svg\~\*\]\:pl-7>svg~*{padding-left:1.75rem}.\[\&\>tr\]\:last\:border-b-0:last-child>tr{border-bottom-width:0}.\[\&\[data-panel-group-direction\=vertical\]\>div\]\:rotate-90[data-panel-group-direction=vertical]>div{--tw-rotate:90deg}.\[\&\[data-panel-group-direction\=vertical\]\>div\]\:rotate-90[data-panel-group-direction=vertical]>div,.\[\&\[data-state\=open\]\>svg\]\:rotate-180[data-state=open]>svg{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.\[\&\[data-state\=open\]\>svg\]\:rotate-180[data-state=open]>svg{--tw-rotate:180deg}.\[\&_\[cmdk-group-heading\]\]\:px-2 [cmdk-group-heading]{padding-left:.5rem;padding-right:.5rem}.\[\&_\[cmdk-group-heading\]\]\:py-1\.5 [cmdk-group-heading]{padding-bottom:.375rem;padding-top:.375rem}.\[\&_\[cmdk-group-heading\]\]\:text-xs [cmdk-group-heading]{font-size:.75rem;line-height:1rem}.\[\&_\[cmdk-group-heading\]\]\:font-medium [cmdk-group-heading]{font-weight:500}.\[\&_\[cmdk-group-heading\]\]\:text-muted-foreground [cmdk-group-heading]{color:#737373;color:hsl(var(--muted-foreground))}.\[\&_\[cmdk-group\]\:not\(\[hidden\]\)_\~\[cmdk-group\]\]\:pt-0 [cmdk-group]:not([hidden])~[cmdk-group]{padding-top:0}.\[\&_\[cmdk-group\]\]\:px-2 [cmdk-group]{padding-left:.5rem;padding-right:.5rem}.\[\&_\[cmdk-input-wrapper\]_svg\]\:h-5 [cmdk-input-wrapper] svg{height:1.25rem}.\[\&_\[cmdk-input-wrapper\]_svg\]\:w-5 [cmdk-input-wrapper] svg{width:1.25rem}.\[\&_\[cmdk-input\]\]\:h-12 [cmdk-input]{height:3rem}.\[\&_\[cmdk-item\]\]\:px-2 [cmdk-item]{padding-left:.5rem;padding-right:.5rem}.\[\&_\[cmdk-item\]\]\:py-3 [cmdk-item]{padding-bottom:.75rem;padding-top:.75rem}.\[\&_\[cmdk-item\]_svg\]\:h-5 [cmdk-item] svg{height:1.25rem}.\[\&_\[cmdk-item\]_svg\]\:w-5 [cmdk-item] svg{width:1.25rem}.\[\&_p\]\:leading-relaxed p{line-height:1.625}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:size-4 svg{height:1rem;width:1rem}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&_tr\:last-child\]\:border-0 tr:last-child{border-width:0}.\[\&_tr\]\:border-b tr{border-bottom-width:1px}.App-logo{height:40vmin;pointer-events:none}@media (prefers-reduced-motion:no-preference){.App-logo{animation:App-logo-spin 20s linear infinite}}.App-header{align-items:center;background-color:#0f0f10;color:#fff;display:flex;flex-direction:column;font-size:calc(10px + 2vmin);justify-content:center;min-height:100vh}.App-link{color:#61dafb}@keyframes App-logo-spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}} +/*# sourceMappingURL=main.7791f349.css.map*/ \ No newline at end of file diff --git a/static/css/main.7791f349.css.map b/static/css/main.7791f349.css.map new file mode 100644 index 0000000..f554559 --- /dev/null +++ b/static/css/main.7791f349.css.map @@ -0,0 +1 @@ +{"version":3,"file":"static/css/main.7791f349.css","mappings":"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","sources":["index.css","App.css"],"sourcesContent":["@tailwind base;\n@tailwind components;\n@tailwind utilities;\n\nbody {\n margin: 0;\n font-family:\n -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Roboto\", \"Oxygen\",\n \"Ubuntu\", \"Cantarell\", \"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\",\n sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\ncode {\n font-family:\n source-code-pro, Menlo, Monaco, Consolas, \"Courier New\", monospace;\n}\n\n@layer base {\n :root {\n --background: 0 0% 100%;\n --foreground: 0 0% 3.9%;\n --card: 0 0% 100%;\n --card-foreground: 0 0% 3.9%;\n --popover: 0 0% 100%;\n --popover-foreground: 0 0% 3.9%;\n --primary: 0 0% 9%;\n --primary-foreground: 0 0% 98%;\n --secondary: 0 0% 96.1%;\n --secondary-foreground: 0 0% 9%;\n --muted: 0 0% 96.1%;\n --muted-foreground: 0 0% 45.1%;\n --accent: 0 0% 96.1%;\n --accent-foreground: 0 0% 9%;\n --destructive: 0 84.2% 60.2%;\n --destructive-foreground: 0 0% 98%;\n --border: 0 0% 89.8%;\n --input: 0 0% 89.8%;\n --ring: 0 0% 3.9%;\n --chart-1: 12 76% 61%;\n --chart-2: 173 58% 39%;\n --chart-3: 197 37% 24%;\n --chart-4: 43 74% 66%;\n --chart-5: 27 87% 67%;\n --radius: 0.5rem;\n }\n .dark {\n --background: 0 0% 3.9%;\n --foreground: 0 0% 98%;\n --card: 0 0% 3.9%;\n --card-foreground: 0 0% 98%;\n --popover: 0 0% 3.9%;\n --popover-foreground: 0 0% 98%;\n --primary: 0 0% 98%;\n --primary-foreground: 0 0% 9%;\n --secondary: 0 0% 14.9%;\n --secondary-foreground: 0 0% 98%;\n --muted: 0 0% 14.9%;\n --muted-foreground: 0 0% 63.9%;\n --accent: 0 0% 14.9%;\n --accent-foreground: 0 0% 98%;\n --destructive: 0 62.8% 30.6%;\n --destructive-foreground: 0 0% 98%;\n --border: 0 0% 14.9%;\n --input: 0 0% 14.9%;\n --ring: 0 0% 83.1%;\n --chart-1: 220 70% 50%;\n --chart-2: 160 60% 45%;\n --chart-3: 30 80% 55%;\n --chart-4: 280 65% 60%;\n --chart-5: 340 75% 55%;\n }\n}\n\n@layer base {\n * {\n @apply border-border;\n }\n body {\n @apply bg-background text-foreground;\n }\n}\n\n@layer base {\n [data-debug-wrapper=\"true\"] {\n display: contents !important;\n }\n\n [data-debug-wrapper=\"true\"] > * {\n margin-left: inherit;\n margin-right: inherit;\n margin-top: inherit;\n margin-bottom: inherit;\n padding-left: inherit;\n padding-right: inherit;\n padding-top: inherit;\n padding-bottom: inherit;\n column-gap: inherit;\n row-gap: inherit;\n gap: inherit;\n border-left-width: inherit;\n border-right-width: inherit;\n border-top-width: inherit;\n border-bottom-width: inherit;\n border-left-style: inherit;\n border-right-style: inherit;\n border-top-style: inherit;\n border-bottom-style: inherit;\n border-left-color: inherit;\n border-right-color: inherit;\n border-top-color: inherit;\n border-bottom-color: inherit;\n }\n}\n",".App-logo {\n height: 40vmin;\n pointer-events: none;\n}\n\n@media (prefers-reduced-motion: no-preference) {\n .App-logo {\n animation: App-logo-spin infinite 20s linear;\n }\n}\n\n.App-header {\n background-color: #0f0f10;\n min-height: 100vh;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n font-size: calc(10px + 2vmin);\n color: white;\n}\n\n.App-link {\n color: #61dafb;\n}\n\n@keyframes App-logo-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n"],"names":[],"ignoreList":[],"sourceRoot":""} \ No newline at end of file diff --git a/static/js/admin-portal-v2.js b/static/js/admin-portal-v2.js new file mode 100644 index 0000000..d6961ba --- /dev/null +++ b/static/js/admin-portal-v2.js @@ -0,0 +1,541 @@ +(function(){ +'use strict'; +const API='https://epictravelexpeditions.com/api'; + +function authHdr(){return{'Content-Type':'application/json',Authorization:`Bearer ${localStorage.getItem('auth_token')}`};} +async function api(path,opts){ + const res=await fetch(API+path,{headers:authHdr(),...opts}); + const d=await res.json(); + if(!res.ok)throw new Error(d.error||res.statusText); + return d; +} +async function uploadImg(file){ + const fd=new FormData();fd.append('file',file); + const res=await fetch(API+'/upload/image',{method:'POST',headers:{Authorization:`Bearer ${localStorage.getItem('auth_token')}`},body:fd}); + const d=await res.json(); + if(!res.ok)throw new Error(d.error||'Upload failed'); + return d.url; +} +async function getImg(inputId,fallback){ + const el=document.getElementById(inputId); + if(el&&el.files&&el.files[0]){ + const st=document.getElementById(inputId+'-st'); + if(st)st.textContent='Uploading…'; + try{const url=await uploadImg(el.files[0]);if(st)st.textContent='';return url;} + catch(e){if(st){st.textContent='Upload failed: '+e.message;st.style.color='#dc2626';}throw e;} + } + return fallback!=null?fallback:null; +} +function imgPicker(id,src){ + const pr=src + ?`` + :`
🖼
`; + return `
${pr}
`; +} + +function daysAgo(s){return Math.floor((Date.now()-new Date(s))/86400000);} +function daysLeft(s){return Math.ceil((new Date(s)-Date.now())/86400000);} +function ageBdg(d){const c=d<30?'bg':d<90?'by':'br';return`${d}d ago`;} +function expBdg(d){if(d<0)return`Expired`;const c=d>14?'bg':d>7?'by':'br';return`${d}d left`;} +function esc(s){const e=document.createElement('div');e.textContent=s||'';return e.innerHTML;} +function catOpts(cats,sel){return cats.map(c=>``).join('');} +function fmtPrice(p){return p!=null?'$'+parseFloat(p).toLocaleString(undefined,{minimumFractionDigits:0,maximumFractionDigits:2}):'';} + +/* CSS */ +const css=` +#ep-portal{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;color:#111827;min-height:100vh;background:#f3f4f6} +#ep-portal *,#ep-portal *::before,#ep-portal *::after{box-sizing:border-box} +#ep-hdr{background:#fff;border-bottom:1px solid #e5e7eb;padding:0 28px;height:60px;display:flex;align-items:center;justify-content:space-between;position:sticky;top:0;z-index:100;box-shadow:0 1px 3px rgba(0,0,0,.06)} +.ep-logo{font-size:17px;font-weight:800;color:#1d4ed8;letter-spacing:-.4px}.ep-logo span{color:#6b7280;font-weight:400} +.ep-hdr-acts{display:flex;gap:8px} +.ep-hbtn{padding:6px 14px;border-radius:7px;font-size:13px;font-weight:600;border:1px solid #d1d5db;background:#fff;color:#374151;cursor:pointer;transition:all .15s;text-decoration:none;display:inline-flex;align-items:center;gap:5px} +.ep-hbtn:hover{background:#f9fafb}.ep-hbtn.red{border-color:#fca5a5;color:#dc2626}.ep-hbtn.red:hover{background:#fef2f2} +#ep-tabs{background:#fff;border-bottom:1px solid #e5e7eb;padding:0 28px;display:flex;gap:2px} +.ep-tab{padding:13px 18px;font-size:13px;font-weight:600;color:#6b7280;border:none;background:none;cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px;transition:all .15s;display:inline-flex;align-items:center;gap:7px} +.ep-tab:hover{color:#1d4ed8}.ep-tab.active{color:#1d4ed8;border-bottom-color:#1d4ed8} +.ep-tbadge{background:#fee2e2;color:#dc2626;border-radius:999px;font-size:11px;padding:1px 6px;font-weight:700} +#ep-body{padding:28px;max-width:1180px;margin:0 auto} +.ep-g4{display:grid;grid-template-columns:repeat(4,1fr);gap:18px;margin-bottom:28px} +@media(max-width:880px){.ep-g4{grid-template-columns:repeat(2,1fr)}} +.ep-stat{background:#fff;border:1px solid #e5e7eb;border-radius:12px;padding:20px 22px;position:relative;overflow:hidden} +.ep-si{font-size:26px;margin-bottom:6px}.ep-sv{font-size:30px;font-weight:800;color:#111827}.ep-sl{font-size:12px;color:#6b7280;margin-top:1px} +.ep-acc{position:absolute;right:0;top:0;bottom:0;width:4px;border-radius:0 12px 12px 0} +.acb{background:#3b82f6}.acg{background:#10b981}.aca{background:#f59e0b}.acp{background:#8b5cf6} +.ep-card{background:#fff;border:1px solid #e5e7eb;border-radius:12px;margin-bottom:22px;overflow:hidden} +.ep-ch{padding:16px 22px;border-bottom:1px solid #e5e7eb;display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:10px} +.ep-ct{font-size:14px;font-weight:700;color:#111827}.ep-cs{font-size:12px;color:#6b7280;margin-top:1px} +.ep-cb{padding:22px} +.ep-tbl{width:100%;border-collapse:collapse;font-size:13px} +.ep-tbl th{text-align:left;font-size:11px;font-weight:700;color:#6b7280;text-transform:uppercase;letter-spacing:.05em;padding:9px 12px;border-bottom:1px solid #e5e7eb;white-space:nowrap} +.ep-tbl td{padding:11px 12px;border-bottom:1px solid #f3f4f6;vertical-align:middle} +.ep-tbl tr:last-child td{border-bottom:none}.ep-tbl tr:hover td{background:#fafafa} +.ep-b{display:inline-block;padding:2px 9px;border-radius:999px;font-size:11px;font-weight:700} +.bg{background:#d1fae5;color:#065f46}.by{background:#fef3c7;color:#92400e}.br{background:#fee2e2;color:#991b1b}.bb{background:#dbeafe;color:#1e40af}.bgr{background:#f3f4f6;color:#374151} +.ep-btn{padding:6px 13px;border-radius:7px;font-size:12px;font-weight:600;border:none;cursor:pointer;transition:opacity .15s;display:inline-flex;align-items:center;gap:4px;white-space:nowrap} +.ep-btn:hover{opacity:.82}.ep-btn:disabled{opacity:.4;cursor:not-allowed} +.ep-pri{background:#2563eb;color:#fff}.ep-suc{background:#16a34a;color:#fff}.ep-dan{background:#dc2626;color:#fff}.ep-gho{background:#f3f4f6;color:#374151} +.ep-form{display:grid;grid-template-columns:1fr 1fr;gap:14px} +@media(max-width:640px){.ep-form{grid-template-columns:1fr}} +.ep-full{grid-column:1/-1}.ep-fld{display:flex;flex-direction:column;gap:4px} +.ep-lbl{font-size:11px;font-weight:700;color:#374151;text-transform:uppercase;letter-spacing:.04em} +.ep-inp,.ep-sel,.ep-ta{padding:8px 11px;border:1px solid #d1d5db;border-radius:7px;font-size:13px;color:#111827;background:#fff;outline:none;transition:border-color .15s;width:100%} +.ep-inp:focus,.ep-sel:focus,.ep-ta:focus{border-color:#3b82f6;box-shadow:0 0 0 3px rgba(59,130,246,.1)} +.ep-ta{resize:vertical;min-height:72px} +.ep-frow{grid-column:1/-1;display:flex;gap:10px;justify-content:flex-end;padding-top:4px;align-items:center} +.ep-addbox{border:1px dashed #d1d5db;border-radius:10px;padding:18px;margin-bottom:20px;background:#fafafa;display:none} +.ep-addbox.open{display:block} +.ep-thumb{width:40px;height:40px;border-radius:7px;object-fit:cover;background:#e5e7eb} +.ep-smsg{font-size:12px}.ep-smsg.ok{color:#16a34a}.ep-smsg.err{color:#dc2626} +.ep-alert{padding:10px 15px;border-radius:8px;font-size:13px;margin-bottom:16px;border-left:3px solid} +.ep-alert.warn{background:#fffbeb;color:#92400e;border-color:#f59e0b} +.ep-inline{display:grid;grid-template-columns:1fr 1fr;gap:10px;padding:14px} +@media(max-width:640px){.ep-inline{grid-column:1fr}} +.ep-cat-row{display:flex;align-items:center;gap:10px;padding:9px 12px;border-radius:8px;border:1px solid #e5e7eb;background:#fff;margin-bottom:8px} +.ep-cat-nm{flex:1;font-size:13px;font-weight:600}.ep-cat-ct{font-size:11px;color:#9ca3af} +.ep-cat-ei{flex:1;padding:5px 9px;border:1px solid #3b82f6;border-radius:6px;font-size:13px;outline:none} +.ep-tc{border:1px solid #e5e7eb;border-radius:10px;padding:16px;margin-bottom:12px;display:flex;gap:12px;background:#fff} +.ep-tav{width:42px;height:42px;border-radius:50%;object-fit:cover;flex-shrink:0;background:#e5e7eb} +.ep-tavph{width:42px;height:42px;border-radius:50%;background:#2563eb;color:#fff;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:16px;flex-shrink:0} +.ep-tb{flex:1;min-width:0}.ep-tn{font-weight:700;font-size:13px}.ep-tl{font-size:11px;color:#6b7280;margin-bottom:5px} +.ep-tm{font-size:13px;color:#374151;margin-bottom:8px;line-height:1.5} +.ep-te{width:100%;border:1px solid #d1d5db;border-radius:6px;padding:6px 9px;font-size:12px;margin-bottom:7px;resize:vertical;min-height:52px} +.ep-tacts{display:flex;gap:7px;flex-wrap:wrap} +.ep-ftabs{display:flex;gap:7px;margin-bottom:18px;flex-wrap:wrap} +.ep-ft{padding:6px 15px;border-radius:7px;font-size:12px;font-weight:600;cursor:pointer;border:1px solid #d1d5db;background:#fff;color:#374151;transition:all .15s} +.ep-ft.active{background:#2563eb;color:#fff;border-color:#2563eb} +.ep-empty{text-align:center;padding:36px;color:#9ca3af;font-size:13px} +.ep-spec-img{width:52px;height:52px;border-radius:8px;object-fit:cover;background:#e5e7eb;flex-shrink:0} +.ep-price-old{text-decoration:line-through;color:#9ca3af;font-size:11px} +.ep-price-new{color:#16a34a;font-weight:700} +`; +const sel=document.createElement('style');sel.textContent=css;document.head.appendChild(sel); + +/* State */ +let activeTab='dashboard',tFilter='pending'; +let destinations=[],specials=[],testimonials=[],categories=[]; + +async function loadAll(){ + const r=await Promise.allSettled([ + fetch(API+'/destinations',{headers:authHdr()}).then(r=>r.json()), + fetch(API+'/specials', {headers:authHdr()}).then(r=>r.json()), + fetch(API+'/testimonials/all',{headers:authHdr()}).then(r=>r.json()), + fetch(API+'/categories', {headers:authHdr()}).then(r=>r.json()) + ]); + if(r[0].status==='fulfilled'&&Array.isArray(r[0].value))destinations=r[0].value; + if(r[1].status==='fulfilled'&&Array.isArray(r[1].value))specials=r[1].value; + if(r[2].status==='fulfilled'&&Array.isArray(r[2].value))testimonials=r[2].value; + if(r[3].status==='fulfilled'&&Array.isArray(r[3].value))categories=r[3].value; +} + +/* Shell */ +function buildShell(){ + const p=document.createElement('div');p.id='ep-portal'; + p.innerHTML=` +
+ +
+ 🌐 View Site + +
+
+
+ + + + +
+
`; + p.querySelector('#ep-logout').onclick=()=>{localStorage.removeItem('isAdminAuthenticated');localStorage.removeItem('auth_token');window.location.href='/admin';}; + p.querySelectorAll('.ep-tab[data-tab]').forEach(b=>{b.onclick=()=>{activeTab=b.dataset.tab;p.querySelectorAll('.ep-tab').forEach(t=>t.classList.remove('active'));b.classList.add('active');render();};}); + return p; +} + +/* Dashboard */ +function rDash(){ + const dm=Object.fromEntries(destinations.map(d=>[d.id,d])); + const pen=testimonials.filter(t=>t.status==='pending').length; + const app=testimonials.filter(t=>t.status==='approved').length; + let h=`
+
🗺
${destinations.length}
Destinations
+
${specials.length}
Active Specials
+
${pen}
Pending Reviews
+
${app}
Approved Testimonials
+
`; + if(pen>0)h+=`
⚠️ ${pen} testimonial${pen>1?'s':''} awaiting review.
`; + + /* Destinations age */ + const sd=[...destinations].sort((a,b)=>new Date(a.created_at)-new Date(b.created_at)); + h+=`
🗺 Destinations
Oldest entries first
`; + sd.forEach(d=>{h+=``;}); + h+=`
DestinationCategoryPriceIn System Since
${esc(d.name)} ${esc(d.location)}${esc(d.category)}${fmtPrice(d.price)}${ageBdg(daysAgo(d.created_at))}
`; + + /* Specials expiry */ + const ss=[...specials].sort((a,b)=>new Date(a.end_date)-new Date(b.end_date)); + h+=`
⭐ Weekly Specials
Expiring soonest first
`; + ss.forEach(s=>{ + const dest=dm[s.destination_id]; + const basePrice=s.price!=null?parseFloat(s.price):(dest?parseFloat(dest.price):0); + const salePrice=basePrice*(1-parseFloat(s.discount)/100); + const imgSrc=s.image_path||(dest?dest.image:''); + h+=` + + + + + + + + `; + }); + h+=`
ImageDestinationOriginal PriceDiscountSale PriceExpiresStatus
${imgSrc?``:''}${esc(dest?dest.name:s.destination_id)}${fmtPrice(basePrice)}${parseFloat(s.discount)}% OFF${fmtPrice(salePrice)}${new Date(s.end_date).toLocaleDateString()}${expBdg(daysLeft(s.end_date))}
`; + + /* Pending testimonials */ + const pl=testimonials.filter(t=>t.status==='pending'); + if(pl.length){ + h+=`
⏳ Pending Testimonials
`; + pl.forEach(t=>{ + const av=t.image_path?``:`
${esc(t.full_name.charAt(0))}
`; + h+=`
${av}
${esc(t.full_name)}
${esc(t.location)}
${esc(t.message)}
`; + }); + h+=`
`; + } + return h; +} + +/* Destinations */ +function destRow(d){ + return` + + ${esc(d.name)}
${esc(d.location)} + ${esc(d.category)} + ${fmtPrice(d.price)} + ⭐ ${parseFloat(d.rating).toFixed(1)} + ${ageBdg(daysAgo(d.created_at))} + + `; +} + +function rDest(){ + const cc={};destinations.forEach(d=>{cc[d.category]=(cc[d.category]||0)+1;}); + return`
+
🏷 Categories
Add, rename, or remove destination categories
+
+
+
+ + + + +
+
+
${categories.map(c=>{const n=cc[c.name]||0;return`
${esc(c.name)}${n} destination${n!==1?'s':''}
`;}).join('')}
+
+
+
+
🗺 All Destinations (${destinations.length})
+
+
+
New Destination
+
+
Name *
+
Location *
+
Category *
+
Price (USD) *
+
Rating (1–5)
+
Image *${imgPicker('ep-dn-img','')}
+
Description *
+
+
+
+ + ${destinations.map(destRow).join('')}
PhotoName & LocationCategoryPriceRatingIn SystemActions
+
+
`; +} + +/* Specials */ +function specImg(s){ + const dm=Object.fromEntries(destinations.map(d=>[d.id,d])); + const dest=dm[s.destination_id]; + return s.image_path||(dest?dest.image:'')||''; +} +function specRow(s){ + const dm=Object.fromEntries(destinations.map(d=>[d.id,d])); + const dest=dm[s.destination_id]; + const base=s.price!=null?parseFloat(s.price):(dest?parseFloat(dest.price):0); + const sale=base*(1-parseFloat(s.discount)/100); + const img=specImg(s); + return` + ${img?``:''} + ${esc(dest?dest.name:s.destination_id)} + ${parseFloat(s.discount)}% OFF + ${fmtPrice(base)} + ${fmtPrice(sale)} + ${new Date(s.end_date).toLocaleDateString()} + ${expBdg(daysLeft(s.end_date))} + + `; +} + +function rSpec(){ + const destOpts=destinations.map(d=>``).join(''); + return`
+
⭐ Weekly Specials (${specials.length})
+
+
+
New Special
+
+
Destination *
+
Original Price (USD) *
+
Discount % *
+
End Date *
+
Special Image (optional — defaults to destination photo)${imgPicker('ep-sn-img','')}
+
Highlights (one per line)
+
+
+
+ + ${specials.map(specRow).join('')}
ImageDestinationDiscountOriginal PriceSale PriceEnd DateStatusActions
+
+
`; +} + +/* Testimonials */ +function rTest(){ + const cn={pending:0,approved:0,denied:0};testimonials.forEach(t=>cn[t.status]++); + const list=tFilter==='all'?testimonials:testimonials.filter(t=>t.status===tFilter); + let h=`
+ + + + +
`; + if(!list.length)return h+`
💬 No testimonials here.
`; + list.forEach(t=>{ + const av=t.image_path?``:`
${esc(t.full_name.charAt(0))}
`; + const sb=`${t.status}`; + h+=`
${av}
+
${esc(t.full_name)} ${sb}
${esc(t.location)}
+
${esc(t.message)}
+ +
+ ${t.status!=='approved'?``:''} + ${t.status!=='denied'?``:''} + + +
`; + }); + return h; +} + +/* Render */ +function render(){ + const body=document.getElementById('ep-body');if(!body)return; + switch(activeTab){ + case'dashboard': body.innerHTML=rDash(); wireDash(); break; + case'destinations':body.innerHTML=rDest(); wireDest(); break; + case'specials': body.innerHTML=rSpec(); wireSpec(); break; + case'testimonials':body.innerHTML=rTest(); wireTest(); break; + } + const pb=document.getElementById('ep-pb'); + if(pb){const n=testimonials.filter(t=>t.status==='pending').length;pb.textContent=n||'';pb.style.display=n?'':'none';} +} + +/* Wire: Dashboard */ +function wireDash(){ + document.querySelectorAll('[data-qa]').forEach(b=>b.onclick=async()=>{await api(`/testimonials/${b.dataset.qa}`,{method:'PUT',body:JSON.stringify({status:'approved'})});await loadAll();render();}); + document.querySelectorAll('[data-qd]').forEach(b=>b.onclick=async()=>{await api(`/testimonials/${b.dataset.qd}`,{method:'PUT',body:JSON.stringify({status:'denied'})});await loadAll();render();}); +} + +/* Wire: Destinations */ +function wireDest(){ + /* Categories */ + const ct=document.getElementById('ep-cat-tog'),cb=document.getElementById('ep-cat-box'); + if(ct)ct.onclick=()=>cb.classList.toggle('open'); + const cc=document.getElementById('ep-cat-cancel');if(cc)cc.onclick=()=>cb.classList.remove('open'); + const cs=document.getElementById('ep-cat-save'); + if(cs)cs.onclick=async()=>{ + const m=document.getElementById('ep-cat-msg'),nm=document.getElementById('ep-cat-new').value.trim(); + if(!nm){m.textContent='Name required';m.className='ep-smsg err';return;} + try{await api('/categories',{method:'POST',body:JSON.stringify({name:nm})});m.textContent='Added!';m.className='ep-smsg ok';await loadAll();activeTab='destinations';render();} + catch(e){m.textContent=e.message;m.className='ep-smsg err';} + }; + document.querySelectorAll('[data-ren]').forEach(b=>b.onclick=()=>{ + const id=b.dataset.ren,cur=b.dataset.cv,row=b.closest('.ep-cat-row'); + row.innerHTML=``; + row.querySelector('[data-rc]').onclick=()=>{activeTab='destinations';render();}; + row.querySelector(`[data-rs="${id}"]`).onclick=async()=>{ + const nm=document.getElementById(`ep-ren-${id}`).value.trim(),m=document.getElementById(`ep-rm-${id}`); + if(!nm){m.textContent='Required';m.className='ep-smsg err';return;} + try{await api(`/categories/${id}`,{method:'PUT',body:JSON.stringify({name:nm})});await loadAll();activeTab='destinations';render();} + catch(e){m.textContent=e.message;m.className='ep-smsg err';} + }; + }); + document.querySelectorAll('[data-dc]').forEach(b=>b.onclick=async()=>{ + if(!confirm(`Delete category "${b.dataset.dn}"?`))return; + try{await api(`/categories/${b.dataset.dc}`,{method:'DELETE'});await loadAll();activeTab='destinations';render();}catch(e){alert(e.message);} + }); + + /* Destination add */ + const dt=document.getElementById('ep-dest-tog'),db=document.getElementById('ep-dest-box'); + if(dt)dt.onclick=()=>db.classList.toggle('open'); + const dn=document.getElementById('ep-dn-cancel');if(dn)dn.onclick=()=>db.classList.remove('open'); + const ds=document.getElementById('ep-dn-save'); + if(ds)ds.onclick=async()=>{ + const m=document.getElementById('ep-dn-msg'); + try{ + const img=await getImg('ep-dn-img',''); + await api('/destinations',{method:'POST',body:JSON.stringify({ + name:document.getElementById('ep-dn-name').value.trim(), + location:document.getElementById('ep-dn-loc').value.trim(), + category:document.getElementById('ep-dn-cat').value, + price:document.getElementById('ep-dn-price').value, + rating:document.getElementById('ep-dn-rating').value||'4.5', + image:img, + description:document.getElementById('ep-dn-desc').value.trim() + })}); + m.textContent='Saved!';m.className='ep-smsg ok';await loadAll();activeTab='destinations';render(); + }catch(e){m.textContent=e.message;m.className='ep-smsg err';} + }; + + /* Destination edit */ + document.querySelectorAll('[data-ed]').forEach(b=>b.onclick=()=>{ + const id=b.dataset.ed,d=destinations.find(x=>x.id==id);if(!d)return; + const row=document.querySelector(`tr[data-did="${id}"]`); + row.innerHTML=`
+
Name
+
Location
+
Category
+
Price
+
Rating
+
Image (upload new to replace)${imgPicker('ei-i-'+id,d.image)}
+
Description
+
+ + +
+
`; + row.querySelector(`[data-ec="${id}"]`).onclick=()=>{row.outerHTML=destRow(d);wireDest();}; + row.querySelector(`[data-es="${id}"]`).onclick=async()=>{ + try{ + const img=await getImg('ei-i-'+id,d.image); + await api(`/destinations/${id}`,{method:'PUT',body:JSON.stringify({ + name:document.getElementById(`ei-n-${id}`).value, + location:document.getElementById(`ei-l-${id}`).value, + category:document.getElementById(`ei-c-${id}`).value, + price:document.getElementById(`ei-p-${id}`).value, + rating:document.getElementById(`ei-r-${id}`).value, + image:img, + description:document.getElementById(`ei-d-${id}`).value + })}); + await loadAll();activeTab='destinations';render(); + }catch(e){alert(e.message);} + }; + }); + + /* Destination delete */ + document.querySelectorAll('[data-dd]').forEach(b=>b.onclick=async()=>{ + if(!confirm('Delete this destination? This cannot be undone.'))return; + try{await api(`/destinations/${b.dataset.dd}`,{method:'DELETE'});await loadAll();activeTab='destinations';render();}catch(e){alert(e.message);} + }); +} + +/* Wire: Specials */ +function wireSpec(){ + const st=document.getElementById('ep-spec-tog'),sb=document.getElementById('ep-spec-box'); + if(st)st.onclick=()=>sb.classList.toggle('open'); + const sc=document.getElementById('ep-sn-cancel');if(sc)sc.onclick=()=>sb.classList.remove('open'); + const ss=document.getElementById('ep-sn-save'); + if(ss)ss.onclick=async()=>{ + const m=document.getElementById('ep-sn-msg'); + try{ + const img=await getImg('ep-sn-img',null); + const hls=document.getElementById('ep-sn-hls').value.split('\n').map(l=>l.trim()).filter(Boolean); + await api('/specials',{method:'POST',body:JSON.stringify({ + destination_id:document.getElementById('ep-sn-dest').value, + price:document.getElementById('ep-sn-price').value, + discount:document.getElementById('ep-sn-disc').value, + end_date:document.getElementById('ep-sn-end').value, + image_path:img, + highlights:hls + })}); + m.textContent='Saved!';m.className='ep-smsg ok';await loadAll();activeTab='specials';render(); + }catch(e){m.textContent=e.message;m.className='ep-smsg err';} + }; + + /* Specials edit */ + document.querySelectorAll('[data-es]').forEach(b=>b.onclick=()=>{ + const id=b.dataset.es,s=specials.find(x=>x.id==id);if(!s)return; + const dm=Object.fromEntries(destinations.map(d=>[d.id,d])); + const dest=dm[s.destination_id]; + const hls=Array.isArray(s.highlights)?s.highlights.join('\n'):''; + const curImg=specImg(s); + const row=document.querySelector(`tr[data-sid="${id}"]`); + row.innerHTML=`
+
Original Price
+
Discount %
+
End Date
+
Image (upload to replace; leave blank to use destination photo)${imgPicker('si-i-'+id,curImg)}
+
Highlights (one per line)
+
+ + +
+
`; + row.querySelector(`[data-sc="${id}"]`).onclick=()=>{row.outerHTML=specRow(s);wireSpec();}; + row.querySelector(`[data-sv="${id}"]`).onclick=async()=>{ + try{ + const newImg=await getImg('si-i-'+id,s.image_path||null); + const hls2=document.getElementById(`si-h-${id}`).value.split('\n').map(l=>l.trim()).filter(Boolean); + await api(`/specials/${id}`,{method:'PUT',body:JSON.stringify({ + price:document.getElementById(`si-p-${id}`).value, + discount:document.getElementById(`si-d-${id}`).value, + end_date:document.getElementById(`si-e-${id}`).value, + image_path:newImg, + highlights:hls2 + })}); + await loadAll();activeTab='specials';render(); + }catch(e){alert(e.message);} + }; + }); + + /* Specials delete */ + document.querySelectorAll('[data-ds]').forEach(b=>b.onclick=async()=>{ + if(!confirm('Delete this special?'))return; + try{await api(`/specials/${b.dataset.ds}`,{method:'DELETE'});await loadAll();activeTab='specials';render();}catch(e){alert(e.message);} + }); +} + +/* Wire: Testimonials */ +function wireTest(){ + document.querySelectorAll('[data-tf]').forEach(b=>b.onclick=()=>{tFilter=b.dataset.tf;render();}); + document.querySelectorAll('[data-ta]').forEach(b=>b.onclick=async()=>{ + const id=b.dataset.tid,action=b.dataset.ta; + const card=document.querySelector(`.ep-tc[data-tid="${id}"]`); + try{ + if(action==='approve')await api(`/testimonials/${id}`,{method:'PUT',body:JSON.stringify({status:'approved'})}); + else if(action==='deny')await api(`/testimonials/${id}`,{method:'PUT',body:JSON.stringify({status:'denied'})}); + else if(action==='save'){const ta=card.querySelector('.ep-te');await api(`/testimonials/${id}`,{method:'PUT',body:JSON.stringify({message:ta.value})});} + else if(action==='delete'){if(!confirm('Delete?'))return;await api(`/testimonials/${id}`,{method:'DELETE'});} + await loadAll();render(); + }catch(e){alert(e.message);} + }); +} + +/* Init */ +let injected=false; +function tryInject(){ + if(injected)return; + if(!window.location.pathname.startsWith('/admin/dashboard'))return; + if(!localStorage.getItem('isAdminAuthenticated'))return; + const root=document.getElementById('root'); + if(!root||!root.children.length)return; + injected=true;obs.disconnect(); + Array.from(root.children).forEach(c=>c.style.display='none'); + const portal=buildShell();root.insertBefore(portal,root.firstChild); + loadAll().then(render); +} +const obs=new MutationObserver(tryInject); +obs.observe(document.body,{childList:true,subtree:true}); +tryInject(); +})(); diff --git a/static/js/admin-portal.js b/static/js/admin-portal.js new file mode 100644 index 0000000..d6961ba --- /dev/null +++ b/static/js/admin-portal.js @@ -0,0 +1,541 @@ +(function(){ +'use strict'; +const API='https://epictravelexpeditions.com/api'; + +function authHdr(){return{'Content-Type':'application/json',Authorization:`Bearer ${localStorage.getItem('auth_token')}`};} +async function api(path,opts){ + const res=await fetch(API+path,{headers:authHdr(),...opts}); + const d=await res.json(); + if(!res.ok)throw new Error(d.error||res.statusText); + return d; +} +async function uploadImg(file){ + const fd=new FormData();fd.append('file',file); + const res=await fetch(API+'/upload/image',{method:'POST',headers:{Authorization:`Bearer ${localStorage.getItem('auth_token')}`},body:fd}); + const d=await res.json(); + if(!res.ok)throw new Error(d.error||'Upload failed'); + return d.url; +} +async function getImg(inputId,fallback){ + const el=document.getElementById(inputId); + if(el&&el.files&&el.files[0]){ + const st=document.getElementById(inputId+'-st'); + if(st)st.textContent='Uploading…'; + try{const url=await uploadImg(el.files[0]);if(st)st.textContent='';return url;} + catch(e){if(st){st.textContent='Upload failed: '+e.message;st.style.color='#dc2626';}throw e;} + } + return fallback!=null?fallback:null; +} +function imgPicker(id,src){ + const pr=src + ?`` + :`
🖼
`; + return `
${pr}
`; +} + +function daysAgo(s){return Math.floor((Date.now()-new Date(s))/86400000);} +function daysLeft(s){return Math.ceil((new Date(s)-Date.now())/86400000);} +function ageBdg(d){const c=d<30?'bg':d<90?'by':'br';return`${d}d ago`;} +function expBdg(d){if(d<0)return`Expired`;const c=d>14?'bg':d>7?'by':'br';return`${d}d left`;} +function esc(s){const e=document.createElement('div');e.textContent=s||'';return e.innerHTML;} +function catOpts(cats,sel){return cats.map(c=>``).join('');} +function fmtPrice(p){return p!=null?'$'+parseFloat(p).toLocaleString(undefined,{minimumFractionDigits:0,maximumFractionDigits:2}):'';} + +/* CSS */ +const css=` +#ep-portal{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;color:#111827;min-height:100vh;background:#f3f4f6} +#ep-portal *,#ep-portal *::before,#ep-portal *::after{box-sizing:border-box} +#ep-hdr{background:#fff;border-bottom:1px solid #e5e7eb;padding:0 28px;height:60px;display:flex;align-items:center;justify-content:space-between;position:sticky;top:0;z-index:100;box-shadow:0 1px 3px rgba(0,0,0,.06)} +.ep-logo{font-size:17px;font-weight:800;color:#1d4ed8;letter-spacing:-.4px}.ep-logo span{color:#6b7280;font-weight:400} +.ep-hdr-acts{display:flex;gap:8px} +.ep-hbtn{padding:6px 14px;border-radius:7px;font-size:13px;font-weight:600;border:1px solid #d1d5db;background:#fff;color:#374151;cursor:pointer;transition:all .15s;text-decoration:none;display:inline-flex;align-items:center;gap:5px} +.ep-hbtn:hover{background:#f9fafb}.ep-hbtn.red{border-color:#fca5a5;color:#dc2626}.ep-hbtn.red:hover{background:#fef2f2} +#ep-tabs{background:#fff;border-bottom:1px solid #e5e7eb;padding:0 28px;display:flex;gap:2px} +.ep-tab{padding:13px 18px;font-size:13px;font-weight:600;color:#6b7280;border:none;background:none;cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px;transition:all .15s;display:inline-flex;align-items:center;gap:7px} +.ep-tab:hover{color:#1d4ed8}.ep-tab.active{color:#1d4ed8;border-bottom-color:#1d4ed8} +.ep-tbadge{background:#fee2e2;color:#dc2626;border-radius:999px;font-size:11px;padding:1px 6px;font-weight:700} +#ep-body{padding:28px;max-width:1180px;margin:0 auto} +.ep-g4{display:grid;grid-template-columns:repeat(4,1fr);gap:18px;margin-bottom:28px} +@media(max-width:880px){.ep-g4{grid-template-columns:repeat(2,1fr)}} +.ep-stat{background:#fff;border:1px solid #e5e7eb;border-radius:12px;padding:20px 22px;position:relative;overflow:hidden} +.ep-si{font-size:26px;margin-bottom:6px}.ep-sv{font-size:30px;font-weight:800;color:#111827}.ep-sl{font-size:12px;color:#6b7280;margin-top:1px} +.ep-acc{position:absolute;right:0;top:0;bottom:0;width:4px;border-radius:0 12px 12px 0} +.acb{background:#3b82f6}.acg{background:#10b981}.aca{background:#f59e0b}.acp{background:#8b5cf6} +.ep-card{background:#fff;border:1px solid #e5e7eb;border-radius:12px;margin-bottom:22px;overflow:hidden} +.ep-ch{padding:16px 22px;border-bottom:1px solid #e5e7eb;display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:10px} +.ep-ct{font-size:14px;font-weight:700;color:#111827}.ep-cs{font-size:12px;color:#6b7280;margin-top:1px} +.ep-cb{padding:22px} +.ep-tbl{width:100%;border-collapse:collapse;font-size:13px} +.ep-tbl th{text-align:left;font-size:11px;font-weight:700;color:#6b7280;text-transform:uppercase;letter-spacing:.05em;padding:9px 12px;border-bottom:1px solid #e5e7eb;white-space:nowrap} +.ep-tbl td{padding:11px 12px;border-bottom:1px solid #f3f4f6;vertical-align:middle} +.ep-tbl tr:last-child td{border-bottom:none}.ep-tbl tr:hover td{background:#fafafa} +.ep-b{display:inline-block;padding:2px 9px;border-radius:999px;font-size:11px;font-weight:700} +.bg{background:#d1fae5;color:#065f46}.by{background:#fef3c7;color:#92400e}.br{background:#fee2e2;color:#991b1b}.bb{background:#dbeafe;color:#1e40af}.bgr{background:#f3f4f6;color:#374151} +.ep-btn{padding:6px 13px;border-radius:7px;font-size:12px;font-weight:600;border:none;cursor:pointer;transition:opacity .15s;display:inline-flex;align-items:center;gap:4px;white-space:nowrap} +.ep-btn:hover{opacity:.82}.ep-btn:disabled{opacity:.4;cursor:not-allowed} +.ep-pri{background:#2563eb;color:#fff}.ep-suc{background:#16a34a;color:#fff}.ep-dan{background:#dc2626;color:#fff}.ep-gho{background:#f3f4f6;color:#374151} +.ep-form{display:grid;grid-template-columns:1fr 1fr;gap:14px} +@media(max-width:640px){.ep-form{grid-template-columns:1fr}} +.ep-full{grid-column:1/-1}.ep-fld{display:flex;flex-direction:column;gap:4px} +.ep-lbl{font-size:11px;font-weight:700;color:#374151;text-transform:uppercase;letter-spacing:.04em} +.ep-inp,.ep-sel,.ep-ta{padding:8px 11px;border:1px solid #d1d5db;border-radius:7px;font-size:13px;color:#111827;background:#fff;outline:none;transition:border-color .15s;width:100%} +.ep-inp:focus,.ep-sel:focus,.ep-ta:focus{border-color:#3b82f6;box-shadow:0 0 0 3px rgba(59,130,246,.1)} +.ep-ta{resize:vertical;min-height:72px} +.ep-frow{grid-column:1/-1;display:flex;gap:10px;justify-content:flex-end;padding-top:4px;align-items:center} +.ep-addbox{border:1px dashed #d1d5db;border-radius:10px;padding:18px;margin-bottom:20px;background:#fafafa;display:none} +.ep-addbox.open{display:block} +.ep-thumb{width:40px;height:40px;border-radius:7px;object-fit:cover;background:#e5e7eb} +.ep-smsg{font-size:12px}.ep-smsg.ok{color:#16a34a}.ep-smsg.err{color:#dc2626} +.ep-alert{padding:10px 15px;border-radius:8px;font-size:13px;margin-bottom:16px;border-left:3px solid} +.ep-alert.warn{background:#fffbeb;color:#92400e;border-color:#f59e0b} +.ep-inline{display:grid;grid-template-columns:1fr 1fr;gap:10px;padding:14px} +@media(max-width:640px){.ep-inline{grid-column:1fr}} +.ep-cat-row{display:flex;align-items:center;gap:10px;padding:9px 12px;border-radius:8px;border:1px solid #e5e7eb;background:#fff;margin-bottom:8px} +.ep-cat-nm{flex:1;font-size:13px;font-weight:600}.ep-cat-ct{font-size:11px;color:#9ca3af} +.ep-cat-ei{flex:1;padding:5px 9px;border:1px solid #3b82f6;border-radius:6px;font-size:13px;outline:none} +.ep-tc{border:1px solid #e5e7eb;border-radius:10px;padding:16px;margin-bottom:12px;display:flex;gap:12px;background:#fff} +.ep-tav{width:42px;height:42px;border-radius:50%;object-fit:cover;flex-shrink:0;background:#e5e7eb} +.ep-tavph{width:42px;height:42px;border-radius:50%;background:#2563eb;color:#fff;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:16px;flex-shrink:0} +.ep-tb{flex:1;min-width:0}.ep-tn{font-weight:700;font-size:13px}.ep-tl{font-size:11px;color:#6b7280;margin-bottom:5px} +.ep-tm{font-size:13px;color:#374151;margin-bottom:8px;line-height:1.5} +.ep-te{width:100%;border:1px solid #d1d5db;border-radius:6px;padding:6px 9px;font-size:12px;margin-bottom:7px;resize:vertical;min-height:52px} +.ep-tacts{display:flex;gap:7px;flex-wrap:wrap} +.ep-ftabs{display:flex;gap:7px;margin-bottom:18px;flex-wrap:wrap} +.ep-ft{padding:6px 15px;border-radius:7px;font-size:12px;font-weight:600;cursor:pointer;border:1px solid #d1d5db;background:#fff;color:#374151;transition:all .15s} +.ep-ft.active{background:#2563eb;color:#fff;border-color:#2563eb} +.ep-empty{text-align:center;padding:36px;color:#9ca3af;font-size:13px} +.ep-spec-img{width:52px;height:52px;border-radius:8px;object-fit:cover;background:#e5e7eb;flex-shrink:0} +.ep-price-old{text-decoration:line-through;color:#9ca3af;font-size:11px} +.ep-price-new{color:#16a34a;font-weight:700} +`; +const sel=document.createElement('style');sel.textContent=css;document.head.appendChild(sel); + +/* State */ +let activeTab='dashboard',tFilter='pending'; +let destinations=[],specials=[],testimonials=[],categories=[]; + +async function loadAll(){ + const r=await Promise.allSettled([ + fetch(API+'/destinations',{headers:authHdr()}).then(r=>r.json()), + fetch(API+'/specials', {headers:authHdr()}).then(r=>r.json()), + fetch(API+'/testimonials/all',{headers:authHdr()}).then(r=>r.json()), + fetch(API+'/categories', {headers:authHdr()}).then(r=>r.json()) + ]); + if(r[0].status==='fulfilled'&&Array.isArray(r[0].value))destinations=r[0].value; + if(r[1].status==='fulfilled'&&Array.isArray(r[1].value))specials=r[1].value; + if(r[2].status==='fulfilled'&&Array.isArray(r[2].value))testimonials=r[2].value; + if(r[3].status==='fulfilled'&&Array.isArray(r[3].value))categories=r[3].value; +} + +/* Shell */ +function buildShell(){ + const p=document.createElement('div');p.id='ep-portal'; + p.innerHTML=` +
+ +
+ 🌐 View Site + +
+
+
+ + + + +
+
`; + p.querySelector('#ep-logout').onclick=()=>{localStorage.removeItem('isAdminAuthenticated');localStorage.removeItem('auth_token');window.location.href='/admin';}; + p.querySelectorAll('.ep-tab[data-tab]').forEach(b=>{b.onclick=()=>{activeTab=b.dataset.tab;p.querySelectorAll('.ep-tab').forEach(t=>t.classList.remove('active'));b.classList.add('active');render();};}); + return p; +} + +/* Dashboard */ +function rDash(){ + const dm=Object.fromEntries(destinations.map(d=>[d.id,d])); + const pen=testimonials.filter(t=>t.status==='pending').length; + const app=testimonials.filter(t=>t.status==='approved').length; + let h=`
+
🗺
${destinations.length}
Destinations
+
${specials.length}
Active Specials
+
${pen}
Pending Reviews
+
${app}
Approved Testimonials
+
`; + if(pen>0)h+=`
⚠️ ${pen} testimonial${pen>1?'s':''} awaiting review.
`; + + /* Destinations age */ + const sd=[...destinations].sort((a,b)=>new Date(a.created_at)-new Date(b.created_at)); + h+=`
🗺 Destinations
Oldest entries first
`; + sd.forEach(d=>{h+=``;}); + h+=`
DestinationCategoryPriceIn System Since
${esc(d.name)} ${esc(d.location)}${esc(d.category)}${fmtPrice(d.price)}${ageBdg(daysAgo(d.created_at))}
`; + + /* Specials expiry */ + const ss=[...specials].sort((a,b)=>new Date(a.end_date)-new Date(b.end_date)); + h+=`
⭐ Weekly Specials
Expiring soonest first
`; + ss.forEach(s=>{ + const dest=dm[s.destination_id]; + const basePrice=s.price!=null?parseFloat(s.price):(dest?parseFloat(dest.price):0); + const salePrice=basePrice*(1-parseFloat(s.discount)/100); + const imgSrc=s.image_path||(dest?dest.image:''); + h+=` + + + + + + + + `; + }); + h+=`
ImageDestinationOriginal PriceDiscountSale PriceExpiresStatus
${imgSrc?``:''}${esc(dest?dest.name:s.destination_id)}${fmtPrice(basePrice)}${parseFloat(s.discount)}% OFF${fmtPrice(salePrice)}${new Date(s.end_date).toLocaleDateString()}${expBdg(daysLeft(s.end_date))}
`; + + /* Pending testimonials */ + const pl=testimonials.filter(t=>t.status==='pending'); + if(pl.length){ + h+=`
⏳ Pending Testimonials
`; + pl.forEach(t=>{ + const av=t.image_path?``:`
${esc(t.full_name.charAt(0))}
`; + h+=`
${av}
${esc(t.full_name)}
${esc(t.location)}
${esc(t.message)}
`; + }); + h+=`
`; + } + return h; +} + +/* Destinations */ +function destRow(d){ + return` + + ${esc(d.name)}
${esc(d.location)} + ${esc(d.category)} + ${fmtPrice(d.price)} + ⭐ ${parseFloat(d.rating).toFixed(1)} + ${ageBdg(daysAgo(d.created_at))} + + `; +} + +function rDest(){ + const cc={};destinations.forEach(d=>{cc[d.category]=(cc[d.category]||0)+1;}); + return`
+
🏷 Categories
Add, rename, or remove destination categories
+
+
+
+ + + + +
+
+
${categories.map(c=>{const n=cc[c.name]||0;return`
${esc(c.name)}${n} destination${n!==1?'s':''}
`;}).join('')}
+
+
+
+
🗺 All Destinations (${destinations.length})
+
+
+
New Destination
+
+
Name *
+
Location *
+
Category *
+
Price (USD) *
+
Rating (1–5)
+
Image *${imgPicker('ep-dn-img','')}
+
Description *
+
+
+
+ + ${destinations.map(destRow).join('')}
PhotoName & LocationCategoryPriceRatingIn SystemActions
+
+
`; +} + +/* Specials */ +function specImg(s){ + const dm=Object.fromEntries(destinations.map(d=>[d.id,d])); + const dest=dm[s.destination_id]; + return s.image_path||(dest?dest.image:'')||''; +} +function specRow(s){ + const dm=Object.fromEntries(destinations.map(d=>[d.id,d])); + const dest=dm[s.destination_id]; + const base=s.price!=null?parseFloat(s.price):(dest?parseFloat(dest.price):0); + const sale=base*(1-parseFloat(s.discount)/100); + const img=specImg(s); + return` + ${img?``:''} + ${esc(dest?dest.name:s.destination_id)} + ${parseFloat(s.discount)}% OFF + ${fmtPrice(base)} + ${fmtPrice(sale)} + ${new Date(s.end_date).toLocaleDateString()} + ${expBdg(daysLeft(s.end_date))} + + `; +} + +function rSpec(){ + const destOpts=destinations.map(d=>``).join(''); + return`
+
⭐ Weekly Specials (${specials.length})
+
+
+
New Special
+
+
Destination *
+
Original Price (USD) *
+
Discount % *
+
End Date *
+
Special Image (optional — defaults to destination photo)${imgPicker('ep-sn-img','')}
+
Highlights (one per line)
+
+
+
+ + ${specials.map(specRow).join('')}
ImageDestinationDiscountOriginal PriceSale PriceEnd DateStatusActions
+
+
`; +} + +/* Testimonials */ +function rTest(){ + const cn={pending:0,approved:0,denied:0};testimonials.forEach(t=>cn[t.status]++); + const list=tFilter==='all'?testimonials:testimonials.filter(t=>t.status===tFilter); + let h=`
+ + + + +
`; + if(!list.length)return h+`
💬 No testimonials here.
`; + list.forEach(t=>{ + const av=t.image_path?``:`
${esc(t.full_name.charAt(0))}
`; + const sb=`${t.status}`; + h+=`
${av}
+
${esc(t.full_name)} ${sb}
${esc(t.location)}
+
${esc(t.message)}
+ +
+ ${t.status!=='approved'?``:''} + ${t.status!=='denied'?``:''} + + +
`; + }); + return h; +} + +/* Render */ +function render(){ + const body=document.getElementById('ep-body');if(!body)return; + switch(activeTab){ + case'dashboard': body.innerHTML=rDash(); wireDash(); break; + case'destinations':body.innerHTML=rDest(); wireDest(); break; + case'specials': body.innerHTML=rSpec(); wireSpec(); break; + case'testimonials':body.innerHTML=rTest(); wireTest(); break; + } + const pb=document.getElementById('ep-pb'); + if(pb){const n=testimonials.filter(t=>t.status==='pending').length;pb.textContent=n||'';pb.style.display=n?'':'none';} +} + +/* Wire: Dashboard */ +function wireDash(){ + document.querySelectorAll('[data-qa]').forEach(b=>b.onclick=async()=>{await api(`/testimonials/${b.dataset.qa}`,{method:'PUT',body:JSON.stringify({status:'approved'})});await loadAll();render();}); + document.querySelectorAll('[data-qd]').forEach(b=>b.onclick=async()=>{await api(`/testimonials/${b.dataset.qd}`,{method:'PUT',body:JSON.stringify({status:'denied'})});await loadAll();render();}); +} + +/* Wire: Destinations */ +function wireDest(){ + /* Categories */ + const ct=document.getElementById('ep-cat-tog'),cb=document.getElementById('ep-cat-box'); + if(ct)ct.onclick=()=>cb.classList.toggle('open'); + const cc=document.getElementById('ep-cat-cancel');if(cc)cc.onclick=()=>cb.classList.remove('open'); + const cs=document.getElementById('ep-cat-save'); + if(cs)cs.onclick=async()=>{ + const m=document.getElementById('ep-cat-msg'),nm=document.getElementById('ep-cat-new').value.trim(); + if(!nm){m.textContent='Name required';m.className='ep-smsg err';return;} + try{await api('/categories',{method:'POST',body:JSON.stringify({name:nm})});m.textContent='Added!';m.className='ep-smsg ok';await loadAll();activeTab='destinations';render();} + catch(e){m.textContent=e.message;m.className='ep-smsg err';} + }; + document.querySelectorAll('[data-ren]').forEach(b=>b.onclick=()=>{ + const id=b.dataset.ren,cur=b.dataset.cv,row=b.closest('.ep-cat-row'); + row.innerHTML=``; + row.querySelector('[data-rc]').onclick=()=>{activeTab='destinations';render();}; + row.querySelector(`[data-rs="${id}"]`).onclick=async()=>{ + const nm=document.getElementById(`ep-ren-${id}`).value.trim(),m=document.getElementById(`ep-rm-${id}`); + if(!nm){m.textContent='Required';m.className='ep-smsg err';return;} + try{await api(`/categories/${id}`,{method:'PUT',body:JSON.stringify({name:nm})});await loadAll();activeTab='destinations';render();} + catch(e){m.textContent=e.message;m.className='ep-smsg err';} + }; + }); + document.querySelectorAll('[data-dc]').forEach(b=>b.onclick=async()=>{ + if(!confirm(`Delete category "${b.dataset.dn}"?`))return; + try{await api(`/categories/${b.dataset.dc}`,{method:'DELETE'});await loadAll();activeTab='destinations';render();}catch(e){alert(e.message);} + }); + + /* Destination add */ + const dt=document.getElementById('ep-dest-tog'),db=document.getElementById('ep-dest-box'); + if(dt)dt.onclick=()=>db.classList.toggle('open'); + const dn=document.getElementById('ep-dn-cancel');if(dn)dn.onclick=()=>db.classList.remove('open'); + const ds=document.getElementById('ep-dn-save'); + if(ds)ds.onclick=async()=>{ + const m=document.getElementById('ep-dn-msg'); + try{ + const img=await getImg('ep-dn-img',''); + await api('/destinations',{method:'POST',body:JSON.stringify({ + name:document.getElementById('ep-dn-name').value.trim(), + location:document.getElementById('ep-dn-loc').value.trim(), + category:document.getElementById('ep-dn-cat').value, + price:document.getElementById('ep-dn-price').value, + rating:document.getElementById('ep-dn-rating').value||'4.5', + image:img, + description:document.getElementById('ep-dn-desc').value.trim() + })}); + m.textContent='Saved!';m.className='ep-smsg ok';await loadAll();activeTab='destinations';render(); + }catch(e){m.textContent=e.message;m.className='ep-smsg err';} + }; + + /* Destination edit */ + document.querySelectorAll('[data-ed]').forEach(b=>b.onclick=()=>{ + const id=b.dataset.ed,d=destinations.find(x=>x.id==id);if(!d)return; + const row=document.querySelector(`tr[data-did="${id}"]`); + row.innerHTML=`
+
Name
+
Location
+
Category
+
Price
+
Rating
+
Image (upload new to replace)${imgPicker('ei-i-'+id,d.image)}
+
Description
+
+ + +
+
`; + row.querySelector(`[data-ec="${id}"]`).onclick=()=>{row.outerHTML=destRow(d);wireDest();}; + row.querySelector(`[data-es="${id}"]`).onclick=async()=>{ + try{ + const img=await getImg('ei-i-'+id,d.image); + await api(`/destinations/${id}`,{method:'PUT',body:JSON.stringify({ + name:document.getElementById(`ei-n-${id}`).value, + location:document.getElementById(`ei-l-${id}`).value, + category:document.getElementById(`ei-c-${id}`).value, + price:document.getElementById(`ei-p-${id}`).value, + rating:document.getElementById(`ei-r-${id}`).value, + image:img, + description:document.getElementById(`ei-d-${id}`).value + })}); + await loadAll();activeTab='destinations';render(); + }catch(e){alert(e.message);} + }; + }); + + /* Destination delete */ + document.querySelectorAll('[data-dd]').forEach(b=>b.onclick=async()=>{ + if(!confirm('Delete this destination? This cannot be undone.'))return; + try{await api(`/destinations/${b.dataset.dd}`,{method:'DELETE'});await loadAll();activeTab='destinations';render();}catch(e){alert(e.message);} + }); +} + +/* Wire: Specials */ +function wireSpec(){ + const st=document.getElementById('ep-spec-tog'),sb=document.getElementById('ep-spec-box'); + if(st)st.onclick=()=>sb.classList.toggle('open'); + const sc=document.getElementById('ep-sn-cancel');if(sc)sc.onclick=()=>sb.classList.remove('open'); + const ss=document.getElementById('ep-sn-save'); + if(ss)ss.onclick=async()=>{ + const m=document.getElementById('ep-sn-msg'); + try{ + const img=await getImg('ep-sn-img',null); + const hls=document.getElementById('ep-sn-hls').value.split('\n').map(l=>l.trim()).filter(Boolean); + await api('/specials',{method:'POST',body:JSON.stringify({ + destination_id:document.getElementById('ep-sn-dest').value, + price:document.getElementById('ep-sn-price').value, + discount:document.getElementById('ep-sn-disc').value, + end_date:document.getElementById('ep-sn-end').value, + image_path:img, + highlights:hls + })}); + m.textContent='Saved!';m.className='ep-smsg ok';await loadAll();activeTab='specials';render(); + }catch(e){m.textContent=e.message;m.className='ep-smsg err';} + }; + + /* Specials edit */ + document.querySelectorAll('[data-es]').forEach(b=>b.onclick=()=>{ + const id=b.dataset.es,s=specials.find(x=>x.id==id);if(!s)return; + const dm=Object.fromEntries(destinations.map(d=>[d.id,d])); + const dest=dm[s.destination_id]; + const hls=Array.isArray(s.highlights)?s.highlights.join('\n'):''; + const curImg=specImg(s); + const row=document.querySelector(`tr[data-sid="${id}"]`); + row.innerHTML=`
+
Original Price
+
Discount %
+
End Date
+
Image (upload to replace; leave blank to use destination photo)${imgPicker('si-i-'+id,curImg)}
+
Highlights (one per line)
+
+ + +
+
`; + row.querySelector(`[data-sc="${id}"]`).onclick=()=>{row.outerHTML=specRow(s);wireSpec();}; + row.querySelector(`[data-sv="${id}"]`).onclick=async()=>{ + try{ + const newImg=await getImg('si-i-'+id,s.image_path||null); + const hls2=document.getElementById(`si-h-${id}`).value.split('\n').map(l=>l.trim()).filter(Boolean); + await api(`/specials/${id}`,{method:'PUT',body:JSON.stringify({ + price:document.getElementById(`si-p-${id}`).value, + discount:document.getElementById(`si-d-${id}`).value, + end_date:document.getElementById(`si-e-${id}`).value, + image_path:newImg, + highlights:hls2 + })}); + await loadAll();activeTab='specials';render(); + }catch(e){alert(e.message);} + }; + }); + + /* Specials delete */ + document.querySelectorAll('[data-ds]').forEach(b=>b.onclick=async()=>{ + if(!confirm('Delete this special?'))return; + try{await api(`/specials/${b.dataset.ds}`,{method:'DELETE'});await loadAll();activeTab='specials';render();}catch(e){alert(e.message);} + }); +} + +/* Wire: Testimonials */ +function wireTest(){ + document.querySelectorAll('[data-tf]').forEach(b=>b.onclick=()=>{tFilter=b.dataset.tf;render();}); + document.querySelectorAll('[data-ta]').forEach(b=>b.onclick=async()=>{ + const id=b.dataset.tid,action=b.dataset.ta; + const card=document.querySelector(`.ep-tc[data-tid="${id}"]`); + try{ + if(action==='approve')await api(`/testimonials/${id}`,{method:'PUT',body:JSON.stringify({status:'approved'})}); + else if(action==='deny')await api(`/testimonials/${id}`,{method:'PUT',body:JSON.stringify({status:'denied'})}); + else if(action==='save'){const ta=card.querySelector('.ep-te');await api(`/testimonials/${id}`,{method:'PUT',body:JSON.stringify({message:ta.value})});} + else if(action==='delete'){if(!confirm('Delete?'))return;await api(`/testimonials/${id}`,{method:'DELETE'});} + await loadAll();render(); + }catch(e){alert(e.message);} + }); +} + +/* Init */ +let injected=false; +function tryInject(){ + if(injected)return; + if(!window.location.pathname.startsWith('/admin/dashboard'))return; + if(!localStorage.getItem('isAdminAuthenticated'))return; + const root=document.getElementById('root'); + if(!root||!root.children.length)return; + injected=true;obs.disconnect(); + Array.from(root.children).forEach(c=>c.style.display='none'); + const portal=buildShell();root.insertBefore(portal,root.firstChild); + loadAll().then(render); +} +const obs=new MutationObserver(tryInject); +obs.observe(document.body,{childList:true,subtree:true}); +tryInject(); +})(); diff --git a/static/js/admin-testimonials.js b/static/js/admin-testimonials.js new file mode 100644 index 0000000..810be1d --- /dev/null +++ b/static/js/admin-testimonials.js @@ -0,0 +1,208 @@ +(function () { + const API = 'https://epictravelexpeditions.com/api'; + + const style = document.createElement('style'); + style.textContent = ` + #et-admin-section { padding: 32px 0; } + #et-admin-section h3 { font-size: 1.4rem; font-weight: 700; color: #111827; margin-bottom: 16px; } + .et-admin-card { + background: #fff; + border: 1px solid #e5e7eb; + border-radius: 10px; + padding: 20px; + margin-bottom: 16px; + display: flex; + gap: 16px; + align-items: flex-start; + } + .et-admin-avatar { + width: 48px; height: 48px; border-radius: 50%; + object-fit: cover; flex-shrink: 0; background: #e5e7eb; + } + .et-admin-avatar-ph { + width: 48px; height: 48px; border-radius: 50%; + background: #2563eb; color: #fff; + display: flex; align-items: center; justify-content: center; + font-weight: 700; font-size: 18px; flex-shrink: 0; + } + .et-admin-body { flex: 1; min-width: 0; } + .et-admin-name { font-weight: 700; font-size: 14px; } + .et-admin-loc { font-size: 12px; color: #6b7280; margin-bottom: 6px; } + .et-admin-msg { font-size: 13px; color: #374151; margin-bottom: 10px; } + .et-admin-status { + display: inline-block; + padding: 2px 10px; border-radius: 999px; + font-size: 11px; font-weight: 600; text-transform: uppercase; + margin-bottom: 10px; + } + .et-status-pending { background: #fef3c7; color: #92400e; } + .et-status-approved { background: #d1fae5; color: #065f46; } + .et-status-denied { background: #fee2e2; color: #991b1b; } + .et-admin-actions { display: flex; gap: 8px; flex-wrap: wrap; } + .et-btn { + padding: 6px 14px; border-radius: 6px; font-size: 12px; font-weight: 600; + border: none; cursor: pointer; transition: opacity .15s; + } + .et-btn:hover { opacity: .8; } + .et-btn-approve { background: #16a34a; color: #fff; } + .et-btn-deny { background: #dc2626; color: #fff; } + .et-btn-delete { background: #6b7280; color: #fff; } + .et-btn-save { background: #2563eb; color: #fff; } + .et-edit-area { + width: 100%; box-sizing: border-box; + border: 1px solid #d1d5db; border-radius: 6px; + padding: 8px 10px; font-size: 13px; + resize: vertical; min-height: 60px; margin-bottom: 6px; + } + .et-tabs { display: flex; gap: 4px; margin-bottom: 20px; } + .et-tab { + padding: 6px 16px; border-radius: 6px; font-size: 13px; font-weight: 600; + cursor: pointer; border: 1px solid #d1d5db; background: #fff; color: #374151; + } + .et-tab.active { background: #2563eb; color: #fff; border-color: #2563eb; } + .et-empty { color: #9ca3af; font-size: 14px; text-align: center; padding: 32px 0; } + `; + document.head.appendChild(style); + + function statusBadge(s) { + return `${s}`; + } + + function avatarHtml(t) { + if (t.image_path) return ``; + return `
${t.full_name.charAt(0).toUpperCase()}
`; + } + + async function applyAction(id, payload) { + const token = localStorage.getItem('auth_token'); + const res = await fetch(`${API}/testimonials/${id}`, { + method: 'PUT', + headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` }, + body: JSON.stringify(payload) + }); + return res.json(); + } + + async function deleteTestimonial(id) { + const token = localStorage.getItem('auth_token'); + await fetch(`${API}/testimonials/${id}`, { + method: 'DELETE', + headers: { Authorization: `Bearer ${token}` } + }); + } + + function renderCards(list, container, reload) { + container.innerHTML = ''; + if (!list.length) { + container.innerHTML = '

No testimonials in this category.

'; + return; + } + list.forEach(t => { + const card = document.createElement('div'); + card.className = 'et-admin-card'; + card.dataset.id = t.id; + card.innerHTML = ` + ${avatarHtml(t)} +
+
${t.full_name}
+
${t.location}
+ ${statusBadge(t.status)} +
${t.message}
+ +
+ ${t.status !== 'approved' ? '' : ''} + ${t.status !== 'denied' ? '' : ''} + + +
+
+ `; + + card.querySelectorAll('[data-action]').forEach(btn => { + btn.addEventListener('click', async () => { + const action = btn.dataset.action; + const textarea = card.querySelector('.et-edit-area'); + try { + if (action === 'approve') await applyAction(t.id, { status: 'approved' }); + else if (action === 'deny') await applyAction(t.id, { status: 'denied' }); + else if (action === 'save') await applyAction(t.id, { message: textarea.value }); + else if (action === 'delete') { if (!confirm('Delete this testimonial?')) return; await deleteTestimonial(t.id); } + reload(); + } catch (e) { alert('Error: ' + e.message); } + }); + }); + + container.appendChild(card); + }); + } + + async function buildAdminPanel(mountEl) { + const token = localStorage.getItem('auth_token'); + const res = await fetch(`${API}/testimonials/all`, { + headers: { Authorization: `Bearer ${token}` } + }); + const all = await res.json(); + + const section = document.createElement('div'); + section.id = 'et-admin-section'; + section.innerHTML = ` +

Testimonials

+
+ + + + +
+
+ `; + + let currentFilter = 'pending'; + const cardsEl = section.querySelector('#et-admin-cards'); + + async function reload() { + const res = await fetch(`${API}/testimonials/all`, { + headers: { Authorization: `Bearer ${token}` } + }); + const fresh = await res.json(); + const filtered = currentFilter === 'all' ? fresh : fresh.filter(t => t.status === currentFilter); + renderCards(filtered, cardsEl, reload); + // Update counts + section.querySelectorAll('.et-tab').forEach(tab => { + const f = tab.dataset.filter; + const count = f === 'all' ? fresh.length : fresh.filter(t => t.status === f).length; + tab.textContent = `${f.charAt(0).toUpperCase()+f.slice(1)} (${count})`; + if (f === currentFilter) tab.classList.add('active'); + else tab.classList.remove('active'); + }); + } + + section.querySelectorAll('.et-tab').forEach(tab => { + tab.addEventListener('click', () => { + currentFilter = tab.dataset.filter; + reload(); + }); + }); + + const initialFiltered = all.filter(t => t.status === 'pending'); + renderCards(initialFiltered, cardsEl, reload); + mountEl.appendChild(section); + } + + // Watch for admin dashboard + let adminDone = false; + const observer = new MutationObserver(() => { + if (adminDone) return; + if (!window.location.pathname.startsWith('/admin/dashboard')) return; + if (!localStorage.getItem('isAdminAuthenticated')) return; + + // Find the main content area of the admin panel + const main = document.querySelector('[class*="max-w-7xl"]'); + if (!main) return; + if (document.getElementById('et-admin-section')) return; + + adminDone = true; + observer.disconnect(); + buildAdminPanel(main); + }); + observer.observe(document.body, { childList: true, subtree: true }); +})(); diff --git a/static/js/main.b9c030e8.js b/static/js/main.b9c030e8.js new file mode 100644 index 0000000..49d3a37 --- /dev/null +++ b/static/js/main.b9c030e8.js @@ -0,0 +1,3 @@ +/*! For license information please see main.b9c030e8.js.LICENSE.txt */ +(()=>{"use strict";var e={4(e,t,n){var r=n(853),a=n(43),o=n(950);function l(e){var t="https://react.dev/errors/"+e;if(1F||(e.current=M[F],M[F]=null,F--)}function U(e,t){F++,M[F]=e.current,e.current=t}var H,W,V=I(null),$=I(null),q=I(null),K=I(null);function Y(e,t){switch(U(q,t),U($,e),U(V,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?vd(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)e=yd(t=vd(t),e);else switch(e){case"svg":e=1;break;case"math":e=2;break;default:e=0}}B(V),U(V,e)}function Q(){B(V),B($),B(q)}function G(e){null!==e.memoizedState&&U(K,e);var t=V.current,n=yd(t,e.type);t!==n&&(U($,e),U(V,n))}function X(e){$.current===e&&(B(V),B($)),K.current===e&&(B(K),df._currentValue=z)}function J(e){if(void 0===H)try{throw Error()}catch(yg){var t=yg.stack.trim().match(/\n( *(at )?)/);H=t&&t[1]||"",W=-1)":-1--a||s[r]!==c[a]){var u="\n"+s[r].replace(" at new "," at ");return e.displayName&&u.includes("")&&(u=u.replace("",e.displayName)),u}}while(1<=r&&0<=a);break}}}finally{Z=!1,Error.prepareStackTrace=n}return(n=e?e.displayName||e.name:"")?J(n):""}function te(e,t){switch(e.tag){case 26:case 27:case 5:return J(e.type);case 16:return J("Lazy");case 13:return e.child!==t&&null!==t?J("Suspense Fallback"):J("Suspense");case 19:return J("SuspenseList");case 0:case 15:return ee(e.type,!1);case 11:return ee(e.type.render,!1);case 1:return ee(e.type,!0);case 31:return J("Activity");default:return""}}function ne(e){try{var t="",n=null;do{t+=te(e,n),n=e,e=e.return}while(e);return t}catch(yg){return"\nError generating stack: "+yg.message+"\n"+yg.stack}}var re=Object.prototype.hasOwnProperty,ae=r.unstable_scheduleCallback,oe=r.unstable_cancelCallback,le=r.unstable_shouldYield,ie=r.unstable_requestPaint,se=r.unstable_now,ce=r.unstable_getCurrentPriorityLevel,ue=r.unstable_ImmediatePriority,de=r.unstable_UserBlockingPriority,fe=r.unstable_NormalPriority,pe=r.unstable_LowPriority,me=r.unstable_IdlePriority,he=r.log,ge=r.unstable_setDisableYieldValue,ve=null,ye=null;function be(e){if("function"===typeof he&&ge(e),ye&&"function"===typeof ye.setStrictMode)try{ye.setStrictMode(ve,e)}catch(t){}}var we=Math.clz32?Math.clz32:function(e){return e>>>=0,0===e?32:31-(xe(e)/ke|0)|0},xe=Math.log,ke=Math.LN2;var Se=256,Ee=262144,Ne=4194304;function Ce(e){var t=42&e;if(0!==t)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return 261888&e;case 262144:case 524288:case 1048576:case 2097152:return 3932160&e;case 4194304:case 8388608:case 16777216:case 33554432:return 62914560&e;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function je(e,t,n){var r=e.pendingLanes;if(0===r)return 0;var a=0,o=e.suspendedLanes,l=e.pingedLanes;e=e.warmLanes;var i=134217727&r;return 0!==i?0!==(r=i&~o)?a=Ce(r):0!==(l&=i)?a=Ce(l):n||0!==(n=i&~e)&&(a=Ce(n)):0!==(i=r&~o)?a=Ce(i):0!==l?a=Ce(l):n||0!==(n=r&~e)&&(a=Ce(n)),0===a?0:0!==t&&t!==a&&0===(t&o)&&((o=a&-a)>=(n=t&-t)||32===o&&0!==(4194048&n))?t:a}function Re(e,t){return 0===(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)}function Te(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;default:return-1}}function Pe(){var e=Ne;return 0===(62914560&(Ne<<=1))&&(Ne=4194304),e}function _e(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}function Oe(e,t){e.pendingLanes|=t,268435456!==t&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function Ae(e,t,n){e.pendingLanes|=t,e.suspendedLanes&=~t;var r=31-we(t);e.entangledLanes|=t,e.entanglements[r]=1073741824|e.entanglements[r]|261930&n}function Le(e,t){var n=e.entangledLanes|=t;for(e=e.entanglements;n;){var r=31-we(n),a=1<=Cn),Tn=String.fromCharCode(32),Pn=!1;function _n(e,t){switch(e){case"keyup":return-1!==En.indexOf(t.keyCode);case"keydown":return 229!==t.keyCode;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function On(e){return"object"===typeof(e=e.detail)&&"data"in e?e.data:null}var An=!1;var Ln={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};function Dn(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return"input"===t?!!Ln[e.type]:"textarea"===t}function zn(e,t,n,r){Dt?zt?zt.push(r):zt=[r]:Dt=r,0<(t=rd(t,"onChange")).length&&(n=new nn("onChange","change",null,n,r),e.push({event:n,listeners:t}))}var Mn=null,Fn=null;function In(e){Qu(e,0)}function Bn(e){if(mt(Je(e)))return e}function Un(e,t){if("change"===e)return t}var Hn=!1;if(Ut){var Wn;if(Ut){var Vn="oninput"in document;if(!Vn){var $n=document.createElement("div");$n.setAttribute("oninput","return;"),Vn="function"===typeof $n.oninput}Wn=Vn}else Wn=!1;Hn=Wn&&(!document.documentMode||9=t)return{node:r,offset:t-e};e=n}e:{for(;r;){if(r.nextSibling){r=r.nextSibling;break e}r=r.parentNode}r=void 0}r=er(r)}}function nr(e,t){return!(!e||!t)&&(e===t||(!e||3!==e.nodeType)&&(t&&3===t.nodeType?nr(e,t.parentNode):"contains"in e?e.contains(t):!!e.compareDocumentPosition&&!!(16&e.compareDocumentPosition(t))))}function rr(e){for(var t=ht((e=null!=e&&null!=e.ownerDocument&&null!=e.ownerDocument.defaultView?e.ownerDocument.defaultView:window).document);t instanceof e.HTMLIFrameElement;){try{var n="string"===typeof t.contentWindow.location.href}catch(r){n=!1}if(!n)break;t=ht((e=t.contentWindow).document)}return t}function ar(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&("input"===t&&("text"===e.type||"search"===e.type||"tel"===e.type||"url"===e.type||"password"===e.type)||"textarea"===t||"true"===e.contentEditable)}var or=Ut&&"documentMode"in document&&11>=document.documentMode,lr=null,ir=null,sr=null,cr=!1;function ur(e,t,n){var r=n.window===n?n.document:9===n.nodeType?n:n.ownerDocument;cr||null==lr||lr!==ht(r)||("selectionStart"in(r=lr)&&ar(r)?r={start:r.selectionStart,end:r.selectionEnd}:r={anchorNode:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection()).anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset},sr&&Zn(sr,r)||(sr=r,0<(r=rd(ir,"onSelect")).length&&(t=new nn("onSelect","select",null,t,n),e.push({event:t,listeners:r}),t.target=lr)))}function dr(e,t){var n={};return n[e.toLowerCase()]=t.toLowerCase(),n["Webkit"+e]="webkit"+t,n["Moz"+e]="moz"+t,n}var fr={animationend:dr("Animation","AnimationEnd"),animationiteration:dr("Animation","AnimationIteration"),animationstart:dr("Animation","AnimationStart"),transitionrun:dr("Transition","TransitionRun"),transitionstart:dr("Transition","TransitionStart"),transitioncancel:dr("Transition","TransitionCancel"),transitionend:dr("Transition","TransitionEnd")},pr={},mr={};function hr(e){if(pr[e])return pr[e];if(!fr[e])return e;var t,n=fr[e];for(t in n)if(n.hasOwnProperty(t)&&t in mr)return pr[e]=n[t];return e}Ut&&(mr=document.createElement("div").style,"AnimationEvent"in window||(delete fr.animationend.animation,delete fr.animationiteration.animation,delete fr.animationstart.animation),"TransitionEvent"in window||delete fr.transitionend.transition);var gr=hr("animationend"),vr=hr("animationiteration"),yr=hr("animationstart"),br=hr("transitionrun"),wr=hr("transitionstart"),xr=hr("transitioncancel"),kr=hr("transitionend"),Sr=new Map,Er="abort auxClick beforeToggle cancel canPlay canPlayThrough click close contextMenu copy cut drag dragEnd dragEnter dragExit dragLeave dragOver dragStart drop durationChange emptied encrypted ended error gotPointerCapture input invalid keyDown keyPress keyUp load loadedData loadedMetadata loadStart lostPointerCapture mouseDown mouseMove mouseOut mouseOver mouseUp paste pause play playing pointerCancel pointerDown pointerMove pointerOut pointerOver pointerUp progress rateChange reset resize seeked seeking stalled submit suspend timeUpdate touchCancel touchEnd touchStart volumeChange scroll toggle touchMove waiting wheel".split(" ");function Nr(e,t){Sr.set(e,t),rt(t,[e])}Er.push("scrollEnd");var Cr="function"===typeof reportError?reportError:function(e){if("object"===typeof window&&"function"===typeof window.ErrorEvent){var t=new window.ErrorEvent("error",{bubbles:!0,cancelable:!0,message:"object"===typeof e&&null!==e&&"string"===typeof e.message?String(e.message):String(e),error:e});if(!window.dispatchEvent(t))return}else if("object"===typeof process&&"function"===typeof process.emit)return void process.emit("uncaughtException",e);console.error(e)},jr=[],Rr=0,Tr=0;function Pr(){for(var e=Rr,t=Tr=Rr=0;t>=l,a-=l,na=1<<32-we(t)+a|n<h?(g=d,d=null):g=d.sibling;var v=p(a,d,i[h],s);if(null===v){null===d&&(d=g);break}e&&d&&null===v.alternate&&t(a,d),l=o(v,l,h),null===u?c=v:u.sibling=v,u=v,d=g}if(h===i.length)return n(a,d),da&&aa(a,h),c;if(null===d){for(;hg?(v=h,h=null):v=h.sibling;var b=p(a,h,y.value,c);if(null===b){null===h&&(h=v);break}e&&h&&null===b.alternate&&t(a,h),i=o(b,i,g),null===d?u=b:d.sibling=b,d=b,h=v}if(y.done)return n(a,h),da&&aa(a,g),u;if(null===h){for(;!y.done;g++,y=s.next())null!==(y=f(a,y.value,c))&&(i=o(y,i,g),null===d?u=y:d.sibling=y,d=y);return da&&aa(a,g),u}for(h=r(h);!y.done;g++,y=s.next())null!==(y=m(h,a,g,y.value,c))&&(e&&null!==y.alternate&&h.delete(null===y.key?g:y.key),i=o(y,i,g),null===d?u=y:d.sibling=y,d=y);return e&&h.forEach(function(e){return t(a,e)}),da&&aa(a,g),u}(s,c,u=b.call(u),d)}if("function"===typeof u.then)return y(s,c,co(u),d);if(u.$$typeof===x)return y(s,c,Aa(s,u),d);fo(s,u)}return"string"===typeof u&&""!==u||"number"===typeof u||"bigint"===typeof u?(u=""+u,null!==c&&6===c.tag?(n(s,c.sibling),(d=a(c,u)).return=s,s=d):(n(s,c),(d=Vr(u,s.mode,d)).return=s,s=d),i(s)):n(s,c)}return function(e,t,n,r){try{so=0;var a=y(e,t,n,r);return io=null,a}catch(yg){if(yg===Xa||yg===Za)throw yg;var o=Fr(29,yg,null,e.mode);return o.lanes=r,o.return=e,o}}}var mo=po(!0),ho=po(!1),go=!1;function vo(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function yo(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function bo(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function wo(e,t,n){var r=e.updateQueue;if(null===r)return null;if(r=r.shared,0!==(2&pc)){var a=r.pending;return null===a?t.next=t:(t.next=a.next,a.next=t),r.pending=t,t=Dr(e),Lr(e,null,n),t}return _r(e,r,t,n),Dr(e)}function xo(e,t,n){if(null!==(t=t.updateQueue)&&(t=t.shared,0!==(4194048&n))){var r=t.lanes;n|=r&=e.pendingLanes,t.lanes=n,Le(e,n)}}function ko(e,t){var n=e.updateQueue,r=e.alternate;if(null!==r&&n===(r=r.updateQueue)){var a=null,o=null;if(null!==(n=n.firstBaseUpdate)){do{var l={lane:n.lane,tag:n.tag,payload:n.payload,callback:null,next:null};null===o?a=o=l:o=o.next=l,n=n.next}while(null!==n);null===o?a=o=t:o=o.next=t}else a=o=t;return n={baseState:r.baseState,firstBaseUpdate:a,lastBaseUpdate:o,shared:r.shared,callbacks:r.callbacks},void(e.updateQueue=n)}null===(e=n.lastBaseUpdate)?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}var So=!1;function Eo(){if(So){if(null!==Va)throw Va}}function No(e,t,n,r){So=!1;var a=e.updateQueue;go=!1;var o=a.firstBaseUpdate,l=a.lastBaseUpdate,i=a.shared.pending;if(null!==i){a.shared.pending=null;var s=i,c=s.next;s.next=null,null===l?o=c:l.next=c,l=s;var u=e.alternate;null!==u&&((i=(u=u.updateQueue).lastBaseUpdate)!==l&&(null===i?u.firstBaseUpdate=c:i.next=c,u.lastBaseUpdate=s))}if(null!==o){var d=a.baseState;for(l=0,u=c=s=null,i=o;;){var f=-536870913&i.lane,m=f!==i.lane;if(m?(gc&f)===f:(r&f)===f){0!==f&&f===Wa&&(So=!0),null!==u&&(u=u.next={lane:0,tag:i.tag,payload:i.payload,callback:null,next:null});e:{var h=e,g=i;f=t;var v=n;switch(g.tag){case 1:if("function"===typeof(h=g.payload)){d=h.call(v,d,f);break e}d=h;break e;case 3:h.flags=-65537&h.flags|128;case 0:if(null===(f="function"===typeof(h=g.payload)?h.call(v,d,f):h)||void 0===f)break e;d=p({},d,f);break e;case 2:go=!0}}null!==(f=i.callback)&&(e.flags|=64,m&&(e.flags|=8192),null===(m=a.callbacks)?a.callbacks=[f]:m.push(f))}else m={lane:f,tag:i.tag,payload:i.payload,callback:i.callback,next:null},null===u?(c=u=m,s=d):u=u.next=m,l|=f;if(null===(i=i.next)){if(null===(i=a.shared.pending))break;i=(m=i).next,m.next=null,a.lastBaseUpdate=m,a.shared.pending=null}}null===u&&(s=d),a.baseState=s,a.firstBaseUpdate=c,a.lastBaseUpdate=u,null===o&&(a.shared.lanes=0),Ec|=l,e.lanes=l,e.memoizedState=d}}function Co(e,t){if("function"!==typeof e)throw Error(l(191,e));e.call(t)}function jo(e,t){var n=e.callbacks;if(null!==n)for(e.callbacks=null,e=0;eo?o:8;var l=L.T,i={};L.T=i,di(e,!1,t,n);try{var s=a(),c=L.S;if(null!==c&&c(i,s),null!==s&&"object"===typeof s&&"function"===typeof s.then)ui(e,t,function(e,t){var n=[],r={status:"pending",value:null,reason:null,then:function(e){n.push(e)}};return e.then(function(){r.status="fulfilled",r.value=t;for(var e=0;e<\/script>",o=o.removeChild(o.firstChild);break;case"select":o="string"===typeof r.is?i.createElement("select",{is:r.is}):i.createElement("select"),r.multiple?o.multiple=!0:r.size&&(o.size=r.size);break;default:o="string"===typeof r.is?i.createElement(a,{is:r.is}):i.createElement(a)}}o[Ue]=t,o[He]=r;e:for(i=t.child;null!==i;){if(5===i.tag||6===i.tag)o.appendChild(i.stateNode);else if(4!==i.tag&&27!==i.tag&&null!==i.child){i.child.return=i,i=i.child;continue}if(i===t)break e;for(;null===i.sibling;){if(null===i.return||i.return===t)break e;i=i.return}i.sibling.return=i.return,i=i.sibling}t.stateNode=o;e:switch(fd(o,a,r),a){case"button":case"input":case"select":case"textarea":r=!!r.autoFocus;break e;case"img":r=!0;break e;default:r=!1}r&&is(t)}}return fs(t),ss(t,t.type,null===e||e.memoizedProps,t.pendingProps,n),null;case 6:if(e&&null!=t.stateNode)e.memoizedProps!==r&&is(t);else{if("string"!==typeof r&&null===t.stateNode)throw Error(l(166));if(e=q.current,ya(t)){if(e=t.stateNode,n=t.memoizedProps,r=null,null!==(a=ca))switch(a.tag){case 27:case 5:r=a.memoizedProps}e[Ue]=t,(e=!!(e.nodeValue===n||null!==r&&!0===r.suppressHydrationWarning||cd(e.nodeValue,n)))||ha(t,!0)}else(e=gd(e).createTextNode(r))[Ue]=t,t.stateNode=e}return fs(t),null;case 31:if(n=t.memoizedState,null===e||null!==e.memoizedState){if(r=ya(t),null!==n){if(null===e){if(!r)throw Error(l(318));if(!(e=null!==(e=t.memoizedState)?e.dehydrated:null))throw Error(l(557));e[Ue]=t}else ba(),0===(128&t.flags)&&(t.memoizedState=null),t.flags|=4;fs(t),e=!1}else n=wa(),null!==e&&null!==e.memoizedState&&(e.memoizedState.hydrationErrors=n),e=!0;if(!e)return 256&t.flags?(Io(t),t):(Io(t),null);if(0!==(128&t.flags))throw Error(l(558))}return fs(t),null;case 13:if(r=t.memoizedState,null===e||null!==e.memoizedState&&null!==e.memoizedState.dehydrated){if(a=ya(t),null!==r&&null!==r.dehydrated){if(null===e){if(!a)throw Error(l(318));if(!(a=null!==(a=t.memoizedState)?a.dehydrated:null))throw Error(l(317));a[Ue]=t}else ba(),0===(128&t.flags)&&(t.memoizedState=null),t.flags|=4;fs(t),a=!1}else a=wa(),null!==e&&null!==e.memoizedState&&(e.memoizedState.hydrationErrors=a),a=!0;if(!a)return 256&t.flags?(Io(t),t):(Io(t),null)}return Io(t),0!==(128&t.flags)?(t.lanes=n,t):(n=null!==r,e=null!==e&&null!==e.memoizedState,n&&(a=null,null!==(r=t.child).alternate&&null!==r.alternate.memoizedState&&null!==r.alternate.memoizedState.cachePool&&(a=r.alternate.memoizedState.cachePool.pool),o=null,null!==r.memoizedState&&null!==r.memoizedState.cachePool&&(o=r.memoizedState.cachePool.pool),o!==a&&(r.flags|=2048)),n!==e&&n&&(t.child.flags|=8192),us(t,t.updateQueue),fs(t),null);case 4:return Q(),null===e&&Zu(t.stateNode.containerInfo),fs(t),null;case 10:return Ca(t.type),fs(t),null;case 19:if(B(Bo),null===(r=t.memoizedState))return fs(t),null;if(a=0!==(128&t.flags),null===(o=r.rendering))if(a)ds(r,!1);else{if(0!==Sc||null!==e&&0!==(128&e.flags))for(e=t.child;null!==e;){if(null!==(o=Uo(e))){for(t.flags|=128,ds(r,!1),e=o.updateQueue,t.updateQueue=e,us(t,e),t.subtreeFlags=0,e=n,n=t.child;null!==n;)Ur(n,e),n=n.sibling;return U(Bo,1&Bo.current|2),da&&aa(t,r.treeForkCount),t.child}e=e.sibling}null!==r.tail&&se()>Lc&&(t.flags|=128,a=!0,ds(r,!1),t.lanes=4194304)}else{if(!a)if(null!==(e=Uo(o))){if(t.flags|=128,a=!0,e=e.updateQueue,t.updateQueue=e,us(t,e),ds(r,!0),null===r.tail&&"hidden"===r.tailMode&&!o.alternate&&!da)return fs(t),null}else 2*se()-r.renderingStartTime>Lc&&536870912!==n&&(t.flags|=128,a=!0,ds(r,!1),t.lanes=4194304);r.isBackwards?(o.sibling=t.child,t.child=o):(null!==(e=r.last)?e.sibling=o:t.child=o,r.last=o)}return null!==r.tail?(e=r.tail,r.rendering=e,r.tail=e.sibling,r.renderingStartTime=se(),e.sibling=null,n=Bo.current,U(Bo,a?1&n|2:1&n),da&&aa(t,r.treeForkCount),e):(fs(t),null);case 22:case 23:return Io(t),Oo(),r=null!==t.memoizedState,null!==e?null!==e.memoizedState!==r&&(t.flags|=8192):r&&(t.flags|=8192),r?0!==(536870912&n)&&0===(128&t.flags)&&(fs(t),6&t.subtreeFlags&&(t.flags|=8192)):fs(t),null!==(n=t.updateQueue)&&us(t,n.retryQueue),n=null,null!==e&&null!==e.memoizedState&&null!==e.memoizedState.cachePool&&(n=e.memoizedState.cachePool.pool),r=null,null!==t.memoizedState&&null!==t.memoizedState.cachePool&&(r=t.memoizedState.cachePool.pool),r!==n&&(t.flags|=2048),null!==e&&B(Ka),null;case 24:return n=null,null!==e&&(n=e.memoizedState.cache),t.memoizedState.cache!==n&&(t.flags|=2048),Ca(Fa),fs(t),null;case 25:case 30:return null}throw Error(l(156,t.tag))}function ms(e,t){switch(ia(t),t.tag){case 1:return 65536&(e=t.flags)?(t.flags=-65537&e|128,t):null;case 3:return Ca(Fa),Q(),0!==(65536&(e=t.flags))&&0===(128&e)?(t.flags=-65537&e|128,t):null;case 26:case 27:case 5:return X(t),null;case 31:if(null!==t.memoizedState){if(Io(t),null===t.alternate)throw Error(l(340));ba()}return 65536&(e=t.flags)?(t.flags=-65537&e|128,t):null;case 13:if(Io(t),null!==(e=t.memoizedState)&&null!==e.dehydrated){if(null===t.alternate)throw Error(l(340));ba()}return 65536&(e=t.flags)?(t.flags=-65537&e|128,t):null;case 19:return B(Bo),null;case 4:return Q(),null;case 10:return Ca(t.type),null;case 22:case 23:return Io(t),Oo(),null!==e&&B(Ka),65536&(e=t.flags)?(t.flags=-65537&e|128,t):null;case 24:return Ca(Fa),null;default:return null}}function hs(e,t){switch(ia(t),t.tag){case 3:Ca(Fa),Q();break;case 26:case 27:case 5:X(t);break;case 4:Q();break;case 31:null!==t.memoizedState&&Io(t);break;case 13:Io(t);break;case 19:B(Bo);break;case 10:Ca(t.type);break;case 22:case 23:Io(t),Oo(),null!==e&&B(Ka);break;case 24:Ca(Fa)}}function gs(e,t){try{var n=t.updateQueue,r=null!==n?n.lastEffect:null;if(null!==r){var a=r.next;n=a;do{if((n.tag&e)===e){r=void 0;var o=n.create,l=n.inst;r=o(),l.destroy=r}n=n.next}while(n!==a)}}catch(i){Su(t,t.return,i)}}function vs(e,t,n){try{var r=t.updateQueue,a=null!==r?r.lastEffect:null;if(null!==a){var o=a.next;r=o;do{if((r.tag&e)===e){var l=r.inst,i=l.destroy;if(void 0!==i){l.destroy=void 0,a=t;var s=n,c=i;try{c()}catch(u){Su(a,s,u)}}}r=r.next}while(r!==o)}}catch(u){Su(t,t.return,u)}}function ys(e){var t=e.updateQueue;if(null!==t){var n=e.stateNode;try{jo(t,n)}catch(r){Su(e,e.return,r)}}}function bs(e,t,n){n.props=Si(e.type,e.memoizedProps),n.state=e.memoizedState;try{n.componentWillUnmount()}catch(r){Su(e,t,r)}}function ws(e,t){try{var n=e.ref;if(null!==n){switch(e.tag){case 26:case 27:case 5:var r=e.stateNode;break;default:r=e.stateNode}"function"===typeof n?e.refCleanup=n(r):n.current=r}}catch(a){Su(e,t,a)}}function xs(e,t){var n=e.ref,r=e.refCleanup;if(null!==n)if("function"===typeof r)try{r()}catch(a){Su(e,t,a)}finally{e.refCleanup=null,null!=(e=e.alternate)&&(e.refCleanup=null)}else if("function"===typeof n)try{n(null)}catch(o){Su(e,t,o)}else n.current=null}function ks(e){var t=e.type,n=e.memoizedProps,r=e.stateNode;try{e:switch(t){case"button":case"input":case"select":case"textarea":n.autoFocus&&r.focus();break e;case"img":n.src?r.src=n.src:n.srcSet&&(r.srcset=n.srcSet)}}catch(a){Su(e,e.return,a)}}function Ss(e,t,n){try{var r=e.stateNode;!function(e,t,n,r){switch(t){case"div":case"span":case"svg":case"path":case"a":case"g":case"p":case"li":break;case"input":var a=null,o=null,i=null,s=null,c=null,u=null,d=null;for(m in n){var f=n[m];if(n.hasOwnProperty(m)&&null!=f)switch(m){case"checked":case"value":break;case"defaultValue":c=f;default:r.hasOwnProperty(m)||ud(e,t,m,null,r,f)}}for(var p in r){var m=r[p];if(f=n[p],r.hasOwnProperty(p)&&(null!=m||null!=f))switch(p){case"type":o=m;break;case"name":a=m;break;case"checked":u=m;break;case"defaultChecked":d=m;break;case"value":i=m;break;case"defaultValue":s=m;break;case"children":case"dangerouslySetInnerHTML":if(null!=m)throw Error(l(137,t));break;default:m!==f&&ud(e,t,p,m,r,f)}}return void yt(e,i,s,c,u,d,o,a);case"select":for(o in m=i=s=p=null,n)if(c=n[o],n.hasOwnProperty(o)&&null!=c)switch(o){case"value":break;case"multiple":m=c;default:r.hasOwnProperty(o)||ud(e,t,o,null,r,c)}for(a in r)if(o=r[a],c=n[a],r.hasOwnProperty(a)&&(null!=o||null!=c))switch(a){case"value":p=o;break;case"defaultValue":s=o;break;case"multiple":i=o;default:o!==c&&ud(e,t,a,o,r,c)}return t=s,n=i,r=m,void(null!=p?xt(e,!!n,p,!1):!!r!==!!n&&(null!=t?xt(e,!!n,t,!0):xt(e,!!n,n?[]:"",!1)));case"textarea":for(s in m=p=null,n)if(a=n[s],n.hasOwnProperty(s)&&null!=a&&!r.hasOwnProperty(s))switch(s){case"value":case"children":break;default:ud(e,t,s,null,r,a)}for(i in r)if(a=r[i],o=n[i],r.hasOwnProperty(i)&&(null!=a||null!=o))switch(i){case"value":p=a;break;case"defaultValue":m=a;break;case"children":break;case"dangerouslySetInnerHTML":if(null!=a)throw Error(l(91));break;default:a!==o&&ud(e,t,i,a,r,o)}return void kt(e,p,m);case"option":for(var h in n)if(p=n[h],n.hasOwnProperty(h)&&null!=p&&!r.hasOwnProperty(h))if("selected"===h)e.selected=!1;else ud(e,t,h,null,r,p);for(c in r)if(p=r[c],m=n[c],r.hasOwnProperty(c)&&p!==m&&(null!=p||null!=m))if("selected"===c)e.selected=p&&"function"!==typeof p&&"symbol"!==typeof p;else ud(e,t,c,p,r,m);return;case"img":case"link":case"area":case"base":case"br":case"col":case"embed":case"hr":case"keygen":case"meta":case"param":case"source":case"track":case"wbr":case"menuitem":for(var g in n)p=n[g],n.hasOwnProperty(g)&&null!=p&&!r.hasOwnProperty(g)&&ud(e,t,g,null,r,p);for(u in r)if(p=r[u],m=n[u],r.hasOwnProperty(u)&&p!==m&&(null!=p||null!=m))switch(u){case"children":case"dangerouslySetInnerHTML":if(null!=p)throw Error(l(137,t));break;default:ud(e,t,u,p,r,m)}return;default:if(Rt(t)){for(var v in n)p=n[v],n.hasOwnProperty(v)&&void 0!==p&&!r.hasOwnProperty(v)&&dd(e,t,v,void 0,r,p);for(d in r)p=r[d],m=n[d],!r.hasOwnProperty(d)||p===m||void 0===p&&void 0===m||dd(e,t,d,p,r,m);return}}for(var y in n)p=n[y],n.hasOwnProperty(y)&&null!=p&&!r.hasOwnProperty(y)&&ud(e,t,y,null,r,p);for(f in r)p=r[f],m=n[f],!r.hasOwnProperty(f)||p===m||null==p&&null==m||ud(e,t,f,p,r,m)}(r,e.type,n,t),r[He]=t}catch(a){Su(e,e.return,a)}}function Es(e){return 5===e.tag||3===e.tag||26===e.tag||27===e.tag&&Cd(e.type)||4===e.tag}function Ns(e){e:for(;;){for(;null===e.sibling;){if(null===e.return||Es(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;5!==e.tag&&6!==e.tag&&18!==e.tag;){if(27===e.tag&&Cd(e.type))continue e;if(2&e.flags)continue e;if(null===e.child||4===e.tag)continue e;e.child.return=e,e=e.child}if(!(2&e.flags))return e.stateNode}}function Cs(e,t,n){var r=e.tag;if(5===r||6===r)e=e.stateNode,t?(9===n.nodeType?n.body:"HTML"===n.nodeName?n.ownerDocument.body:n).insertBefore(e,t):((t=9===n.nodeType?n.body:"HTML"===n.nodeName?n.ownerDocument.body:n).appendChild(e),null!==(n=n._reactRootContainer)&&void 0!==n||null!==t.onclick||(t.onclick=Ot));else if(4!==r&&(27===r&&Cd(e.type)&&(n=e.stateNode,t=null),null!==(e=e.child)))for(Cs(e,t,n),e=e.sibling;null!==e;)Cs(e,t,n),e=e.sibling}function js(e,t,n){var r=e.tag;if(5===r||6===r)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(4!==r&&(27===r&&Cd(e.type)&&(n=e.stateNode),null!==(e=e.child)))for(js(e,t,n),e=e.sibling;null!==e;)js(e,t,n),e=e.sibling}function Rs(e){var t=e.stateNode,n=e.memoizedProps;try{for(var r=e.type,a=t.attributes;a.length;)t.removeAttributeNode(a[0]);fd(t,r,n),t[Ue]=e,t[He]=n}catch(o){Su(e,e.return,o)}}var Ts=!1,Ps=!1,_s=!1,Os="function"===typeof WeakSet?WeakSet:Set,As=null;function Ls(e,t,n){var r=n.flags;switch(n.tag){case 0:case 11:case 15:Ys(e,n),4&r&&gs(5,n);break;case 1:if(Ys(e,n),4&r)if(e=n.stateNode,null===t)try{e.componentDidMount()}catch(l){Su(n,n.return,l)}else{var a=Si(n.type,t.memoizedProps);t=t.memoizedState;try{e.componentDidUpdate(a,t,e.__reactInternalSnapshotBeforeUpdate)}catch(i){Su(n,n.return,i)}}64&r&&ys(n),512&r&&ws(n,n.return);break;case 3:if(Ys(e,n),64&r&&null!==(e=n.updateQueue)){if(t=null,null!==n.child)switch(n.child.tag){case 27:case 5:case 1:t=n.child.stateNode}try{jo(e,t)}catch(l){Su(n,n.return,l)}}break;case 27:null===t&&4&r&&Rs(n);case 26:case 5:Ys(e,n),null===t&&4&r&&ks(n),512&r&&ws(n,n.return);break;case 12:Ys(e,n);break;case 31:Ys(e,n),4&r&&Bs(e,n);break;case 13:Ys(e,n),4&r&&Us(e,n),64&r&&(null!==(e=n.memoizedState)&&(null!==(e=e.dehydrated)&&function(e,t){var n=e.ownerDocument;if("$~"===e.data)e._reactRetry=t;else if("$?"!==e.data||"loading"!==n.readyState)t();else{var r=function(){t(),n.removeEventListener("DOMContentLoaded",r)};n.addEventListener("DOMContentLoaded",r),e._reactRetry=r}}(e,n=ju.bind(null,n))));break;case 22:if(!(r=null!==n.memoizedState||Ts)){t=null!==t&&null!==t.memoizedState||Ps,a=Ts;var o=Ps;Ts=r,(Ps=t)&&!o?Gs(e,n,0!==(8772&n.subtreeFlags)):Ys(e,n),Ts=a,Ps=o}break;case 30:break;default:Ys(e,n)}}function Ds(e){var t=e.alternate;null!==t&&(e.alternate=null,Ds(t)),e.child=null,e.deletions=null,e.sibling=null,5===e.tag&&(null!==(t=e.stateNode)&&Qe(t)),e.stateNode=null,e.return=null,e.dependencies=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.stateNode=null,e.updateQueue=null}var zs=null,Ms=!1;function Fs(e,t,n){for(n=n.child;null!==n;)Is(e,t,n),n=n.sibling}function Is(e,t,n){if(ye&&"function"===typeof ye.onCommitFiberUnmount)try{ye.onCommitFiberUnmount(ve,n)}catch(o){}switch(n.tag){case 26:Ps||xs(n,t),Fs(e,t,n),n.memoizedState?n.memoizedState.count--:n.stateNode&&(n=n.stateNode).parentNode.removeChild(n);break;case 27:Ps||xs(n,t);var r=zs,a=Ms;Cd(n.type)&&(zs=n.stateNode,Ms=!1),Fs(e,t,n),Fd(n.stateNode),zs=r,Ms=a;break;case 5:Ps||xs(n,t);case 6:if(r=zs,a=Ms,zs=null,Fs(e,t,n),Ms=a,null!==(zs=r))if(Ms)try{(9===zs.nodeType?zs.body:"HTML"===zs.nodeName?zs.ownerDocument.body:zs).removeChild(n.stateNode)}catch(l){Su(n,t,l)}else try{zs.removeChild(n.stateNode)}catch(l){Su(n,t,l)}break;case 18:null!==zs&&(Ms?(jd(9===(e=zs).nodeType?e.body:"HTML"===e.nodeName?e.ownerDocument.body:e,n.stateNode),$f(e)):jd(zs,n.stateNode));break;case 4:r=zs,a=Ms,zs=n.stateNode.containerInfo,Ms=!0,Fs(e,t,n),zs=r,Ms=a;break;case 0:case 11:case 14:case 15:vs(2,n,t),Ps||vs(4,n,t),Fs(e,t,n);break;case 1:Ps||(xs(n,t),"function"===typeof(r=n.stateNode).componentWillUnmount&&bs(n,t,r)),Fs(e,t,n);break;case 21:Fs(e,t,n);break;case 22:Ps=(r=Ps)||null!==n.memoizedState,Fs(e,t,n),Ps=r;break;default:Fs(e,t,n)}}function Bs(e,t){if(null===t.memoizedState&&(null!==(e=t.alternate)&&null!==(e=e.memoizedState))){e=e.dehydrated;try{$f(e)}catch(n){Su(t,t.return,n)}}}function Us(e,t){if(null===t.memoizedState&&(null!==(e=t.alternate)&&(null!==(e=e.memoizedState)&&null!==(e=e.dehydrated))))try{$f(e)}catch(n){Su(t,t.return,n)}}function Hs(e,t){var n=function(e){switch(e.tag){case 31:case 13:case 19:var t=e.stateNode;return null===t&&(t=e.stateNode=new Os),t;case 22:return null===(t=(e=e.stateNode)._retryCache)&&(t=e._retryCache=new Os),t;default:throw Error(l(435,e.tag))}}(e);t.forEach(function(t){if(!n.has(t)){n.add(t);var r=Ru.bind(null,e,t);t.then(r,r)}})}function Ws(e,t){var n=t.deletions;if(null!==n)for(var r=0;r title"))),fd(o,r,n),o[Ue]=e,et(o),r=o;break e;case"link":var i=nf("link","href",a).get(r+(n.href||""));if(i)for(var s=0;si)break;var u=s.transferSize,d=s.initiatorType;u&&pd(d)&&(l+=u*((s=s.responseEnd)of?50:800)+t);return e.unsuspend=n,function(){e.unsuspend=null,clearTimeout(r),clearTimeout(a)}}:null}(d,m),null!==m)return Bc=o,e.cancelPendingCommit=m(hu.bind(null,e,t,o,n,r,a,l,i,s,u,d,null,f,p)),void Jc(e,o,l,!c)}hu(e,t,o,n,r,a,l,i,s)}function Xc(e){for(var t=e;;){var n=t.tag;if((0===n||11===n||15===n)&&16384&t.flags&&(null!==(n=t.updateQueue)&&null!==(n=n.stores)))for(var r=0;rg&&(l=g,g=h,h=l);var v=tr(i,h),y=tr(i,g);if(v&&y&&(1!==p.rangeCount||p.anchorNode!==v.node||p.anchorOffset!==v.offset||p.focusNode!==y.node||p.focusOffset!==y.offset)){var b=d.createRange();b.setStart(v.node,v.offset),p.removeAllRanges(),h>g?(p.addRange(b),p.extend(y.node,y.offset)):(b.setEnd(y.node,y.offset),p.addRange(b))}}}}for(d=[],p=i;p=p.parentNode;)1===p.nodeType&&d.push({element:p,left:p.scrollLeft,top:p.scrollTop});for("function"===typeof i.focus&&i.focus(),i=0;in?32:n,L.T=null,n=Hc,Hc=null;var o=Fc,i=Bc;if(Mc=0,Ic=Fc=null,Bc=0,0!==(6&pc))throw Error(l(331));var s=pc;if(pc|=4,sc(o.current),ec(o,o.current,i,n),pc=s,zu(0,!1),ye&&"function"===typeof ye.onPostCommitFiberRoot)try{ye.onPostCommitFiberRoot(ve,o)}catch(c){}return!0}finally{D.p=a,L.T=r,bu(e,t)}}function ku(e,t,n){t=Yr(n,t),null!==(e=wo(e,t=Ti(e.stateNode,t,2),2))&&(Oe(e,2),Du(e))}function Su(e,t,n){if(3===e.tag)ku(e,e,n);else for(;null!==t;){if(3===t.tag){ku(t,e,n);break}if(1===t.tag){var r=t.stateNode;if("function"===typeof t.type.getDerivedStateFromError||"function"===typeof r.componentDidCatch&&(null===zc||!zc.has(r))){e=Yr(n,e),null!==(r=wo(t,n=Pi(2),2))&&(_i(n,r,t,e),Oe(r,2),Du(r));break}}t=t.return}}function Eu(e,t,n){var r=e.pingCache;if(null===r){r=e.pingCache=new fc;var a=new Set;r.set(t,a)}else void 0===(a=r.get(t))&&(a=new Set,r.set(t,a));a.has(n)||(xc=!0,a.add(n),e=Nu.bind(null,e,t,n),t.then(e,e))}function Nu(e,t,n){var r=e.pingCache;null!==r&&r.delete(t),e.pingedLanes|=e.suspendedLanes&n,e.warmLanes&=~n,mc===e&&(gc&n)===n&&(4===Sc||3===Sc&&(62914560&gc)===gc&&300>se()-Oc?0===(2&pc)&&tu(e,0):Cc|=n,Rc===gc&&(Rc=0)),Du(e)}function Cu(e,t){0===t&&(t=Pe()),null!==(e=Ar(e,t))&&(Oe(e,t),Du(e))}function ju(e){var t=e.memoizedState,n=0;null!==t&&(n=t.retryLane),Cu(e,n)}function Ru(e,t){var n=0;switch(e.tag){case 31:case 13:var r=e.stateNode,a=e.memoizedState;null!==a&&(n=a.retryLane);break;case 19:r=e.stateNode;break;case 22:r=e.stateNode._retryCache;break;default:throw Error(l(314))}null!==r&&r.delete(t),Cu(e,n)}var Tu=null,Pu=null,_u=!1,Ou=!1,Au=!1,Lu=0;function Du(e){e!==Pu&&null===e.next&&(null===Pu?Tu=Pu=e:Pu=Pu.next=e),Ou=!0,_u||(_u=!0,Ed(function(){0!==(6&pc)?ae(ue,Mu):Fu()}))}function zu(e,t){if(!Au&&Ou){Au=!0;do{for(var n=!1,r=Tu;null!==r;){if(!t)if(0!==e){var a=r.pendingLanes;if(0===a)var o=0;else{var l=r.suspendedLanes,i=r.pingedLanes;o=(1<<31-we(42|e)+1)-1,o=201326741&(o&=a&~(l&~i))?201326741&o|1:o?2|o:0}0!==o&&(n=!0,Uu(r,o))}else o=gc,0===(3&(o=je(r,r===mc?o:0,null!==r.cancelPendingCommit||-1!==r.timeoutHandle)))||Re(r,o)||(n=!0,Uu(r,o));r=r.next}}while(n);Au=!1}}function Mu(){Fu()}function Fu(){Ou=_u=!1;var e=0;0!==Lu&&function(){var e=window.event;if(e&&"popstate"===e.type)return e!==wd&&(wd=e,!0);return wd=null,!1}()&&(e=Lu);for(var t=se(),n=null,r=Tu;null!==r;){var a=r.next,o=Iu(r,t);0===o?(r.next=null,null===n?Tu=a:n.next=a,null===a&&(Pu=n)):(n=r,(0!==e||0!==(3&o))&&(Ou=!0)),r=a}0!==Mc&&5!==Mc||zu(e,!1),0!==Lu&&(Lu=0)}function Iu(e,t){for(var n=e.suspendedLanes,r=e.pingedLanes,a=e.expirationTimes,o=-62914561&e.pendingLanes;0 title"):null)}function af(e){return"stylesheet"!==e.type||0!==(3&e.state.loading)}var of=0;function lf(){if(this.count--,0===this.count&&(0===this.imgCount||!this.waitingForImages))if(this.stylesheets)cf(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}var sf=null;function cf(e,t){e.stylesheets=null,null!==e.unsuspend&&(e.count++,sf=new Map,t.forEach(uf,e),sf=null,lf.call(e))}function uf(e,t){if(!(4&t.state.loading)){var n=sf.get(e);if(n)var r=n.get(null);else{n=new Map,sf.set(e,n);for(var a=e.querySelectorAll("link[data-precedence],style[data-precedence]"),o=0;o>>1,a=e[r];if(!(0>>1;ro(s,n))co(u,s)?(e[r]=u,e[c]=n,r=c):(e[r]=s,e[i]=n,r=i);else{if(!(co(u,n)))break e;e[r]=u,e[c]=n,r=c}}}return t}function o(e,t){var n=e.sortIndex-t.sortIndex;return 0!==n?n:e.id-t.id}if(t.unstable_now=void 0,"object"===typeof performance&&"function"===typeof performance.now){var l=performance;t.unstable_now=function(){return l.now()}}else{var i=Date,s=i.now();t.unstable_now=function(){return i.now()-s}}var c=[],u=[],d=1,f=null,p=3,m=!1,h=!1,g=!1,v=!1,y="function"===typeof setTimeout?setTimeout:null,b="function"===typeof clearTimeout?clearTimeout:null,w="undefined"!==typeof setImmediate?setImmediate:null;function x(e){for(var t=r(u);null!==t;){if(null===t.callback)a(u);else{if(!(t.startTime<=e))break;a(u),t.sortIndex=t.expirationTime,n(c,t)}t=r(u)}}function k(e){if(g=!1,x(e),!h)if(null!==r(c))h=!0,E||(E=!0,S());else{var t=r(u);null!==t&&O(k,t.startTime-e)}}var S,E=!1,N=-1,C=5,j=-1;function R(){return!!v||!(t.unstable_now()-je&&R());){var l=f.callback;if("function"===typeof l){f.callback=null,p=f.priorityLevel;var i=l(f.expirationTime<=e);if(e=t.unstable_now(),"function"===typeof i){f.callback=i,x(e),n=!0;break t}f===r(c)&&a(c),x(e)}else a(c);f=r(c)}if(null!==f)n=!0;else{var s=r(u);null!==s&&O(k,s.startTime-e),n=!1}}break e}finally{f=null,p=o,m=!1}n=void 0}}finally{n?S():E=!1}}}if("function"===typeof w)S=function(){w(T)};else if("undefined"!==typeof MessageChannel){var P=new MessageChannel,_=P.port2;P.port1.onmessage=T,S=function(){_.postMessage(null)}}else S=function(){y(T,0)};function O(e,n){N=y(function(){e(t.unstable_now())},n)}t.unstable_IdlePriority=5,t.unstable_ImmediatePriority=1,t.unstable_LowPriority=4,t.unstable_NormalPriority=3,t.unstable_Profiling=null,t.unstable_UserBlockingPriority=2,t.unstable_cancelCallback=function(e){e.callback=null},t.unstable_forceFrameRate=function(e){0>e||125l?(e.sortIndex=o,n(u,e),null===r(c)&&e===r(u)&&(g?(b(N),N=-1):g=!0,O(k,o-l))):(e.sortIndex=i,n(c,e),h||m||(h=!0,E||(E=!0,S()))),e},t.unstable_shouldYield=R,t.unstable_wrapCallback=function(e){var t=p;return function(){var n=p;p=t;try{return e.apply(this,arguments)}finally{p=n}}}},950(e,t,n){!function e(){if("undefined"!==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"===typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE)try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}(),e.exports=n(672)}},t={};function n(r){var a=t[r];if(void 0!==a)return a.exports;var o=t[r]={exports:{}};return e[r](o,o.exports,n),o.exports}(()=>{var e,t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__;n.t=function(r,a){if(1&a&&(r=this(r)),8&a)return r;if("object"===typeof r&&r){if(4&a&&r.__esModule)return r;if(16&a&&"function"===typeof r.then)return r}var o=Object.create(null);n.r(o);var l={};e=e||[null,t({}),t([]),t(t)];for(var i=2&a&&r;("object"==typeof i||"function"==typeof i)&&!~e.indexOf(i);i=t(i))Object.getOwnPropertyNames(i).forEach(e=>l[e]=()=>r[e]);return l.default=()=>r,n.d(o,l),o}})(),n.d=(e,t)=>{for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.g=function(){if("object"===typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"===typeof window)return window}}(),n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),n.r=e=>{"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.nc=void 0;var r={};n.r(r),n.d(r,{hasBrowserEnv:()=>Ja,hasStandardBrowserEnv:()=>eo,hasStandardBrowserWebWorkerEnv:()=>to,navigator:()=>Za,origin:()=>no});var a=n(43),o=n.t(a,2),l=n(391);function i(e,t){if(null==e)return{};var n,r,a=function(e,t){if(null==e)return{};var n={};for(var r in e)if({}.hasOwnProperty.call(e,r)){if(-1!==t.indexOf(r))continue;n[r]=e[r]}return n}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r0&&void 0!==arguments[0]?arguments[0]:{})}function x(e,t){if(!1===e||null===e||"undefined"===typeof e)throw new Error(t)}function k(e,t){if(!e){"undefined"!==typeof console&&console.warn(t);try{throw new Error(t)}catch(n){}}}function S(e,t){return{usr:e.state,key:e.key,idx:t}}function E(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,r=arguments.length>3?arguments[3]:void 0;return f(f({pathname:"string"===typeof e?e:e.pathname,search:"",hash:""},"string"===typeof t?C(t):t),{},{state:n,key:t&&t.key||r||Math.random().toString(36).substring(2,10)})}function N(e){let{pathname:t="/",search:n="",hash:r=""}=e;return n&&"?"!==n&&(t+="?"===n.charAt(0)?n:"?"+n),r&&"#"!==r&&(t+="#"===r.charAt(0)?r:"#"+r),t}function C(e){let t={};if(e){let n=e.indexOf("#");n>=0&&(t.hash=e.substring(n),e=e.substring(0,n));let r=e.indexOf("?");r>=0&&(t.search=e.substring(r),e=e.substring(0,r)),e&&(t.pathname=e)}return t}function j(e,t,n){let r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},{window:a=document.defaultView,v5Compat:o=!1}=r,l=a.history,i="POP",s=null,c=u();function u(){return(l.state||{idx:null}).idx}function d(){i="POP";let e=u(),t=null==e?null:e-c;c=e,s&&s({action:i,location:m.location,delta:t})}function p(e){return R(e)}null==c&&(c=0,l.replaceState(f(f({},l.state),{},{idx:c}),""));let m={get action(){return i},get location(){return e(a,l)},listen(e){if(s)throw new Error("A history only accepts one active listener");return a.addEventListener(b,d),s=e,()=>{a.removeEventListener(b,d),s=null}},createHref:e=>t(a,e),createURL:p,encodeLocation(e){let t=p(e);return{pathname:t.pathname,search:t.search,hash:t.hash}},push:function(e,t){i="PUSH";let r=E(m.location,e,t);n&&n(r,e),c=u()+1;let d=S(r,c),f=m.createHref(r);try{l.pushState(d,"",f)}catch(p){if(p instanceof DOMException&&"DataCloneError"===p.name)throw p;a.location.assign(f)}o&&s&&s({action:i,location:m.location,delta:1})},replace:function(e,t){i="REPLACE";let r=E(m.location,e,t);n&&n(r,e),c=u();let a=S(r,c),d=m.createHref(r);l.replaceState(a,"",d),o&&s&&s({action:i,location:m.location,delta:0})},go:e=>l.go(e)};return m}function R(e){let t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n="http://localhost";"undefined"!==typeof window&&(n="null"!==window.location.origin?window.location.origin:window.location.href),x(n,"No window.location.(origin|href) available to create URL");let r="string"===typeof e?e:N(e);return r=r.replace(/ $/,"%20"),!t&&r.startsWith("//")&&(r=n+r),new URL(r,n)}new WeakMap;function T(e,t){return P(e,t,arguments.length>2&&void 0!==arguments[2]?arguments[2]:"/",!1)}function P(e,t,n,r){let a=$(("string"===typeof t?C(t):t).pathname||"/",n);if(null==a)return null;let o=_(e);!function(e){e.sort((e,t)=>e.score!==t.score?t.score-e.score:function(e,t){let n=e.length===t.length&&e.slice(0,-1).every((e,n)=>e===t[n]);return n?e[e.length-1]-t[t.length-1]:0}(e.routesMeta.map(e=>e.childrenIndex),t.routesMeta.map(e=>e.childrenIndex)))}(o);let l=null;for(let i=0;null==l&&i1&&void 0!==arguments[1]?arguments[1]:[],n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"",a=arguments.length>4&&void 0!==arguments[4]&&arguments[4],o=function(e,o){let l=arguments.length>2&&void 0!==arguments[2]?arguments[2]:a,i=arguments.length>3?arguments[3]:void 0,s={relativePath:void 0===i?e.path||"":i,caseSensitive:!0===e.caseSensitive,childrenIndex:o,route:e};if(s.relativePath.startsWith("/")){if(!s.relativePath.startsWith(r)&&l)return;x(s.relativePath.startsWith(r),'Absolute route path "'.concat(s.relativePath,'" nested under path "').concat(r,'" is not valid. An absolute child route path must start with the combined path of all its parent routes.')),s.relativePath=s.relativePath.slice(r.length)}let c=Z([r,s.relativePath]),u=n.concat(s);e.children&&e.children.length>0&&(x(!0!==e.index,'Index routes must not have child routes. Please remove all child routes from route path "'.concat(c,'".')),_(e.children,t,u,c,l)),(null!=e.path||e.index)&&t.push({path:c,score:B(c,e.index),routesMeta:u})};return e.forEach((e,t)=>{var n;if(""!==e.path&&null!==(n=e.path)&&void 0!==n&&n.includes("?"))for(let r of O(e.path))o(e,t,!0,r);else o(e,t)}),t}function O(e){let t=e.split("/");if(0===t.length)return[];let[n,...r]=t,a=n.endsWith("?"),o=n.replace(/\?$/,"");if(0===r.length)return a?[o,""]:[o];let l=O(r.join("/")),i=[];return i.push(...l.map(e=>""===e?o:[o,e].join("/"))),a&&i.push(...l),i.map(t=>e.startsWith("/")&&""===t?"/":t)}var A=/^:[\w-]+$/,L=3,D=2,z=1,M=10,F=-2,I=e=>"*"===e;function B(e,t){let n=e.split("/"),r=n.length;return n.some(I)&&(r+=F),t&&(r+=D),n.filter(e=>!I(e)).reduce((e,t)=>e+(A.test(t)?L:""===t?z:M),r)}function U(e,t){let n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],{routesMeta:r}=e,a={},o="/",l=[];for(let i=0;i{let{paramName:r,isOptional:a}=t;if("*"===r){let e=i[n]||"";l=o.slice(0,o.length-e.length).replace(/(.)\/+$/,"$1")}const s=i[n];return e[r]=a&&!s?void 0:(s||"").replace(/%2F/g,"/"),e},{});return{params:s,pathname:o,pathnameBase:l,pattern:e}}function W(e){let t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];k("*"===e||!e.endsWith("*")||e.endsWith("/*"),'Route path "'.concat(e,'" will be treated as if it were "').concat(e.replace(/\*$/,"/*"),'" because the `*` character must always follow a `/` in the pattern. To get rid of this warning, please change the route path to "').concat(e.replace(/\*$/,"/*"),'".'));let r=[],a="^"+e.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(e,t,n)=>(r.push({paramName:t,isOptional:null!=n}),n?"/?([^\\/]+)?":"/([^\\/]+)")).replace(/\/([\w-]+)\?(\/|$)/g,"(/$1)?$2");return e.endsWith("*")?(r.push({paramName:"*"}),a+="*"===e||"/*"===e?"(.*)$":"(?:\\/(.+)|\\/*)$"):n?a+="\\/*$":""!==e&&"/"!==e&&(a+="(?:(?=\\/|$))"),[new RegExp(a,t?void 0:"i"),r]}function V(e){try{return e.split("/").map(e=>decodeURIComponent(e).replace(/\//g,"%2F")).join("/")}catch(t){return k(!1,'The URL path "'.concat(e,'" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (').concat(t,").")),e}}function $(e,t){if("/"===t)return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let n=t.endsWith("/")?t.length-1:t.length,r=e.charAt(n);return r&&"/"!==r?null:e.slice(n)||"/"}var q=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,K=e=>q.test(e);function Y(e,t){let n=t.replace(/\/+$/,"").split("/");return e.split("/").forEach(e=>{".."===e?n.length>1&&n.pop():"."!==e&&n.push(e)}),n.length>1?n.join("/"):"/"}function Q(e,t,n,r){return"Cannot include a '".concat(e,"' character in a manually specified `to.").concat(t,"` field [").concat(JSON.stringify(r),"]. Please separate it out to the `to.").concat(n,'` field. Alternatively you may provide the full path as a string in and the router will parse it for you.')}function G(e){return e.filter((e,t)=>0===t||e.route.path&&e.route.path.length>0)}function X(e){let t=G(e);return t.map((e,n)=>n===t.length-1?e.pathname:e.pathnameBase)}function J(e,t,n){let r,a=arguments.length>3&&void 0!==arguments[3]&&arguments[3];"string"===typeof e?r=C(e):(r=f({},e),x(!r.pathname||!r.pathname.includes("?"),Q("?","pathname","search",r)),x(!r.pathname||!r.pathname.includes("#"),Q("#","pathname","hash",r)),x(!r.search||!r.search.includes("#"),Q("#","search","hash",r)));let o,l=""===e||""===r.pathname,i=l?"/":r.pathname;if(null==i)o=n;else{let e=t.length-1;if(!a&&i.startsWith("..")){let t=i.split("/");for(;".."===t[0];)t.shift(),e-=1;r.pathname=t.join("/")}o=e>=0?t[e]:"/"}let s=function(e){let t,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"/",{pathname:r,search:a="",hash:o=""}="string"===typeof e?C(e):e;if(r)if(K(r))t=r;else{if(r.includes("//")){let e=r;r=r.replace(/\/\/+/g,"/"),k(!1,"Pathnames cannot have embedded double slashes - normalizing ".concat(e," -> ").concat(r))}t=r.startsWith("/")?Y(r.substring(1),"/"):Y(r,n)}else t=n;return{pathname:t,search:te(a),hash:ne(o)}}(r,o),c=i&&"/"!==i&&i.endsWith("/"),u=(l||"."===i)&&n.endsWith("/");return s.pathname.endsWith("/")||!c&&!u||(s.pathname+="/"),s}var Z=e=>e.join("/").replace(/\/\/+/g,"/"),ee=e=>e.replace(/\/+$/,"").replace(/^\/*/,"/"),te=e=>e&&"?"!==e?e.startsWith("?")?e:"?"+e:"",ne=e=>e&&"#"!==e?e.startsWith("#")?e:"#"+e:"";var re=class{constructor(e,t,n){let r=arguments.length>3&&void 0!==arguments[3]&&arguments[3];this.status=e,this.statusText=t||"",this.internal=r,n instanceof Error?(this.data=n.toString(),this.error=n):this.data=n}};function ae(e){return null!=e&&"number"===typeof e.status&&"string"===typeof e.statusText&&"boolean"===typeof e.internal&&"data"in e}function oe(e){return e.map(e=>e.route.path).filter(Boolean).join("/").replace(/\/\/*/g,"/")||"/"}var le="undefined"!==typeof window&&"undefined"!==typeof window.document&&"undefined"!==typeof window.document.createElement;function ie(e,t){let n=e;if("string"!==typeof n||!q.test(n))return{absoluteURL:void 0,isExternal:!1,to:n};let r=n,a=!1;if(le)try{let e=new URL(window.location.href),r=n.startsWith("//")?new URL(e.protocol+n):new URL(n),o=$(r.pathname,t);r.origin===e.origin&&null!=o?n=o+r.search+r.hash:a=!0}catch(o){k(!1,' contains an invalid URL which will probably break when clicked - please update to a valid URL path.'))}return{absoluteURL:r,isExternal:a,to:n}}Symbol("Uninstrumented");Object.getOwnPropertyNames(Object.prototype).sort().join("\0");var se=["POST","PUT","PATCH","DELETE"],ce=(new Set(se),["GET",...se]);new Set(ce),Symbol("ResetLoaderData");var ue=a.createContext(null);ue.displayName="DataRouter";var de=a.createContext(null);de.displayName="DataRouterState";var fe=a.createContext(!1);function pe(){return a.useContext(fe)}var me=a.createContext({isTransitioning:!1});me.displayName="ViewTransition";var he=a.createContext(new Map);he.displayName="Fetchers";var ge=a.createContext(null);ge.displayName="Await";var ve=a.createContext(null);ve.displayName="Navigation";var ye=a.createContext(null);ye.displayName="Location";var be=a.createContext({outlet:null,matches:[],isDataRoute:!1});be.displayName="Route";var we=a.createContext(null);we.displayName="RouteError";var xe="REACT_ROUTER_ERROR";function ke(){return null!=a.useContext(ye)}function Se(){return x(ke(),"useLocation() may be used only in the context of a component."),a.useContext(ye).location}var Ee="You should call navigate() in a React.useEffect(), not when your component is first rendered.";function Ne(e){a.useContext(ve).static||a.useLayoutEffect(e)}function Ce(){let{isDataRoute:e}=a.useContext(be);return e?function(){let{router:e}=Me("useNavigate"),t=Ie("useNavigate"),n=a.useRef(!1);Ne(()=>{n.current=!0});let r=a.useCallback(async function(r){let a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};k(n.current,Ee),n.current&&("number"===typeof r?await e.navigate(r):await e.navigate(r,f({fromRouteId:t},a)))},[e,t]);return r}():function(){x(ke(),"useNavigate() may be used only in the context of a component.");let e=a.useContext(ue),{basename:t,navigator:n}=a.useContext(ve),{matches:r}=a.useContext(be),{pathname:o}=Se(),l=JSON.stringify(X(r)),i=a.useRef(!1);Ne(()=>{i.current=!0});let s=a.useCallback(function(r){let a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(k(i.current,Ee),!i.current)return;if("number"===typeof r)return void n.go(r);let s=J(r,JSON.parse(l),o,"path"===a.relative);null==e&&"/"!==t&&(s.pathname="/"===s.pathname?t:Z([t,s.pathname])),(a.replace?n.replace:n.push)(s,a.state,a)},[t,n,l,o,e]);return s}()}a.createContext(null);function je(e){let{relative:t}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},{matches:n}=a.useContext(be),{pathname:r}=Se(),o=JSON.stringify(X(n));return a.useMemo(()=>J(e,JSON.parse(o),r,"path"===t),[e,o,r,t])}function Re(e,t,n,r,o){x(ke(),"useRoutes() may be used only in the context of a component.");let{navigator:l}=a.useContext(ve),{matches:i}=a.useContext(be),s=i[i.length-1],c=s?s.params:{},u=s?s.pathname:"/",d=s?s.pathnameBase:"/",p=s&&s.route;{let e=p&&p.path||"";He(u,!p||e.endsWith("*")||e.endsWith("*?"),'You rendered descendant (or called `useRoutes()`) at "'.concat(u,'" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won\'t match anymore and therefore the child routes will never render.\n\nPlease change the parent to .'))}let m,h=Se();if(t){var g;let e="string"===typeof t?C(t):t;x("/"===d||(null===(g=e.pathname)||void 0===g?void 0:g.startsWith(d)),'When overriding the location using `` or `useRoutes(routes, location)`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "'.concat(d,'" but pathname "').concat(e.pathname,'" was given in the `location` prop.')),m=e}else m=h;let v=m.pathname||"/",y=v;if("/"!==d){let e=d.replace(/^\//,"").split("/");y="/"+v.replace(/^\//,"").split("/").slice(e.length).join("/")}let b=T(e,{pathname:y});k(p||null!=b,'No routes matched location "'.concat(m.pathname).concat(m.search).concat(m.hash,'" ')),k(null==b||void 0!==b[b.length-1].route.element||void 0!==b[b.length-1].route.Component||void 0!==b[b.length-1].route.lazy,'Matched leaf route at location "'.concat(m.pathname).concat(m.search).concat(m.hash,'" does not have an element or Component. This means it will render an with a null value by default resulting in an "empty" page.'));let w=De(b&&b.map(e=>Object.assign({},e,{params:Object.assign({},c,e.params),pathname:Z([d,l.encodeLocation?l.encodeLocation(e.pathname.replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:e.pathname]),pathnameBase:"/"===e.pathnameBase?d:Z([d,l.encodeLocation?l.encodeLocation(e.pathnameBase.replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:e.pathnameBase])})),i,n,r,o);return t&&w?a.createElement(ye.Provider,{value:{location:f({pathname:"/",search:"",hash:"",state:null,key:"default"},m),navigationType:"POP"}},w):w}function Te(){let e=Be(),t=ae(e)?"".concat(e.status," ").concat(e.statusText):e instanceof Error?e.message:JSON.stringify(e),n=e instanceof Error?e.stack:null,r="rgba(200,200,200, 0.5)",o={padding:"0.5rem",backgroundColor:r},l={padding:"2px 4px",backgroundColor:r},i=null;return console.error("Error handled by React Router default ErrorBoundary:",e),i=a.createElement(a.Fragment,null,a.createElement("p",null,"\ud83d\udcbf Hey developer \ud83d\udc4b"),a.createElement("p",null,"You can provide a way better UX than this when your app throws errors by providing your own ",a.createElement("code",{style:l},"ErrorBoundary")," or"," ",a.createElement("code",{style:l},"errorElement")," prop on your route.")),a.createElement(a.Fragment,null,a.createElement("h2",null,"Unexpected Application Error!"),a.createElement("h3",{style:{fontStyle:"italic"}},t),n?a.createElement("pre",{style:o},n):null,i)}var Pe=a.createElement(Te,null),_e=class extends a.Component{constructor(e){super(e),this.state={location:e.location,revalidation:e.revalidation,error:e.error}}static getDerivedStateFromError(e){return{error:e}}static getDerivedStateFromProps(e,t){return t.location!==e.location||"idle"!==t.revalidation&&"idle"===e.revalidation?{error:e.error,location:e.location,revalidation:e.revalidation}:{error:void 0!==e.error?e.error:t.error,location:t.location,revalidation:e.revalidation||t.revalidation}}componentDidCatch(e,t){this.props.onError?this.props.onError(e,t):console.error("React Router caught the following error during render",e)}render(){let e=this.state.error;if(this.context&&"object"===typeof e&&e&&"digest"in e&&"string"===typeof e.digest){const t=function(e){if(e.startsWith("".concat(xe,":").concat("ROUTE_ERROR_RESPONSE",":{")))try{let t=JSON.parse(e.slice(40));if("object"===typeof t&&t&&"number"===typeof t.status&&"string"===typeof t.statusText)return new re(t.status,t.statusText,t.data)}catch(t){}}(e.digest);t&&(e=t)}let t=void 0!==e?a.createElement(be.Provider,{value:this.props.routeContext},a.createElement(we.Provider,{value:e,children:this.props.component})):this.props.children;return this.context?a.createElement(Ae,{error:e},t):t}};_e.contextType=fe;var Oe=new WeakMap;function Ae(e){let{children:t,error:n}=e,{basename:r}=a.useContext(ve);if("object"===typeof n&&n&&"digest"in n&&"string"===typeof n.digest){let e=function(e){if(e.startsWith("".concat(xe,":").concat("REDIRECT",":{")))try{let t=JSON.parse(e.slice(28));if("object"===typeof t&&t&&"number"===typeof t.status&&"string"===typeof t.statusText&&"string"===typeof t.location&&"boolean"===typeof t.reloadDocument&&"boolean"===typeof t.replace)return t}catch(t){}}(n.digest);if(e){let t=Oe.get(n);if(t)throw t;let o=ie(e.location,r);if(le&&!Oe.get(n)){if(!o.isExternal&&!e.reloadDocument){const t=Promise.resolve().then(()=>window.__reactRouterDataRouter.navigate(o.to,{replace:e.replace}));throw Oe.set(n,t),t}window.location.href=o.absoluteURL||o.to}return a.createElement("meta",{httpEquiv:"refresh",content:"0;url=".concat(o.absoluteURL||o.to)})}}return t}function Le(e){let{routeContext:t,match:n,children:r}=e,o=a.useContext(ue);return o&&o.static&&o.staticContext&&(n.route.errorElement||n.route.ErrorBoundary)&&(o.staticContext._deepestRenderedBoundaryId=n.route.id),a.createElement(be.Provider,{value:t},r)}function De(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null;if(null==e){if(!n)return null;if(n.errors)e=n.matches;else{if(0!==t.length||n.initialized||!(n.matches.length>0))return null;e=n.matches}}let o=e,l=null===n||void 0===n?void 0:n.errors;if(null!=l){let e=o.findIndex(e=>e.route.id&&void 0!==(null===l||void 0===l?void 0:l[e.route.id]));x(e>=0,"Could not find a matching route for errors on route IDs: ".concat(Object.keys(l).join(","))),o=o.slice(0,Math.min(o.length,e+1))}let i=!1,s=-1;if(n)for(let a=0;a=0?o.slice(0,s+1):[o[0]];break}}}let c=n&&r?(e,t)=>{var a,o;r(e,{location:n.location,params:null!==(a=null===(o=n.matches)||void 0===o||null===(o=o[0])||void 0===o?void 0:o.params)&&void 0!==a?a:{},unstable_pattern:oe(n.matches),errorInfo:t})}:void 0;return o.reduceRight((e,r,u)=>{let d,f=!1,p=null,m=null;n&&(d=l&&r.route.id?l[r.route.id]:void 0,p=r.route.errorElement||Pe,i&&(s<0&&0===u?(He("route-fallback",!1,"No `HydrateFallback` element provided to render during initial hydration"),f=!0,m=null):s===u&&(f=!0,m=r.route.hydrateFallbackElement||null)));let h=t.concat(o.slice(0,u+1)),g=()=>{let t;return t=d?p:f?m:r.route.Component?a.createElement(r.route.Component,null):r.route.element?r.route.element:e,a.createElement(Le,{match:r,routeContext:{outlet:e,matches:h,isDataRoute:null!=n},children:t})};return n&&(r.route.ErrorBoundary||r.route.errorElement||0===u)?a.createElement(_e,{location:n.location,revalidation:n.revalidation,component:p,error:d,children:g(),routeContext:{outlet:null,matches:h,isDataRoute:!0},onError:c}):g()},null)}function ze(e){return"".concat(e," must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.")}function Me(e){let t=a.useContext(ue);return x(t,ze(e)),t}function Fe(e){let t=a.useContext(de);return x(t,ze(e)),t}function Ie(e){let t=function(e){let t=a.useContext(be);return x(t,ze(e)),t}(e),n=t.matches[t.matches.length-1];return x(n.route.id,"".concat(e,' can only be used on routes that contain a unique "id"')),n.route.id}function Be(){var e;let t=a.useContext(we),n=Fe("useRouteError"),r=Ie("useRouteError");return void 0!==t?t:null===(e=n.errors)||void 0===e?void 0:e[r]}var Ue={};function He(e,t,n){t||Ue[e]||(Ue[e]=!0,k(!1,n))}var We={};function Ve(e,t){e||We[t]||(We[t]=!0,console.warn(t))}o.useOptimistic;a.memo(function(e){let{routes:t,future:n,state:r,onError:a}=e;return Re(t,void 0,r,a,n)});function $e(e){x(!1,"A is only ever to be used as the child of element, never rendered directly. Please wrap your in a .")}function qe(e){let{basename:t="/",children:n=null,location:r,navigationType:o="POP",navigator:l,static:i=!1,unstable_useTransitions:s}=e;x(!ke(),"You cannot render a inside another . You should never have more than one in your app.");let c=t.replace(/^\/*/,"/"),u=a.useMemo(()=>({basename:c,navigator:l,static:i,unstable_useTransitions:s,future:{}}),[c,l,i,s]);"string"===typeof r&&(r=C(r));let{pathname:d="/",search:f="",hash:p="",state:m=null,key:h="default"}=r,g=a.useMemo(()=>{let e=$(d,c);return null==e?null:{location:{pathname:e,search:f,hash:p,state:m,key:h},navigationType:o}},[c,d,f,p,m,h,o]);return k(null!=g,' is not able to match the URL "').concat(d).concat(f).concat(p,"\" because it does not start with the basename, so the won't render anything.")),null==g?null:a.createElement(ve.Provider,{value:u},a.createElement(ye.Provider,{children:n,value:g}))}function Ke(e){let{children:t,location:n}=e;return Re(Ye(t),n)}a.Component;function Ye(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=[];return a.Children.forEach(e,(e,r)=>{if(!a.isValidElement(e))return;let o=[...t,r];if(e.type===a.Fragment)return void n.push.apply(n,Ye(e.props.children,o));x(e.type===$e,"[".concat("string"===typeof e.type?e.type:e.type.name,"] is not a component. All component children of must be a or ")),x(!e.props.index||!e.props.children,"An index route cannot have child routes.");let l={id:e.props.id||o.join("-"),caseSensitive:e.props.caseSensitive,element:e.props.element,Component:e.props.Component,index:e.props.index,path:e.props.path,middleware:e.props.middleware,loader:e.props.loader,action:e.props.action,hydrateFallbackElement:e.props.hydrateFallbackElement,HydrateFallback:e.props.HydrateFallback,errorElement:e.props.errorElement,ErrorBoundary:e.props.ErrorBoundary,hasErrorBoundary:!0===e.props.hasErrorBoundary||null!=e.props.ErrorBoundary||null!=e.props.errorElement,shouldRevalidate:e.props.shouldRevalidate,handle:e.props.handle,lazy:e.props.lazy};e.props.children&&(l.children=Ye(e.props.children,o)),n.push(l)}),n}var Qe="get",Ge="application/x-www-form-urlencoded";function Xe(e){return"undefined"!==typeof HTMLElement&&e instanceof HTMLElement}var Je=null;var Ze=new Set(["application/x-www-form-urlencoded","multipart/form-data","text/plain"]);function et(e){return null==e||Ze.has(e)?e:(k(!1,'"'.concat(e,'" is not a valid `encType` for `
`/`` and will default to "').concat(Ge,'"')),null)}function tt(e,t){let n,r,a,o,l;if(Xe(i=e)&&"form"===i.tagName.toLowerCase()){let l=e.getAttribute("action");r=l?$(l,t):null,n=e.getAttribute("method")||Qe,a=et(e.getAttribute("enctype"))||Ge,o=new FormData(e)}else if(function(e){return Xe(e)&&"button"===e.tagName.toLowerCase()}(e)||function(e){return Xe(e)&&"input"===e.tagName.toLowerCase()}(e)&&("submit"===e.type||"image"===e.type)){let l=e.form;if(null==l)throw new Error('Cannot submit a