This commit is contained in:
Flatlogic Bot 2025-10-15 02:30:11 +00:00
parent 2c8c9bfe04
commit ef71b241ae
22 changed files with 845 additions and 217 deletions

61
admin/add_menu_item.php Normal file
View File

@ -0,0 +1,61 @@
<?php
include 'header.php';
require_once '../db/config.php';
// Check if the user is logged in as an admin
if (!isset($_SESSION['admin_logged_in']) || $_SESSION['admin_logged_in'] !== true) {
header('Location: login.php');
exit;
}
$restaurant_id = $_GET['restaurant_id'] ?? null;
if (!$restaurant_id) {
header('Location: index.php');
exit;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = $_POST['name'] ?? '';
$description = $_POST['description'] ?? '';
$price = $_POST['price'] ?? '';
$restaurant_id = $_POST['restaurant_id'] ?? null;
if ($name && $price && $restaurant_id) {
$pdo = db();
$stmt = $pdo->prepare("INSERT INTO menu_items (restaurant_id, name, description, price) VALUES (?, ?, ?, ?)");
$stmt->execute([$restaurant_id, $name, $description, $price]);
header('Location: menu.php?restaurant_id=' . $restaurant_id);
exit;
} else {
$error = "Name and price are required.";
}
}
?>
<div class="container mt-4">
<h2>Add New Menu Item</h2>
<?php if (isset($error)): ?>
<div class="alert alert-danger"><?php echo $error; ?></div>
<?php endif; ?>
<form action="add_menu_item.php" method="POST">
<input type="hidden" name="restaurant_id" value="<?php echo $restaurant_id; ?>">
<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="description" class="form-label">Description</label>
<textarea class="form-control" id="description" name="description"></textarea>
</div>
<div class="mb-3">
<label for="price" class="form-label">Price</label>
<input type="number" step="0.01" class="form-control" id="price" name="price" required>
</div>
<button type="submit" class="btn btn-primary">Add Item</button>
<a href="menu.php?restaurant_id=<?php echo $restaurant_id; ?>" class="btn btn-secondary">Cancel</a>
</form>
</div>
<?php include 'footer.php'; ?>

53
admin/add_restaurant.php Normal file
View File

@ -0,0 +1,53 @@
<?php
include 'header.php';
require_once '../db/config.php';
// Check if the user is logged in as an admin
if (!isset($_SESSION['admin_logged_in']) || $_SESSION['admin_logged_in'] !== true) {
header('Location: login.php');
exit;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = $_POST['name'] ?? '';
$cuisine = $_POST['cuisine'] ?? '';
$image_url = $_POST['image_url'] ?? '';
if ($name && $cuisine) {
$pdo = db();
$stmt = $pdo->prepare("INSERT INTO restaurants (name, cuisine, image_url) VALUES (?, ?, ?)");
$stmt->execute([$name, $cuisine, $image_url]);
header('Location: index.php');
exit;
} else {
$error = "Name and cuisine are required.";
}
}
?>
<div class="container mt-4">
<h2>Add New Restaurant</h2>
<?php if (isset($error)): ?>
<div class="alert alert-danger"><?php echo $error; ?></div>
<?php endif; ?>
<form action="add_restaurant.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="cuisine" class="form-label">Cuisine</label>
<input type="text" class="form-control" id="cuisine" name="cuisine" required>
</div>
<div class="mb-3">
<label for="image_url" class="form-label">Image URL</label>
<input type="text" class="form-control" id="image_url" name="image_url">
</div>
<button type="submit" class="btn btn-primary">Add Restaurant</button>
<a href="index.php" class="btn btn-secondary">Cancel</a>
</form>
</div>
<?php include 'footer.php'; ?>

View File

@ -0,0 +1,26 @@
<?php
session_start();
require_once '../db/config.php';
// Check if the user is logged in as an admin
if (!isset($_SESSION['admin_logged_in']) || $_SESSION['admin_logged_in'] !== true) {
header('Location: login.php');
exit;
}
$id = $_GET['id'] ?? null;
$restaurant_id = $_GET['restaurant_id'] ?? null;
if ($id) {
$pdo = db();
$stmt = $pdo->prepare("DELETE FROM menu_items WHERE id = ?");
$stmt->execute([$id]);
}
if ($restaurant_id) {
header('Location: menu.php?restaurant_id=' . $restaurant_id);
} else {
header('Location: index.php');
}
exit;
?>

View File

@ -0,0 +1,21 @@
<?php
session_start();
require_once '../db/config.php';
// Check if the user is logged in as an admin
if (!isset($_SESSION['admin_logged_in']) || $_SESSION['admin_logged_in'] !== true) {
header('Location: login.php');
exit;
}
$id = $_GET['id'] ?? null;
if ($id) {
$pdo = db();
$stmt = $pdo->prepare("DELETE FROM restaurants WHERE id = ?");
$stmt->execute([$id]);
}
header('Location: index.php');
exit;
?>

73
admin/edit_menu_item.php Normal file
View File

