This commit is contained in:
Flatlogic Bot 2025-11-11 08:51:27 +00:00
parent 54db8f0222
commit 7d531ef9a4
14 changed files with 963 additions and 145 deletions

221
admin.php Normal file
View File

@ -0,0 +1,221 @@
<?php
session_start();
if (!isset($_SESSION['user_id']) || $_SESSION['role'] !== 'admin') {
header("Location: login.php");
exit;
}
require_once __DIR__ . '/db/config.php';
function getMealTypeName($char) {
$types = ['N' => 'Normal', 'V' => 'Vegetarian', 'G' => 'Vegan'];
return $types[$char] ?? 'Unknown';
}
$message = '';
$error = '';
$edit_meal = null;
try {
$pdo = db();
// Handle Delete
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_id'])) {
$stmt = $pdo->prepare("DELETE FROM meals WHERE id = ?");
$stmt->execute([$_POST['delete_id']]);
$message = 'Meal deleted successfully!';
}
// Handle Add/Update
elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
$day_of_week = $_POST['day_of_week'] ?? '';
$meal_type = $_POST['meal_type'] ?? '';
$name = $_POST['name'] ?? '';
$description = $_POST['description'] ?? '';
$id = $_POST['update_id'] ?? null;
if (empty($day_of_week) || empty($meal_type) || empty($name)) {
$error = 'Please fill in all required fields (Day, Meal Type, Name).';
} else {
if ($id) {
// Update
$stmt = $pdo->prepare("UPDATE meals SET day_of_week = ?, meal_type = ?, name = ?, description = ? WHERE id = ?");
$stmt->execute([$day_of_week, $meal_type, $name, $description, $id]);
$message = 'Meal updated successfully!';
} else {
// Insert
$stmt = $pdo->prepare("INSERT INTO meals (day_of_week, meal_type, name, description) VALUES (?, ?, ?, ?)");
$stmt->execute([$day_of_week, $meal_type, $name, $description]);
$message = 'Meal added successfully!';
}
}
}
// Handle Edit - Fetch meal to edit
if (isset($_GET['edit_id'])) {
$stmt = $pdo->prepare("SELECT * FROM meals WHERE id = ?");
$stmt->execute([$_GET['edit_id']]);
$edit_meal = $stmt->fetch(PDO::FETCH_ASSOC);
}
// Fetch all meals for display
$stmt = $pdo->query("SELECT * FROM meals ORDER BY FIELD(day_of_week, 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'), meal_type");
$meals = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
$error = 'Database error: ' . $e->getMessage();
$meals = [];
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Admin - Meal Management</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&family=Lato:wght@400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
<script src="https://unpkg.com/feather-icons"></script>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-white shadow-sm sticky-top">
<div class="container">
<a class="navbar-brand fw-bold" href="/">eMenza</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item"><a class="nav-link" href="/">Home</a></li>
<li class="nav-item"><a class="nav-link" href="menu.php">Weekly Menu</a></li>
<?php if (isset($_SESSION['user_id'])): ?>
<li class="nav-item"><a class="nav-link active" href="admin.php">Admin</a></li>
<li class="nav-item"><a class="nav-link" href="profile.php">Profile</a></li>
<li class="nav-item"><a class="nav-link" href="logout.php">Logout</a></li>
<?php else: ?>
<li class="nav-item"><a class="nav-link" href="login.php">Login</a></li>
<li class="nav-item"><a class="btn btn-primary ms-lg-2" href="register.php">Register</a></li>
<?php endif; ?>
</ul>
</div>
</div>
</nav>
<main class="container py-5">
<h1 class="mb-4">Meal Management</h1>
<?php if ($message): ?>
<div class="alert alert-success"><?php echo $message; ?></div>
<?php endif; ?>
<?php if ($error): ?>
<div class="alert alert-danger"><?php echo $error; ?></div>
<?php endif; ?>
<div class="card mb-4">
<div class="card-header">
<?php echo $edit_meal ? 'Edit Meal' : 'Add New Meal'; ?>
</div>
<div class="card-body">
<form action="admin.php" method="POST">
<?php if ($edit_meal): ?>
<input type="hidden" name="update_id" value="<?php echo $edit_meal['id']; ?>">
<?php endif; ?>
<div class="row">
<div class="col-md-3 mb-3">
<label for="day_of_week" class="form-label">Day of the Week</label>
<select class="form-select" id="day_of_week" name="day_of_week" required>
<option value="">Choose...</option>
<?php $days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']; ?>
<?php foreach ($days as $day): ?>
<option value="<?php echo $day; ?>" <?php echo (isset($edit_meal['day_of_week']) && $edit_meal['day_of_week'] === $day) ? 'selected' : ''; ?>><?php echo $day; ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-3 mb-3">
<label for="meal_type" class="form-label">Meal Type</label>
<select class="form-select" id="meal_type" name="meal_type" required>
<option value="">Choose...</option>
<?php $types = ['N' => 'Normal', 'V' => 'Vegetarian', 'G' => 'Vegan']; ?>
<?php foreach ($types as $char => $name): ?>
<option value="<?php echo $char; ?>" <?php echo (isset($edit_meal['meal_type']) && $edit_meal['meal_type'] === $char) ? 'selected' : ''; ?>><?php echo $name; ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-6 mb-3">
<label for="name" class="form-label">Meal Name</label>
<input type="text" class="form-control" id="name" name="name" value="<?php echo htmlspecialchars($edit_meal['name'] ?? ''); ?>" required>
</div>
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<textarea class="form-control" id="description" name="description" rows="3"><?php echo htmlspecialchars($edit_meal['description'] ?? ''); ?></textarea>
</div>
<button type="submit" class="btn btn-primary"><?php echo $edit_meal ? 'Update Meal' : 'Add Meal'; ?></button>
<?php if ($edit_meal): ?>
<a href="admin.php" class="btn btn-secondary">Cancel</a>
<?php endif; ?>
</form>
</div>
</div>
<div class="card">
<div class="card-header">
Existing Meals
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Day</th>
<th>Type</th>
<th>Name</th>
<th>Description</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php if (empty($meals)): ?>
<tr>
<td colspan="5" class="text-center">No meals found. Add one above!</td>
</tr>
<?php endif; ?>
<?php foreach ($meals as $meal): ?>
<tr>
<td><?php echo htmlspecialchars($meal['day_of_week']); ?></td>
<td><?php echo getMealTypeName($meal['meal_type']); ?></td>
<td><?php echo htmlspecialchars($meal['name']); ?></td>
<td><?php echo htmlspecialchars($meal['description']); ?></td>
<td>
<a href="admin.php?edit_id=<?php echo $meal['id']; ?>" class="btn btn-sm btn-outline-primary">Edit</a>
<form action="admin.php" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this meal?');">
<input type="hidden" name="delete_id" value="<?php echo $meal['id']; ?>">
<button type="submit" class="btn btn-sm btn-outline-danger">Delete</button>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
</main>
<footer class="py-4 bg-light mt-auto">
<div class="container text-center">
<p class="mb-0 text-muted">&copy; <?php echo date("Y"); ?> eMenza. All Rights Reserved.</p>
</div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script>
feather.replace()
</script>
</body>
</html>

