This commit is contained in:
Flatlogic Bot 2025-10-15 04:02:50 +00:00
parent ec17506c33
commit 727b6fcf29
34 changed files with 1414 additions and 159 deletions

View File

@ -10,20 +10,20 @@ if (!isset($_SESSION['admin_logged_in']) || $_SESSION['admin_logged_in'] !== tru
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Admin Panel</title>
<title>Admin Dashboard</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="index.php">Admin Panel</a>
<a class="navbar-brand" href="index.php">Admin Dashboard</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">
<li class="nav-item">
<a class="nav-link" href="index.php">Restaurants</a>
<a class="nav-link" href="index.php">Dashboard</a>
</li>
<li class="nav-item">
<a class="nav-link" href="orders.php">Orders</a>

View File

@ -9,12 +9,86 @@ if (!isset($_SESSION['admin_logged_in']) || $_SESSION['admin_logged_in'] !== tru
}
$pdo = db();
$stmt = $pdo->query("SELECT id, name, cuisine FROM restaurants ORDER BY name");
$restaurants = $stmt->fetchAll();
// Analytics Queries
// Total Revenue
$stmt_revenue = $pdo->prepare("SELECT SUM(total_price) as total_revenue FROM orders WHERE status = ?");
$stmt_revenue->execute(['completed']);
$total_revenue = $stmt_revenue->fetchColumn();
// Total Orders
$total_orders = $pdo->query("SELECT COUNT(*) FROM orders")->fetchColumn();
// Total Customers
$total_customers = $pdo->query("SELECT COUNT(*) FROM users WHERE role = 'customer'")->fetchColumn();
// Most Popular Restaurants
$stmt_popular = $pdo->query("
SELECT r.name, COUNT(o.id) as order_count
FROM restaurants r
JOIN orders o ON r.id = o.restaurant_id
GROUP BY r.id
ORDER BY order_count DESC
LIMIT 5
");
$popular_restaurants = $stmt_popular->fetchAll();
// Fetch all restaurants for the management table
$stmt_restaurants = $pdo->query("SELECT id, name, cuisine FROM restaurants ORDER BY name");
$restaurants = $stmt_restaurants->fetchAll();
?>
<div class="container mt-4">
<h2>Restaurant Management</h2>
<h2>Admin Dashboard</h2>
<!-- Analytics Cards -->
<div class="row mb-4">
<div class="col-md-4">
<div class="card text-white bg-primary mb-3">
<div class="card-header">Total Revenue</div>
<div class="card-body">
<h5 class="card-title">$<?php echo number_format($total_revenue, 2); ?></h5>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card text-white bg-info mb-3">
<div class="card-header">Total Orders</div>
<div class="card-body">
<h5 class="card-title"><?php echo $total_orders; ?></h5>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card text-white bg-success mb-3">
<div class="card-header">Total Customers</div>
<div class="card-body">
<h5 class="card-title"><?php echo $total_customers; ?></h5>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header">
Most Popular Restaurants
</div>
<ul class="list-group list-group-flush">
<?php foreach ($popular_restaurants as $restaurant): ?>
<li class="list-group-item d-flex justify-content-between align-items-center">
<?php echo htmlspecialchars($restaurant['name']); ?>
<span class="badge bg-primary rounded-pill"><?php echo $restaurant['order_count']; ?> orders</span>
</li>
<?php endforeach; ?>
</ul>
</div>
</div>
</div>
<h2 class="mt-5">Restaurant Management</h2>
<p><a href="add_restaurant.php" class="btn btn-success">Add New Restaurant</a></p>
<table class="table table-striped">
@ -41,4 +115,4 @@ $restaurants = $stmt->fetchAll();
</table>
</div>
<?php include 'footer.php'; ?>
<?php include 'footer.php'; ?>

29
api/get_order_status.php Normal file
View File

@ -0,0 +1,29 @@
<?php
header('Content-Type: application/json');
session_start();
require_once '../db/config.php';
if (!isset($_SESSION['user_id'])) {
echo json_encode(['error' => 'Unauthorized']);
exit();
}
if (!isset($_GET['order_id'])) {
echo json_encode(['error' => 'No order ID specified']);
exit();
}
$order_id = $_GET['order_id'];
$user_id = $_SESSION['user_id'];
// Fetch order status, ensuring the user owns the order
$stmt = $db->prepare("SELECT status FROM orders WHERE id = ? AND user_id = ?");
$stmt->execute([$order_id, $user_id]);
$order = $stmt->fetch(PDO::FETCH_ASSOC);
if ($order) {
echo json_encode(['status' => $order['status']]);
} else {
echo json_encode(['error' => 'Order not found or permission denied']);
}
?>

View File

@ -2,26 +2,28 @@
session_start();
require_once 'db/config.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['coupon_code'])) {
if (isset($_POST['coupon_code']) && !empty($_POST['coupon_code'])) {
$coupon_code = trim($_POST['coupon_code']);
$pdo = db();
$stmt = $pdo->prepare("SELECT * FROM coupons WHERE code = :code AND is_active = TRUE");
$stmt->execute(['code' => $coupon_code]);
$coupon = $stmt->fetch();
$pdo = db();
$stmt = $pdo->prepare("SELECT * FROM coupons WHERE code = ? AND is_active = 1");
$stmt->execute([$coupon_code]);
$coupon = $stmt->fetch(PDO::FETCH_ASSOC);
if ($coupon) {
$_SESSION['coupon'] = [
'id' => $coupon['id'],
'code' => $coupon['code'],
'discount_percentage' => $coupon['discount_percentage']
];
$_SESSION['coupon_id'] = $coupon['id'];
$_SESSION['coupon_code'] = $coupon['code'];
$_SESSION['discount_percentage'] = $coupon['discount_percentage'];
unset($_SESSION['coupon_error']);
} else {
$_SESSION['coupon_error'] = "Invalid or expired coupon code.";
unset($_SESSION['coupon']);
unset($_SESSION['coupon_id']);
unset($_SESSION['coupon_code']);
unset($_SESSION['discount_percentage']);
}
} else {
$_SESSION['coupon_error'] = "Please enter a coupon code.";
}
header('Location: cart.php');
exit;
header("Location: cart.php");
exit();

View File

@ -807,3 +807,75 @@ footer {
.search-button:hover {
background-color: #ff4f4f;
}
/* Filter Bar */
.filter-bar {
margin-top: 1.5rem;
display: flex;
justify-content: center;
}
.filter-dropdown {
position: relative;
display: inline-block;
}
.filter-button {
background-color: rgba(255, 255, 255, 0.2);
color: var(--white);
padding: 12px 24px;
font-size: 1rem;
font-weight: 600;
border: 1px solid rgba(255, 255, 255, 0.5);
border-radius: 50px;
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
transition: all 0.3s ease;
}
.filter-button:hover {
background-color: rgba(255, 255, 255, 0.3);
border-color: var(--white);
}
.filter-button-icon {
transition: transform 0.3s ease;
}
.filter-options {
display: none;
position: absolute;
background-color: var(--white);
min-width: 200px;
box-shadow: var(--shadow-soft);
border-radius: var(--border-radius);
z-index: 1;
margin-top: 8px;
padding: 8px 0;
max-height: 300px;
overflow-y: auto;
}
.filter-option {
color: var(--text-color);
padding: 12px 20px;
text-decoration: none;
display: block;
font-weight: 500;
transition: background-color 0.2s ease;
}
.filter-option:hover, .filter-option.active {
background-color: var(--light-gray);
color: var(--coral);
}
.filter-dropdown:hover .filter-options {
display: block;
}
.filter-dropdown:hover .filter-button-icon {
transform: rotate(180deg);
}

View File

@ -95,4 +95,22 @@ document.addEventListener('DOMContentLoaded', function() {
});
});
}
// Filter dropdown
const filterDropdown = document.querySelector('.filter-dropdown');
if (filterDropdown) {
const filterButton = filterDropdown.querySelector('.filter-button');
const filterOptions = filterDropdown.querySelector('.filter-options');
filterButton.addEventListener('click', () => {
const isVisible = filterOptions.style.display === 'block';
filterOptions.style.display = isVisible ? 'none' : 'block';
});
window.addEventListener('click', (event) => {
if (!filterDropdown.contains(event.target)) {
filterOptions.style.display = 'none';
}
});
}
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 KiB

