diff --git a/api/get_driver_location.php b/api/get_driver_location.php new file mode 100644 index 00000000..ab113515 --- /dev/null +++ b/api/get_driver_location.php @@ -0,0 +1,53 @@ + 'Order ID is required.']); + exit; +} + +$order_id = $_GET['order_id']; +$user_id = $_SESSION['user_id'] ?? null; + +// For guest users, we need a token +$token = $_GET['token'] ?? null; + +$pdoconn = db(); + +// Verify the user or guest has permission to view this order +if ($user_id) { + $stmt = $pdoconn->prepare("SELECT id FROM orders WHERE id = :order_id AND user_id = :user_id"); + $stmt->execute(['order_id' => $order_id, 'user_id' => $user_id]); +} else if ($token) { + $stmt = $pdoconn->prepare("SELECT id FROM orders WHERE id = :order_id AND token = :token"); + $stmt->execute(['order_id' => $order_id, 'token' => $token]); +} else { + http_response_code(403); + echo json_encode(['error' => 'Authentication required.']); + exit; +} + +if ($stmt->rowCount() == 0) { + http_response_code(404); + echo json_encode(['error' => 'Order not found or access denied.']); + exit; +} + +// Fetch driver location +$stmt = $pdoconn->prepare("SELECT driver_lat, driver_lng FROM orders WHERE id = :order_id"); +$stmt->execute(['order_id' => $order_id]); +$location = $stmt->fetch(PDO::FETCH_ASSOC); + +if (!$location || is_null($location['driver_lat']) || is_null($location['driver_lng'])) { + http_response_code(404); + echo json_encode(['error' => 'Driver location not available yet.']); + exit; +} + +header('Content-Type: application/json'); +echo json_encode([ + 'lat' => $location['driver_lat'], + 'lng' => $location['driver_lng'] +]); diff --git a/assets/css/main.css b/assets/css/main.css index e1dc23b3..930baf64 100644 --- a/assets/css/main.css +++ b/assets/css/main.css @@ -23,10 +23,7 @@ MajuroEats Theme /* --- Global Styles --- */ body { font-family: var(--font-family); - background-image: url('../assets/pasted-20251016-192041-2abf91d9.jpg'); - background-size: cover; - background-attachment: fixed; - background-position: center; + background-color: var(--coconut-white); color: var(--text-dark); margin: 0; padding-top: 80px; /* Space for fixed header */ @@ -188,225 +185,174 @@ main { /* --- Hero Section --- */ .hero-section { - background-image: url('../assets/pasted-20251016-192041-2abf91d9.jpg'); - background-size: cover; - background-attachment: fixed; - background-position: center; - position: relative; - padding: 120px 0; + background-color: #f8f9fa; + padding: 100px 0; text-align: center; } -.hero-overlay { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; -} - -.hero-content-container { - position: relative; - z-index: 2; -} - -.hero-content h1 { - font-size: 3.8rem; +.hero-title { + font-size: 3.5rem; font-weight: 800; - margin: 0 0 15px; - text-shadow: 0 3px 10px rgba(0,0,0,0.3); + margin-bottom: 1rem; } -.hero-content p { - font-size: 1.3rem; - margin: 0 auto 40px; - opacity: 0.95; - max-width: 600px; +.hero-subtitle { + font-size: 1.25rem; + color: var(--text-light); + margin-bottom: 2.5rem; } -.hero-search-form { - display: flex; - justify-content: center; - margin: 30px auto; - box-shadow: var(--shadow-medium); +.hero-section .btn-primary { + background-color: #ff5a5f; + border-color: #ff5a5f; + font-size: 1.25rem; + padding: 15px 40px; border-radius: 50px; - overflow: hidden; - max-width: 600px; - background-color: var(--coconut-white); - border: 3px solid var(--coconut-white); -} - -#address-input { - flex-grow: 1; - border: none; - padding: 20px; - font-size: 1.1rem; - font-family: var(--font-family); - color: var(--text-dark); - background: transparent; -} - -#address-input:focus { - outline: none; -} - -#find-food-btn { - background-color: var(--coral); - color: var(--coconut-white); - border: none; - padding: 0 40px; - font-size: 1.1rem; font-weight: 700; - cursor: pointer; - transition: var(--transition); - border-radius: 50px; } -#find-food-btn:hover { - background-color: var(--orange); +.hero-section .btn-primary:hover { + background-color: #e04f54; + border-color: #e04f54; } -.delivery-note { - font-size: 0.9rem; - opacity: 0.8; +.hero-section .text-muted { + color: #6c757d !important; + text-decoration: underline; } -/* --- Promo Section --- */ -.promo-section { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); - gap: 30px; - margin-bottom: 60px; +/* --- How It Works Section --- */ +#how-it-works { + padding: 60px 0; + background-color: #fff; } -.promo-card { - background: var(--coconut-white); - padding: 30px; - border-radius: var(--border-radius); - text-align: center; - box-shadow: var(--shadow-soft); - transition: var(--transition); +.step { + padding: 20px; } -.promo-card:hover { - transform: translateY(-10px); - box-shadow: var(--shadow-medium); +.step-icon { + width: 80px; + height: 80px; + margin-bottom: 1.5rem; } -.promo-card h3 { +.step h3 { font-size: 1.5rem; - font-weight: 800; - color: var(--ocean-blue); - margin: 0 0 10px; + font-weight: 700; + margin-bottom: 0.5rem; } -.promo-card p { - font-size: 1rem; +.step p { color: var(--text-light); - margin: 0; } -/* --- Featured Restaurants --- */ -.featured-restaurants { - margin-bottom: 60px; -} - -.restaurant-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); - gap: 30px; -} - -.restaurant-card { - background: var(--coconut-white); +/* --- Restaurant & Cuisine Cards --- */ +.restaurant-card, .cuisine-card { + border: 1px solid var(--border-color); border-radius: var(--border-radius); - box-shadow: var(--shadow-soft); - overflow: hidden; transition: var(--transition); - color: var(--text-dark); - border: 2px solid transparent; + background-color: #fff; } -.restaurant-card:hover { - transform: translateY(-10px); +.restaurant-card:hover, .cuisine-card:hover { + transform: translateY(-5px); box-shadow: var(--shadow-medium); - border-color: var(--coral); } -.card-image { +.restaurant-card .card-img-top { + border-top-left-radius: var(--border-radius); + border-top-right-radius: var(--border-radius); height: 200px; - background-size: cover; - background-position: center; + object-fit: cover; } -.card-content { - padding: 20px; +.restaurant-card .card-body { + padding: 1.5rem; } -.card-content h3 { - font-size: 1.4rem; - font-weight: 800; - margin: 0 0 5px; -} - -.cuisine-tags { - font-size: 0.9rem; - color: var(--text-light); - margin: 0 0 15px; -} - -.restaurant-info { - display: flex; - justify-content: space-between; - align-items: center; - font-size: 1rem; +.restaurant-card .card-title a { + color: var(--text-dark); font-weight: 700; } -.rating-display { - display: flex; - align-items: center; - gap: 5px; -} - -.rating-display .star { - color: #FFC700; - font-size: 1.2rem; -} - -.delivery-info { - color: var(--text-light); -} - -.see-all-container { - text-align: center; - margin-top: 40px; -} - -.see-all-btn { - background-color: var(--coral); - color: var(--coconut-white); - padding: 15px 35px; - border-radius: 50px; - font-size: 1.1rem; - font-weight: 700; - border: 2px solid var(--coral); - transition: var(--transition); -} - -.see-all-btn:hover { - background-color: transparent; +.restaurant-card .card-title a:hover { color: var(--coral); } -/* --- Footer --- */ -.main-footer { - background-color: var(--text-dark); - color: var(--sand); - padding: 40px 0; +.cuisine-card { + display: block; + padding: 1rem; text-align: center; } +.cuisine-card img { + width: 100px; + height: 100px; + object-fit: cover; + border-radius: 50%; + margin-bottom: 1rem; +} + +.cuisine-card h5 { + color: var(--text-dark); + font-weight: 700; +} + +/* --- 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); +} + +.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; + text-decoration: none; + cursor: pointer; +} + +#map { + height: 400px; + width: 100%; + margin-top: 20px; + margin-bottom: 20px; + border-radius: var(--border-radius); +} + +#confirm-location-btn { + width: 100%; + padding: 15px; + font-size: 1.1rem; +} + /* --- Responsive Design --- */ @media (max-width: 992px) { .nav-links { @@ -456,7 +402,7 @@ main { display: block; } - .hero-content h1 { + .hero-title { font-size: 2.8rem; } } @@ -471,265 +417,10 @@ main { .nav-links { top: 70px; } - .hero-content h1 { + .hero-title { font-size: 2.2rem; } - .hero-content p { + .hero-subtitle { font-size: 1.1rem; } - .location-actions { - flex-direction: column; - gap: 15px; - } -} - - - -/* --- Empty State --- */ -.empty-state { - padding: 80px 40px; - background-color: var(--sand); - border-radius: var(--border-radius); - margin-top: 40px; -} - -.empty-state h3 { - font-size: 1.8rem; - font-weight: 800; - color: var(--text-dark); -} - -.empty-state p { - font-size: 1.1rem; - color: var(--text-light); - max-width: 400px; - margin: 10px auto 0; -} - -.btn { - padding: 15px 35px; - border-radius: 50px; - font-weight: 700; - font-size: 1.1rem; - border: 2px solid transparent; - transition: var(--transition); - cursor: pointer; - text-align: center; - display: inline-block; -} - -.btn-primary { - background-color: var(--coral); - color: var(--coconut-white); - box-shadow: var(--shadow-soft); -} - -.btn-primary:hover { - background-color: var(--orange); - transform: translateY(-2px); - box-shadow: var(--shadow-medium); -} - -.btn-secondary { - background-color: rgba(255, 255, 255, 0.2); - color: var(--coconut-white); - border-color: var(--coconut-white); -} - -.btn-secondary:hover { - background-color: var(--coconut-white); - color: var(--text-dark); -} - -.location-actions { - display: flex; - gap: 20px; - justify-content: center; -} - -.w-100 { - width: 100%; -} - -.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); -} - -.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-button { - color: #aaa; - position: absolute; - top: 10px; - right: 20px; - font-size: 28px; - font-weight: bold; -} - -.close-button:hover, -.close-button:focus { - color: black; - text-decoration: none; - cursor: pointer; -} - -#map { - height: 400px; - width: 100%; - margin-top: 20px; - margin-bottom: 20px; - border-radius: var(--border-radius); -} - -#confirm-location { - width: 100%; - padding: 15px; - font-size: 1.1rem; -} - -/* --- Back to Home Button --- */ -.back-to-home-btn { - display: inline-block; - margin-top: 10px; - margin-bottom: -10px; /* to reduce space */ - padding: 8px 15px; - background-color: #f8f9fa; - color: var(--text-light); - border-radius: 50px; - font-size: 0.9rem; - font-weight: 700; - border: 1px solid var(--border-color); - transition: var(--transition); -} - -.back-to-home-btn:hover { - background-color: #e9ecef; - color: var(--text-dark); - border-color: #ccc; -} - -/* --- Featured Cuisines --- */ -.featured-cuisines { - margin-bottom: 60px; -} - -.cuisine-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); - gap: 30px; -} - -.cuisine-card { - position: relative; - border-radius: var(--border-radius); - overflow: hidden; - transition: var(--transition); - color: var(--coconut-white); - display: block; -} - -.cuisine-card:hover { - transform: translateY(-10px); - box-shadow: var(--shadow-medium); -} - -.cuisine-card .card-image { - height: 180px; - background-size: cover; - background-position: center; - transition: var(--transition); -} - -.cuisine-card:hover .card-image { - transform: scale(1.05); -} - -.cuisine-card-content { - position: absolute; - bottom: 0; - left: 0; - padding: 20px; - width: 100%; - box-sizing: border-box; - background: linear-gradient(to top, rgba(0,0,0,0.8), transparent); -} - -.cuisine-card-content h3 { - font-size: 1.5rem; - font-weight: 800; - margin: 0; - text-shadow: 0 2px 5px rgba(0,0,0,0.4); -} - -/* --- Restaurants Page --- */ -.filter-bar { - background-color: var(--sand); - padding: 20px; - border-radius: var(--border-radius); - margin-bottom: 40px; - box-shadow: var(--shadow-soft); -} - -.filter-bar .form-control, .filter-bar .form-select { - border-radius: 50px; - padding: 10px 20px; - border: 1px solid var(--border-color); -} - -.filter-bar .btn-primary { - background-color: var(--coral); - border-color: var(--coral); - border-radius: 50px; - padding: 10px 20px; - font-weight: 700; - width: 100%; -} - -.restaurant-card .card-img-top { - height: 200px; - object-fit: cover; -} - -.restaurant-card .card-body { - padding: 20px; -} - -.restaurant-card .card-title { - font-size: 1.3rem; - font-weight: 800; - margin-bottom: 10px; -} - -.restaurant-card .card-text { - color: var(--text-light); - margin-bottom: 15px; -} - -.restaurant-card .btn-outline-primary { - border-color: var(--coral); - color: var(--coral); - border-radius: 50px; - font-weight: 700; -} - -.restaurant-card .btn-outline-primary:hover { - background-color: var(--coral); - color: var(--coconut-white); } diff --git a/assets/images/driver-icon.svg b/assets/images/driver-icon.svg new file mode 100644 index 00000000..45f00545 --- /dev/null +++ b/assets/images/driver-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/restaurant-icon.svg b/assets/images/restaurant-icon.svg new file mode 100644 index 00000000..a78d4024 --- /dev/null +++ b/assets/images/restaurant-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/step1.svg b/assets/images/step1.svg new file mode 100644 index 00000000..7d8eae43 --- /dev/null +++ b/assets/images/step1.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/step2.svg b/assets/images/step2.svg new file mode 100644 index 00000000..34c2cda3 --- /dev/null +++ b/assets/images/step2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/step3.svg b/assets/images/step3.svg new file mode 100644 index 00000000..db028221 --- /dev/null +++ b/assets/images/step3.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/pasted-20251016-201202-44c2bc42.png b/assets/pasted-20251016-201202-44c2bc42.png new file mode 100644 index 00000000..1bbb0a00 Binary files /dev/null and b/assets/pasted-20251016-201202-44c2bc42.png differ diff --git a/assets/pasted-20251016-203923-9f036b50.png b/assets/pasted-20251016-203923-9f036b50.png new file mode 100644 index 00000000..32058a82 Binary files /dev/null and b/assets/pasted-20251016-203923-9f036b50.png differ diff --git a/assets/pasted-20251016-204207-d203ea6e.png b/assets/pasted-20251016-204207-d203ea6e.png new file mode 100644 index 00000000..34456406 Binary files /dev/null and b/assets/pasted-20251016-204207-d203ea6e.png differ diff --git a/hero.php b/hero.php index 99d35448..a2196efd 100644 --- a/hero.php +++ b/hero.php @@ -1,25 +1,96 @@ -
-
-
-
-