67
assets/css/custom.css Normal file
View File

@ -0,0 +1,67 @@
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&family=Lato:wght@400;700&display=swap');
:root {
--primary-color: #4A90E2;
--secondary-color: #50E3C2;
--background-color: #F4F7F6;
--surface-color: #FFFFFF;
--text-color: #333333;
--text-muted-color: #6c757d;
--border-radius: 0.5rem;
}
body {
font-family: 'Lato', sans-serif;
background-color: var(--background-color);
color: var(--text-color);
}
h1, h2, h3, h4, h5, h6, .navbar-brand, .fw-bold {
font-family: 'Poppins', sans-serif;
}
.btn-primary {
background-color: var(--primary-color);
border-color: var(--primary-color);
transition: all 0.3s ease;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
.text-primary {
color: var(--primary-color) !important;
}
.hero-section {
background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%);
padding: 6rem 0;
margin-bottom: 3rem;
}
.navbar-brand {
color: var(--primary-color) !important;
}
.nav-link.active {
font-weight: bold;
color: var(--primary-color) !important;
}
.day-card {
border-radius: var(--border-radius);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.day-card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 25px rgba(0,0,0,0.08);
}
.meal-card {
background-color: #f8f9fa;
border-radius: var(--border-radius);
border: 1px solid #e9ecef;
}