View File

@ -69,21 +69,29 @@ include 'header.php';
</div>
<div class="col-md-6 text-end">
<h4>Subtotal: $<?php echo number_format($totalPrice, 2); ?></h4>
<?php if (isset($_SESSION['coupon'])): ?>
<?php
$discount_percentage = $_SESSION['coupon']['discount_percentage'];
<?php
$discount_amount = 0;
$final_total = $totalPrice;
if (isset($_SESSION['coupon_code']) && isset($_SESSION['discount_percentage'])) {
$discount_percentage = $_SESSION['discount_percentage'];
$discount_amount = ($totalPrice * $discount_percentage) / 100;
$discounted_total = $totalPrice - $discount_amount;
$_SESSION['discount_amount'] = $discount_amount;
$_SESSION['total_price'] = $discounted_total;
?>
<h5 class="text-success">Discount (<?php echo $discount_percentage; ?>%): -$<?php echo number_format($discount_amount, 2); ?></h5>
<h3>Total: $<?php echo number_format($discounted_total, 2); ?></h3>
<a href="remove_coupon.php" class="btn btn-danger btn-sm">Remove Coupon</a>
<?php else: ?>
<?php $_SESSION['total_price'] = $totalPrice; $_SESSION['discount_amount'] = 0; ?>
<h3>Total: $<?php echo number_format($totalPrice, 2); ?></h3>
<?php endif; ?>
$final_total = $totalPrice - $discount_amount;
?>
<h5 class="text-success">Discount (<?php echo htmlspecialchars($_SESSION['coupon_code']); ?> @ <?php echo $discount_percentage; ?>%): -$<?php echo number_format($discount_amount, 2); ?></h5>
<h3>Total: $<?php echo number_format($final_total, 2); ?></h3>
<a href="remove_coupon.php" class="btn btn-danger btn-sm mt-2">Remove Coupon</a>
<?php
} else {
?>
<h3>Total: $<?php echo number_format($final_total, 2); ?></h3>
<?php
}
$_SESSION['total_price'] = $final_total;
$_SESSION['discount_amount'] = $discount_amount;
$_SESSION['subtotal'] = $totalPrice;
?>
<a href="checkout.php" class="btn btn-primary mt-3">Proceed to Checkout</a>
</div>
</div>
@ -95,4 +103,4 @@ include 'header.php';
<?php endif; ?>
</div>
<?php require_once 'footer.php'; ?>
<?php require_once 'footer.php'; ?>

View File

