Password
diff --git a/admin/login_process.php b/admin/login_process.php
index 098c0cba..5801d916 100644
--- a/admin/login_process.php
+++ b/admin/login_process.php
@@ -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;
}
diff --git a/admin/menu.php b/admin/menu.php
new file mode 100644
index 00000000..7e3c56b4
--- /dev/null
+++ b/admin/menu.php
@@ -0,0 +1,64 @@
+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();
+?>
+
+
+
+
diff --git a/cart_actions.php b/cart_actions.php
index 567e5890..7a43fa79 100644
--- a/cart_actions.php
+++ b/cart_actions.php
@@ -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;
-}
\ No newline at end of file
+// --- 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;
diff --git a/db/run_migration.php b/db/run_migration.php
new file mode 100644
index 00000000..65c74013
--- /dev/null
+++ b/db/run_migration.php
@@ -0,0 +1,18 @@
+exec($sql);
+ echo "Migration successful: $migration_file\n";
+} catch (PDOException $e) {
+ die("Migration failed: " . $e->getMessage() . "\n");
+}
\ No newline at end of file
diff --git a/index.php b/index.php
index 352072c3..bc1876a1 100644
--- a/index.php
+++ b/index.php
@@ -32,19 +32,19 @@
prepare($sql);
$stmt->execute($params);
@@ -67,10 +67,10 @@
echo '
';
echo '
' . htmlspecialchars($restaurant['name']) . ' ';
echo '
' . htmlspecialchars($restaurant['cuisine']) . '
';
- if (isset($restaurant['rating']) && $restaurant['rating'] > 0) {
+ if ($restaurant['rating_count'] > 0) {
echo '
';
echo '★ ';
- echo '' . htmlspecialchars(number_format($restaurant['rating'], 1)) . ' ';
+ echo '' . htmlspecialchars(number_format($restaurant['average_rating'], 1)) . ' ';
echo '(' . htmlspecialchars($restaurant['rating_count']) . ' ratings) ';
echo '
';
} else {
@@ -86,4 +86,4 @@
-
+
\ No newline at end of file
diff --git a/menu.php b/menu.php
index b585b63f..441b7183 100644
--- a/menu.php
+++ b/menu.php
@@ -1,53 +1,201 @@
Restaurant ID is missing.
";
+$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 "
Error fetching restaurant data.
";
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();
-
?>
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
Menu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
This restaurant has no menu items yet.
+
+
+
+
+
+
+
+
+
Reviews & Ratings
+
+
+
+
+
+
+
+
+
+
Thank you for your review!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
This restaurant has no reviews yet. Be the first!
+
+
+
+
+
+
Restaurant not found.
+
-
+
\ No newline at end of file
diff --git a/migrations/20251015_add_address_to_users.sql b/migrations/20251015_add_address_to_users.sql
new file mode 100644
index 00000000..4b772dc7
--- /dev/null
+++ b/migrations/20251015_add_address_to_users.sql
@@ -0,0 +1 @@
+ALTER TABLE "users" ADD "address" TEXT;
\ No newline at end of file
diff --git a/migrations/20251015_add_is_admin_to_users.sql b/migrations/20251015_add_is_admin_to_users.sql
new file mode 100644
index 00000000..3c680348
--- /dev/null
+++ b/migrations/20251015_add_is_admin_to_users.sql
@@ -0,0 +1 @@
+ALTER TABLE users ADD COLUMN is_admin BOOLEAN DEFAULT FALSE;
diff --git a/migrations/20251015_add_password_to_users.sql b/migrations/20251015_add_password_to_users.sql
new file mode 100644
index 00000000..1b24a1a7
--- /dev/null
+++ b/migrations/20251015_add_password_to_users.sql
@@ -0,0 +1 @@
+ALTER TABLE users ADD COLUMN password VARCHAR(255);
diff --git a/migrations/20251015_create_admin_user.sql b/migrations/20251015_create_admin_user.sql
new file mode 100644
index 00000000..1677d050
--- /dev/null
+++ b/migrations/20251015_create_admin_user.sql
@@ -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;
\ No newline at end of file
diff --git a/migrations/20251015_create_admin_user_with_password.sql b/migrations/20251015_create_admin_user_with_password.sql
new file mode 100644
index 00000000..f6ab28fb
--- /dev/null
+++ b/migrations/20251015_create_admin_user_with_password.sql
@@ -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;
diff --git a/migrations/20251015_create_ratings_table.sql b/migrations/20251015_create_ratings_table.sql
index 54268171..7a795ef0 100644
--- a/migrations/20251015_create_ratings_table.sql
+++ b/migrations/20251015_create_ratings_table.sql
@@ -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
);
diff --git a/order_details.php b/order_details.php
new file mode 100644
index 00000000..148a1992
--- /dev/null
+++ b/order_details.php
@@ -0,0 +1,65 @@
+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 "
Order not found or you do not have permission to view it.
";
+ 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);
+?>
+
+
+
Order Details #
+
+
+
+
Summary
+
Restaurant:
+
Order Date:
+
Total: $
+
Status:
+
+
+
+
+
Back to My Orders
+
+
+
diff --git a/profile.php b/profile.php
index b615f8a8..6eb8c7b4 100644
--- a/profile.php
+++ b/profile.php
@@ -1,6 +1,7 @@
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);
?>
My Profile
- My Orders
- ' . $_SESSION['rating_success'] . '';
- unset($_SESSION['rating_success']);
- }
- if (isset($_SESSION['rating_error'])) {
- echo '
' . $_SESSION['rating_error'] . '
';
- unset($_SESSION['rating_error']);
- }
- ?>
- 0): ?>
-
-
-
- Order ID
- Order Date
- Restaurant
- Total Amount
- Status
- Action
-
-
-
-
-
-
-
-
- $
-
-
- View Details
-
-
- Rate Restaurant
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
- Rating (1-5)
-
-
-
- Comment
-
-
- Submit Rating
-
-
-
-
+
+
+
+
+
+
+
+
+
+ Name
+
+
+
+ Email address
+
+
+
+ Address
+
+
+ Update Profile
+
+
+
My Orders
+
+ 0): ?>
+
-
+
Total: $
+
Status:
+
+
+
You have no past orders.