20
db/migrate.php Normal file
View File

@ -0,0 +1,20 @@
<?php
require_once __DIR__ . '/config.php';
$pdo = db();
$migrationsDir = __DIR__ . '/migrations';
$files = glob($migrationsDir . '/*.sql');
sort($files);
foreach ($files as $file) {
$sql = file_get_contents($file);
try {
$pdo->exec($sql);
echo "Successfully executed migration: " . basename($file) . "\n";
} catch (PDOException $e) {
echo "Error executing migration: " . basename($file) . " - " . $e->getMessage() . "\n";
}
}

View File

@ -0,0 +1,9 @@
CREATE TABLE IF NOT EXISTS meals (
id INT AUTO_INCREMENT PRIMARY KEY,
day_of_week VARCHAR(20) NOT NULL,
meal_type CHAR(1) NOT NULL,
name VARCHAR(255) NOT NULL,
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

View File

@ -0,0 +1,17 @@
-- Sample Meals
INSERT INTO `meals` (`day_of_week`, `name`, `description`, `meal_type`) VALUES
('Monday', 'Spaghetti Bolognese', 'Classic Italian meat sauce with pasta', 'N'),
('Monday', 'Lentil Shepherd''s Pie', 'A hearty vegetarian shepherd''s pie with a lentil filling.', 'V'),
('Monday', 'Mushroom Risotto', 'Creamy risotto with fresh mushrooms', 'G'),
('Tuesday', 'Chicken Teriyaki', 'Grilled chicken with a sweet and savory teriyaki sauce', 'N'),
('Tuesday', 'Black Bean Burgers', 'Homemade black bean burgers on a whole wheat bun.', 'V'),
('Tuesday', 'Quinoa Salad', 'Healthy and refreshing quinoa salad with mixed vegetables', 'G'),
('Wednesday', 'Beef Tacos', 'Spicy ground beef in a crispy taco shell', 'N'),
('Wednesday', 'Spinach and Feta Stuffed Peppers', 'Bell peppers stuffed with a savory mixture of spinach, feta cheese, and rice.', 'V'),
('Wednesday', 'Vegetable Curry', 'A flavorful curry with a variety of fresh vegetables', 'G'),
('Thursday', 'Fish and Chips', 'Classic battered fish with a side of french fries', 'N'),
('Thursday', 'Eggplant Parmesan', 'Slices of breaded eggplant, fried and layered with cheese and tomato sauce.', 'V'),
('Thursday', 'Sweet Potato and Black Bean Burritos', 'Hearty burritos filled with a sweet and savory mixture.', 'G'),
('Friday', 'Pizza Salami', 'Classic pizza with tomato sauce, cheese, and salami', 'N'),
('Friday', 'Four Cheese Pizza', 'A delicious pizza topped with four different kinds of cheese.', 'V'),
('Friday', 'Vegan Pizza', 'Pizza with a variety of fresh vegetables and vegan cheese', 'G');

View File

@ -0,0 +1,7 @@
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

View File

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

233
index.php
View File

@ -1,150 +1,105 @@
<?php <?php session_start(); ?>
declare(strict_types=1); <!DOCTYPE html>
@ini_set('display_errors', '1');
@error_reporting(E_ALL);
@date_default_timezone_set('UTC');
$phpVersion = PHP_VERSION;
$now = date('Y-m-d H:i:s');
?>
<!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>New Style</title> <title>eMenza - School Meal Management</title>
<?php <meta name="description" content="eMenza is a modern web-based system for transparent and easy school meal management.">
// Read project preview data from environment <meta name="keywords" content="school meal, menu, lunch order, catering, school food, eMenza, online ordering, meal management, Built with Flatlogic Generator">
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? ''; <meta property="og:title" content="eMenza - School Meal Management">
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? ''; <meta property="og:description" content="eMenza is a modern web-based system for transparent and easy school meal management.">
?> <meta property="og:image" content="">
<?php if ($projectDescription): ?> <meta name="twitter:card" content="summary_large_image">
<!-- Meta description --> <meta name="twitter:image" content="">
<meta name="description" content='<?= htmlspecialchars($projectDescription) ?>' />
<!-- Open Graph meta tags --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<meta property="og:description" content="<?= htmlspecialchars($projectDescription) ?>" />
<!-- Twitter meta tags -->
<meta property="twitter:description" content="<?= htmlspecialchars($projectDescription) ?>" />
<?php endif; ?>
<?php if ($projectImageUrl): ?>
<!-- Open Graph image -->
<meta property="og:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
<!-- Twitter image -->
<meta property="twitter:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
<?php endif; ?>
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&family=Lato:wght@400;700&display=swap" rel="stylesheet">
<style> <link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
:root { <script src="https://unpkg.com/feather-icons"></script>
--bg-color-start: #6a11cb;
--bg-color-end: #2575fc;
--text-color: #ffffff;
--card-bg-color: rgba(255, 255, 255, 0.01);
--card-border-color: rgba(255, 255, 255, 0.1);
}
body {
margin: 0;
font-family: 'Inter', sans-serif;
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
color: var(--text-color);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
text-align: center;
overflow: hidden;
position: relative;
}
body::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path d="M-10 10L110 10M10 -10L10 110" stroke-width="1" stroke="rgba(255,255,255,0.05)"/></svg>');
animation: bg-pan 20s linear infinite;
z-index: -1;
}
@keyframes bg-pan {
0% { background-position: 0% 0%; }
100% { background-position: 100% 100%; }
}
main {
padding: 2rem;
}
.card {
background: var(--card-bg-color);
border: 1px solid var(--card-border-color);
border-radius: 16px;
padding: 2rem;
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.1);
}
.loader {
margin: 1.25rem auto 1.25rem;
width: 48px;
height: 48px;
border: 3px solid rgba(255, 255, 255, 0.25);
border-top-color: #fff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.hint {
opacity: 0.9;
}
.sr-only {
position: absolute;
width: 1px; height: 1px;
padding: 0; margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap; border: 0;
}
h1 {
font-size: 3rem;
font-weight: 700;
margin: 0 0 1rem;
letter-spacing: -1px;
}
p {
margin: 0.5rem 0;
font-size: 1.1rem;
}
code {
background: rgba(0,0,0,0.2);
padding: 2px 6px;
border-radius: 4px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
footer {
position: absolute;
bottom: 1rem;
font-size: 0.8rem;
opacity: 0.7;
}
</style>
</head> </head>
<body> <body>
<main>
<div class="card"> <nav class="navbar navbar-expand-lg navbar-light bg-white shadow-sm sticky-top">
<h1>Analyzing your requirements and generating your website…</h1> <div class="container">
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes"> <a class="navbar-brand fw-bold" href="/">eMenza</a>
<span class="sr-only">Loading…</span> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item"><a class="nav-link active" href="/">Home</a></li>
<li class="nav-item"><a class="nav-link" href="menu.php">Weekly Menu</a></li>
<?php if (isset($_SESSION['user_id'])): ?>
<li class="nav-item"><a class="nav-link" href="admin.php">Admin</a></li>
<li class="nav-item"><a class="nav-link" href="profile.php">Profile</a></li>
<li class="nav-item"><a class="nav-link" href="logout.php">Logout</a></li>
<?php else: ?>
<li class="nav-item"><a class="nav-link" href="login.php">Login</a></li>
<li class="nav-item"><a class="btn btn-primary ms-lg-2" href="register.php">Register</a></li>
<?php endif; ?>
</ul>
</div> </div>
<p class="hint"><?= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWizzy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.</p>
<p class="hint">This page will update automatically as the plan is implemented.</p>
<p>Runtime: PHP <code><?= htmlspecialchars($phpVersion) ?></code> — UTC <code><?= htmlspecialchars($now) ?></code></p>
</div> </div>
</main> </nav>
<footer>
Page updated: <?= htmlspecialchars($now) ?> (UTC) <header class="hero-section">
<div class="container text-center">
<?php if (isset($_SESSION['user_id'])): ?>
<h1 class="display-4 fw-bold text-white">Welcome, <?php echo htmlspecialchars($_SESSION['username']); ?>!</h1>
<?php else: ?>
<h1 class="display-4 fw-bold text-white">Welcome to eMenza</h1>
<?php endif; ?>
<p class="lead text-white-75 mb-4">The future of school meal management is here. Simple, transparent, and efficient.</p>
<a href="menu.php" class="btn btn-lg btn-light text-primary fw-bold">View This Week's Menu</a>
</div>
</header>
<section class="py-5">
<div class="container">
<div class="row text-center">
<div class="col-md-4 mb-4">
<div class="card border-0 shadow-sm h-100">
<div class="card-body p-5">
<i data-feather="eye" class="text-primary mb-3" width="48" height="48"></i>
<h3 class="h4">View Menus</h3>
<p class="text-muted">Easily check the upcoming weekly menu with detailed descriptions and allergen info.</p>
</div>
</div>
</div>
<div class="col-md-4 mb-4">
<div class="card border-0 shadow-sm h-100">
<div class="card-body p-5">
<i data-feather="shopping-cart" class="text-primary mb-3" width="48" height="48"></i>
<h3 class="h4">Order Ahead</h3>
<p class="text-muted">Pre-order your meals for the week with just a few clicks. Cancel anytime before the deadline.</p>
</div>
</div>
</div>
<div class="col-md-4 mb-4">
<div class="card border-0 shadow-sm h-100">
<div class="card-body p-5">
<i data-feather="credit-card" class="text-primary mb-3" width="48" height="48"></i>
<h3 class="h4">Easy Payments</h3>
<p class="text-muted">Manage your balance and pay for your meals securely online or in person.</p>
</div>
</div>
</div>
</div>
</div>
</section>
<footer class="py-4 bg-light">
<div class="container text-center">
<p class="mb-0 text-muted">&copy; <?php echo date("Y"); ?> eMenza. All Rights Reserved.</p>
</div>
</footer> </footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script>
feather.replace()
</script>
</body> </body>
</html> </html>

105
login.php Normal file
View File

@ -0,0 +1,105 @@
<?php
session_start();
require_once __DIR__ . '/db/config.php';
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$email = $_POST['email'] ?? '';
$password = $_POST['password'] ?? '';
if (empty($email) || empty($password)) {
$error = 'Please fill in all fields.';
} else {
try {
$pdo = db();
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
$stmt->execute([$email]);
$user = $stmt->fetch();
if ($user && password_verify($password, $user['password'])) {
$_SESSION['user_id'] = $user['id'];
$_SESSION['role'] = $user['role'];
$_SESSION['username'] = $user['username'];
header("Location: index.php");
exit;
} else {
$error = 'Invalid email or password.';
}
} catch (PDOException $e) {
$error = 'Database error: ' . $e->getMessage();
}
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login - eMenza</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&family=Lato:wght@400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-white shadow-sm sticky-top">
<div class="container">
<a class="navbar-brand fw-bold" href="/">eMenza</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item"><a class="nav-link" href="/">Home</a></li>
<li class="nav-item"><a class="nav-link" href="menu.php">Weekly Menu</a></li>
<?php if (isset($_SESSION['user_id'])): ?>
<li class="nav-item"><a class="nav-link" href="admin.php">Admin</a></li>
<li class="nav-item"><a class="nav-link" href="logout.php">Logout</a></li>
<?php else: ?>
<li class="nav-item"><a class="nav-link active" href="login.php">Login</a></li>
<li class="nav-item"><a class="btn btn-primary ms-lg-2" href="register.php">Register</a></li>
<?php endif; ?>
</ul>
</div>
</div>
</nav>
<main class="container py-5" style="max-width: 500px;">
<h1 class="mb-4 text-center">Login</h1>
<?php if ($error): ?>
<div class="alert alert-danger"><?php echo $error; ?></div>
<?php endif; ?>
<div class="card">
<div class="card-body p-5">
<form action="login.php" method="POST">
<div class="mb-3">
<label for="email" class="form-label">Email address</label>
<input type="email" class="form-control" id="email" name="email" required>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" name="password" required>
</div>
<button type="submit" class="btn btn-primary w-100">Login</button>
</form>
</div>
</div>
</main>
<footer class="py-4 bg-light mt-auto">
<div class="container text-center">
<p class="mb-0 text-muted">&copy; <?php echo date("Y"); ?> eMenza. All Rights Reserved.</p>
</div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

6
logout.php Normal file
View File

@ -0,0 +1,6 @@
<?php
session_start();
session_unset();
session_destroy();
header("Location: index.php");
exit;

123
menu.php Normal file
View File

@ -0,0 +1,123 @@
<?php
session_start();
require_once __DIR__ . '/db/config.php';
function getMealTypeName($char) {
$types = ['N' => 'Normal', 'V' => 'Vegetarian', 'G' => 'Vegan'];
return $types[$char] ?? 'Unknown';
}
$menu = [];
$error = '';
try {
$pdo = db();
$stmt = $pdo->query("SELECT * FROM meals ORDER BY FIELD(day_of_week, 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'), meal_type");
$meals = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($meals as $meal) {
$menu[$meal['day_of_week']][] = [
'name' => $meal['name'],
'option' => getMealTypeName($meal['meal_type']),
'description' => $meal['description'],
'allergens' => [] // Placeholder for allergens
];
}
} catch (PDOException $e) {
$error = 'Database error: ' . $e->getMessage();
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Weekly Menu - eMenza</title>
<meta name="description" content="View the weekly school meal menu. Options A and B available each day.">
<meta name="keywords" content="weekly menu, school lunch, eMenza, meal plan, school food, menu view, Built with Flatlogic Generator">
<meta property="og:title" content="Weekly Menu - eMenza">
<meta property="og:description" content="View the weekly school meal menu. Options A and B available each day.">
<meta property="og:image" content="">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&family=Lato:wght@400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
<script src="https://unpkg.com/feather-icons"></script>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-white shadow-sm sticky-top">
<div class="container">
<a class="navbar-brand fw-bold" href="/">eMenza</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item"><a class="nav-link" href="/">Home</a></li>
<li class="nav-item"><a class="nav-link active" href="menu.php">Weekly Menu</a></li>
<?php if (isset($_SESSION['user_id'])): ?>
<li class="nav-item"><a class="nav-link" href="admin.php">Admin</a></li>
<li class="nav-item"><a class="nav-link" href="profile.php">Profile</a></li>
<li class="nav-item"><a class="nav-link" href="logout.php">Logout</a></li>
<?php else: ?>
<li class="nav-item"><a class="nav-link" href="login.php">Login</a></li>
<li class="nav-item"><a class="btn btn-primary ms-lg-2" href="register.php">Register</a></li>
<?php endif; ?>
</ul>
</div>
</div>
</nav>
<main class="container my-5">
<div class="text-center mb-5">
<h1 class="fw-bold">This Week's Menu</h1>
<p class="text-muted">Here are the meal options for the upcoming week. Orders can be placed until 10:00 AM for the next day.</p>
</div>
<div class="row">
<?php foreach ($menu as $day => $options): ?>
<div class="col-lg mb-4">
<div class="card h-100 shadow-sm border-0 day-card">
<div class="card-header bg-white text-center border-0 pt-4">
<h3 class="h5 fw-bold"><?php echo $day; ?></h3>
</div>
<div class="card-body p-3">
<?php foreach ($options as $meal): ?>
<div class="meal-card mb-3">
<div class="card-body">
<div class="d-flex justify-content-between align-items-start mb-2">
<h5 class="card-title h6 fw-bold mb-0"><?php echo $meal['option']; ?>: <?php echo $meal['name']; ?></h5>
</div>
<p class="card-text small text-muted"><?php echo $meal['description']; ?></p>
<div>
<?php foreach ($meal['allergens'] as $allergen): ?>
<span class="badge bg-light text-dark me-1"><?php echo $allergen; ?></span>
<?php endforeach; ?>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
</main>
<footer class="py-4 bg-light mt-auto">
<div class="container text-center">
<p class="mb-0 text-muted">&copy; <?php echo date("Y"); ?> eMenza. All Rights Reserved.</p>
</div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script>
feather.replace()
</script>
</body>
</html>

140
profile.php Normal file
View File

@ -0,0 +1,140 @@
<?php
session_start();
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
exit;
}
require_once __DIR__ . '/db/config.php';
$message = '';
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['old_password'])) {
$old_password = $_POST['old_password'] ?? '';
$new_password = $_POST['new_password'] ?? '';
$confirm_new_password = $_POST['confirm_new_password'] ?? '';
if (empty($old_password) || empty($new_password) || empty($confirm_new_password)) {
$error = 'Please fill in all password fields.';
} elseif ($new_password !== $confirm_new_password) {
$error = 'New passwords do not match.';
} else {
try {
$pdo = db();
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
$user = $stmt->fetch();
if ($user && password_verify($old_password, $user['password'])) {
$hashed_password = password_hash($new_password, PASSWORD_DEFAULT);
$stmt = $pdo->prepare("UPDATE users SET password = ? WHERE id = ?");
$stmt->execute([$hashed_password, $_SESSION['user_id']]);
$message = 'Password changed successfully!';
} else {
$error = 'Incorrect old password.';
}
} catch (PDOException $e) {
$error = 'Database error: ' . $e->getMessage();
}
}
}
try {
$pdo = db();
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
$user = $stmt->fetch();
} catch (PDOException $e) {
$error = 'Database error: ' . $e->getMessage();
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Profile - eMenza</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&family=Lato:wght@400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-white shadow-sm sticky-top">
<div class="container">
<a class="navbar-brand fw-bold" href="/">eMenza</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item"><a class="nav-link" href="/">Home</a></li>
<li class="nav-item"><a class="nav-link" href="menu.php">Weekly Menu</a></li>
<?php if (isset($_SESSION['user_id'])): ?>
<li class="nav-item"><a class="nav-link" href="admin.php">Admin</a></li>
<li class="nav-item"><a class="nav-link active" href="profile.php">Profile</a></li>
<li class="nav-item"><a class="nav-link" href="logout.php">Logout</a></li>
<?php else: ?>
<li class="nav-item"><a class="nav-link" href="login.php">Login</a></li>
<li class="nav-item"><a class="btn btn-primary ms-lg-2" href="register.php">Register</a></li>
<?php endif; ?>
</ul>
</div>
</div>
</nav>
<main class="container py-5" style="max-width: 600px;">
<h1 class="mb-4">Your Profile</h1>
<?php if ($message): ?>
<div class="alert alert-success"><?php echo $message; ?></div>
<?php endif; ?>
<?php if ($error): ?>
<div class="alert alert-danger"><?php echo $error; ?></div>
<?php endif; ?>
<div class="card mb-4">
<div class="card-header">Your Information</div>
<div class="card-body">
<p><strong>Username:</strong> <?php echo htmlspecialchars($user['username']); ?></p>
<p><strong>Email:</strong> <?php echo htmlspecialchars($user['email']); ?></p>
</div>
</div>
<div class="card">
<div class="card-header">Change Password</div>
<div class="card-body">
<form action="profile.php" method="POST">
<div class="mb-3">
<label for="old_password" class="form-label">Old Password</label>
<input type="password" class="form-control" id="old_password" name="old_password" required>
</div>
<div class="mb-3">
<label for="new_password" class="form-label">New Password</label>
<input type="password" class="form-control" id="new_password" name="new_password" required>
</div>
<div class="mb-3">
<label for="confirm_new_password" class="form-label">Confirm New Password</label>
<input type="password" class="form-control" id="confirm_new_password" name="confirm_new_password" required>
</div>
<button type="submit" class="btn btn-primary">Change Password</button>
</form>
</div>
</div>
</main>
<footer class="py-4 bg-light mt-auto">
<div class="container text-center">
<p class="mb-0 text-muted">&copy; <?php echo date("Y"); ?> eMenza. All Rights Reserved.</p>
</div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

28
promote_user.php Normal file
View File

@ -0,0 +1,28 @@
<?php
require_once __DIR__ . '/db/config.php';
if (php_sapi_name() !== 'cli') {
die("This script can only be run from the command line.");
}
if ($argc !== 2) {
die("Usage: php promote_user.php <email>\n");
}
$email = $argv[1];
try {
$pdo = db();
$stmt = $pdo->prepare("UPDATE users SET role = 'admin' WHERE email = ?");
$stmt->execute([$email]);
if ($stmt->rowCount() > 0) {
echo "User with email '{$email}' has been promoted to admin.\n";
} else {
echo "No user found with email '{$email}'.\n";
}
} catch (PDOException $e) {
die("Database error: " . $e->getMessage() . "\n");
}

119
register.php Normal file
View File

@ -0,0 +1,119 @@
<?php
session_start();
require_once __DIR__ . '/db/config.php';
$message = '';
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'] ?? '';
$email = $_POST['email'] ?? '';
$password = $_POST['password'] ?? '';
$confirm_password = $_POST['confirm_password'] ?? '';
if (empty($username) || empty($email) || empty($password) || empty($confirm_password)) {
$error = 'Please fill in all fields.';
} elseif ($password !== $confirm_password) {
$error = 'Passwords do not match.';
} else {
try {
$pdo = db();
// Check if username or email already exists
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ? OR email = ?");
$stmt->execute([$username, $email]);
if ($stmt->fetch()) {
$error = 'Username or email already exists.';
} else {
// Hash password and insert user
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
$stmt = $pdo->prepare("INSERT INTO users (username, email, password) VALUES (?, ?, ?)");
$stmt->execute([$username, $email, $hashed_password]);
$message = 'Registration successful! You can now log in.';
}
} catch (PDOException $e) {
$error = 'Database error: ' . $e->getMessage();
}
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Register - eMenza</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&family=Lato:wght@400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-white shadow-sm sticky-top">
<div class="container">
<a class="navbar-brand fw-bold" href="/">eMenza</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item"><a class="nav-link" href="/">Home</a></li>
<li class="nav-item"><a class="nav-link" href="menu.php">Weekly Menu</a></li>
<?php if (isset($_SESSION['user_id'])): ?>
<li class="nav-item"><a class="nav-link" href="admin.php">Admin</a></li>
<li class="nav-item"><a class="nav-link" href="logout.php">Logout</a></li>
<?php else: ?>
<li class="nav-item"><a class="nav-link" href="login.php">Login</a></li>
<li class="nav-item"><a class="btn btn-primary ms-lg-2" href="register.php">Register</a></li>
<?php endif; ?>
</ul>
</div>
</div>
</nav>
<main class="container py-5" style="max-width: 500px;">
<h1 class="mb-4 text-center">Create an Account</h1>
<?php if ($message): ?>
<div class="alert alert-success"><?php echo $message; ?></div>
<?php endif; ?>
<?php if ($error): ?>
<div class="alert alert-danger"><?php echo $error; ?></div>
<?php endif; ?>
<div class="card">
<div class="card-body p-5">
<form action="register.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>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email address</label>
<input type="email" class="form-control" id="email" name="email" required>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" name="password" required>
</div>
<div class="mb-3">
<label for="confirm_password" class="form-.label">Confirm Password</label>
<input type="password" class="form-control" id="confirm_password" name="confirm_password" required>
</div>
<button type="submit" class="btn btn-primary w-100">Register</button>
</form>
</div>
</div>
</main>
<footer class="py-4 bg-light mt-auto">
<div class="container text-center">
<p class="mb-0 text-muted">&copy; <?php echo date("Y"); ?> eMenza. All Rights Reserved.</p>
</div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>