@ -1,69 +1,39 @@
<?php
session_start();
require_once 'db/config.php';
require_once 'vendor/autoload.php';
require_once 'db/config.php';
require_once 'includes/api_keys.php';
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
exit();
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
header("Location: checkout.php");
exit();
}
\Stripe\Stripe::setApiKey($stripeSecretKey);
$user_id = $_SESSION['user_id'];
$pdo = db();
$total_price = $_SESSION['total_price'] ?? 0;
$coupon_id = $_SESSION['coupon_id'] ?? null;
$user_id = $_SESSION['user_id'] ?? null;
// Fetch cart items
$stmt = $pdo->prepare("SELECT mi.name, mi.price, c.quantity FROM cart c JOIN menu_items mi ON c.menu_item_id = mi.id WHERE c.user_id = ?");
$stmt->execute([$user_id]);
$cart_items = $stmt->fetchAll();
if (empty($cart_items)) {
if ($total_price <= 0) {
header("Location: cart.php");
exit();
}
$line_items = [];
foreach ($cart_items as $item) {
$line_items[] = [
$checkout_session = \Stripe\Checkout\Session::create([
'payment_method_types' => ['card'],
'line_items' => [[
'price_data' => [
'currency' => 'usd',
'product_data' => [
'name' => $item['name'],
'name' => 'Total Order Amount',
],
'unit_amount' => $item['price'] * 100, // Price in cents
'unit_amount' => $total_price * 100, // Amount in cents
],
'quantity' => $item['quantity'],
];
}
// Add delivery fee
$delivery_fee = 5.00;
$line_items[] = [
'price_data' => [
'currency' => 'usd',
'product_data' => [
'name' => 'Delivery Fee',
],
'unit_amount' => $delivery_fee * 100,
],
'quantity' => 1,
];
$checkout_session = \Stripe\Checkout\Session::create([
'payment_method_types' => ['card'],
'line_items' => $line_items,
'quantity' => 1,
]],
'mode' => 'payment',
'success_url' => 'http://' . $_SERVER['HTTP_HOST'] . '/payment-success.php?session_id={CHECKOUT_SESSION_ID}',
'cancel_url' => 'http://' . $_SERVER['HTTP_HOST'] . '/payment-cancel.php',
'success_url' => 'http://localhost:8080/payment-success.php?session_id={CHECKOUT_SESSION_ID}',
'cancel_url' => 'http://localhost:8080/payment-cancel.php',
'metadata' => [
'user_id' => $user_id,
'coupon_id' => $coupon_id
]
]);
header("HTTP/1.1 303 See Other");
header("Location: " . $checkout_session->url);
header("Location: " . $checkout_session->url);

View File

@ -19,12 +19,7 @@ session_start();
<div class="address-container">
<span id="address-display">Enter delivery address</span>
</div>
<div class="search-container">
<form action="search.php" method="get">
<input type="text" name="query" placeholder="Search restaurants..." required>
<button type="submit">Search</button>
</form>
</div>
<div class="user-actions">
<?php
require_once 'db/config.php';
@ -53,6 +48,7 @@ session_start();
<?php if (isset($_SESSION['user_id'])): ?>
<span>Welcome, <?php echo htmlspecialchars($_SESSION['user_name']); ?></span>
<a href="profile.php">My Profile</a>
<a href="order_history.php">Order History</a>
<a href="logout.php">Logout</a>
<?php else: ?>
<a href="login.php">Login</a>

View File

@ -4,22 +4,28 @@
<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 restaurants..." value="<?= isset($_GET['search']) ? htmlspecialchars($_GET['search']) : '' ?>">
<form action="search.php" method="get" class="search-form">
<input type="text" name="query" class="search-bar" placeholder="Search for restaurants, cuisines..." required>
<button type="submit" class="search-button">Search</button>
</form>
<div class="cuisine-filters">
<a href="index.php<?= isset($_GET['search']) ? '?search=' . urlencode($_GET['search']) : '' ?>" class="cuisine-filter-link <?= !isset($_GET['cuisine']) || $_GET['cuisine'] == '' ? 'active' : '' ?>">All Cuisines</a>
<?php
require_once 'db/config.php';
$pdo = db();
$cuisine_stmt = $pdo->query("SELECT DISTINCT cuisine FROM restaurants ORDER BY cuisine");
$cuisines = $cuisine_stmt->fetchAll(PDO::FETCH_COLUMN);
$search_param = isset($_GET['search']) ? '&search=' . urlencode($_GET['search']) : '';
foreach ($cuisines as $cuisine):
?>
<a href="index.php?cuisine=<?= htmlspecialchars($cuisine) ?><?= $search_param ?>" class="cuisine-filter-link <?= (isset($_GET['cuisine']) && $_GET['cuisine'] == $cuisine) ? 'active' : '' ?>"><?= htmlspecialchars($cuisine) ?></a>
<?php endforeach; ?>
<div class="filter-bar">
<div class="filter-dropdown">
<button class="filter-button">
<span class="filter-button-text"><?= isset($_GET['cuisine']) && $_GET['cuisine'] != '' ? htmlspecialchars($_GET['cuisine']) : 'All Cuisines' ?></span>
<span class="filter-button-icon"></span>
</button>
<div class="filter-options">
<a href="index.php<?= isset($_GET['search']) ? '?search=' . urlencode($_GET['search']) : '' ?>" class="filter-option <?= !isset($_GET['cuisine']) || $_GET['cuisine'] == '' ? 'active' : '' ?>">All Cuisines</a>
<?php
$cuisine_stmt = $pdo->query("SELECT DISTINCT cuisine FROM restaurants ORDER BY cuisine");
$cuisines = $cuisine_stmt->fetchAll(PDO::FETCH_COLUMN);
$search_param = isset($_GET['search']) ? '&search=' . urlencode($_GET['search']) : '';
foreach ($cuisines as $cuisine):
?>
<a href="index.php?cuisine=<?= htmlspecialchars($cuisine) ?><?= $search_param ?>" class="filter-option <?= (isset($_GET['cuisine']) && $_GET['cuisine'] == $cuisine) ? 'active' : '' ?>"><?= htmlspecialchars($cuisine) ?></a>
<?php endforeach; ?>
</div>
</div>
</div>
</div>
</section>

View File

@ -0,0 +1 @@
ALTER TABLE users ADD COLUMN role VARCHAR(255) NOT NULL DEFAULT 'customer';

View File

@ -0,0 +1,2 @@
ALTER TABLE restaurants ADD COLUMN user_id INT NULL;
ALTER TABLE restaurants ADD CONSTRAINT fk_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL ON UPDATE CASCADE;

56
order_history.php Normal file
View File

@ -0,0 +1,56 @@
<?php
session_start();
require_once 'db/config.php';
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
exit();
}
include 'header.php';
$user_id = $_SESSION['user_id'];
$db = db();
$stmt = $db->prepare("SELECT * FROM orders WHERE user_id = ? ORDER BY order_date DESC");
$stmt->execute([$user_id]);
$orders = $stmt->fetchAll();
?>
<div class="container mt-5">
<h2>My Order History</h2>
<hr>
<?php if (empty($orders)): ?>
<div class="alert alert-info">You have not placed any orders yet.</div>
<?php else: ?>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Order ID</th>
<th>Date</th>
<th>Total</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(date('F j, Y, g:i a', strtotime($order['order_date']))); ?></td>
<td>$<?php echo htmlspecialchars(number_format($order['total_price'], 2)); ?></td>
<td><?php echo htmlspecialchars(ucfirst($order['status'])); ?></td>
<td>
<a href="order_details.php?id=<?php echo $order['id']; ?>" class="btn btn-primary btn-sm">View Details</a>
<a href="order_status.php?order_id=<?php echo $order['id']; ?>" class="btn btn-info btn-sm">Track Order</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>
<?php include 'footer.php'; ?>

123
order_status.php Normal file
View File

@ -0,0 +1,123 @@
<?php
session_start();
require_once 'db/config.php';
include 'header.php';
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
exit();
}
if (!isset($_GET['order_id'])) {
echo "<div class='container mt-5'><p>No order specified.</p></div>";
include 'footer.php';
exit();
}
$order_id = $_GET['order_id'];
$user_id = $_SESSION['user_id'];
// Fetch order details to ensure the user owns this order
$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 Status for #<?php echo $order['id']; ?></h2>
<hr>
<div class="card mb-4">
<div class="card-body">
<h5 class="card-title">Live Status</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>
<div id="order-status-container">
<p><strong>Status:</strong> <span class="badge bg-primary fs-6" id="order-status"><?php echo htmlspecialchars($order['status']); ?></span></p>
</div>
<div class="progress" style="height: 25px;">
<div id="progress-bar" class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" style="width: 0%;" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
</div>
<div class="card">
<div class="card-body">
<h5 class="card-title">Order Summary</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; ?>
<li class="list-group-item d-flex justify-content-between align-items-center">
<strong>Total</strong>
<strong>$<?php echo number_format($order['total_price'], 2); ?></strong>
</li>
</ul>
</div>
</div>
<a href="order_history.php" class="btn btn-secondary mt-3">Back to Order History</a>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const orderId = <?php echo $order_id; ?>;
const statusElement = document.getElementById('order-status');
const progressBar = document.getElementById('progress-bar');
const statusToProgress = {
'Pending': 10,
'In Progress': 40,
'Out for Delivery': 75,
'Delivered': 100,
'Cancelled': 0
};
function updateProgress(status) {
const progress = statusToProgress[status] || 0;
progressBar.style.width = progress + '%';
progressBar.textContent = status;
if (status === 'Delivered') {
progressBar.classList.remove('progress-bar-animated', 'bg-primary');
progressBar.classList.add('bg-success');
} else if (status === 'Cancelled') {
progressBar.classList.remove('progress-bar-animated', 'bg-primary');
progressBar.classList.add('bg-danger');
} else {
progressBar.classList.remove('bg-success', 'bg-danger');
progressBar.classList.add('bg-primary', 'progress-bar-animated');
}
}
function fetchStatus() {
fetch(`api/get_order_status.php?order_id=${orderId}`)
.then(response => response.json())
.then(data => {
if (data.status && data.status !== statusElement.textContent) {
statusElement.textContent = data.status;
updateProgress(data.status);
}
})
.catch(error => console.error('Error fetching status:', error));
}
updateProgress(statusElement.textContent);
setInterval(fetchStatus, 10000); // Poll every 10 seconds
});
</script>
<?php include 'footer.php'; ?>

