4
This commit is contained in:
parent
fdcc78312c
commit
ac9362bcab
56
api/favorites.php
Normal file
56
api/favorites.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
session_start();
|
||||
header('Content-Type: application/json');
|
||||
|
||||
require_once '../db/config.php';
|
||||
|
||||
$response = ['success' => false, 'loggedIn' => false, 'isFavorite' => false, 'message' => ''];
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
$response['message'] = 'You must be logged in to favorite a restaurant.';
|
||||
echo json_encode($response);
|
||||
exit;
|
||||
}
|
||||
|
||||
$response['loggedIn'] = true;
|
||||
$user_id = $_SESSION['user_id'];
|
||||
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
$restaurant_id = $data['restaurant_id'] ?? null;
|
||||
|
||||
if (!$restaurant_id || !is_numeric($restaurant_id)) {
|
||||
$response['message'] = 'Invalid restaurant ID.';
|
||||
echo json_encode($response);
|
||||
exit;
|
||||
}
|
||||
|
||||
$pdo = db();
|
||||
|
||||
// Check if it's already a favorite
|
||||
$stmt = $pdo->prepare("SELECT id FROM favorite_restaurants WHERE user_id = ? AND restaurant_id = ?");
|
||||
$stmt->execute([$user_id, $restaurant_id]);
|
||||
$existing_favorite = $stmt->fetch();
|
||||
|
||||
if ($existing_favorite) {
|
||||
// Remove from favorites
|
||||
$stmt = $pdo->prepare("DELETE FROM favorite_restaurants WHERE id = ?");
|
||||
if ($stmt->execute([$existing_favorite['id']])) {
|
||||
$response['success'] = true;
|
||||
$response['isFavorite'] = false;
|
||||
$response['message'] = 'Restaurant removed from favorites.';
|
||||
} else {
|
||||
$response['message'] = 'Failed to remove from favorites.';
|
||||
}
|
||||
} else {
|
||||
// Add to favorites
|
||||
$stmt = $pdo->prepare("INSERT INTO favorite_restaurants (user_id, restaurant_id) VALUES (?, ?)");
|
||||
if ($stmt->execute([$user_id, $restaurant_id])) {
|
||||
$response['success'] = true;
|
||||
$response['isFavorite'] = true;
|
||||
$response['message'] = 'Restaurant added to favorites.';
|
||||
} else {
|
||||
$response['message'] = 'Failed to add to favorites.';
|
||||
}
|
||||
}
|
||||
|
||||
echo json_encode($response);
|
||||
8
db/migrations/003_create_users_table.sql
Normal file
8
db/migrations/003_create_users_table.sql
Normal file
@ -0,0 +1,8 @@
|
||||
-- 003_create_users_table.sql
|
||||
CREATE TABLE IF NOT EXISTS `users` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`email` VARCHAR(255) NOT NULL UNIQUE,
|
||||
`password_hash` VARCHAR(255) NOT NULL,
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
10
db/migrations/004_create_favorite_restaurants_table.sql
Normal file
10
db/migrations/004_create_favorite_restaurants_table.sql
Normal file
@ -0,0 +1,10 @@
|
||||
-- 004_create_favorite_restaurants_table.sql
|
||||
CREATE TABLE IF NOT EXISTS `favorite_restaurants` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`user_id` INT NOT NULL,
|
||||
`restaurant_id` INT NOT NULL,
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE,
|
||||
FOREIGN KEY (`restaurant_id`) REFERENCES `restaurants`(`id`) ON DELETE CASCADE,
|
||||
UNIQUE KEY `user_restaurant_unique` (`user_id`, `restaurant_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
59
favorites.php
Normal file
59
favorites.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
require_once 'includes/header.php';
|
||||
require_once 'db/config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header("Location: login.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
$user_id = $_SESSION['user_id'];
|
||||
$favorite_restaurants = [];
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT r.id, r.name, r.cuisine, r.address
|
||||
FROM restaurants r
|
||||
JOIN favorite_restaurants fr ON r.id = fr.restaurant_id
|
||||
WHERE fr.user_id = ?
|
||||
ORDER BY r.name ASC
|
||||
");
|
||||
$stmt->execute([$user_id]);
|
||||
$favorite_restaurants = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
} catch (PDOException $e) {
|
||||
error_log("Database error fetching favorites: " . $e->getMessage());
|
||||
// Optionally, show a friendly error to the user
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<div class="container my-5">
|
||||
<h1 class="mb-4">My Favorite Restaurants</h1>
|
||||
|
||||
<div class="row">
|
||||
<?php if (empty($favorite_restaurants)): ?>
|
||||
<div class="col">
|
||||
<p class="text-center text-muted">You haven't added any favorite restaurants yet.</p>
|
||||
<div class="text-center">
|
||||
<a href="index.php" class="btn btn-primary">Find some restaurants</a>
|
||||
</div>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<?php foreach ($favorite_restaurants as $restaurant): ?>
|
||||
<div class="col-md-4 mb-4">
|
||||
<div class="card h-100 restaurant-card">
|
||||
<div class="card-body d-flex flex-column">
|
||||
<h5 class="card-title"><?= htmlspecialchars($restaurant['name']) ?></h5>
|
||||
<p class="card-text"><span class="badge bg-secondary"><?= htmlspecialchars($restaurant['cuisine']) ?></span></p>
|
||||
<p class="card-text text-muted flex-grow-1"><?= htmlspecialchars($restaurant['address']) ?></p>
|
||||
<a href="menu.php?restaurant_id=<?= $restaurant['id'] ?>" class="btn btn-primary mt-auto">View Menu</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php require_once 'includes/footer.php'; ?>
|
||||
5
includes/footer.php
Normal file
5
includes/footer.php
Normal file
@ -0,0 +1,5 @@
|
||||
</div> <!-- close container -->
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
45
includes/header.php
Normal file
45
includes/header.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
session_start();
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Restaurant Marketplace</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="index.php"><i class="fas fa-utensils"></i> Restaurant Marketplace</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav ms-auto">
|
||||
<?php if (isset($_SESSION['user_id'])): ?>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="favorites.php">My Favorites</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<span class="nav-link">Welcome, <?php echo htmlspecialchars($_SESSION['user_name']); ?>!</span>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="logout.php">Logout</a>
|
||||
</li>
|
||||
<?php else: ?>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="login.php">Login</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="register.php">Register</a>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container mt-4">
|
||||
119
index.php
119
index.php
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
require_once 'includes/header.php';
|
||||
require_once 'db/config.php';
|
||||
|
||||
$restaurants = [];
|
||||
@ -15,52 +16,14 @@ try {
|
||||
}
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Find a Restaurant</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Poppins', sans-serif;
|
||||
background-color: #F8F9FA;
|
||||
}
|
||||
.hero {
|
||||
background-color: #343A40;
|
||||
color: #FFFFFF;
|
||||
padding: 4rem 0;
|
||||
text-align: center;
|
||||
}
|
||||
.restaurant-card {
|
||||
transition: transform 0.2s, box-shadow 0.2s;
|
||||
}
|
||||
.restaurant-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 0.5rem 1rem rgba(0,0,0,0.15);
|
||||
}
|
||||
.btn-primary {
|
||||
background-color: #FF6347;
|
||||
border-color: #FF6347;
|
||||
}
|
||||
.btn-primary:hover {
|
||||
background-color: #E5533D;
|
||||
border-color: #E5533D;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header class="hero">
|
||||
<div class="container">
|
||||
<h1 class="display-4">Find Your Next Meal</h1>
|
||||
<p class="lead">Browse through our collection of partner restaurants.</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<header class="hero">
|
||||
<div class="container">
|
||||
<h1 class="display-4">Find Your Next Meal</h1>
|
||||
<p class="lead">Browse through our collection of partner restaurants.</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="container my-5">
|
||||
<main class="container my-5">
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-8">
|
||||
<input type="text" id="searchInput" class="form-control" placeholder="Search by restaurant name...">
|
||||
@ -99,45 +62,39 @@ try {
|
||||
<p>No restaurants match your search.</p>
|
||||
</div>
|
||||
</main>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const searchInput = document.getElementById('searchInput');
|
||||
const cuisineFilter = document.getElementById('cuisineFilter');
|
||||
const restaurantList = document.getElementById('restaurantList');
|
||||
const restaurantItems = restaurantList.querySelectorAll('.restaurant-item');
|
||||
const noResults = document.getElementById('noResults');
|
||||
|
||||
<footer class="text-center text-muted py-4">
|
||||
<p>© <?= date('Y') ?> Food Marketplace</p>
|
||||
</footer>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const searchInput = document.getElementById('searchInput');
|
||||
const cuisineFilter = document.getElementById('cuisineFilter');
|
||||
const restaurantList = document.getElementById('restaurantList');
|
||||
const restaurantItems = restaurantList.querySelectorAll('.restaurant-item');
|
||||
const noResults = document.getElementById('noResults');
|
||||
function filterRestaurants() {
|
||||
const searchTerm = searchInput.value.toLowerCase();
|
||||
const cuisineTerm = cuisineFilter.value.toLowerCase();
|
||||
let resultsFound = false;
|
||||
|
||||
function filterRestaurants() {
|
||||
const searchTerm = searchInput.value.toLowerCase();
|
||||
const cuisineTerm = cuisineFilter.value.toLowerCase();
|
||||
let resultsFound = false;
|
||||
restaurantItems.forEach(item => {
|
||||
const name = item.dataset.name;
|
||||
const cuisine = item.dataset.cuisine;
|
||||
|
||||
restaurantItems.forEach(item => {
|
||||
const name = item.dataset.name;
|
||||
const cuisine = item.dataset.cuisine;
|
||||
const nameMatch = name.includes(searchTerm);
|
||||
const cuisineMatch = cuisineTerm === '' || cuisine.includes(cuisineTerm);
|
||||
|
||||
const nameMatch = name.includes(searchTerm);
|
||||
const cuisineMatch = cuisineTerm === '' || cuisine.includes(cuisineTerm);
|
||||
if (nameMatch && cuisineMatch) {
|
||||
item.style.display = '';
|
||||
resultsFound = true;
|
||||
} else {
|
||||
item.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
if (nameMatch && cuisineMatch) {
|
||||
item.style.display = '';
|
||||
resultsFound = true;
|
||||
} else {
|
||||
item.style.display = 'none';
|
||||
}
|
||||
});
|
||||
noResults.style.display = resultsFound ? 'none' : '';
|
||||
}
|
||||
|
||||
noResults.style.display = resultsFound ? 'none' : '';
|
||||
}
|
||||
|
||||
searchInput.addEventListener('input', filterRestaurants);
|
||||
cuisineFilter.addEventListener('change', filterRestaurants);
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
searchInput.addEventListener('input', filterRestaurants);
|
||||
cuisineFilter.addEventListener('change', filterRestaurants);
|
||||
});
|
||||
</script>
|
||||
<?php require_once 'includes/footer.php'; ?>
|
||||
|
||||
84
login.php
Normal file
84
login.php
Normal file
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once 'db/config.php';
|
||||
|
||||
$error_message = '';
|
||||
|
||||
if (isset($_SESSION['user_id'])) {
|
||||
header("Location: index.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||
$email = trim($_POST['email']);
|
||||
$password = $_POST['password'];
|
||||
|
||||
if (empty($email) || empty($password)) {
|
||||
$error_message = "Please enter both email and password.";
|
||||
} else {
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare("SELECT id, name, password_hash FROM users WHERE email = ?");
|
||||
$stmt->execute([$email]);
|
||||
$user = $stmt->fetch();
|
||||
|
||||
if ($user && password_verify($password, $user['password_hash'])) {
|
||||
$_SESSION['user_id'] = $user['id'];
|
||||
$_SESSION['user_name'] = $user['name'];
|
||||
header("Location: index.php");
|
||||
exit;
|
||||
} else {
|
||||
$error_message = "Invalid email or password.";
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Login</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="index.php"><i class="fas fa-utensils"></i> Restaurant Marketplace</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container mt-5">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3>Login</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<?php if ($error_message): ?>
|
||||
<div class="alert alert-danger"><?php echo $error_message; ?></div>
|
||||
<?php endif; ?>
|
||||
<form action="login.php" method="POST">
|
||||
<div class="mb-3">
|
||||
<label for="email" class="form-label">Email address</label>
|
||||
<input type="email" class="form-control" id="email" name="email" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">Password</label>
|
||||
<input type="password" class="form-control" id="password" name="password" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Login</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="card-footer text-center">
|
||||
Don't have an account? <a href="register.php">Register here</a>.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
6
logout.php
Normal file
6
logout.php
Normal file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
session_start();
|
||||
session_unset();
|
||||
session_destroy();
|
||||
header("Location: index.php");
|
||||
exit;
|
||||
121
menu.php
121
menu.php
@ -1,8 +1,11 @@
|
||||
<?php
|
||||
require_once 'includes/header.php';
|
||||
require_once 'db/config.php';
|
||||
|
||||
if (!isset($_GET['restaurant_id']) || !is_numeric($_GET['restaurant_id'])) {
|
||||
die("A valid restaurant ID is required.");
|
||||
// Redirect or show a generic error page
|
||||
header("Location: index.php?error=invalid_restaurant");
|
||||
exit;
|
||||
}
|
||||
$restaurant_id = intval($_GET['restaurant_id']);
|
||||
|
||||
@ -15,10 +18,23 @@ try {
|
||||
$restaurant = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
} catch (PDOException $e) {
|
||||
error_log("DB error fetching restaurant: " . $e->getMessage());
|
||||
// Show a generic error page to the user
|
||||
die("Error: Could not load restaurant information.");
|
||||
}
|
||||
|
||||
if (!$restaurant) {
|
||||
die("Restaurant not found.");
|
||||
// Redirect or show a 404 page
|
||||
header("Location: index.php?error=not_found");
|
||||
exit;
|
||||
}
|
||||
|
||||
$is_favorite = false;
|
||||
if (isset($_SESSION['user_id'])) {
|
||||
$stmt = $pdo->prepare("SELECT id FROM favorite_restaurants WHERE user_id = ? AND restaurant_id = ?");
|
||||
$stmt->execute([$_SESSION['user_id'], $restaurant_id]);
|
||||
if ($stmt->fetch()) {
|
||||
$is_favorite = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch menu items
|
||||
@ -29,6 +45,7 @@ try {
|
||||
$menu_items = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
} catch (PDOException $e) {
|
||||
error_log("DB error fetching menu items: " . $e->getMessage());
|
||||
// It's okay to show the restaurant info even if menu fails to load
|
||||
}
|
||||
|
||||
// Group menu items by category
|
||||
@ -39,44 +56,27 @@ foreach ($menu_items as $item) {
|
||||
}
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Menu for <?= htmlspecialchars($restaurant['name']) ?></title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
body { font-family: 'Poppins', sans-serif; background-color: #F8F9FA; }
|
||||
.menu-header {
|
||||
background: #343A40;
|
||||
color: white;
|
||||
padding: 3rem 0;
|
||||
}
|
||||
.menu-item {
|
||||
border-bottom: 1px dashed #E0E0E0;
|
||||
padding: 1rem 0;
|
||||
}
|
||||
.menu-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="menu-header text-center">
|
||||
<div class="container">
|
||||
<h1 class="display-5"><?= htmlspecialchars($restaurant['name']) ?></h1>
|
||||
<p class="lead"><?= htmlspecialchars($restaurant['address']) ?></p>
|
||||
<?php if ($restaurant['phone']): ?>
|
||||
<p class="text-white-50">Call us at: <?= htmlspecialchars($restaurant['phone']) ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="menu-header text-center">
|
||||
<div class="container">
|
||||
<h1 class="display-5"><?= htmlspecialchars($restaurant['name']) ?></h1>
|
||||
<p class="lead"><?= htmlspecialchars($restaurant['address']) ?></p>
|
||||
<?php if ($restaurant['phone']): ?>
|
||||
<p class="text-white-50">Call us at: <?= htmlspecialchars($restaurant['phone']) ?></p>
|
||||
<?php endif; ?>
|
||||
<a href="index.php" class="btn btn-sm btn-outline-light mt-3"><i class="bi bi-arrow-left"></i> Back to all restaurants</a>
|
||||
</div>
|
||||
<?php if (isset($_SESSION['user_id'])):
|
||||
$btn_class = $is_favorite ? 'btn-danger' : 'btn-outline-warning';
|
||||
$btn_text = $is_favorite ? '<i class="fas fa-heart-broken"></i> Unfavorite' : '<i class="fas fa-heart"></i> Favorite';
|
||||
?>
|
||||
<button id="favoriteBtn" class="btn btn-lg <?= $btn_class ?> mt-3" data-restaurant-id="<?= $restaurant_id ?>">
|
||||
<?= $btn_text ?>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
|
||||
<a href="index.php" class="btn btn-sm btn-outline-light mt-3"><i class="bi bi-arrow-left"></i> Back to all restaurants</a>
|
||||
</div>
|
||||
|
||||
<main class="container my-5">
|
||||
</div>
|
||||
<main class="container my-5">
|
||||
<?php if (empty($menu_by_category)): ?>
|
||||
<div class="text-center">
|
||||
<p class="text-muted fs-4">This restaurant hasn't added any menu items yet.</p>
|
||||
@ -100,10 +100,43 @@ foreach ($menu_items as $item) {
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</main>
|
||||
<?php require_once 'includes/footer.php'; ?>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const favoriteBtn = document.getElementById('favoriteBtn');
|
||||
if (favoriteBtn) {
|
||||
favoriteBtn.addEventListener('click', function() {
|
||||
const restaurantId = this.dataset.restaurantId;
|
||||
|
||||
fetch('api/favorites.php', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ restaurant_id: restaurantId })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
if (data.isFavorite) {
|
||||
this.classList.remove('btn-outline-warning');
|
||||
this.classList.add('btn-danger');
|
||||
this.innerHTML = '<i class="fas fa-heart-broken"></i> Unfavorite';
|
||||
} else {
|
||||
this.classList.remove('btn-danger');
|
||||
this.classList.add('btn-outline-warning');
|
||||
this.innerHTML = '<i class="fas fa-heart"></i> Favorite';
|
||||
}
|
||||
} else {
|
||||
alert(data.message || 'An error occurred.');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
alert('An error occurred. Please try again.');
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<footer class="text-center text-muted py-4">
|
||||
<p>© <?= date('Y') ?> Food Marketplace</p>
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
99
register.php
Normal file
99
register.php
Normal file
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once 'db/config.php';
|
||||
|
||||
$error_message = '';
|
||||
$success_message = '';
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||
$name = trim($_POST['name']);
|
||||
$email = trim($_POST['email']);
|
||||
$password = $_POST['password'];
|
||||
$password_confirm = $_POST['password_confirm'];
|
||||
|
||||
if (empty($name) || empty($email) || empty($password)) {
|
||||
$error_message = "Please fill in all fields.";
|
||||
} elseif ($password !== $password_confirm) {
|
||||
$error_message = "Passwords do not match.";
|
||||
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
$error_message = "Invalid email format.";
|
||||
} else {
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare("SELECT id FROM users WHERE email = ?");
|
||||
$stmt->execute([$email]);
|
||||
if ($stmt->fetch()) {
|
||||
$error_message = "An account with this email already exists.";
|
||||
} else {
|
||||
$password_hash = password_hash($password, PASSWORD_DEFAULT);
|
||||
$stmt = $pdo->prepare("INSERT INTO users (name, email, password_hash) VALUES (?, ?, ?)");
|
||||
if ($stmt->execute([$name, $email, $password_hash])) {
|
||||
$success_message = "Registration successful! You can now <a href='login.php'>log in</a>.";
|
||||
} else {
|
||||
$error_message = "An error occurred. Please try again.";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Register</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="index.php"><i class="fas fa-utensils"></i> Restaurant Marketplace</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container mt-5">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3>Register</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<?php if ($error_message): ?>
|
||||
<div class="alert alert-danger"><?php echo $error_message; ?></div>
|
||||
<?php endif; ?>
|
||||
<?php if ($success_message): ?>
|
||||
<div class="alert alert-success"><?php echo $success_message; ?></div>
|
||||
<?php else: ?>
|
||||
<form action="register.php" method="POST">
|
||||
<div class="mb-3">
|
||||
<label for="name" class="form-label">Name</label>
|
||||
<input type="text" class="form-control" id="name" name="name" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="email" class="form-label">Email address</label>
|
||||
<input type="email" class="form-control" id="email" name="email" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">Password</label>
|
||||
<input type="password" class="form-control" id="password" name="password" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="password_confirm" class="form-label">Confirm Password</label>
|
||||
<input type="password" class="form-control" id="password_confirm" name="password_confirm" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Register</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="card-footer text-center">
|
||||
Already have an account? <a href="login.php">Login here</a>.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
x
Reference in New Issue
Block a user