@ -0,0 +1,73 @@
<?php
include 'header.php';
require_once '../db/config.php';
// Check if the user is logged in as an admin
if (!isset($_SESSION['admin_logged_in']) || $_SESSION['admin_logged_in'] !== true) {
header('Location: login.php');
exit;
}
$id = $_GET['id'] ?? null;
if (!$id) {
header('Location: index.php');
exit;
}
$pdo = db();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = $_POST['name'] ?? '';
$description = $_POST['description'] ?? '';
$price = $_POST['price'] ?? '';
$id = $_POST['id'] ?? null;
$restaurant_id = $_POST['restaurant_id'] ?? null;
if ($name && $price && $id && $restaurant_id) {
$stmt = $pdo->prepare("UPDATE menu_items SET name = ?, description = ?, price = ? WHERE id = ?");
$stmt->execute([$name, $description, $price, $id]);
header('Location: menu.php?restaurant_id=' . $restaurant_id);
exit;
} else {
$error = "Name and price are required.";
}
}
$stmt = $pdo->prepare("SELECT * FROM menu_items WHERE id = ?");
$stmt->execute([$id]);
$item = $stmt->fetch();
if (!$item) {
header('Location: index.php');
exit;
}
?>
<div class="container mt-4">
<h2>Edit Menu Item</h2>
<?php if (isset($error)): ?>
<div class="alert alert-danger"><?php echo $error; ?></div>
<?php endif; ?>
<form action="edit_menu_item.php?id=<?php echo $item['id']; ?>" method="POST">
<input type="hidden" name="id" value="<?php echo $item['id']; ?>">
<input type="hidden" name="restaurant_id" value="<?php echo $item['restaurant_id']; ?>">
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input type="text" class="form-control" id="name" name="name" value="<?php echo htmlspecialchars($item['name']); ?>" required>
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<textarea class="form-control" id="description" name="description"><?php echo htmlspecialchars($item['description']); ?></textarea>
</div>
<div class="mb-3">
<label for="price" class="form-label">Price</label>
<input type="number" step="0.01" class="form-control" id="price" name="price" value="<?php echo htmlspecialchars($item['price']); ?>" required>
</div>
<button type="submit" class="btn btn-primary">Update Item</button>
<a href="menu.php?restaurant_id=<?php echo $item['restaurant_id']; ?>" class="btn btn-secondary">Cancel</a>
</form>
</div>
<?php include 'footer.php'; ?>

71
admin/edit_restaurant.php Normal file
View File

@ -0,0 +1,71 @@
<?php
include 'header.php';
require_once '../db/config.php';
// Check if the user is logged in as an admin
if (!isset($_SESSION['admin_logged_in']) || $_SESSION['admin_logged_in'] !== true) {
header('Location: login.php');
exit;
}
$id = $_GET['id'] ?? null;
if (!$id) {
header('Location: index.php');
exit;
}
$pdo = db();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = $_POST['name'] ?? '';
$cuisine = $_POST['cuisine'] ?? '';
$image_url = $_POST['image_url'] ?? '';
$id = $_POST['id'] ?? null;
if ($name && $cuisine && $id) {
$stmt = $pdo->prepare("UPDATE restaurants SET name = ?, cuisine = ?, image_url = ? WHERE id = ?");
$stmt->execute([$name, $cuisine, $image_url, $id]);
header('Location: index.php');
exit;
} else {
$error = "Name and cuisine are required.";
}
}
$stmt = $pdo->prepare("SELECT * FROM restaurants WHERE id = ?");
$stmt->execute([$id]);
$restaurant = $stmt->fetch();
if (!$restaurant) {
header('Location: index.php');
exit;
}
?>
<div class="container mt-4">
<h2>Edit Restaurant</h2>
<?php if (isset($error)): ?>
<div class="alert alert-danger"><?php echo $error; ?></div>
<?php endif; ?>
<form action="edit_restaurant.php?id=<?php echo $restaurant['id']; ?>" method="POST">
<input type="hidden" name="id" value="<?php echo $restaurant['id']; ?>">
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input type="text" class="form-control" id="name" name="name" value="<?php echo htmlspecialchars($restaurant['name']); ?>" required>
</div>
<div class="mb-3">
<label for="cuisine" class="form-label">Cuisine</label>
<input type="text" class="form-control" id="cuisine" name="cuisine" value="<?php echo htmlspecialchars($restaurant['cuisine']); ?>" required>
</div>
<div class="mb-3">
<label for="image_url" class="form-label">Image URL</label>
<input type="text" class_="form-control" id="image_url" name="image_url" value="<?php echo htmlspecialchars($restaurant['image_url']); ?>">
</div>
<button type="submit" class="btn btn-primary">Update Restaurant</button>
<a href="index.php" class="btn btn-secondary">Cancel</a>
</form>
</div>
<?php include 'footer.php'; ?>

View File