Your favorite local food, delivered.

-

Set your location to find restaurants near you.

-
- - -
- -

MajuroEats delivers only within the main island zone (Rita–Laura).

+ +
+
+

Your Favorite Food, Delivered

+

Enter your location to see which restaurants deliver to you.

+ Pin a Location on Map +
-
+ + \ No newline at end of file + + + diff --git a/index.php b/index.php index a9c38a52..1096e358 100644 --- a/index.php +++ b/index.php @@ -1,132 +1,96 @@ query(" + SELECT r.*, AVG(ra.rating) as avg_rating + FROM restaurants r + LEFT JOIN ratings ra ON r.id = ra.restaurant_id + GROUP BY r.id + ORDER BY avg_rating DESC + LIMIT 6 +"); +$top_restaurants = $stmt->fetchAll(); - $db = db(); - // Haversine formula to calculate distance - $stmt = $db->prepare(" - SELECT r.id, r.name, r.image_url, AVG(rt.rating) as average_rating, - (6371 * acos(cos(radians(?)) * cos(radians(latitude)) * cos(radians(longitude) - radians(?)) + sin(radians(?)) * sin(radians(latitude)))) AS distance - FROM restaurants r - LEFT JOIN ratings rt ON r.id = rt.restaurant_id - WHERE latitude IS NOT NULL AND longitude IS NOT NULL - GROUP BY r.id - HAVING distance < ? - ORDER BY distance - LIMIT 12 - "); - - $stmt->execute([$lat, $lng, $lat, $radius]); - $restaurants = $stmt->fetchAll(PDO::FETCH_ASSOC); - - // Get cuisines for each restaurant - $cuisine_sql = "SELECT c.name FROM cuisines c JOIN restaurant_cuisines rc ON c.id = rc.cuisine_id WHERE rc.restaurant_id = ?"; - $cuisine_stmt = $db->prepare($cuisine_sql); - - foreach ($restaurants as &$restaurant) { - $cuisine_stmt->execute([$restaurant['id']]); - $restaurant['cuisines'] = $cuisine_stmt->fetchAll(PDO::FETCH_COLUMN); - } - - echo json_encode($restaurants); - exit; -} +// Fetch featured cuisines +$stmt = $pdo->query("SELECT * FROM cuisines ORDER BY name ASC LIMIT 6"); +$cuisines = $stmt->fetchAll(); ?> - - -
- -
-
-

