diff --git a/.gitignore b/.gitignore index e427ff3c..e6f4f92a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules/ */node_modules/ */build/ +includes/api_keys.php \ No newline at end of file diff --git a/about.php b/about.php new file mode 100644 index 00000000..39e8efdd --- /dev/null +++ b/about.php @@ -0,0 +1,28 @@ +prepare("SELECT * FROM pages WHERE page_key = :page_key"); +$stmt->bindValue(':page_key', 'about_us'); +$stmt->execute(); +$page = $stmt->fetch(); + +?> + +
Content not found. Please set up the 'About Us' page in the admin dashboard.
+ +Define which documents are required for driver and restaurant sign-ups.
+ +| Document Name | +Applies To | +Action | +
|---|---|---|
| No required documents have been defined yet. | +||
| + | + | + + | +
Congratulations! The location for your restaurant, " . htmlspecialchars($restaurant_name) . ", has been approved.
Your restaurant is now fully visible to customers.
"; + } elseif ($status == 'rejected') { + $subject = "Action Required: Your Restaurant Location has been Rejected"; + $body = "There was an issue with the location provided for your restaurant, " . htmlspecialchars($restaurant_name) . ".
Please log in to your account and update the location pin for our team to review again.
"; + } + + if (!empty($subject)) { + MailService::sendMail($owner_email, $subject, $body); + } + } + + header('Location: index.php'); + exit; +} else { + // If id or status is not provided, redirect + header('Location: index.php'); + exit; +} +?> \ No newline at end of file diff --git a/api/pexels.php b/api/pexels.php new file mode 100644 index 00000000..4fb4c8c2 --- /dev/null +++ b/api/pexels.php @@ -0,0 +1,19 @@ +'Failed to fetch image']); exit; } +$photo = $data['photos'][0]; +$src = $photo['src']['large2x'] ?? ($photo['src']['large'] ?? $photo['src']['original']); +$target = __DIR__ . '/../assets/images/pexels/' . $photo['id'] . '.jpg'; +download_to($src, $target); +// Return minimal info and local relative path +echo json_encode([ + 'id' => $photo['id'], + 'local' => 'assets/images/pexels/' . $photo['id'] . '.jpg', + 'photographer' => $photo['photographer'] ?? null, + 'photographer_url' => $photo['photographer_url'] ?? null, +]); diff --git a/assets/css/main.css b/assets/css/main.css index 930baf64..6e575747 100644 --- a/assets/css/main.css +++ b/assets/css/main.css @@ -1,426 +1,214 @@ -/* -MajuroEats Theme -*/ - :root { - --coral: #FF6F61; - --orange: #FF9A8B; - --ocean-blue: #00A7E1; - --palm-green: #3D9970; - --coconut-white: #FFFFFF; - --sand: #F4F1EA; - --text-dark: #333333; - --text-light: #666666; - --border-color: #EAEAEA; - - --font-family: 'Nunito', sans-serif; - --border-radius: 12px; - --shadow-soft: 0 4px 15px rgba(0, 0, 0, 0.07); - --shadow-medium: 0 8px 25px rgba(0, 0, 0, 0.1); - --transition: all 0.3s ease-in-out; + --primary-color: #007bff; + --secondary-color: #6c757d; + --success-color: #28a745; + --danger-color: #dc3545; + --warning-color: #ffc107; + --info-color: #17a2b8; + --light-color: #f8f9fa; + --dark-color: #343a40; + --font-family-sans-serif: 'Inter', sans-serif; + --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; } -/* --- Global Styles --- */ body { - font-family: var(--font-family); - background-color: var(--coconut-white); - color: var(--text-dark); - margin: 0; - padding-top: 80px; /* Space for fixed header */ + font-family: var(--font-family-sans-serif); + line-height: 1.6; } -.container { - max-width: 1200px; - margin: 0 auto; - padding: 0 20px; +.main-header .navbar-brand { + font-weight: 700; + font-size: 1.5rem; } -a { - text-decoration: none; - color: var(--coral); - transition: var(--transition); +.main-header .nav-link { + font-weight: 600; } -a:hover { - opacity: 0.8; -} - -img { - max-width: 100%; - height: auto; -} - -main { - display: block; /* For older browsers */ -} - -.page-content { - padding-top: 40px; - padding-bottom: 40px; -} - -.section-title { - font-size: 2.8rem; - font-weight: 800; +.hero-section { + background: url('https://images.pexels.com/photos/1640777/pexels-photo-1640-1.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2') no-repeat center center; + background-size: cover; + height: 60vh; + display: flex; + align-items: center; + justify-content: center; text-align: center; - margin-bottom: 50px; - color: var(--text-dark); + color: white; position: relative; - padding-bottom: 15px; } -.section-title::after { +.hero-section::before { content: ''; position: absolute; - bottom: 0; - left: 50%; - transform: translateX(-50%); - width: 80px; - height: 4px; - background-color: var(--coral); - border-radius: 2px; -} - -/* --- Navigation Bar --- */ -.main-header { - background-color: rgba(255, 255, 255, 0.85); - backdrop-filter: blur(10px); - border-bottom: 1px solid var(--border-color); - box-shadow: var(--shadow-soft); - position: fixed; top: 0; left: 0; - width: 100%; - z-index: 1000; - height: 80px; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.5); } -.main-nav { - display: flex; - align-items: center; - justify-content: space-between; - height: 100%; -} - -.logo { - display: flex; - align-items: center; - gap: 10px; - font-size: 1.8rem; - font-weight: 800; - color: var(--text-dark); -} - -.logo-icon { - font-size: 2rem; -} - -.nav-links { - display: flex; - list-style: none; - margin: 0; - padding: 0; - gap: 30px; -} - -.nav-links a { - color: var(--text-light); - font-weight: 700; - font-size: 1rem; - padding: 10px 0; - border-bottom: 2px solid transparent; -} - -.nav-links a:hover, .nav-links a.active { - color: var(--coral); - border-bottom-color: var(--coral); -} - -.nav-actions { - display: flex; - align-items: center; - gap: 15px; -} - -.nav-link-button { - color: var(--text-light); - font-weight: 700; - font-size: 1rem; -} - -.nav-button { - padding: 10px 20px; - border-radius: 50px; - font-weight: 700; - font-size: 1rem; - border: 2px solid var(--coral); -} - -.nav-button.primary { - background-color: var(--coral); - color: var(--coconut-white); -} - -.nav-button.primary:hover { - background-color: transparent; - color: var(--coral); -} - -.hamburger { - display: none; - background: none; - border: none; - cursor: pointer; - padding: 0; -} - -.hamburger span { - display: block; - width: 25px; - height: 3px; - background-color: var(--text-dark); - margin: 5px 0; - transition: var(--transition); -} - -/* --- Hero Section --- */ -.hero-section { - background-color: #f8f9fa; - padding: 100px 0; - text-align: center; +.hero-content { + position: relative; + z-index: 1; } .hero-title { font-size: 3.5rem; - font-weight: 800; - margin-bottom: 1rem; + font-weight: 700; } .hero-subtitle { font-size: 1.25rem; - color: var(--text-light); - margin-bottom: 2.5rem; } -.hero-section .btn-primary { - background-color: #ff5a5f; - border-color: #ff5a5f; - font-size: 1.25rem; - padding: 15px 40px; - border-radius: 50px; +.section-title { font-weight: 700; + margin-bottom: 3rem; } -.hero-section .btn-primary:hover { - background-color: #e04f54; - border-color: #e04f54; +.feature-card { + border: none; + transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out; } -.hero-section .text-muted { - color: #6c757d !important; - text-decoration: underline; -} - -/* --- How It Works Section --- */ -#how-it-works { - padding: 60px 0; - background-color: #fff; -} - -.step { - padding: 20px; -} - -.step-icon { - width: 80px; - height: 80px; - margin-bottom: 1.5rem; -} - -.step h3 { - font-size: 1.5rem; - font-weight: 700; - margin-bottom: 0.5rem; -} - -.step p { - color: var(--text-light); -} - -/* --- Restaurant & Cuisine Cards --- */ -.restaurant-card, .cuisine-card { - border: 1px solid var(--border-color); - border-radius: var(--border-radius); - transition: var(--transition); - background-color: #fff; -} - -.restaurant-card:hover, .cuisine-card:hover { +.feature-card:hover { transform: translateY(-5px); - box-shadow: var(--shadow-medium); + box-shadow: 0 8px 16px rgba(0,0,0,0.1); } -.restaurant-card .card-img-top { - border-top-left-radius: var(--border-radius); - border-top-right-radius: var(--border-radius); - height: 200px; - object-fit: cover; +.feature-icon { + font-size: 3rem; + color: var(--primary-color); } -.restaurant-card .card-body { - padding: 1.5rem; +.restaurant-card { + border: 1px solid #eee; + border-radius: .5rem; + transition: transform .2s, box-shadow .2s; } -.restaurant-card .card-title a { - color: var(--text-dark); - font-weight: 700; -} - -.restaurant-card .card-title a:hover { - color: var(--coral); +.restaurant-card:hover { + transform: translateY(-5px); + box-shadow: 0 8px 16px rgba(0,0,0,0.1); } .cuisine-card { - display: block; - padding: 1rem; text-align: center; + text-decoration: none; + color: var(--dark-color); + display: block; + transition: transform .2s; +} + +.cuisine-card:hover { + transform: translateY(-5px); } .cuisine-card img { width: 100px; height: 100px; - object-fit: cover; border-radius: 50%; - margin-bottom: 1rem; + object-fit: cover; + box-shadow: 0 4px 8px rgba(0,0,0,0.1); } -.cuisine-card h5 { - color: var(--text-dark); - font-weight: 700; +/* Restaurant Page Styles */ +.restaurant-card-new { + border: none; + border-radius: .75rem; + overflow: hidden; + transition: transform 0.3s ease, box-shadow 0.3s ease; } -/* --- Modal Styles --- */ -.modal { - display: none; - position: fixed; - z-index: 1001; - left: 0; - top: 0; - width: 100%; - height: 100%; - overflow: auto; - background-color: rgba(0,0,0,0.5); +.restaurant-card-new:hover { + transform: translateY(-8px); + box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15) !important; } -.modal-content { - background-color: #fefefe; - margin: 10% auto; - padding: 20px; - border: 1px solid #888; - width: 80%; - max-width: 600px; - border-radius: var(--border-radius); - position: relative; -} - -.close-btn { - color: #aaa; - position: absolute; - top: 10px; - right: 20px; - font-size: 28px; - font-weight: bold; -} - -.close-btn:hover, -.close-btn:focus { - color: black; +.restaurant-card-new .card-link { text-decoration: none; - cursor: pointer; + color: inherit; + display: block; } -#map { - height: 400px; +.restaurant-card-new .img-container { + height: 200px; + overflow: hidden; +} + +.restaurant-card-new .card-img-top { width: 100%; - margin-top: 20px; - margin-bottom: 20px; - border-radius: var(--border-radius); + height: 100%; + object-fit: cover; + transition: transform 0.5s ease; } -#confirm-location-btn { - width: 100%; - padding: 15px; - font-size: 1.1rem; +.restaurant-card-new:hover .card-img-top { + transform: scale(1.05); } -/* --- Responsive Design --- */ -@media (max-width: 992px) { - .nav-links { - display: none; - position: absolute; - top: 80px; - left: 0; - width: 100%; - background-color: var(--coconut-white); - flex-direction: column; - gap: 0; - padding: 20px 0; - box-shadow: var(--shadow-medium); - } - - .nav-links.active { - display: flex; - } - - .nav-links li { - text-align: center; - } - - .nav-links a { - padding: 15px; - display: block; - border-bottom: 1px solid var(--border-color); - } - - .nav-actions { - display: none; /* Simple toggle, for complex logic more JS is needed */ - } - - .nav-actions.active { - display: flex; - position: absolute; - top: calc(80px + 250px); /* Adjust based on nav-links height */ - left: 0; - width: 100%; - background-color: var(--coconut-white); - justify-content: center; - padding: 20px 0; - box-shadow: var(--shadow-medium); - } - - .hamburger { - display: block; - } - - .hero-title { - font-size: 2.8rem; - } +.restaurant-card-new .card-body { + padding: 1.25rem; } -@media (max-width: 768px) { - body { - padding-top: 70px; - } - .main-header, .main-nav { - height: 70px; - } - .nav-links { - top: 70px; - } - .hero-title { - font-size: 2.2rem; - } - .hero-subtitle { - font-size: 1.1rem; - } +.restaurant-card-new .card-footer { + padding-top: 0; +} + +.restaurant-card-new .btn-sm { + font-size: 0.8rem; + padding: 0.4rem 0.8rem; +} + +/* Menu Page Styles */ +.restaurant-hero-menu { + height: 50vh; + background-size: cover; + background-position: center; + position: relative; + display: flex; + align-items: center; + justify-content: center; + text-align: center; + color: white; +} + +.restaurant-hero-menu::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.5); +} + +.restaurant-hero-menu-content { + position: relative; + z-index: 1; +} + +.menu-item-card-new { + transition: transform 0.2s ease, box-shadow 0.2s ease; + border: none; + border-radius: .75rem; + overflow: hidden; +} + +.menu-item-card-new:hover { + transform: translateY(-5px); + box-shadow: 0 8px 16px rgba(0,0,0,0.1); +} + +.menu-item-card-new .img-fluid { + height: 100%; + object-fit: cover; +} + +.reviews-section .review-card:last-child { + margin-bottom: 0 !important; +} + +.reviews-section hr:last-of-type { + display: none; } diff --git a/assets/images/pexels/34251952.jpg b/assets/images/pexels/34251952.jpg new file mode 100644 index 00000000..ce1e4819 Binary files /dev/null and b/assets/images/pexels/34251952.jpg differ diff --git a/assets/js/main.js b/assets/js/main.js index c581022e..8a8ecdbd 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -1,87 +1,23 @@ -document.addEventListener('DOMContentLoaded', function() { - const mapElement = document.getElementById('map'); - const modal = document.getElementById('location-modal'); - const pinLocationBtn = document.getElementById('pin-location-btn'); - const useLocationBtn = document.getElementById('use-location-btn'); - const closeBtn = document.querySelector('.close-btn'); - const confirmLocationBtn = document.getElementById('confirm-location-btn'); - const findRestaurantsBtn = document.querySelector('.find-restaurants-btn'); +document.addEventListener('DOMContentLoaded', () => { + const themeSwitch = document.querySelector('#checkbox'); + const body = document.body; - let map, marker; - let selectedCoords = null; + const currentTheme = localStorage.getItem('theme'); - function initMap(lat, lng) { - if (map) map.remove(); - map = L.map(mapElement).setView([lat, lng], 13); - L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { - attribution: '© OpenStreetMap contributors' - }).addTo(map); - marker = L.marker([lat, lng], { draggable: true }).addTo(map); - - map.on('click', function(e) { - marker.setLatLng(e.latlng); - selectedCoords = e.latlng; - }); - - marker.on('dragend', function(e) { - selectedCoords = marker.getLatLng(); - }); + if (currentTheme) { + body.classList.add(currentTheme); + if (currentTheme === 'dark-mode') { + themeSwitch.checked = true; + } } - if (pinLocationBtn) { - pinLocationBtn.addEventListener('click', function() { - modal.style.display = 'block'; - // Default to a central Majuro location - initMap(7.09, 171.38); - }); - } - - if (useLocationBtn) { - useLocationBtn.addEventListener('click', function() { - if (navigator.geolocation) { - navigator.geolocation.getCurrentPosition(function(position) { - const userCoords = { lat: position.coords.latitude, lng: position.coords.longitude }; - sessionStorage.setItem('userLocation', JSON.stringify(userCoords)); - findRestaurantsBtn.click(); - }, function() { - alert('Could not get your location. Please pin it on the map.'); - }); - } else { - alert('Geolocation is not supported by this browser.'); - } - }); - } - - if (closeBtn) { - closeBtn.addEventListener('click', () => modal.style.display = 'none'); - } - - window.addEventListener('click', (e) => { - if (e.target == modal) { - modal.style.display = 'none'; + themeSwitch.addEventListener('change', () => { + if (themeSwitch.checked) { + body.classList.add('dark-mode'); + localStorage.setItem('theme', 'dark-mode'); + } else { + body.classList.remove('dark-mode'); + localStorage.setItem('theme', 'light-mode'); } }); - - if (confirmLocationBtn) { - confirmLocationBtn.addEventListener('click', function() { - if (selectedCoords) { - sessionStorage.setItem('userLocation', JSON.stringify(selectedCoords)); - modal.style.display = 'none'; - findRestaurantsBtn.click(); - } else { - alert('Please select a location on the map.'); - } - }); - } - - if(findRestaurantsBtn) { - findRestaurantsBtn.addEventListener('click', function(e) { - const userLocation = sessionStorage.getItem('userLocation'); - if (!userLocation) { - e.preventDefault(); - alert('Please set your location first to find restaurants near you.'); - pinLocationBtn.click(); - } - }); - } -}); \ No newline at end of file +}); diff --git a/assets/pasted-20251016-204625-3165bcc5.png b/assets/pasted-20251016-204625-3165bcc5.png new file mode 100644 index 00000000..cf18659e Binary files /dev/null and b/assets/pasted-20251016-204625-3165bcc5.png differ diff --git a/assets/pasted-20251017-003154-7b32bc9f.png b/assets/pasted-20251017-003154-7b32bc9f.png new file mode 100644 index 00000000..cf6901a6 Binary files /dev/null and b/assets/pasted-20251017-003154-7b32bc9f.png differ diff --git a/assets/pasted-20251017-003440-ba856bda.png b/assets/pasted-20251017-003440-ba856bda.png new file mode 100644 index 00000000..67dbb5b0 Binary files /dev/null and b/assets/pasted-20251017-003440-ba856bda.png differ diff --git a/cart.php b/cart.php index 1c422484..c1c8e3a5 100644 --- a/cart.php +++ b/cart.php @@ -1,115 +1,125 @@ prepare("SELECT c.id, mi.name, mi.price, c.quantity, r.name as restaurant_name FROM cart c JOIN menu_items mi ON c.menu_item_id = mi.id JOIN restaurants r ON mi.restaurant_id = r.id WHERE c.user_id = :user_id"); - $stmt->bindParam(':user_id', $user_id); + $stmt = db()->prepare(" + SELECT c.menu_item_id, c.quantity, mi.name, mi.price, mi.image_url, r.name as restaurant_name, r.id as restaurant_id + FROM cart c + JOIN menu_items mi ON c.menu_item_id = mi.id + JOIN restaurants r ON c.restaurant_id = r.id + WHERE c.user_id = ? + "); + $stmt->execute([$user_id]); + $cart_items = $stmt->fetchAll(PDO::FETCH_ASSOC); } else { - $stmt = $pdoconnection->prepare("SELECT c.id, mi.name, mi.price, c.quantity, r.name as restaurant_name FROM cart c JOIN menu_items mi ON c.menu_item_id = mi.id JOIN restaurants r ON mi.restaurant_id = r.id WHERE c.session_id = :session_id"); - $stmt->bindParam(':session_id', $session_id); + $stmt = db()->prepare(" + SELECT c.menu_item_id, c.quantity, mi.name, mi.price, mi.image_url, r.name as restaurant_name, r.id as restaurant_id + FROM cart c + JOIN menu_items mi ON c.menu_item_id = mi.id + JOIN restaurants r ON c.restaurant_id = r.id + WHERE c.session_id = ? + "); + $stmt->execute([$session_id]); + $cart_items = $stmt->fetchAll(PDO::FETCH_ASSOC); } -$stmt->execute(); -$cartItems = $stmt->fetchAll(PDO::FETCH_ASSOC); - -$totalPrice = 0; - -include 'header.php'; +if ($cart_items) { + foreach ($cart_items as $item) { + $total_quantity += $item['quantity']; + $subtotal += $item['price'] * $item['quantity']; + } + $total_bill = $subtotal; // For now, total is same as subtotal. Can add taxes/fees later. +} ?> -| Item | -Price | -Quantity | -Total | -
|---|---|---|---|
| - | $ | -- | $ | -
Looks like you haven't added anything to your cart yet.
+ Continue ShoppingYour cart is empty.
- Continue Shopping +