@ -1,45 +1,44 @@
<?php
require_once 'header.php';
include 'header.php';
require_once '../db/config.php';
$db = db();
$stmt = $db->query("SELECT o.id, o.user_id, o.total_price, o.status, o.created_at, u.name AS user_name FROM orders o JOIN users u ON o.user_id = u.id ORDER BY o.created_at DESC");
$orders = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Check if the user is logged in as an admin
if (!isset($_SESSION['admin_logged_in']) || $_SESSION['admin_logged_in'] !== true) {
header('Location: login.php');
exit;
}
$pdo = db();
$stmt = $pdo->query("SELECT id, name, cuisine FROM restaurants ORDER BY name");
$restaurants = $stmt->fetchAll();
?>
<h2>Order Management</h2>
<div class="container mt-4">
<h2>Restaurant Management</h2>
<p><a href="add_restaurant.php" class="btn btn-success">Add New Restaurant</a></p>
<table class="table table-striped">
<thead>
<tr>
<th>Order ID</th>
<th>Customer</th>
<th>Total Price</th>
<th>Status</th>
<th>Order Date</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php if (empty($orders)): ?>
<table class="table table-striped">
<thead>
<tr>
<td colspan="6" class="text-center">No orders found.</td>
<th>Name</th>
<th>Cuisine</th>
<th>Actions</th>
</tr>
<?php else: ?>
<?php foreach ($orders as $order): ?>
</thead>
<tbody>
<?php foreach ($restaurants as $restaurant): ?>
<tr>
<td><?php echo htmlspecialchars($order['id']); ?></td>
<td><?php echo htmlspecialchars($order['user_name']); ?></td>
<td>$<?php echo htmlspecialchars(number_format($order['total_price'], 2)); ?></td>
<td><?php echo htmlspecialchars($order['status']); ?></td>
<td><?php echo htmlspecialchars($order['created_at']); ?></td>
<td><?php echo htmlspecialchars($restaurant['name']); ?></td>
<td><?php echo htmlspecialchars($restaurant['cuisine']); ?></td>
<td>
<a href="order_details.php?id=<?php echo $order['id']; ?>" class="btn btn-primary btn-sm">View Details</a>
<a href="menu.php?restaurant_id=<?php echo $restaurant['id']; ?>" class="btn btn-info btn-sm">Manage Menu</a>
<a href="edit_restaurant.php?id=<?php echo $restaurant['id']; ?>" class="btn btn-primary btn-sm">Edit</a>
<a href="delete_restaurant.php?id=<?php echo $restaurant['id']; ?>" class="btn btn-danger btn-sm" onclick="return confirm('Are you sure you want to delete this restaurant?');">Delete</a>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</tbody>
</table>
</div>
<?php require_once 'footer.php'; ?>
<?php include 'footer.php'; ?>

View File

@ -29,8 +29,8 @@ unset($_SESSION['login_error']);
<?php endif; ?>
<form action="login_process.php" method="POST">
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" id="username" name="username" required>
<label for="email" class="form-label">Email</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>

View File