$0 Delivery Fee

-

On your first order

-
-
-

Earn Rewards

-

With every meal

-
-
-

Support Local

-

Majuro Restaurants

+
+
+

How It Works

+
+
+
+ Step 1: Choose a restaurant +

Choose A Restaurant

+

Browse from our extensive list of local restaurants.

+
+
+
+
+ Step 2: Pick your meal +

Pick Your Meal

+

Select your favorite dishes and add them to your cart.

+
+
+
+
+ Step 3: Fast delivery +

Fast Delivery

+

Get your food delivered right to your doorstep, fast!

+
+
- query(" - SELECT r.id, r.name, r.image_url, GROUP_CONCAT(c.name SEPARATOR ', ') as cuisines, AVG(rt.rating) as average_rating - FROM restaurants r - LEFT JOIN restaurant_cuisines rc ON r.id = rc.restaurant_id - LEFT JOIN cuisines c ON rc.cuisine_id = c.id - LEFT JOIN ratings rt ON r.id = rt.restaurant_id - GROUP BY r.id - ORDER BY average_rating DESC - LIMIT 4 - "); - $top_restaurants = $top_restaurants_stmt->fetchAll(PDO::FETCH_ASSOC); - - // Fetch Featured Cuisines - $featured_cuisines_stmt = $db->query(" - SELECT c.id, c.name, c.image_url - FROM cuisines c - JOIN ( - SELECT cuisine_id, COUNT(*) as restaurant_count - FROM restaurant_cuisines - GROUP BY cuisine_id - ORDER BY restaurant_count DESC - LIMIT 4 - ) as popular_cuisines ON c.id = popular_cuisines.cuisine_id - "); - $featured_cuisines = $featured_cuisines_stmt->fetchAll(PDO::FETCH_ASSOC); - ?> - -
-

Top-rated restaurants

-
- - -
-
-

-

-
-
- - - - New - +
+

Top-Rated Restaurants

+
+ 0): ?> + +
+
+ + <?php echo htmlspecialchars($restaurant['name']); ?> + +
+
+

...

+
+ + View Menu +
- - + + +

No restaurants found.

+
-