This commit is contained in:
Flatlogic Bot 2025-10-15 15:33:06 +00:00
parent 7a0a2165fc
commit 5fc6fe4ad4
14 changed files with 358 additions and 190 deletions

View File

@ -1,8 +1,9 @@
/* Global Styles & Variables */
:root {
--turquoise: #40E0D0;
--green: #228B22;
--coral: #FF6B6B;
--sandy-beige: #F4E8D8;
--turquoise: #40E0D0;
--ocean-blue: #1E90FF;
--white: #FFFFFF;
--off-white: #f8f9fa;
--text-color: #333;
@ -10,8 +11,8 @@
--medium-gray: #ccc;
--dark-gray: #555;
--font-heading: 'Inter', sans-serif;
--font-body: 'Open Sans', sans-serif;
--font-heading: 'Poppins', sans-serif;
--font-body: 'Lato', sans-serif;
--shadow-soft: 0 4px 12px rgba(0, 0, 0, 0.08);
--border-radius: 16px;
@ -20,7 +21,7 @@
body {
font-family: var(--font-body);
color: var(--text-color);
background-color: var(--white); /* Changed to white for a cleaner base */
background-color: var(--off-white);
margin: 0;
padding: 0;
-webkit-font-smoothing: antialiased;
@ -30,7 +31,6 @@ body {
h1, h2, h3, h4, h5, h6 {
font-family: var(--font-heading);
font-weight: 600;
letter-spacing: 0.5px; /* Reduced for better readability */
}
a {
@ -172,57 +172,6 @@ header {
animation: fadeIn 0.5s ease-in-out forwards;
}
/* Hero Section */
.hero {
position: relative;
height: 400px;
background-image: url('../pasted-20251014-230507-170c4564.jpg');
background-size: cover;
background-position: center;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
color: var(--white);
margin-bottom: 40px;
}
.hero::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.4);
}
.hero-content {
position: relative;
z-index: 1;
max-width: 600px;
}
.hero h1 {
font-size: 3rem;
font-weight: 700;
margin-bottom: 1rem;
text-shadow: 0 2px 4px rgba(0,0,0,0.5);
}
.search-bar {
width: 100%;
padding: 1rem;
font-size: 1rem;
border-radius: 50px;
border: none;
box-shadow: var(--shadow-soft);
padding-left: 3rem;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23767676' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-search'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: 1rem center;
}
/* Restaurant Grid */
.page-title {
font-size: 2rem;
@ -260,28 +209,35 @@ header {
}
.restaurant-card-content {
padding: 1.5rem;
padding: 1rem;
display: flex;
flex-direction: column;
flex-grow: 1;
}
.restaurant-card-content h3 {
font-size: 1.25rem;
font-size: 1.15rem;
font-weight: 700;
margin-bottom: 0.5rem;
margin-bottom: 0.25rem;
}
.restaurant-card-content p {
color: var(--dark-gray);
font-size: 0.95rem;
font-size: 0.9rem;
margin-bottom: 0.5rem;
}
.restaurant-info {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: auto;
}
.rating-display {
display: flex;
align-items: center;
font-size: 1rem;
font-size: 0.9rem;
font-weight: 600;
color: var(--text-color);
}
@ -291,18 +247,17 @@ header {
margin-right: 0.25rem;
}
.rating-display .rating-count {
.delivery-info {
font-size: 0.9rem;
font-weight: 600;
color: var(--dark-gray);
margin-left: 0.5rem;
font-weight: 400;
}
footer {
text-align: center;
padding: 3rem 0;
margin-top: 3rem;
background-color: var(--off-white);
background-color: var(--white);
border-top: 1px solid var(--light-gray);
}
@ -738,7 +693,7 @@ footer {
}
.order-confirmation h1 {
color: var(--green);
color: var(--ocean-blue);
font-size: 2.5rem;
margin-bottom: 1rem;
}
@ -971,3 +926,107 @@ footer {
.search-bar {
flex-grow: 1;
}
/* Cuisine Carousel */
.cuisine-carousel {
display: flex;
overflow-x: auto;
padding-bottom: 1rem;
margin-bottom: 1.5rem;
scrollbar-width: thin; /* For Firefox */
scrollbar-color: var(--medium-gray) var(--light-gray);
}
.cuisine-carousel::-webkit-scrollbar {
height: 8px;
}
.cuisine-carousel::-webkit-scrollbar-track {
background: var(--light-gray);
border-radius: 10px;
}
.cuisine-carousel::-webkit-scrollbar-thumb {
background-color: var(--medium-gray);
border-radius: 10px;
}
.cuisine-card {
position: relative;
margin-right: 1rem;
}
.cuisine-card input[type="checkbox"] {
position: absolute;
opacity: 0;
width: 100%;
height: 100%;
cursor: pointer;
}
.cuisine-card label {
display: block;
padding: 0.75rem 1.5rem;
border: 1px solid var(--medium-gray);
border-radius: 50px;
background-color: var(--white);
color: var(--text-color);
font-weight: 600;
white-space: nowrap;
transition: all 0.3s ease;
}
.cuisine-card input[type="checkbox"]:checked + label {
background-color: var(--coral);
color: var(--white);
border-color: var(--coral);
}
.cuisine-card label:hover {
background-color: var(--light-gray);
}
.cuisine-card input[type="checkbox"]:checked + label:hover {
background-color: #ff4f4f;
}
/* New Filter Bar */
.filter-bar-new {
display: flex;
align-items: center;
gap: 1.5rem;
margin-bottom: 2rem;
background-color: var(--white);
padding: 1rem;
border-radius: var(--border-radius);
box-shadow: var(--shadow-soft);
}
.filter-bar-new .form-group,
.filter-bar-new .form-check {
margin-bottom: 0;
}
.filter-bar-new .form-control {
border-radius: 50px;
border: 1px solid var(--medium-gray);
padding: 0.5rem 1rem;
}
.filter-bar-new .form-check-label {
font-weight: 600;
}
.filter-bar-new .btn-secondary {
margin-left: auto;
}
/* Remove old column styles */
.row {
display: block;
}
.col-md-3,
.col-md-9 {
width: 100%;
padding: 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 973 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 827 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 755 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

103
hero.php Normal file
View File

@ -0,0 +1,103 @@
<?php
function get_hero_image() {
// Check if we have a cached image URL
if (isset($_SESSION['hero_image_url'])) {
return $_SESSION['hero_image_url'];
}
// If not, fetch a new one from Pexels
require_once __DIR__ . '/includes/pexels.php';
$query = 'island food';
$orientation = 'landscape';
$url = 'https://api.pexels.com/v1/search?query=' . urlencode($query) . '&orientation=' . urlencode($orientation) . '&per_page=1&page=' . rand(1, 100);
$data = pexels_get($url);
if (!empty($data['photos'])) {
$photo = $data['photos'][0];
$image_url = $photo['src']['large2x'] ?? $photo['src']['large'];
// Cache the URL in the session
$_SESSION['hero_image_url'] = $image_url;
return $image_url;
}
// Fallback image
return 'assets/images/hero.jpg';
}
$hero_image_url = get_hero_image();
?>
<style>
.hero-section {
background-image: linear-gradient(rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.3)), url('<?= $hero_image_url ?>');
background-size: cover;
background-position: center;
color: white;
text-align: left;
padding: 100px 50px;
display: flex;
align-items: center;
}
.hero-content {
max-width: 600px;
}
.hero-content h1 {
font-size: 3.5rem;
font-weight: 700;
margin-bottom: 1rem;
text-shadow: 2px 2px 8px rgba(0,0,0,0.6);
}
.hero-content p {
font-size: 1.25rem;
margin-bottom: 2rem;
}
.hero-search-form {
display: flex;
border-radius: 50px;
overflow: hidden;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}
.hero-search-input {
flex-grow: 1;
border: none;
padding: 1rem 1.5rem;
font-size: 1rem;
}
.hero-search-input:focus {
outline: none;
}
.hero-search-button {
border: none;
background-color: #FF6B6B;
color: white;
padding: 0 2rem;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: background-color 0.3s;
}
.hero-search-button:hover {
background-color: #ff4f4f;
}
</style>
<section class="hero-section">
<div class="hero-content">
<h1>Everything you crave, delivered.</h1>
<p>Your favorite local restaurants, delivered to your door.</p>
<form action="index.php" method="get" class="hero-search-form">
<input type="text" name="search" class="hero-search-input" placeholder="Find restaurants" value="<?= isset($_GET['search']) ? htmlspecialchars($_GET['search']) : '' ?>">
<button type="submit" class="hero-search-button">Find restaurants</button>
</form>
</div>
</section>

View File

@ -1,70 +1,55 @@
<?php include 'header.php'; ?>
<main>
<section class="hero">
<div class="hero-content">
<h1>Order from Majuro's best</h1>
<form action="index.php" method="get" class="search-form">
<input type="text" name="search" class="search-bar" placeholder="Search for restaurants..." value="<?= isset($_GET['search']) ? htmlspecialchars($_GET['search']) : '' ?>">
<button type="submit" class="search-button">Search</button>
</form>
<div class="location-actions">
<button class="location-button" id="pin-location">Pin a Location</button>
<button class="location-button" id="my-location">My Location</button>
</div>
</div>
</section>
<?php include 'hero.php'; ?>
<div class="container">
<div class="row">
<!-- Filter Sidebar -->
<div class="col-md-3">
<h4>Filter Results</h4>
<form action="index.php" method="get" id="filter-form">
<!-- Hidden search field to persist search query -->
<?php if (isset($_GET['search'])):
<input type="hidden" name="search" value="<?= htmlspecialchars($_GET['search']) ?>">
<?php endif; ?>
<input type="hidden" name="search" value="<?= isset($_GET['search']) ? htmlspecialchars($_GET['search']) : '' ?>">
<h5>By Cuisine</h5>
<h2 class="page-title">Explore Cuisines</h2>
<div class="cuisine-carousel">
<?php
$cuisine_stmt = db()->query("SELECT * FROM cuisines ORDER BY name");
$all_cuisines = $cuisine_stmt->fetchAll(PDO::FETCH_ASSOC);
$selected_cuisines = isset($_GET['cuisines']) && is_array($_GET['cuisines']) ? $_GET['cuisines'] : [];
foreach ($all_cuisines as $cuisine): ?>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="cuisines[]" value="<?= $cuisine['id'] ?>" id="cuisine-<?= $cuisine['id'] ?>" <?= in_array($cuisine['id'], $selected_cuisines) ? 'checked' : '' ?>>
<label class="form-check-label" for="cuisine-<?= $cuisine['id'] ?>">
<div class="cuisine-card">
<input type="checkbox" name="cuisines[]" value="<?= $cuisine['id'] ?>" id="cuisine-<?= $cuisine['id'] ?>" <?= in_array($cuisine['id'], $selected_cuisines) ? 'checked' : '' ?> onchange="this.form.submit()">
<label for="cuisine-<?= $cuisine['id'] ?>">
<?= htmlspecialchars($cuisine['name']) ?>
</label>
</div>
<?php endforeach; ?>
</div>
<h5 class="mt-4">By Rating</h5>
<div class="filter-bar-new">
<div class="form-group">
<select name="min_rating" class="form-control">
<option value="">Any Rating</option>
<option value="4" <?= isset($_GET['min_rating']) && $_GET['min_rating'] == 4 ? 'selected' : '' ?>>4 stars & up</option>
<option value="3" <?= isset($_GET['min_rating']) && $_GET['min_rating'] == 3 ? 'selected' : '' ?>>3 stars & up</option>
<option value="2" <?= isset($_GET['min_rating']) && $_GET['min_rating'] == 2 ? 'selected' : '' ?>>2 stars & up</option>
<option value="1" <?= isset($_GET['min_rating']) && $_GET['min_rating'] == 1 ? 'selected' : '' ?>>1 star & up</option>
<label for="min_rating">Rating</label>
<select name="min_rating" id="min_rating" class="form-control" onchange="this.form.submit()">
<option value="">Any</option>
<option value="4" <?= isset($_GET['min_rating']) && $_GET['min_rating'] == 4 ? 'selected' : '' ?>>4+ stars</option>
<option value="3" <?= isset($_GET['min_rating']) && $_GET['min_rating'] == 3 ? 'selected' : '' ?>>3+ stars</option>
<option value="2" <?= isset($_GET['min_rating']) && $_GET['min_rating'] == 2 ? 'selected' : '' ?>>2+ stars</option>
<option value="1" <?= isset($_GET['min_rating']) && $_GET['min_rating'] == 1 ? 'selected' : '' ?>>1+ star</option>
</select>
</div>
<button type="submit" class="btn btn-primary mt-3">Apply Filters</button>
<a href="index.php" class="btn btn-secondary mt-3">Clear Filters</a>
</form>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="open_now" value="1" id="open-now" <?= isset($_GET['open_now']) ? 'checked' : '' ?> onchange="this.form.submit()">
<label class="form-check-label" for="open-now">
Open Now
</label>
</div>
<a href="index.php" class="btn btn-secondary">Clear Filters</a>
</div>
</form>
<!-- Restaurant Listing -->
<div class="col-md-9">
<h2 class="page-title">All Restaurants</h2>
<h2 class="page-title mt-4">All Restaurants</h2>
<section class="restaurant-list">
<div class="restaurant-grid" id="restaurant-grid">
<?php
// Base query
$sql = "SELECT DISTINCT r.id, r.name, r.image_url, AVG(rt.rating) as average_rating, COUNT(rt.id) as rating_count
$sql = "SELECT DISTINCT r.id, r.name, r.image_url, r.opening_time, r.closing_time, r.days_open, AVG(rt.rating) as average_rating, COUNT(rt.id) as rating_count
FROM restaurants r
LEFT JOIN ratings rt ON r.id = rt.restaurant_id";
$params = [];
@ -89,11 +74,22 @@
$params = array_merge($params, $selected_cuisines);
}
// Append "Open Now" filter
if (isset($_GET['open_now'])) {
$current_time = date('H:i:s');
$current_day = date('D'); // Mon, Tue, etc.
$where_clauses[] = "r.opening_time <= ? AND r.closing_time >= ? AND r.days_open LIKE ?";
$params[] = $current_time;
$params[] = $current_time;
$params[] = '%' . $current_day . '%';
}
if (!empty($where_clauses)) {
$sql .= " WHERE " . implode(' AND ', $where_clauses);
}
$sql .= " GROUP BY r.id, r.name, r.image_url";
$sql .= " GROUP BY r.id, r.name, r.image_url, r.opening_time, r.closing_time, r.days_open";
// Add rating filter (HAVING clause)
$selected_min_rating = isset($_GET['min_rating']) && is_numeric($_GET['min_rating']) ? (int)$_GET['min_rating'] : 0;
@ -123,16 +119,17 @@
echo '<div class="restaurant-card-content">';
echo '<h3>' . htmlspecialchars($restaurant['name']) . '</h3>';
echo '<p>' . htmlspecialchars(implode(', ', $restaurant_cuisines_list)) . '</p>';
echo '<div class="restaurant-info">';
if ($restaurant['rating_count'] > 0) {
echo '<div class="rating-display">';
echo '<span class="star">★</span>';
echo '<span>' . htmlspecialchars(number_format($restaurant['average_rating'], 1)) . '</span>';
echo '<span class="rating-count">(' . htmlspecialchars($restaurant['rating_count']) . ' ratings)</span>';
echo '</div>';
} else {
echo '<div class="rating-display"><span class="rating-count">No ratings yet</span></div>';
}
echo '</div>';
echo '</div>';
echo '</a>';
}
}
@ -140,8 +137,6 @@
</div>
</section>
</div>
</div>
</div>
</main>

View File

@ -0,0 +1,11 @@
ALTER TABLE restaurants
ADD COLUMN opening_time TIME,
ADD COLUMN closing_time TIME,
ADD COLUMN days_open VARCHAR(255);
-- Update existing restaurants with some default hours (e.g., 9 AM to 9 PM, open all week)
UPDATE restaurants SET
opening_time = '09:00:00',
closing_time = '21:00:00',
days_open = 'Mon,Tue,Wed,Thu,Fri,Sat,Sun';