View File

@ -4,27 +4,30 @@ require_once 'db/config.php';
require_once 'vendor/autoload.php';
require_once 'includes/api_keys.php';
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
exit();
}
if (!isset($_GET['session_id'])) {
header("Location: index.php");
exit();
}
$stripe_session_id = $_GET['session_id'];
$user_id = $_SESSION['user_id'];
$pdo = db();
\Stripe\Stripe::setApiKey($stripeSecretKey);
try {
$checkout_session = \Stripe\Checkout\Session::retrieve($stripe_session_id);
$metadata = $checkout_session->metadata;
$user_id = $metadata->user_id;
$coupon_id = $metadata->coupon_id;
if ($checkout_session->payment_status == 'paid') {
// Fetch cart items and delivery details
// Fetch user's address
$stmt = $pdo->prepare("SELECT address FROM users WHERE id = ?");
$stmt->execute([$user_id]);
$user = $stmt->fetch();
$delivery_address = $user ? $user['address'] : 'N/A';
// Fetch cart items
$stmt = $pdo->prepare("SELECT c.*, mi.price, mi.restaurant_id FROM cart c JOIN menu_items mi ON c.menu_item_id = mi.id WHERE c.user_id = ?");
$stmt->execute([$user_id]);
$cart_items = $stmt->fetchAll();
@ -36,16 +39,11 @@ try {
$total_price = $_SESSION['total_price'] ?? 0;
$discount_amount = $_SESSION['discount_amount'] ?? 0;
$coupon_id = $_SESSION['coupon']['id'] ?? null;
// Get delivery details stored in cart
$delivery_name = $cart_items[0]['delivery_name'];
$delivery_address = $cart_items[0]['delivery_address'];
$delivery_phone = $cart_items[0]['delivery_phone'];
$restaurant_id = $cart_items[0]['restaurant_id']; // Assuming order from one restaurant
// Create order
$stmt = $pdo->prepare("INSERT INTO orders (user_id, restaurant_id, total_price, status, stripe_session_id, delivery_name, delivery_address, delivery_phone, coupon_id, discount_amount) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([$user_id, $restaurant_id, $total_price, 'paid', $stripe_session_id, $delivery_name, $delivery_address, $delivery_phone, $coupon_id, $discount_amount]);
$stmt = $pdo->prepare("INSERT INTO orders (user_id, restaurant_id, total_price, status, stripe_session_id, delivery_address, coupon_id, discount_amount) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([$user_id, $restaurant_id, $total_price, 'paid', $stripe_session_id, $delivery_address, $coupon_id, $discount_amount]);
$order_id = $pdo->lastInsertId();
// Insert order items
@ -58,6 +56,15 @@ try {
$stmt = $pdo->prepare("DELETE FROM cart WHERE user_id = ?");
$stmt->execute([$user_id]);
// Clear coupon session variables
unset($_SESSION['coupon_id']);
unset($_SESSION['coupon_code']);
unset($_SESSION['discount_percentage']);
unset($_SESSION['total_price']);
unset($_SESSION['discount_amount']);
unset($_SESSION['subtotal']);
$_SESSION['order_id'] = $order_id;
header("Location: order_confirmation.php");
exit();
@ -71,4 +78,4 @@ try {
error_log($e->getMessage());
header("Location: payment-cancel.php");
exit();
}
}

View File

@ -56,6 +56,12 @@ $details = json_decode($result);
if (isset($details->status) && $details->status == 'COMPLETED') {
$pdo = db();
// Fetch user's address
$stmt = $pdo->prepare("SELECT address FROM users WHERE id = ?");
$stmt->execute([$user_id]);
$user = $stmt->fetch();
$delivery_address = $user ? $user['address'] : 'N/A';
// Fetch cart items
$stmt = $pdo->prepare("SELECT c.*, mi.price, mi.restaurant_id FROM cart c JOIN menu_items mi ON c.menu_item_id = mi.id WHERE c.user_id = ?");
$stmt->execute([$user_id]);
@ -68,19 +74,12 @@ if (isset($details->status) && $details->status == 'COMPLETED') {
$total_price = $_SESSION['total_price'] ?? 0;
$discount_amount = $_SESSION['discount_amount'] ?? 0;
$coupon_id = $_SESSION['coupon']['id'] ?? null;
$restaurant_id = null;
foreach ($cart_items as $item) {
$restaurant_id = $item['restaurant_id'];
}
$delivery_name = $_POST['name'];
$delivery_address = $_POST['address'];
$delivery_phone = $_POST['phone'];
$coupon_id = $_SESSION['coupon_id'] ?? null;
$restaurant_id = $cart_items[0]['restaurant_id']; // Assuming order from one restaurant
// Create order
$stmt = $pdo->prepare("INSERT INTO orders (user_id, restaurant_id, total_price, status, stripe_session_id, delivery_name, delivery_address, delivery_phone, coupon_id, discount_amount) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([$user_id, $restaurant_id, $total_price, 'paid', $orderID, $delivery_name, $delivery_address, $delivery_phone, $coupon_id, $discount_amount]);
$stmt = $pdo->prepare("INSERT INTO orders (user_id, restaurant_id, total_price, status, stripe_session_id, delivery_address, coupon_id, discount_amount) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([$user_id, $restaurant_id, $total_price, 'paid', $orderID, $delivery_address, $coupon_id, $discount_amount]);
$order_id = $pdo->lastInsertId();
// Insert order items
@ -93,10 +92,18 @@ if (isset($details->status) && $details->status == 'COMPLETED') {
$stmt = $pdo->prepare("DELETE FROM cart WHERE user_id = ?");
$stmt->execute([$user_id]);
// Clear coupon session variables
unset($_SESSION['coupon_id']);
unset($_SESSION['coupon_code']);
unset($_SESSION['discount_percentage']);
unset($_SESSION['total_price']);
unset($_SESSION['discount_amount']);
unset($_SESSION['subtotal']);
$_SESSION['order_id'] = $order_id;
echo json_encode(['success' => true]);
echo json_encode(['success' => true, 'order_id' => $order_id]);
} else {
error_log('PayPal Capture Failed: ' . print_r($details, true));
echo json_encode(['error' => 'Payment failed. Please try again.']);
}
}

View File

@ -31,10 +31,7 @@ $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">
@ -64,24 +61,9 @@ $orders = $p_orders->fetchAll(PDO::FETCH_ASSOC);
<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>
<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; ?>
<div class="mt-5">
<a href="order_history.php" class="btn btn-secondary">View Order History</a>
</div>
</div>
<?php include 'footer.php'; ?>

View File

@ -1,9 +1,10 @@
<?php
session_start();
unset($_SESSION['coupon']);
unset($_SESSION['coupon_id']);
unset($_SESSION['coupon_code']);
unset($_SESSION['discount_percentage']);
unset($_SESSION['coupon_error']);
unset($_SESSION['discount_amount']);
header('Location: cart.php');
exit;
header("Location: cart.php");
exit();

View File

@ -0,0 +1,66 @@
<?php
include 'header.php';
require_once '../db/config.php';
// Check if the user is logged in as a restaurant owner
if (!isset($_SESSION['user_id']) || $_SESSION['role'] !== 'restaurant_owner') {
header('Location: ../restaurant_login.php');
exit;
}
$pdo = db();
// Get the restaurant ID associated with the logged-in user
$stmt = $pdo->prepare("SELECT id FROM restaurants WHERE user_id = ?");
$stmt->execute([$_SESSION['user_id']]);
$restaurant = $stmt->fetch();
if (!$restaurant) {
// If for some reason the user is a restaurant owner but has no restaurant, redirect them
header('Location: ../index.php');
exit;
}
$restaurant_id = $restaurant['id'];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = $_POST['name'] ?? '';
$description = $_POST['description'] ?? '';
$price = $_POST['price'] ?? '';
if ($name && $price) {
$stmt = $pdo->prepare("INSERT INTO menu_items (restaurant_id, name, description, price) VALUES (?, ?, ?, ?)");
$stmt->execute([$restaurant_id, $name, $description, $price]);
header('Location: menu.php');
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">
<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" class="btn btn-secondary">Cancel</a>
</form>
</div>
<?php include 'footer.php'; ?>

View File

@ -0,0 +1,32 @@
<?php
session_start();
require_once '../db/config.php';
// Check if the user is logged in as a restaurant owner
if (!isset($_SESSION['user_id']) || $_SESSION['role'] !== 'restaurant_owner') {
header('Location: ../restaurant_login.php');
exit;
}
$menu_item_id = $_GET['id'] ?? null;
if ($menu_item_id) {
$pdo = db();
// Get the restaurant ID associated with the logged-in user
$stmt = $pdo->prepare("SELECT id FROM restaurants WHERE user_id = ?");
$stmt->execute([$_SESSION['user_id']]);
$restaurant = $stmt->fetch();
if ($restaurant) {
$restaurant_id = $restaurant['id'];
// Delete the menu item only if it belongs to the owner's restaurant
$stmt = $pdo->prepare("DELETE FROM menu_items WHERE id = ? AND restaurant_id = ?");
$stmt->execute([$menu_item_id, $restaurant_id]);
}
}
header('Location: menu.php');
exit;
?>

View File

@ -0,0 +1,82 @@
<?php
include 'header.php';
require_once '../db/config.php';
// Check if the user is logged in as a restaurant owner
if (!isset($_SESSION['user_id']) || $_SESSION['role'] !== 'restaurant_owner') {
header('Location: ../restaurant_login.php');
exit;
}
$menu_item_id = $_GET['id'] ?? null;
if (!$menu_item_id) {
header('Location: menu.php');
exit;
}
$pdo = db();
// Get the restaurant ID associated with the logged-in user
$stmt = $pdo->prepare("SELECT id FROM restaurants WHERE user_id = ?");
$stmt->execute([$_SESSION['user_id']]);
$restaurant = $stmt->fetch();
if (!$restaurant) {
header('Location: ../index.php');
exit;
}
$restaurant_id = $restaurant['id'];
// Get the menu item and verify it belongs to the correct restaurant
$stmt = $pdo->prepare("SELECT * FROM menu_items WHERE id = ? AND restaurant_id = ?");
$stmt->execute([$menu_item_id, $restaurant_id]);
$item = $stmt->fetch();
if (!$item) {
// If the item doesn't exist or doesn't belong to this owner, redirect
header('Location: menu.php');
exit;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = $_POST['name'] ?? '';
$description = $_POST['description'] ?? '';
$price = $_POST['price'] ?? '';
if ($name && $price) {
$stmt = $pdo->prepare("UPDATE menu_items SET name = ?, description = ?, price = ? WHERE id = ? AND restaurant_id = ?");
$stmt->execute([$name, $description, $price, $menu_item_id, $restaurant_id]);
header('Location: menu.php');
exit;
} else {
$error = "Name and price are required.";
}
}
?>
<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">
<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" class="btn btn-secondary">Cancel</a>
</form>
</div>
<?php include 'footer.php'; ?>

View File

@ -0,0 +1,88 @@
<?php
include 'header.php';
require_once '../db/config.php';
// Ensure the user is a logged-in restaurant owner
if (!isset($_SESSION['user_id']) || $_SESSION['role'] !== 'restaurant_owner') {
header('Location: ../login.php');
exit;
}
$owner_id = $_SESSION['user_id'];
$pdo = db();
// Find the restaurant ID managed by the owner
$stmt = $pdo->prepare("SELECT id FROM restaurants WHERE user_id = ?");
$stmt->execute([$owner_id]);
$restaurant = $stmt->fetch();
if (!$restaurant) {
echo "<div class='alert alert-danger'>You are not associated with any restaurant.</div>";
include 'footer.php';
exit;
}
$restaurant_id = $restaurant['id'];
// Handle form submission
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = $_POST['name'] ?? '';
$cuisine = $_POST['cuisine'] ?? '';
$address = $_POST['address'] ?? '';
$phone_number = $_POST['phone_number'] ?? '';
$image_url = $_POST['image_url'] ?? '';
if ($name && $cuisine && $address) {
$update_stmt = $pdo->prepare("UPDATE restaurants SET name = ?, cuisine = ?, address = ?, phone_number = ?, image_url = ? WHERE id = ? AND user_id = ?");
$update_stmt->execute([$name, $cuisine, $address, $phone_number, $image_url, $restaurant_id, $owner_id]);
// Redirect to the dashboard with a success message
$_SESSION['success_message'] = "Your restaurant details have been updated successfully!";
header('Location: index.php');
exit;
} else {
$error = "Name, Cuisine, and Address are required fields.";
}
}
// Fetch current restaurant details
$stmt = $pdo->prepare("SELECT * FROM restaurants WHERE id = ?");
$stmt->execute([$restaurant_id]);
$restaurant_details = $stmt->fetch();
?>
<div class="container mt-4">
<h2>Edit Your Restaurant Details</h2>
<?php if (isset($error)): ?>
<div class="alert alert-danger"><?php echo $error; ?></div>
<?php endif; ?>
<form action="edit_restaurant.php" method="POST">
<div class="mb-3">
<label for="name" class="form-label">Restaurant Name</label>
<input type="text" class="form-control" id="name" name="name" value="<?php echo htmlspecialchars($restaurant_details['name']); ?>" required>
</div>
<div class="mb-3">
<label for="cuisine" class="form-label">Cuisine Type</label>
<input type="text" class="form-control" id="cuisine" name="cuisine" value="<?php echo htmlspecialchars($restaurant_details['cuisine']); ?>" required>
</div>
<div class="mb-3">
<label for="address" class="form-label">Address</label>
<input type="text" class="form-control" id="address" name="address" value="<?php echo htmlspecialchars($restaurant_details['address']); ?>" required>
</div>
<div class="mb-3">
<label for="phone_number" class="form-label">Phone Number</label>
<input type="text" class="form-control" id="phone_number" name="phone_number" value="<?php echo htmlspecialchars($restaurant_details['phone_number']); ?>">
</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_details['image_url']); ?>">
<small class="form-text text-muted">A URL to a publicly accessible image of your restaurant.</small>
</div>
<button type="submit" class="btn btn-primary">Save Changes</button>
<a href="index.php" class="btn btn-secondary">Cancel</a>
</form>
</div>
<?php include 'footer.php'; ?>

4
restaurant/footer.php Normal file
View File

@ -0,0 +1,4 @@
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

43
restaurant/header.php Normal file
View File

@ -0,0 +1,43 @@
<?php
session_start();
if (!isset($_SESSION['user_role']) || $_SESSION['user_role'] !== 'restaurant_owner') {
header('Location: ../restaurant_login.php');
exit;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Restaurant Dashboard</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="index.php">Restaurant Dashboard</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">
<li class="nav-item">
<a class="nav-link" href="index.php">Dashboard</a>
</li>
<li class="nav-item">
<a class="nav-link" href="menu.php">Menu</a>
</li>
<li class="nav-item">
<a class="nav-link" href="orders.php">Orders</a>
</li>
</ul>
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link" href="../logout.php">Logout</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container mt-4">

13
restaurant/index.php Normal file
View File

@ -0,0 +1,13 @@
<?php include 'header.php'; ?>
<h1>Welcome, <?php echo htmlspecialchars($_SESSION['user_name']); ?>!</h1>
<p>This is your restaurant dashboard. From here you can manage your restaurant's menu, view orders, and update your restaurant's information.</p>
<div class="list-group">
<a href="menu.php" class="list-group-item list-group-item-action">Manage Menu</a>
<a href="orders.php" class="list-group-item list-group-item-action">View Orders</a>
<a href="edit_restaurant.php" class="list-group-item list-group-item-action">Edit Restaurant Information</a>
</div>
<?php include 'footer.php'; ?>

73
restaurant/menu.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 a restaurant owner
if (!isset($_SESSION['user_id']) || $_SESSION['role'] !== 'restaurant_owner') {
header('Location: ../restaurant_login.php');
exit;
}
$pdo = db();
// Get the restaurant ID associated with the logged-in user
$stmt = $pdo->prepare("SELECT id FROM restaurants WHERE user_id = ?");
$stmt->execute([$_SESSION['user_id']]);
$restaurant = $stmt->fetch();
if (!$restaurant) {
// If for some reason the user is a restaurant owner but has no restaurant, redirect them
header('Location: ../index.php');
exit;
}
$restaurant_id = $restaurant['id'];
// Get restaurant details
$stmt = $pdo->prepare("SELECT name FROM restaurants WHERE id = ?");
$stmt->execute([$restaurant_id]);
$restaurant_details = $stmt->fetch();
// 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_details['name']); ?></h2>
<p><a href="add_menu_item.php" 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 if (empty($menu_items)): ?>
<tr>
<td colspan="4">No menu items found.</td>
</tr>
<?php else: ?>
<?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']; ?>" class="btn btn-danger btn-sm" onclick="return confirm('Are you sure you want to delete this item?');">Delete</a>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
<a href="index.php" class="btn btn-secondary">Back to Dashboard</a>
</div>
<?php include 'footer.php'; ?>

View File

@ -0,0 +1,124 @@
<?php
include 'header.php';
require_once '../db/config.php';
// Ensure the user is a logged-in restaurant owner
if (!isset($_SESSION['user_id']) || $_SESSION['role'] !== 'restaurant_owner') {
header('Location: ../login.php');
exit;
}
if (!isset($_GET['order_id'])) {
echo "<div class='alert alert-danger'>No order ID specified.</div>";
include 'footer.php';
exit;
}
$owner_id = $_SESSION['user_id'];
$order_id = $_GET['order_id'];
$pdo = db();
// Get the owner's restaurant ID
$stmt = $pdo->prepare("SELECT id FROM restaurants WHERE user_id = ?");
$stmt->execute([$owner_id]);
$restaurant = $stmt->fetch();
if (!$restaurant) {
echo "<div class='alert alert-danger'>You are not associated with any restaurant.</div>";
include 'footer.php';
exit;
}
$restaurant_id = $restaurant['id'];
// Security Check: Verify the order belongs to the restaurant owner
$check_stmt = $pdo->prepare("
SELECT o.id
FROM orders o
JOIN order_items oi ON o.id = oi.order_id
JOIN menu_items mi ON oi.menu_item_id = mi.id
WHERE o.id = ? AND mi.restaurant_id = ?
LIMIT 1
");
$check_stmt->execute([$order_id, $restaurant_id]);
if ($check_stmt->rowCount() == 0) {
echo "<div class='alert alert-danger'>Access Denied: This order does not belong to your restaurant.</div>";
include 'footer.php';
exit;
}
// Fetch order details
$order_stmt = $pdo->prepare("
SELECT o.*, u.name AS user_name, u.email AS user_email, u.address AS user_address
FROM orders o
JOIN users u ON o.user_id = u.id
WHERE o.id = ?
");
$order_stmt->execute([$order_id]);
$order = $order_stmt->fetch(PDO::FETCH_ASSOC);
if (!$order) {
echo "<div class='alert alert-danger'>Order not found.</div>";
include 'footer.php';
exit;
}
// Fetch order items
$items_stmt = $pdo->prepare("
SELECT oi.quantity, oi.price, mi.name AS item_name
FROM order_items oi
JOIN menu_items mi ON oi.menu_item_id = mi.id
WHERE oi.order_id = ? AND mi.restaurant_id = ?
");
$items_stmt->execute([$order_id, $restaurant_id]);
$items = $items_stmt->fetchAll(PDO::FETCH_ASSOC);
$possible_statuses = ['Pending', 'Confirmed', 'Preparing', 'Out for Delivery', 'Delivered', 'Cancelled'];
?>
<div class="container mt-4">
<h2>Order Details #<?php echo htmlspecialchars($order['id']); ?></h2>
<div class="card mb-4">
<div class="card-header">Customer & Order Information</div>
<div class="card-body">
<p><strong>Customer Name:</strong> <?php echo htmlspecialchars($order['user_name']); ?></p>
<p><strong>Customer Email:</strong> <?php echo htmlspecialchars($order['user_email']); ?></p>
<p><strong>Delivery Address:</strong> <?php echo htmlspecialchars($order['user_address']); ?></p>
<hr>
<p><strong>Order Total:</strong> $<?php echo number_format($order['total_price'], 2); ?></p>
<p><strong>Order Status:</strong> <?php echo htmlspecialchars($order['status']); ?></p>
<p><strong>Order Date:</strong> <?php echo $order['created_at']; ?></p>
</div>
</div>
<div class="card mb-4">
<div class="card-header">Order Items</div>
<div class="card-body">
<table class="table table-striped">
<thead>
<tr>
<th>Item Name</th>
<th>Quantity</th>
<th>Price per item</th>
<th>Subtotal</th>
</tr>
</thead>
<tbody>
<?php foreach ($items as $item): ?>
<tr>
<td><?php echo htmlspecialchars($item['item_name']); ?></td>
<td><?php echo $item['quantity']; ?></td>
<td>$<?php echo number_format($item['price'], 2); ?></td>
<td>$<?php echo number_format($item['price'] * $item['quantity'], 2); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<a href="orders.php" class="btn btn-secondary">Back to Orders List</a>
</div>
<?php include 'footer.php'; ?>

148
restaurant/orders.php Normal file
View File

@ -0,0 +1,148 @@
<?php
include 'header.php';
require_once '../db/config.php';
// Ensure the user is a logged-in restaurant owner
if (!isset($_SESSION['restaurant_user_id'])) {
header('Location: ../restaurant_login.php');
exit;
}
$restaurant_id = $_SESSION['restaurant_id'];
// Fetch orders belonging to this restaurant
$stmt = $pdo->prepare("
SELECT o.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
WHERE o.restaurant_id = ?
ORDER BY o.created_at DESC
");
$stmt->execute([$restaurant_id]);
$orders = $stmt->fetchAll();
$possible_statuses = ['Pending', 'Confirmed', 'Preparing', 'Out for Delivery', 'Delivered', 'Cancelled'];
?>
<div class="container mt-4">
<div class="d-flex justify-content-between align-items-center mb-3">
<h2>Your Restaurant's Orders</h2>
<span class="badge badge-success" id="update-indicator" style="display: none;">Updated just now</span>
</div>
<div id="orders-table-container">
<table class="table table-striped">
<thead>
<tr>
<th>Order ID</th>
<th>Customer</th>
<th>Total Price</th>
<th>Order Date</th>
<th>Status</th>
<th>Details</th>
</tr>
</thead>
<tbody id="orders-tbody">
<?php if (empty($orders)): ?>
<tr>
<td colspan="6" class="text-center">No orders found.</td>
</tr>
<?php else: ?>
<?php foreach ($orders as $order): ?>
<tr data-order-id="<?php echo $order['id']; ?>">
<td><?php echo $order['id']; ?></td>
<td><?php echo htmlspecialchars($order['user_name']); ?></td>
<td>$<?php echo number_format($order['total_price'], 2); ?></td>
<td><?php echo $order['created_at']; ?></td>
<td>
<select class="form-control form-control-sm status-select">
<?php foreach ($possible_statuses as $status): ?>
<option value="<?php echo $status; ?>" <?php echo ($order['status'] === $status) ? 'selected' : ''; ?>>
<?php echo htmlspecialchars($status); ?>
</option>
<?php endforeach; ?>
</select>
</td>
<td>
<a href="order_details.php?order_id=<?php echo $order['id']; ?>" class="btn btn-info btn-sm">View Details</a>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function () {
const ordersTbody = document.getElementById('orders-tbody');
const updateIndicator = document.getElementById('update-indicator');
// --- Function to update status via API ---
async function updateOrderStatus(orderId, newStatus) {
try {
const response = await fetch('update_order_status.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ order_id: orderId, status: newStatus }),
});
const result = await response.json();
if (!response.ok) {
throw new Error(result.error || 'Failed to update status');
}
console.log('Status updated:', result.message);
showUpdateIndicator();
} catch (error) {
console.error('Error updating status:', error);
alert('Error: ' + error.message);
}
}
// --- Attach event listener to dropdowns ---
ordersTbody.addEventListener('change', function (e) {
if (e.target.classList.contains('status-select')) {
const selectedStatus = e.target.value;
const orderId = e.target.closest('tr').dataset.orderId;
updateOrderStatus(orderId, selectedStatus);
}
});
// --- Function to show a brief update indicator ---
function showUpdateIndicator() {
updateIndicator.style.display = 'inline';
setTimeout(() => {
updateIndicator.style.display = 'none';
}, 2000);
}
// --- Function to fetch and refresh the order list ---
async function fetchOrders() {
try {
const response = await fetch(window.location.href, { // Fetch the same page
headers: {
'X-Requested-With': 'XMLHttpRequest' // To identify AJAX request on server if needed
}
});
const html = await response.text();
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
const newTbody = doc.getElementById('orders-tbody');
if (newTbody && ordersTbody.innerHTML.trim() !== newTbody.innerHTML.trim()) {
ordersTbody.innerHTML = newTbody.innerHTML;
console.log('Orders refreshed');
showUpdateIndicator();
}
} catch (error) {
console.error('Error fetching orders:', error);
}
}
// --- Polling: Refresh orders every 15 seconds ---
setInterval(fetchOrders, 15000);
});
</script>
<?php include 'footer.php'; ?>

View File

@ -0,0 +1,49 @@
<?php
session_start();
require_once '../db/config.php';
if (!isset($_SESSION['restaurant_user_id'])) {
http_response_code(401);
echo json_encode(['error' => 'Unauthorized']);
exit;
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['error' => 'Method Not Allowed']);
exit;
}
$data = json_decode(file_get_contents('php://input'), true);
$order_id = $data['order_id'] ?? null;
$status = $data['status'] ?? null;
$restaurant_id = $_SESSION['restaurant_id'];
if (!$order_id || !$status) {
http_response_code(400);
echo json_encode(['error' => 'Missing order_id or status']);
exit;
}
// Verify the order belongs to the restaurant
$stmt = $pdo->prepare('SELECT id FROM orders WHERE id = ? AND restaurant_id = ?');
$stmt->execute([$order_id, $restaurant_id]);
$order = $stmt->fetch();
if (!$order) {
http_response_code(404);
echo json_encode(['error' => 'Order not found or access denied']);
exit;
}
// Update the order status
$stmt = $pdo->prepare('UPDATE orders SET status = ? WHERE id = ?');
$success = $stmt->execute([$status, $order_id]);
if ($success) {
echo json_encode(['success' => true, 'message' => 'Order status updated successfully.']);
} else {
http_response_code(500);
echo json_encode(['error' => 'Failed to update order status']);
}
?>

23
restaurant_login.php Normal file
View File

@ -0,0 +1,23 @@
<?php include 'header.php'; ?>
<main>
<div class="auth-container">
<h1>Restaurant Owner Login</h1>
<form action="restaurant_login_process.php" method="POST">
<div class="form-group">
<label for="email">Email</label>
<input type="email" id="email" name="email" required>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" name="password" required>
</div>
<button type="submit" class="btn-submit">Login</button>
</form>
<div class="form-footer">
<p>Don't have an account? <a href="restaurant_signup.php">Sign up</a></p>
</div>
</div>
</main>
<?php include 'footer.php'; ?>

View File

@ -0,0 +1,52 @@
<?php
session_start();
require_once 'db/config.php';
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$email = $_POST['email'];
$password = $_POST['password'];
if (empty($email) || empty($password)) {
die('Please fill all required fields.');
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
die('Invalid email format.');
}
try {
$pdo = db();
$sql = "SELECT * FROM users WHERE email = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$email]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if ($user && password_verify($password, $user['password'])) {
if ($user['role'] !== 'restaurant_owner') {
die('You are not authorized to access this page.');
}
// Fetch the restaurant ID
$sql = "SELECT id FROM restaurants WHERE user_id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$user['id']]);
$restaurant = $stmt->fetch(PDO::FETCH_ASSOC);
$_SESSION['user_id'] = $user['id'];
$_SESSION['user_name'] = $user['name'];
$_SESSION['user_role'] = $user['role'];
if ($restaurant) {
$_SESSION['restaurant_id'] = $restaurant['id'];
}
header("Location: restaurant/index.php");
exit;
} else {
die('Invalid email or password.');
}
} catch (PDOException $e) {
die("Could not connect to the database: " . $e->getMessage());
}
}
?>

42
restaurant_signup.php Normal file
View File

@ -0,0 +1,42 @@
<?php include 'header.php'; ?>
<main>
<div class="auth-container">
<h1>Create a Restaurant Account</h1>
<p>Sign up to list your restaurant on our platform.</p>
<form action="restaurant_signup_process.php" method="POST">
<div class="form-group">
<label for="name">Your Name</label>
<input type="text" id="name" name="name" required>
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" id="email" name="email" required>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" name="password" required>
</div>
<hr>
<h3>Restaurant Details</h3>
<div class="form-group">
<label for="restaurant_name">Restaurant Name</label>
<input type="text" id="restaurant_name" name="restaurant_name" required>
</div>
<div class="form-group">
<label for="restaurant_address">Restaurant Address</label>
<input type="text" id="restaurant_address" name="restaurant_address" required>
</div>
<div class="form-group">
<label for="restaurant_phone">Restaurant Phone</label>
<input type="text" id="restaurant_phone" name="restaurant_phone" required>
</div>
<button type="submit" class="btn-submit">Sign Up</button>
</form>
<div class="form-footer">
<p>Already have an account? <a href="restaurant_login.php">Log in</a></p>
</div>
</div>
</main>
<?php include 'footer.php'; ?>

View File

@ -0,0 +1,62 @@
<?php
session_start();
require_once 'db/config.php';
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// User details
$name = $_POST['name'];
$email = $_POST['email'];
$password = $_POST['password'];
// Restaurant details
$restaurant_name = $_POST['restaurant_name'];
$restaurant_address = $_POST['restaurant_address'];
$restaurant_phone = $_POST['restaurant_phone'];
if (empty($name) || empty($email) || empty($password) || empty($restaurant_name) || empty($restaurant_address) || empty($restaurant_phone)) {
die('Please fill all required fields.');
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
die('Invalid email format.');
}
try {
$pdo = db();
// Check if email already exists
$sql = "SELECT id FROM users WHERE email = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$email]);
if ($stmt->fetch()) {
die('Email already exists.');
}
// Create the user with 'restaurant_owner' role
$password_hash = password_hash($password, PASSWORD_BCRYPT);
$sql = "INSERT INTO users (name, email, password, role) VALUES (?, ?, ?, 'restaurant_owner')";
$stmt = $pdo->prepare($sql);
$stmt->execute([$name, $email, $password_hash]);
$user_id = $pdo->lastInsertId();
// Create the restaurant
$sql = "INSERT INTO restaurants (name, address, phone_number, user_id) VALUES (?, ?, ?, ?)";
$stmt = $pdo->prepare($sql);
$stmt->execute([$restaurant_name, $restaurant_address, $restaurant_phone, $user_id]);
$restaurant_id = $pdo->lastInsertId();
// Log the user in
$_SESSION['user_id'] = $user_id;
$_SESSION['user_name'] = $name;
$_SESSION['user_role'] = 'restaurant_owner';
$_SESSION['restaurant_id'] = $restaurant_id;
// Redirect to the restaurant dashboard
header("Location: restaurant/index.php");
exit;
} catch (PDOException $e) {
die("Could not connect to the database: " . $e->getMessage());
}
}
?>