@ -2,18 +2,34 @@
session_start();
require_once '../db/config.php';
$username = $_POST['username'] ?? '';
$email = $_POST['email'] ?? '';
$password = $_POST['password'] ?? '';
// For now, we are using hardcoded credentials.
// TODO: Replace with a secure way to store and check admin credentials.
if ($username === 'admin' && $password === 'password') {
$_SESSION['admin_logged_in'] = true;
$_SESSION['admin_username'] = $username;
header('Location: index.php');
if (empty($email) || empty($password)) {
$_SESSION['login_error'] = 'Email and password are required.';
header('Location: login.php');
exit;
} else {
$_SESSION['login_error'] = 'Invalid username or password.';
}
try {
$pdo = db();
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
$stmt->execute([$email]);
$user = $stmt->fetch();
if ($user && password_verify($password, $user['password']) && $user['is_admin']) {
$_SESSION['admin_logged_in'] = true;
$_SESSION['admin_user_id'] = $user['id'];
$_SESSION['admin_email'] = $user['email'];
header('Location: index.php');
exit;
} else {
$_SESSION['login_error'] = 'Invalid credentials or not an admin.';
header('Location: login.php');
exit;
}
} catch (PDOException $e) {
$_SESSION['login_error'] = 'Database error: ' . $e->getMessage();
header('Location: login.php');
exit;
}

64
admin/menu.php Normal file
View File

@ -0,0 +1,64 @@
<?php
include 'header.php';
require_once '../db/config.php';
// Check if the user is logged in as an admin
if (!isset($_SESSION['admin_logged_in']) || $_SESSION['admin_logged_in'] !== true) {
header('Location: login.php');
exit;
}
$restaurant_id = $_GET['restaurant_id'] ?? null;
if (!$restaurant_id) {
header('Location: index.php');
exit;
}
$pdo = db();
// Get restaurant details
$stmt = $pdo->prepare("SELECT name FROM restaurants WHERE id = ?");
$stmt->execute([$restaurant_id]);
$restaurant = $stmt->fetch();
if (!$restaurant) {
header('Location: index.php');
exit;
}
// Get menu items for the restaurant
$stmt = $pdo->prepare("SELECT * FROM menu_items WHERE restaurant_id = ? ORDER BY name");
$stmt->execute([$restaurant_id]);
$menu_items = $stmt->fetchAll();
?>
<div class="container mt-4">
<h2>Manage Menu for <?php echo htmlspecialchars($restaurant['name']); ?></h2>
<p><a href="add_menu_item.php?restaurant_id=<?php echo $restaurant_id; ?>" class="btn btn-success">Add New Menu Item</a></p>
<table class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th>Price</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($menu_items as $item): ?>
<tr>
<td><?php echo htmlspecialchars($item['name']); ?></td>
<td><?php echo htmlspecialchars($item['description']); ?></td>
<td>$<?php echo htmlspecialchars(number_format($item['price'], 2)); ?></td>
<td>
<a href="edit_menu_item.php?id=<?php echo $item['id']; ?>" class="btn btn-primary btn-sm">Edit</a>
<a href="delete_menu_item.php?id=<?php echo $item['id']; ?>&restaurant_id=<?php echo $restaurant_id; ?>" class="btn btn-danger btn-sm" onclick="return confirm('Are you sure you want to delete this item?');">Delete</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<a href="index.php" class="btn btn-secondary">Back to Restaurants</a>
</div>
<?php include 'footer.php'; ?>

View File

@ -2,51 +2,80 @@
session_start();
require_once 'db/config.php';
if (!isset($_GET['action'])) {
// Default redirect location
$redirect_location = 'cart.php';
// Determine action, prioritizing POST
$action = $_POST['action'] ?? $_GET['action'] ?? null;
if (!$action) {
header('Location: index.php');
exit;
}
$action = $_GET['action'];
$user_id = $_SESSION['user_id'] ?? null;
$session_id = session_id();
$pdoconnection = db();
if ($action == 'add') {
if (!isset($_POST['menu_item_id']) || !isset($_POST['quantity'])) {
header('Location: cart.php');
exit;
// --- ADD TO CART ---
if ($action == 'add' && isset($_POST['menu_item_id'], $_POST['quantity'])) {
$menu_item_id = (int)$_POST['menu_item_id'];
$quantity = (int)$_POST['quantity'];
if ($quantity > 0 && $menu_item_id > 0) {
// Check if item is already in cart
$sql = "SELECT id, quantity FROM cart WHERE menu_item_id = :menu_item_id AND " . ($user_id ? "user_id = :identifier" : "session_id = :identifier");
$stmt = $pdoconnection->prepare($sql);
$identifier = $user_id ?: $session_id;
$stmt->execute([':menu_item_id' => $menu_item_id, ':identifier' => $identifier]);
$existing_item = $stmt->fetch();
if ($existing_item) {
// Update quantity
$new_quantity = $existing_item['quantity'] + $quantity;
$stmt = $pdoconnection->prepare("UPDATE cart SET quantity = :quantity WHERE id = :id");
$stmt->execute([':quantity' => $new_quantity, ':id' => $existing_item['id']]);
} else {
// Insert new item
$stmt = $pdoconnection->prepare(
"INSERT INTO cart (user_id, session_id, menu_item_id, quantity) VALUES (:user_id, :session_id, :menu_item_id, :quantity)"
);
$stmt->execute([
':user_id' => $user_id,
':session_id' => $user_id ? null : $session_id,
':menu_item_id' => $menu_item_id,
':quantity' => $quantity
]);
}
}
// Redirect back to the menu page after adding an item
if (isset($_POST['restaurant_id']) && is_numeric($_POST['restaurant_id'])) {
$redirect_location = 'menu.php?id=' . $_POST['restaurant_id'];
}
$menu_item_id = $_POST['menu_item_id'];
$quantity = $_POST['quantity'];
// --- UPDATE CART ---
} elseif ($action == 'update' && isset($_POST['cart_id'], $_POST['quantity'])) {
$cart_id = (int)$_POST['cart_id'];
$quantity = (int)$_POST['quantity'];
// Check if item is already in cart
if ($user_id) {
$stmt = $pdoconnection->prepare("SELECT * FROM cart WHERE user_id = :user_id AND menu_item_id = :menu_item_id");
$stmt->execute([':user_id' => $user_id, ':menu_item_id' => $menu_item_id]);
} else {
$stmt = $pdoconnection->prepare("SELECT * FROM cart WHERE session_id = :session_id AND menu_item_id = :menu_item_id");
$stmt->execute([':session_id' => $session_id, ':menu_item_id' => $menu_item_id]);
}
$existing_item = $stmt->fetch();
if ($existing_item) {
// Update quantity
$new_quantity = $existing_item['quantity'] + $quantity;
$stmt = $pdoconnection->prepare("UPDATE cart SET quantity = :quantity WHERE id = :id");
$stmt->execute([':quantity' => $new_quantity, ':id' => $existing_item['id']]);
} else {
// Insert new item
$stmt = $pdoconnection->prepare("INSERT INTO cart (user_id, session_id, menu_item_id, quantity) VALUES (:user_id, :session_id, :menu_item_id, :quantity)");
$stmt->execute([
':user_id' => $user_id,
':session_id' => $user_id ? null : $session_id,
':menu_item_id' => $menu_item_id,
':quantity' => $quantity
]);
if ($quantity > 0 && $cart_id > 0) {
$sql = "UPDATE cart SET quantity = :quantity WHERE id = :cart_id AND " . ($user_id ? "user_id = :identifier" : "session_id = :identifier");
$stmt = $pdoconnection->prepare($sql);
$identifier = $user_id ?: $session_id;
$stmt->execute([':quantity' => $quantity, ':cart_id' => $cart_id, ':identifier' => $identifier]);
}
header('Location: cart.php');
exit;
}
// --- REMOVE FROM CART ---
} elseif ($action == 'remove' && isset($_POST['cart_id'])) {
$cart_id = (int)$_POST['cart_id'];
if ($cart_id > 0) {
$sql = "DELETE FROM cart WHERE id = :cart_id AND " . ($user_id ? "user_id = :identifier" : "session_id = :identifier");
$stmt = $pdoconnection->prepare($sql);
$identifier = $user_id ?: $session_id;
$stmt->execute([':cart_id' => $cart_id, ':identifier' => $identifier]);
}
}
header('Location: ' . $redirect_location);
exit;

18
db/run_migration.php Normal file
View File

@ -0,0 +1,18 @@
<?php
require_once 'config.php';
$migration_file = end($argv);
if (!file_exists($migration_file)) {
die("Migration file not found: $migration_file");
}
$sql = file_get_contents($migration_file);
$db = db();
try {
$db->exec($sql);
echo "Migration successful: $migration_file\n";
} catch (PDOException $e) {
die("Migration failed: " . $e->getMessage() . "\n");
}

View File

@ -32,19 +32,19 @@
<div class="restaurant-grid" id="restaurant-grid">
<?php
// Base query
$sql = "SELECT id, name, cuisine, image_url, rating, rating_count FROM restaurants";
$sql = "SELECT r.id, r.name, r.cuisine, r.image_url, 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 = [];
$where_clauses = [];
// Append search condition
if (!empty($_GET['search'])) {
$where_clauses[] = "name LIKE ?";
$where_clauses[] = "r.name LIKE ?";
$params[] = '%' . $_GET['search'] . '%';
}
// Append cuisine filter
if (!empty($_GET['cuisine'])) {
$where_clauses[] = "cuisine = ?";
$where_clauses[] = "r.cuisine = ?";
$params[] = $_GET['cuisine'];
}
@ -52,7 +52,7 @@
$sql .= " WHERE " . implode(' AND ', $where_clauses);
}
$sql .= " ORDER BY name";
$sql .= " GROUP BY r.id, r.name, r.cuisine, r.image_url ORDER BY r.name";
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
@ -67,10 +67,10 @@
echo '<div class="restaurant-card-content">';
echo '<h3>' . htmlspecialchars($restaurant['name']) . '</h3>';
echo '<p>' . htmlspecialchars($restaurant['cuisine']) . '</p>';
if (isset($restaurant['rating']) && $restaurant['rating'] > 0) {
if ($restaurant['rating_count'] > 0) {
echo '<div class="rating-display">';
echo '<span class="star">★</span>';
echo '<span>' . htmlspecialchars(number_format($restaurant['rating'], 1)) . '</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 {
@ -86,4 +86,4 @@
</div>
</main>
<?php include 'footer.php'; ?>
<?php include 'footer.php'; ?>

228
menu.php
View File

@ -1,53 +1,201 @@
<?php
require_once 'header.php';
session_start();
require_once 'db/config.php';
if (!isset($_GET['id'])) {
echo "<div class='alert alert-danger'>Restaurant ID is missing.</div>";
$restaurant_id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
if ($restaurant_id === 0) {
header('Location: index.php');
exit;
}
// Handle review submission
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['submit_review'])) {
if (!isset($_SESSION['user_id'])) {
// Redirect to login if not logged in
header('Location: login.php');
exit;
}
$rating = isset($_POST['rating']) ? (int)$_POST['rating'] : 0;
$review = isset($_POST['review']) ? trim($_POST['review']) : '';
$user_id = $_SESSION['user_id'];
if ($rating >= 1 && $rating <= 5) {
try {
$insert_stmt = db()->prepare("INSERT INTO ratings (restaurant_id, user_id, rating, review) VALUES (:restaurant_id, :user_id, :rating, :review)");
$insert_stmt->bindParam(':restaurant_id', $restaurant_id, PDO::PARAM_INT);
$insert_stmt->bindParam(':user_id', $user_id, PDO::PARAM_INT);
$insert_stmt->bindParam(':rating', $rating, PDO::PARAM_INT);
$insert_stmt->bindParam(':review', $review, PDO::PARAM_STR);
$insert_stmt->execute();
// Redirect to the same page to prevent form resubmission
header("Location: menu.php?id=$restaurant_id&rated=true");
exit;
} catch (PDOException $e) {
$submit_error = "Error submitting your review. Please try again.";
// In a real app, you'd log this error.
}
} else {
$submit_error = "Please select a rating between 1 and 5.";
}
}
require_once 'header.php';
try {
// Fetch restaurant details
$stmt = db()->prepare("SELECT name, image_url, cuisine FROM restaurants WHERE id = :id");
$stmt->bindParam(':id', $restaurant_id, PDO::PARAM_INT);
$stmt->execute();
$restaurant = $stmt->fetch(PDO::FETCH_ASSOC);
// Fetch menu items
$menu_stmt = db()->prepare("SELECT id, name, description, price, image_url FROM menu_items WHERE restaurant_id = :restaurant_id");
$menu_stmt->bindParam(':restaurant_id', $restaurant_id, PDO::PARAM_INT);
$menu_stmt->execute();
$menu_items = $menu_stmt->fetchAll(PDO::FETCH_ASSOC);
// Fetch ratings and calculate average
$ratings_stmt = db()->prepare("SELECT r.rating, r.review, r.created_at, u.name as user_name FROM ratings r JOIN users u ON r.user_id = u.id WHERE r.restaurant_id = :restaurant_id ORDER BY r.created_at DESC");
$ratings_stmt->bindParam(':restaurant_id', $restaurant_id, PDO::PARAM_INT);
$ratings_stmt->execute();
$ratings = $ratings_stmt->fetchAll(PDO::FETCH_ASSOC);
$average_rating = 0;
if (count($ratings) > 0) {
$total_rating = 0;
foreach ($ratings as $r) {
$total_rating += $r['rating'];
}
$average_rating = round($total_rating / count($ratings), 1);
}
} catch (PDOException $e) {
echo "<div class='container'><p class='alert alert-danger'>Error fetching restaurant data.</p></div>";
require_once 'footer.php';
exit;
}
$restaurant_id = $_GET['id'];
// Fetch restaurant details
$stmt = db()->prepare("SELECT * FROM restaurants WHERE id = ?");
$stmt->execute([$restaurant_id]);
$restaurant = $stmt->fetch();
// Fetch menu items
$stmt = db()->prepare("SELECT * FROM menu_items WHERE restaurant_id = ?");
$stmt->execute([$restaurant_id]);
$menu_items = $stmt->fetchAll();
?>
<div class="container">
<div class="row">
<div class="col-md-12">
<h1 class="mt-5"><?php echo htmlspecialchars($restaurant['name']); ?></h1>
<p class="lead"><?php echo htmlspecialchars($restaurant['description']); ?></p>
</div>
</div>
<div class="row">
<?php foreach ($menu_items as $item): ?>
<div class="col-md-4">
<div class="card mb-4">
<div class="card-body">
<h5 class="card-title"><?php echo htmlspecialchars($item['name']); ?></h5>
<p class="card-text"><?php echo htmlspecialchars($item['description']); ?></p>
<p class="card-text font-weight-bold">$<?php echo htmlspecialchars($item['price']); ?></p>
<form action="cart_actions.php?action=add" method="post">
<input type="hidden" name="menu_item_id" value="<?php echo $item['id']; ?>">
<input type="number" name="quantity" value="1" min="1" class="form-control mb-2">
<button type="submit" class="btn btn-primary">Add to Cart</button>
</form>
</div>
<div class="container mt-5">
<?php if ($restaurant): ?>
<div class="row mb-4 align-items-center">
<div class="col-md-8">
<h1 class="display-4"><?php echo htmlspecialchars($restaurant['name']); ?></h1>
<p class="lead text-muted"><?php echo htmlspecialchars($restaurant['cuisine']); ?></p>
<div class="d-flex align-items-center">
<span class="h4 text-warning me-2"><?php echo $average_rating; ?> ★</span>
<span class="text-muted">(<?php echo count($ratings); ?> reviews)</span>
</div>
</div>
<?php endforeach; ?>
</div>
<div class="col-md-4">
<?php if (!empty($restaurant['image_url'])): ?>
<img src="<?php echo htmlspecialchars($restaurant['image_url']); ?>" class="img-fluid rounded shadow-sm" alt="Image of <?php echo htmlspecialchars($restaurant['name']); ?>">
<?php endif; ?>
</div>
</div>
<hr>
<h2 class="mt-5 mb-4">Menu</h2>
<div class="row">
<?php if ($menu_items): ?>
<?php foreach ($menu_items as $item): ?>
<div class="col-md-6 col-lg-4 mb-4">
<div class="card h-100 shadow-sm border-light">
<?php if (!empty($item['image_url'])): ?>
<img src="<?php echo htmlspecialchars($item['image_url']); ?>" class="card-img-top" alt="<?php echo htmlspecialchars($item['name']); ?>" style="height: 200px; object-fit: cover;">
<?php endif; ?>
<div class="card-body d-flex flex-column">
<h5 class="card-title"><?php echo htmlspecialchars($item['name']); ?></h5>
<p class="card-text text-muted flex-grow-1"><?php echo htmlspecialchars($item['description']); ?></p>
<p class="card-text h4 text-success">$<?php echo htmlspecialchars(number_format($item['price'], 2)); ?></p>
<form action="cart_actions.php" method="post" class="mt-auto">
<input type="hidden" name="action" value="add">
<input type="hidden" name="restaurant_id" value="<?php echo $restaurant_id; ?>">
<input type="hidden" name="menu_item_id" value="<?php echo $item['id']; ?>">
<div class="input-group">
<input type="number" name="quantity" class="form-control" value="1" min="1">
<button type="submit" class="btn btn-primary">Add to Cart</button>
</div>
</form>
</div>
</div>
</div>
<?php endforeach; ?>
<?php else: ?>
<div class="col">
<p class="alert alert-info">This restaurant has no menu items yet.</p>
</div>
<?php endif; ?>
</div>
<hr class="my-5">
<div class="row">
<div class="col-lg-8 mx-auto">
<h2 class="mb-4">Reviews & Ratings</h2>
<?php if (isset($_SESSION['user_id'])): ?>
<div class="card mb-4">
<div class="card-header">Leave a Review</div>
<div class="card-body">
<?php if (isset($submit_error)): ?>
<div class="alert alert-danger"><?php echo $submit_error; ?></div>
<?php endif; ?>
<?php if (isset($_GET['rated']) && $_GET['rated'] == 'true'): ?>
<div class="alert alert-success">Thank you for your review!</div>
<?php endif; ?>
<form action="menu.php?id=<?php echo $restaurant_id; ?>" method="post">
<div class="mb-3">
<label for="rating" class="form-label">Your Rating</label>
<select class="form-select" id="rating" name="rating" required>
<option value="" disabled selected>Choose a rating...</option>
<option value="5">5 - Excellent</option>
<option value="4">4 - Very Good</option>
<option value="3">3 - Good</option>
<option value="2">2 - Fair</option>
<option value="1">1 - Poor</option>
</select>
</div>
<div class="mb-3">
<label for="review" class="form-label">Your Review</label>
<textarea class="form-control" id="review" name="review" rows="3" placeholder="What did you think?"></textarea>
</div>
<button type="submit" name="submit_review" class="btn btn-success">Submit Review</button>
</form>
</div>
</div>
<?php else: ?>
<div class="alert alert-info">
<a href="login.php?redirect_url=<?php echo urlencode($_SERVER['REQUEST_URI']); ?>">Log in</a> to leave a review.
</div>
<?php endif; ?>
<?php if ($ratings): ?>
<?php foreach ($ratings as $rating): ?>
<div class="card mb-3">
<div class="card-body">
<div class="d-flex justify-content-between">
<h5 class="card-title"><?php echo htmlspecialchars($rating['user_name']); ?></h5>
<span class="text-warning"><?php echo str_repeat('★', $rating['rating']) . str_repeat('☆', 5 - $rating['rating']); ?></span>
</div>
<p class="card-text"><?php echo nl2br(htmlspecialchars($rating['review'])); ?></p>
<p class="card-text"><small class="text-muted"><?php echo date('F j, Y, g:i a', strtotime($rating['created_at'])); ?></small></p>
</div>
</div>
<?php endforeach; ?>
<?php else: ?>
<p>This restaurant has no reviews yet. Be the first!</p>
<?php endif; ?>
</div>
</div>
<?php else: ?>
<p class="alert alert-warning">Restaurant not found.</p>
<?php endif; ?>
</div>
<?php require_once 'footer.php'; ?>
<?php require_once 'footer.php'; ?>

View File

@ -0,0 +1 @@
ALTER TABLE "users" ADD "address" TEXT;

View File

@ -0,0 +1 @@
ALTER TABLE users ADD COLUMN is_admin BOOLEAN DEFAULT FALSE;

View File

@ -0,0 +1 @@
ALTER TABLE users ADD COLUMN password VARCHAR(255);

View File

@ -0,0 +1 @@
INSERT INTO users (name, email, password, is_admin) VALUES ('Admin', 'admin@example.com', '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', TRUE) ON CONFLICT (email) DO NOTHING;

View File

@ -0,0 +1 @@
INSERT INTO users (email, role, password, is_admin) VALUES ('admin@example.com', 'owner', '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', TRUE) ON CONFLICT (email) DO UPDATE SET role = 'owner', password = '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', is_admin = TRUE;

View File

@ -1,12 +1,10 @@
CREATE TABLE IF NOT EXISTS `ratings` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`order_id` INT NOT NULL,
`restaurant_id` INT NOT NULL,
`user_id` INT NOT NULL,
`rating` INT NOT NULL,
`comment` TEXT,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (`order_id`) REFERENCES `orders`(`id`),
FOREIGN KEY (`restaurant_id`) REFERENCES `restaurants`(`id`),
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`)
CREATE TABLE IF NOT EXISTS ratings (
id SERIAL PRIMARY KEY,
restaurant_id INT NOT NULL,
user_id INT NOT NULL,
rating INT NOT NULL,
review TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (restaurant_id) REFERENCES restaurants(id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);

65
order_details.php Normal file
View File

@ -0,0 +1,65 @@
<?php
session_start();
require_once 'db/config.php';
include 'header.php';
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
exit();
}
if (!isset($_GET['id'])) {
header("Location: profile.php");
exit();
}
$order_id = $_GET['id'];
$user_id = $_SESSION['user_id'];
// Fetch order details
$p_order = $db->prepare("SELECT o.*, r.name as restaurant_name FROM orders o JOIN restaurants r ON o.restaurant_id = r.id WHERE o.id = ? AND o.user_id = ?");
$p_order->execute([$order_id, $user_id]);
$order = $p_order->fetch(PDO::FETCH_ASSOC);
if (!$order) {
echo "<div class='container mt-5'><p>Order not found or you do not have permission to view it.</p></div>";
include 'footer.php';
exit();
}
// Fetch order items
$p_items = $db->prepare("SELECT oi.*, mi.name as item_name FROM order_items oi JOIN menu_items mi ON oi.menu_item_id = mi.id WHERE oi.order_id = ?");
$p_items->execute([$order_id]);
$items = $p_items->fetchAll(PDO::FETCH_ASSOC);
?>
<div class="container mt-5">
<h2>Order Details #<?php echo $order['id']; ?></h2>
<hr>
<div class="card mb-4">
<div class="card-body">
<h5 class="card-title">Summary</h5>
<p><strong>Restaurant:</strong> <?php echo htmlspecialchars($order['restaurant_name']); ?></p>
<p><strong>Order Date:</strong> <?php echo date("F j, Y, g:i a", strtotime($order['created_at'])); ?></p>
<p><strong>Total:</strong> $<?php echo number_format($order['total_price'], 2); ?></p>
<p><strong>Status:</strong> <?php echo htmlspecialchars($order['status']); ?></p>
</div>
</div>
<div class="card">
<div class="card-body">
<h5 class="card-title">Items</h5>
<ul class="list-group list-group-flush">
<?php foreach ($items as $item): ?>
<li class="list-group-item d-flex justify-content-between align-items-center">
<?php echo htmlspecialchars($item['item_name']); ?> (x<?php echo $item['quantity']; ?>)
<span>$<?php echo number_format($item['price'] * $item['quantity'], 2); ?></span>
</li>
<?php endforeach; ?>
</ul>
</div>
</div>
<a href="profile.php" class="btn btn-primary mt-3">Back to My Orders</a>
</div>
<?php include 'footer.php'; ?>

View File

@ -1,6 +1,7 @@
<?php
session_start();
require_once 'db/config.php';
include 'header.php';
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
@ -8,96 +9,76 @@ if (!isset($_SESSION['user_id'])) {
}
$user_id = $_SESSION['user_id'];
$db = db();
// Fetch user's orders and restaurant info
$stmt = $db()->prepare("
SELECT o.*, r.id AS restaurant_id, r.name AS restaurant_name
FROM orders o
JOIN order_items oi ON o.id = oi.order_id
JOIN menu_items mi ON oi.menu_item_id = mi.id
JOIN restaurants r ON mi.restaurant_id = r.id
WHERE o.user_id = ?
GROUP BY o.id
ORDER BY o.order_date DESC
");
$stmt->execute([$user_id]);
$orders = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Handle profile update
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['update_profile'])) {
$name = trim($_POST['name']);
$email = trim($_POST['email']);
$address = trim($_POST['address']);
include 'header.php';
if (empty($name) || empty($email)) {
$error = "Name and email are required.";
} else {
$p_update = $db->prepare("UPDATE users SET name = ?, email = ?, address = ? WHERE id = ?");
$p_update->execute([$name, $email, $address, $user_id]);
$success = "Profile updated successfully!";
}
}
// Fetch user data
$p_user = $db->prepare("SELECT * FROM users WHERE id = ?");
$p_user->execute([$user_id]);
$user = $p_user->fetch();
// Fetch user's orders
$p_orders = $db->prepare("SELECT o.*, r.name as restaurant_name FROM orders o JOIN restaurants r ON o.restaurant_id = r.id WHERE o.user_id = ? ORDER BY o.created_at DESC");
$p_orders->execute([$user_id]);
$orders = $p_orders->fetchAll(PDO::FETCH_ASSOC);
?>
<div class="container mt-5">
<h2>My Profile</h2>
<h4>My Orders</h4>
<?php
if (isset($_SESSION['rating_success'])) {
echo '<div class="alert alert-success">' . $_SESSION['rating_success'] . '</div>';
unset($_SESSION['rating_success']);
}
if (isset($_SESSION['rating_error'])) {
echo '<div class="alert alert-danger">' . $_SESSION['rating_error'] . '</div>';
unset($_SESSION['rating_error']);
}
?>
<?php if (count($orders) > 0): ?>
<table class="table table-bordered">
<thead>
<tr>
<th>Order ID</th>
<th>Order Date</th>
<th>Restaurant</th>
<th>Total Amount</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<?php foreach ($orders as $order): ?>
<tr>
<td><?php echo htmlspecialchars($order['id']); ?></td>
<td><?php echo htmlspecialchars($order['order_date']); ?></td>
<td><?php echo htmlspecialchars($order['restaurant_name']); ?></td>
<td>$<?php echo htmlspecialchars(number_format($order['total_amount'], 2)); ?></td>
<td><?php echo htmlspecialchars($order['status']); ?></td>
<td>
<a href="order_details.php?order_id=<?php echo $order['id']; ?>" class="btn btn-primary">View Details</a>
<?php if ($order['status'] == 'Completed'): ?>
<button type="button" class="btn btn-success" data-bs-toggle="modal" data-bs-target="#rateModal-<?php echo $order['id']; ?>">
Rate Restaurant
</button>
<?php endif; ?>
</td>
</tr>
<hr>
<!-- Rating Modal -->
<div class="modal fade" id="rateModal-<?php echo $order['id']; ?>" tabindex="-1" aria-labelledby="rateModalLabel-<?php echo $order['id']; ?>" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="rateModalLabel-<?php echo $order['id']; ?>">Rate <?php echo htmlspecialchars($order['restaurant_name']); ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form action="rate.php" method="POST">
<input type="hidden" name="order_id" value="<?php echo $order['id']; ?>">
<input type="hidden" name="restaurant_id" value="<?php echo $order['restaurant_id']; ?>">
<div class="mb-3">
<label for="rating-<?php echo $order['id']; ?>" class="form-label">Rating (1-5)</label>
<input type="number" class="form-control" id="rating-<?php echo $order['id']; ?>" name="rating" min="1" max="5" required>
</div>
<div class="mb-3">
<label for="comment-<?php echo $order['id']; ?>" class="form-label">Comment</label>
<textarea class="form-control" id="comment-<?php echo $order['id']; ?>" name="comment" rows="3"></textarea>
</div>
<button type="submit" class="btn btn-primary">Submit Rating</button>
</form>
</div>
</div>
</div>
<?php if (isset($success)): ?>
<div class="alert alert-success"><?php echo $success; ?></div>
<?php endif; ?>
<?php if (isset($error)): ?>
<div class="alert alert-danger"><?php echo $error; ?></div>
<?php endif; ?>
<form method="POST" action="profile.php">
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input type="text" class="form-control" id="name" name="name" value="<?php echo htmlspecialchars($user['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" value="<?php echo htmlspecialchars($user['email']); ?>" required>
</div>
<div class="mb-3">
<label for="address" class="form-label">Address</label>
<textarea class="form-control" id="address" name="address" rows="3"><?php echo htmlspecialchars($user['address']); ?></textarea>
</div>
<button type="submit" name="update_profile" class="btn btn-primary">Update Profile</button>
</form>
<h2 class="mt-5">My Orders</h2>
<hr>
<?php if (count($orders) > 0): ?>
<div class="list-group">
<?php foreach ($orders as $order): ?>
<a href="order_details.php?id=<?php echo $order['id']; ?>" class="list-group-item list-group-item-action flex-column align-items-start">
<div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">Order #<?php echo $order['id']; ?> - <?php echo htmlspecialchars($order['restaurant_name']); ?></h5>
<small><?php echo date("F j, Y, g:i a", strtotime($order['created_at'])); ?></small>
</div>
<?php endforeach; ?>
</tbody>
</table>
<p class="mb-1">Total: $<?php echo number_format($order['total_price'], 2); ?></p>
<small>Status: <?php echo htmlspecialchars($order['status']); ?></small>
</a>
<?php endforeach; ?>
</div>
<?php else: ?>
<p>You have no past orders.</p>
<?php endif; ?>