8 Commits

Author SHA1 Message Date
Philip d8b68416d8 Update admin_portal.php
removing requirement for map link and keyword (food type)
2024-11-28 12:23:35 -08:00
djsplice07 4b10001092 Update README.md 2024-11-23 10:22:58 -08:00
djsplice07 17f92ca7a5 Update README.md
Added user guide
2024-11-23 10:22:38 -08:00
djsplice07 8d879045fd Update README.md 2024-11-22 19:40:38 -08:00
djsplice07 04f10b00fc Update README.md 2024-11-22 19:38:46 -08:00
djsplice07 55ad71fbb9 Update README.md 2024-11-22 19:35:40 -08:00
djsplice07 ac64d8fad9 Add files via upload 2024-11-22 19:33:44 -08:00
djsplice07 97e66701ff Add files via upload 2024-11-22 19:30:26 -08:00
16 changed files with 1154 additions and 0 deletions
+93
View File
@@ -1,2 +1,95 @@
# whatsfordinner
My family has a hard time deciding what to get for dinner at least 2-3 times a week. Once we decide, it's about 9:30 PM and we eat the same thing we always eat. There was another project I used to use, but it broke when PHP 7 was released and I thought with a little ChatGPT, I may be able to figure something out... so here it goes.
![Picker_Screenshot](https://github.com/user-attachments/assets/f578baa3-4202-41b3-bbb1-23a8e50d8a5d)
#User Guide
Whats For Dinner?
Search
1. Select the price category on you budget for the meal (can be blank if no preference)
2. Select the type of cuisine you want to narrow it down to (can be blank if no preference)
3. Type a Keyword or Keywords if you want a specific food item (ie. Tacos)
4. Click Find Restaurant to list your destination
* All fields are optional, so if you just want it to spit out something, just click “Find Restaurant”
** The cuisine and price categories are dynamically populated by the database, so if you would like add a different “Price” or change the values, you can do that on the DB side.
![screenshot01](https://github.com/user-attachments/assets/3d0f427c-d16c-4b39-8b7f-cd750a6b67b6)
Results
Once you have clicked “Find Restaurant,” your results should appear on the same page under “Selected Restaurant”
1. This is the restaurant that was chosen for you
2. Click the “View Menu” button to show the food items the restaurant serves
3. A Google Map should appear; you can click “Directions” to launch a new tab and find out how to get to the establishment
![screenshot02](https://github.com/user-attachments/assets/d76dc875-11f4-47bc-83cc-78d5598a9a43)
Admin
Add Restaurants
1. On the top right of the screen, you should see an “Admin” link. Click it to navigate to the login page
![screenshot03](https://github.com/user-attachments/assets/31b9977f-aa4c-416c-97c7-fb247f4706ce)
2. Once logged in, you should see more items in the menu bar
![screenshot04](https://github.com/user-attachments/assets/00bf8a54-ddd4-45a0-9236-998866b449e4)
3. You should automatically be taken to the “Add Restaurants” page. If, not, or you want to get back to this page, click the “Add Restaurants” link
4. This page will allow you to add new restaurants to the database
5. Select the price category the restaurant you intend on adding falls into
6. Type the Restaurant Name (required)
7. Paste the Google Map Link found by doing the following
a. To find the link to enter, search the restaurant and locate the correct one on maps.google.com
![screenshot05](https://github.com/user-attachments/assets/8add17a9-9944-4a8c-bd4e-442ed7b2fd81)
b. Right click the restaurant and select ”Share this location”
![screenshot06](https://github.com/user-attachments/assets/60e6874d-057b-4fba-913d-210d6681a41f)
c. Click the “Embed a map” and click on the “COPY HTML” link
![screenshot07](https://github.com/user-attachments/assets/480813f2-a552-4a2e-8fd5-d2176ba0deae)
d. Paste the link in the “Google Map Link” and remove everything except the actual URL (first part). The first part to delete is as follows:
i. <iframe src="
e. remove everything except the actual URL (last part). The last part to delete is as follows:
i. " width="600" height="450" style="border:0;" allowfullscreen="" loading="lazy" referrerpolicy="no-referrer-when-downgrade"></iframe>
f. I guess the easy way to say it, is only include the part that is between the quotes “””
![screenshot08](https://github.com/user-attachments/assets/2335658b-d311-4d80-9a90-4c6995da2571)
8. If you can find a link to the restaurants, paste that URL in the “Menu Link” Field
![screenshot09](https://github.com/user-attachments/assets/8d9a26c7-2513-488c-8325-06e6f3e27476)
9. Type the food type/cuisine type in the “Food Type” field. Try and keep these consistent (ie. Dont use Mexican and Mexico)
![screenshot10](https://github.com/user-attachments/assets/c0deefb8-8c53-40a3-8151-d789e9adaf3d)
10. Type the Keyword for future searches. Make sure the entries are comma separated. Also try and keep these consistent (ie. taco vs. tacos vs Taco or Tacos)(Capitalization matters)
![screenshot11](https://github.com/user-attachments/assets/5b46d79b-1b7f-482d-ac2b-2877d14a045f)
Manage Restaurats
1. On the Manage Restaurants page, you should see all the restaurants that are entered in the database
2. Here are the different columns as of v.1.0.0
a. Name Name of establishment
b. Menu Link A link to the menu for the establishment
c. Cost Category The price category
d. Food Type The cuisine type (ie. Chinese, Mexican, etc)
e. Subcategory Keywords that you can search for that can be anything (ie. cheeseburger, dinner, sit down, restaurant, vegan, etc)
f. Actions Here you have the options of
i. Edit Edit this entry for the establishment (this will take you to the “Edit Restaurants” page where it will show all the values previously entered and you can edit the entry for this specific establishment
ii. Delete delete the entry
Manage Users
1. In this page you can add, edit passwords and delete the users of the application
![screenshot12](https://github.com/user-attachments/assets/85842a4d-f618-4424-b03f-a57a550e897a)
2. Type a new user in the “Username” field
3. Type a password for the new user in the “Password” field
4. In the section below (Existing Users), it should list the current users of the system (there should always be at least one obviously)
5. Click the “Delete” button to delete the listed user
6. To change the users password, type the desired password in the “New Password” field and click the “Update Password” button
+56
View File
@@ -0,0 +1,56 @@
<?php
require 'db.php';
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'];
$password = $_POST['password'];
$stmt = $pdo->prepare("SELECT * FROM admin_users WHERE username = :username");
$stmt->execute(['username' => $username]);
$user = $stmt->fetch();
if ($user) {
// Check if the password matches using bcrypt
if (password_verify($password, $user['password_hash'])) {
$_SESSION['admin_logged_in'] = true;
header('Location: admin_portal.php');
exit;
}
// Check if the password matches using SHA-256 (legacy support)
elseif (hash('sha256', $password) === $user['password_hash']) {
// Rehash the password with bcrypt for future logins
$new_hash = password_hash($password, PASSWORD_BCRYPT);
$update_stmt = $pdo->prepare("UPDATE admin_users SET password_hash = :new_hash WHERE id = :id");
$update_stmt->execute(['new_hash' => $new_hash, 'id' => $user['id']]);
$_SESSION['admin_logged_in'] = true;
header('Location: admin_portal.php');
exit;
}
}
// If neither bcrypt nor SHA-256 matched
$error = "Invalid username or password.";
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Admin Login</title>
</head>
<body>
<h1>Admin Login</h1>
<?php if (isset($error)): ?>
<p style="color: red;"><?= htmlspecialchars($error) ?></p>
<?php endif; ?>
<form method="POST">
<label>Username: <input type="text" name="username" required></label><br>
<label>Password: <input type="password" name="password" required></label><br>
<button type="submit">Login</button>
</form>
</body>
</html>
+65
View File
@@ -0,0 +1,65 @@
<?php
require 'db.php';
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'];
$password = $_POST['password'];
$stmt = $pdo->prepare("SELECT * FROM admin_users WHERE username = :username");
$stmt->execute(['username' => $username]);
$user = $stmt->fetch();
if ($user) {
// Check if the password matches using bcrypt
if (password_verify($password, $user['password_hash'])) {
$_SESSION['admin_logged_in'] = true;
header('Location: admin_portal.php');
exit;
}
// Check if the password matches using SHA-256 (legacy support)
elseif (hash('sha256', $password) === $user['password_hash']) {
// Rehash the password with bcrypt for future logins
$new_hash = password_hash($password, PASSWORD_BCRYPT);
$update_stmt = $pdo->prepare("UPDATE admin_users SET password_hash = :new_hash WHERE id = :id");
$update_stmt->execute(['new_hash' => $new_hash, 'id' => $user['id']]);
$_SESSION['admin_logged_in'] = true;
header('Location: admin_portal.php');
exit;
}
}
// If neither bcrypt nor SHA-256 matched
$error = "Invalid username or password.";
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/css/main.css">
<title>Restaurant Picker - Admin Login</title>
</head>
<body>
<div class="login">
<?php include "header.php"; ?>
<h2>Admin Login</h2>
<?php if (!empty($error)): ?>
<p style="color: red;"><?= htmlspecialchars($error) ?></p>
<?php endif; ?>
<form method="POST">
<!--<label for="text">Username:</label>
<input type="text" name="username" id="username" required> -->
<input type="text" name="username" id="username" placeholder="Username" required /><br>
<br>
<!--<label for="password">Password:</label>
<input type="password" name="password" id="password" required> -->
<input type="password" name="password" id="password" placeholder="Password" required /><br>
<br>
<button class="btn btn-primary btn-block btn-large" type="submit">Login</button>
</form>
</body>
</html>
+85
View File
@@ -0,0 +1,85 @@
<?php
require 'db.php';
session_start();
if (!isset($_SESSION['admin_logged_in']) || !$_SESSION['admin_logged_in']) {
header('Location: admin_login.php');
exit;
}
// Handle Form Submission (Adding a New Restaurant)
if ($_SERVER['REQUEST_METHOD'] === 'POST' && empty($_GET['edit_id'])) {
$name = $_POST['name'];
$google_map_link = $_POST['google_map_link'];
// $google_map_link = urlencode($_POST['google_map_link']); - tried to remove invalid characters, but affected the :// in URL
$menu_link = $_POST['menu_link'];
$cost_category = $_POST['cost_category'];
$food_type = $_POST['food_type'];
$food_type_subcategory = $_POST['food_type_subcategory'];
$stmt = $pdo->prepare("
INSERT INTO restaurants (name, google_map_link, menu_link, cost_category, food_type, food_type_subcategory)
VALUES (:name, :google_map_link, :menu_link, :cost_category, :food_type, :food_type_subcategory)
");
$stmt->execute([
'name' => $name,
'google_map_link' => $google_map_link,
'menu_link' => $menu_link,
'cost_category' => $cost_category,
'food_type' => $food_type,
'food_type_subcategory' => $food_type_subcategory,
]);
$success = "Restaurant added successfully!";
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="/css/main.css">
<title>Admin Portal</title>
</head>
<body>
<div class="login">
<?php include "header.php"; ?>
<?php if (!empty($success)): ?>
<p style="color: green;"><?= htmlspecialchars($success) ?></p>
<?php endif; ?>
<h2>Add New Restaurant</h2>
<form method="POST">
<label for="cost_category">Cost Category:</label>
<select class="minimal" name="cost_category" id="cost_category" required>
<option value="cheap">Cheap</option>
<option value="moderate">Moderate</option>
<option value="expensive">Expensive</option>
</select><br>
<br>
<!--<label for="name">Restaurant Name:</label>
<input type="text" name="name" id="name" required><br> -->
<input type="text" name="name" placeholder="Restaurant Name" id="name" required /><br>
<!--<label for="google_map_link">Google Map Link:</label>
<input type="url" name="google_map_link" id="google_map_link" required><br> -->
<input type="url" name="google_map_link" placeholder="Google Map Link" id="google_map_link" /><br>
<!--<label for="menu_link">Menu Link (optional):</label>
<input type="url" name="menu_link" id="menu_link"><br> -->
<input type="url" name="menu_link" placeholder="Menu Link (optional)" id="menu_link"/><br>
<!--<label for="food_type">Food Type:</label>
<input type="text" name="food_type" id="food_type" required><br> -->
<input type="text" name="food_type" placeholder="Food Type" id="food_type" required /><br>
<!--<label for="food_type_subcategory">Food Type Subcategory (optional):</label>
<input type="text" name="food_type_subcategory" id="food_type_subcategory"><br> -->
<input type="text" name="food_type_subcategory" placeholder="Keywords (comma seperated)" id="food_type_subcategory" /><br>
<button class="btn btn-primary btn-block btn-large" type="submit">Add Restaurant</button>
</form>
</div>
</body>
</html>
+203
View File
@@ -0,0 +1,203 @@
@import url(https://fonts.googleapis.com/css?family=Open+Sans);
.btn { display: inline-block; *display: inline; *zoom: 1; padding: 4px 10px 4px; margin-bottom: 0; font-size: 13px; line-height: 18px; color: #333333; text-align: center;text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); vertical-align: middle; background-color: #f5f5f5; background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); background-image: -ms-linear-gradient(top, #ffffff, #e6e6e6); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); background-image: linear-gradient(top, #ffffff, #e6e6e6); background-repeat: repeat-x; filter: progid:dximagetransform.microsoft.gradient(startColorstr=#ffffff, endColorstr=#e6e6e6, GradientType=0); border-color: #e6e6e6 #e6e6e6 #e6e6e6; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); border: 1px solid #e6e6e6; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); cursor: pointer; *margin-left: .3em; }
.btn:hover, .btn:active, .btn.active, .btn.disabled, .btn[disabled] { background-color: #e6e6e6; }
.btn-large { padding: 9px 14px; font-size: 15px; line-height: normal; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; }
.btn:hover { color: #333333; text-decoration: none; background-color: #e6e6e6; background-position: 0 -15px; -webkit-transition: background-position 0.1s linear; -moz-transition: background-position 0.1s linear; -ms-transition: background-position 0.1s linear; -o-transition: background-position 0.1s linear; transition: background-position 0.1s linear; }
.btn-primary, .btn-primary:hover { text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); color: #ffffff; }
.btn-primary.active { color: rgba(255, 255, 255, 0.75); }
.btn-primary { background-color: #4a77d4; background-image: -moz-linear-gradient(top, #6eb6de, #4a77d4); background-image: -ms-linear-gradient(top, #6eb6de, #4a77d4); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#6eb6de), to(#4a77d4)); background-image: -webkit-linear-gradient(top, #6eb6de, #4a77d4); background-image: -o-linear-gradient(top, #6eb6de, #4a77d4); background-image: linear-gradient(top, #6eb6de, #4a77d4); background-repeat: repeat-x; filter: progid:dximagetransform.microsoft.gradient(startColorstr=#6eb6de, endColorstr=#4a77d4, GradientType=0); border: 1px solid #3762bc; text-shadow: 1px 1px 1px rgba(0,0,0,0.4); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.5); }
.btn-primary:hover, .btn-primary:active, .btn-primary.active, .btn-primary.disabled, .btn-primary[disabled] { filter: none; background-color: #4a77d4; }
.btn-block { width: 100%; display:block; }
* { -webkit-box-sizing:border-box; -moz-box-sizing:border-box; -ms-box-sizing:border-box; -o-box-sizing:border-box; box-sizing:border-box; }
html { width: 100%; height:100%; }
body {
width: 100%;
height:100%;
font-family: 'Open Sans', sans-serif;
color: #ffffff;
a:link { color: cornflowerblue; } /* Unvisited link color */
a:visited { color: yellow; } /* Visited link color */
a:hover { color: red; } /* Hover color */
a:active { color: yellow; } /* Active link color */
background: #092756;
background: -moz-radial-gradient(0% 100%, ellipse cover, rgba(104,128,138,.4) 10%,rgba(138,114,76,0) 40%),-moz-linear-gradient(top, rgba(57,173,219,.25) 0%, rgba(42,60,87,.4) 100%), -moz-linear-gradient(-45deg, #670d10 0%, #092756 100%);
background: -webkit-radial-gradient(0% 100%, ellipse cover, rgba(104,128,138,.4) 10%,rgba(138,114,76,0) 40%), -webkit-linear-gradient(top, rgba(57,173,219,.25) 0%,rgba(42,60,87,.4) 100%), -webkit-linear-gradient(-45deg, #670d10 0%,#092756 100%);
background: -o-radial-gradient(0% 100%, ellipse cover, rgba(104,128,138,.4) 10%,rgba(138,114,76,0) 40%), -o-linear-gradient(top, rgba(57,173,219,.25) 0%,rgba(42,60,87,.4) 100%), -o-linear-gradient(-45deg, #670d10 0%,#092756 100%);
background: -ms-radial-gradient(0% 100%, ellipse cover, rgba(104,128,138,.4) 10%,rgba(138,114,76,0) 40%), -ms-linear-gradient(top, rgba(57,173,219,.25) 0%,rgba(42,60,87,.4) 100%), -ms-linear-gradient(-45deg, #670d10 0%,#092756 100%);
background: -webkit-radial-gradient(0% 100%, ellipse cover, rgba(104,128,138,.4) 10%,rgba(138,114,76,0) 40%), linear-gradient(to bottom, rgba(57,173,219,.25) 0%,rgba(42,60,87,.4) 100%), linear-gradient(135deg, #670d10 0%,#092756 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#3E1D6D', endColorstr='#092756',GradientType=1 );
}
.login {
position: absolute;
top: 15%;
left: 25%;
margin: -150px 0 0 -150px;
width:1000px;
height:2000px;
}
.login h1 { color: #fff; text-shadow: 0 0 12px rgba(0,0,0,0.3); letter-spacing:1px; text-align:center; }
.login h2 { color: cornflowerblue; text-shadow: 0 0 10px rgba(0,0,0,0.3); letter-spacing:1px; text-align:center; }
.login h3 { color: #fff; text-shadow: 0 0 8px rgba(0,0,0,0.3); letter-spacing:1px; text-align:center; }
input {
width: 100%;
margin-bottom: 10px;
background: rgba(0,0,0,0.3);
border: none;
outline: none;
padding: 10px;
font-size: 13px;
color: #fff;
text-shadow: 1px 1px 1px rgba(0,0,0,0.3);
border: 1px solid rgba(0,0,0,0.3);
border-radius: 4px;
box-shadow: inset 0 -5px 45px rgba(100,100,100,0.2), 0 1px 1px rgba(255,255,255,0.2);
-webkit-transition: box-shadow .5s ease;
-moz-transition: box-shadow .5s ease;
-o-transition: box-shadow .5s ease;
-ms-transition: box-shadow .5s ease;
transition: box-shadow .5s ease;
}
input:focus { box-shadow: inset 0 -5px 45px rgba(100,100,100,0.4), 0 1px 1px rgba(255,255,255,0.2); }
select {
/* styling */
background-color: white;
border: thin solid blue;
border-radius: 4px;
display: inline-block;
font: inherit;
line-height: 1.5em;
padding: 0.5em 3.5em 0.5em 1em;
/* reset */
margin: 0;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
-webkit-appearance: none;
-moz-appearance: none;
}
/* arrows */
select.classic {
background-image:
linear-gradient(45deg, transparent 50%, blue 50%),
linear-gradient(135deg, blue 50%, transparent 50%),
linear-gradient(to right, skyblue, skyblue);
background-position:
calc(100% - 20px) calc(1em + 2px),
calc(100% - 15px) calc(1em + 2px),
100% 0;
background-size:
5px 5px,
5px 5px,
2.5em 2.5em;
background-repeat: no-repeat;
}
select.classic:focus {
background-image:
linear-gradient(45deg, white 50%, transparent 50%),
linear-gradient(135deg, transparent 50%, white 50%),
linear-gradient(to right, gray, gray);
background-position:
calc(100% - 15px) 1em,
calc(100% - 20px) 1em,
100% 0;
background-size:
5px 5px,
5px 5px,
2.5em 2.5em;
background-repeat: no-repeat;
border-color: grey;
outline: 0;
}
select.round {
background-image:
linear-gradient(45deg, transparent 50%, gray 50%),
linear-gradient(135deg, gray 50%, transparent 50%),
radial-gradient(#ddd 70%, transparent 72%);
background-position:
calc(100% - 20px) calc(1em + 2px),
calc(100% - 15px) calc(1em + 2px),
calc(100% - .5em) .5em;
background-size:
5px 5px,
5px 5px,
1.5em 1.5em;
background-repeat: no-repeat;
}
select.round:focus {
background-image:
linear-gradient(45deg, white 50%, transparent 50%),
linear-gradient(135deg, transparent 50%, white 50%),
radial-gradient(gray 70%, transparent 72%);
background-position:
calc(100% - 15px) 1em,
calc(100% - 20px) 1em,
calc(100% - .5em) .5em;
background-size:
5px 5px,
5px 5px,
1.5em 1.5em;
background-repeat: no-repeat;
border-color: green;
outline: 0;
}
select.minimal {
background-image:
linear-gradient(45deg, transparent 50%, gray 50%),
linear-gradient(135deg, gray 50%, transparent 50%),
linear-gradient(to right, #ccc, #ccc);
background-position:
calc(100% - 20px) calc(1em + 2px),
calc(100% - 15px) calc(1em + 2px),
calc(100% - 2.5em) 0.5em;
background-size:
5px 5px,
5px 5px,
1px 1.5em;
background-repeat: no-repeat;
}
select.minimal:focus {
background-image:
linear-gradient(45deg, green 50%, transparent 50%),
linear-gradient(135deg, transparent 50%, green 50%),
linear-gradient(to right, #ccc, #ccc);
background-position:
calc(100% - 15px) 1em,
calc(100% - 20px) 1em,
calc(100% - 2.5em) 0.5em;
background-size:
5px 5px,
5px 5px,
1px 1.5em;
background-repeat: no-repeat;
border-color: green;
outline: 0;
}
select:-moz-focusring {
color: transparent;
text-shadow: 0 0 0 #000;
}
+150
View File
@@ -0,0 +1,150 @@
body{
margin:0;
color:#6a6f8c;
background:#c8c8c8;
font:600 16px/18px 'Open Sans',sans-serif;
}
*,:after,:before{box-sizing:border-box}
.clearfix:after,.clearfix:before{content:'';display:table}
.clearfix:after{clear:both;display:block}
a{color:inherit;text-decoration:none}
.login-wrap{
width:100%;
margin:auto;
max-width:525px;
min-height:670px;
position:relative;
background:url(https://raw.githubusercontent.com/khadkamhn/day-01-login-form/master/img/bg.jpg) no-repeat center;
box-shadow:0 12px 15px 0 rgba(0,0,0,.24),0 17px 50px 0 rgba(0,0,0,.19);
}
.login-html{
width:100%;
height:100%;
position:absolute;
padding:90px 70px 50px 70px;
background:rgba(40,57,101,.9);
}
.login-html .sign-in-htm,
.login-html .sign-up-htm{
top:0;
left:0;
right:0;
bottom:0;
position:absolute;
transform:rotateY(180deg);
backface-visibility:hidden;
transition:all .4s linear;
}
.login-html .sign-in,
.login-html .sign-up,
.login-form .group .check{
display:none;
}
.login-html .tab,
.login-form .group .label,
.login-form .group .button{
text-transform:uppercase;
}
.login-html .tab{
font-size:22px;
margin-right:15px;
padding-bottom:5px;
margin:0 15px 10px 0;
display:inline-block;
border-bottom:2px solid transparent;
}
.login-html .sign-in:checked + .tab,
.login-html .sign-up:checked + .tab{
color:#fff;
border-color:#1161ee;
}
.login-form{
min-height:345px;
position:relative;
perspective:1000px;
transform-style:preserve-3d;
}
.login-form .group{
margin-bottom:15px;
}
.login-form .group .label,
.login-form .group .input,
.login-form .group .button{
width:100%;
color:#fff;
display:block;
}
.login-form .group .input,
.login-form .group .button{
border:none;
padding:15px 20px;
border-radius:25px;
background:rgba(255,255,255,.1);
}
.login-form .group input[data-type="password"]{
text-security:circle;
-webkit-text-security:circle;
}
.login-form .group .label{
color:#aaa;
font-size:12px;
}
.login-form .group .button{
background:#1161ee;
}
.login-form .group label .icon{
width:15px;
height:15px;
border-radius:2px;
position:relative;
display:inline-block;
background:rgba(255,255,255,.1);
}
.login-form .group label .icon:before,
.login-form .group label .icon:after{
content:'';
width:10px;
height:2px;
background:#fff;
position:absolute;
transition:all .2s ease-in-out 0s;
}
.login-form .group label .icon:before{
left:3px;
width:5px;
bottom:6px;
transform:scale(0) rotate(0);
}
.login-form .group label .icon:after{
top:6px;
right:0;
transform:scale(0) rotate(0);
}
.login-form .group .check:checked + label{
color:#fff;
}
.login-form .group .check:checked + label .icon{
background:#1161ee;
}
.login-form .group .check:checked + label .icon:before{
transform:scale(1) rotate(45deg);
}
.login-form .group .check:checked + label .icon:after{
transform:scale(1) rotate(-45deg);
}
.login-html .sign-in:checked + .tab + .sign-up + .tab + .login-form .sign-in-htm{
transform:rotate(0);
}
.login-html .sign-up:checked + .tab + .login-form .sign-up-htm{
transform:rotate(0);
}
.hr{
height:2px;
margin:60px 0 50px 0;
background:rgba(255,255,255,.2);
}
.foot-lnk{
text-align:center;
}
+21
View File
@@ -0,0 +1,21 @@
<?php
// Start the session if not already started
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
// Check if the user is logged in and display the appropriate link
if (isset($_SESSION['admin_logged_in']) && $_SESSION['admin_logged_in'] === true) {
echo '
<table width="600" border="0">
<tbody>
<tr>
<td width="103"><a href="index.php">Home</a></td>
<td width="163"><a href="admin_portal.php">Add Restaurants</a></td>
<td width="208"><a href="manage.php">Manage Restaurants</a></td>
</tbody>
</table>';
} else {
echo '<a href="admin_login.php">Login</a>';
}
?>
+88
View File
@@ -0,0 +1,88 @@
<?php
require 'db.php';
session_start();
if (!isset($_SESSION['admin_logged_in']) || !$_SESSION['admin_logged_in']) {
header('Location: admin_login.php');
exit;
}
$id = $_GET['id'];
$stmt = $pdo->prepare("SELECT * FROM restaurants WHERE id = :id");
$stmt->execute(['id' => $id]);
$restaurant = $stmt->fetch();
if (!$restaurant) {
echo "Restaurant not found.";
exit;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = $_POST['name'];
$google_map_link = $_POST['google_map_link'];
$menu_link = $_POST['menu_link'];
$cost_category = $_POST['cost_category'];
$food_type = $_POST['food_type'];
$food_type_subcategory = $_POST['food_type_subcategory'];
$stmt = $pdo->prepare("
UPDATE restaurants
SET name = :name, google_map_link = :google_map_link, menu_link = :menu_link,
cost_category = :cost_category, food_type = :food_type, food_type_subcategory = :food_type_subcategory
WHERE id = :id
");
$stmt->execute([
'name' => $name,
'google_map_link' => $google_map_link,
'menu_link' => $menu_link,
'cost_category' => $cost_category,
'food_type' => $food_type,
'food_type_subcategory' => $food_type_subcategory,
'id' => $id,
]);
header('Location: manage.php');
exit;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="/css/main.css">
<title>Restaurant Picker - Edit Restaurant</title>
</head>
<body>
<div class="login">
<?php include "header.php"; ?>
<h2>Edit Restaurant</h2>
<form method="POST">
<label for="cost_category">Price:&nbsp;</label>
<select class="minimal" name="cost_category" id="cost_category" required>
<option value="cheap" <?= $restaurant['cost_category'] === 'cheap' ? 'selected' : '' ?>>Cheap</option>
<option value="moderate" <?= $restaurant['cost_category'] === 'moderate' ? 'selected' : '' ?>>Moderate</option>
<option value="expensive" <?= $restaurant['cost_category'] === 'expensive' ? 'selected' : '' ?>>Expensive</option>
</select><br>
<br />
<label for="name">Restaurant Name:</label>
<input type="text" name="name" id="name" value="<?= htmlspecialchars($restaurant['name']) ?>" required><br>
<label for="google_map_link">Google Map Link:</label>
<input type="url" name="google_map_link" id="google_map_link" value="<?= htmlspecialchars($restaurant['google_map_link']) ?>" required><br>
<label for="menu_link">Menu Link (optional):</label>
<input type="url" name="menu_link" id="menu_link" value="<?= htmlspecialchars($restaurant['menu_link']) ?>"><br>
<label for="food_type">Food Type:</label>
<input type="text" name="food_type" id="food_type" value="<?= htmlspecialchars($restaurant['food_type']) ?>" required><br>
<label for="food_type_subcategory">Food Type Subcategory (optional):</label>
<input type="text" name="food_type_subcategory" id="food_type_subcategory" value="<?= htmlspecialchars($restaurant['food_type_subcategory']) ?>"><br>
<button class="btn btn-primary btn-block btn-large" type="submit">Update Restaurant</button>
</form>
</div>
</body>
</html>
+26
View File
@@ -0,0 +1,26 @@
<p align="center"><img src="images/restaurant_logo.png" width="150" align="middle"></src></p>
<h1>Restaurant Picker</h1>
<?php
// Start the session if not already started
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
// Check if the user is logged in and display the appropriate link
if (isset($_SESSION['admin_logged_in']) && $_SESSION['admin_logged_in'] === true) {
echo '
<table border="0">
<tbody>
<tr>
<td width="103"><a href="index.php">Home</a></td>
<td width="180"><a href="admin_portal.php">Add Restaurants</a></td>
<td width="208"><a href="manage.php">Manage Restaurants</a></td>
<td width="208"><a href="usradm.php">Manage Users</a></td>
<td width="208"><a href="logout.php">Log Out</a></td>
</tbody>
</table>';
} else {
echo '<p align="right"><a href="admin_login.php">Admin</a></p>';
}
?>
<br />
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

+144
View File
@@ -0,0 +1,144 @@
<?php
require 'db.php';
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$cost_category = $_POST['cost_category'] ?? '';
$food_type = $_POST['food_type'] ?? '';
$food_type_subcategory = $_POST['food_type_subcategory'] ?? '';
// Start building the query
$query = "SELECT * FROM restaurants WHERE 1=1"; // Always true condition to avoid extra WHERE clauses
$params = [];
// Only apply the cost category filter if it's not 'any'
if ($cost_category && $cost_category !== 'any') {
$query .= " AND cost_category = :cost_category";
$params['cost_category'] = $cost_category;
}
// Only apply the food type filter if it's not 'any'
if ($food_type && $food_type !== 'any') {
$query .= " AND food_type = :food_type";
$params['food_type'] = $food_type;
}
// Apply the food type subcategory filter if provided
if (!empty($food_type_subcategory)) {
// Split the subcategory into keywords by commas and trim any spaces
$keywords = array_map('trim', explode(',', $food_type_subcategory));
// Create an array of LIKE conditions for each keyword
$subquery = [];
foreach ($keywords as $index => $keyword) {
// Use LIKE to match the subcategory
$subquery[] = "food_type_subcategory LIKE :food_type_subcategory_{$index}";
$params["food_type_subcategory_{$index}"] = "%{$keyword}%";
}
// Join the subqueries with OR to match any of the keywords
$query .= " AND (" . implode(' OR ', $subquery) . ")";
}
// Random selection with a limit of 1 result
$query .= " ORDER BY RAND() LIMIT 1";
// Prepare and execute the query
$stmt = $pdo->prepare($query);
$stmt->execute($params);
$restaurant = $stmt->fetch();
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="/css/main.css">
<title>Restaurant Picker</title>
<script>
document.addEventListener("DOMContentLoaded", () => {
const subcategoryInput = document.getElementById("food_type_subcategory");
subcategoryInput.addEventListener("input", () => {
const query = subcategoryInput.value;
if (query.length < 2) return;
fetch(`subcategory_suggestions.php?q=${encodeURIComponent(query)}`)
.then(response => response.json())
.then(data => {
const datalist = document.getElementById("subcategorySuggestions");
datalist.innerHTML = "";
data.forEach(keyword => {
const option = document.createElement("option");
option.value = keyword;
datalist.appendChild(option);
});
});
});
});
</script>
</head>
<body>
<div class="login">
<?php include "header.php"; ?>
<form method="post">
<label for="cost_category">Price:&nbsp;</label>
<select class="minimal" name="cost_category" id="cost_category" required>
<option value="any">Any</option>
<option value="cheap">Cheap</option>
<option value="moderate">Moderate</option>
<option value="expensive">Expensive</option>
</select><br>
<br />
<label for="food_type">Cuisine:&nbsp;</label>
<select class="minimal" name="food_type" id="food_type" required>
<option value="any">Any</option>
<?php
$types = $pdo->query("SELECT DISTINCT food_type FROM restaurants")->fetchAll();
foreach ($types as $type) {
echo "<option value=\"" . htmlspecialchars($type['food_type']) . "\">" . htmlspecialchars($type['food_type']) . "</option>";
}
?>
</select><br>
<br />
<input type="text" name="food_type_subcategory" placeholder="Keyword(s)" id="food_type_subcategory" list="subcategorySuggestions" />
<datalist id="subcategorySuggestions"></datalist><br>
<button type="submit" class="btn btn-primary btn-block btn-large">Find Restaurant</button>
</form>
<?php if (!empty($restaurant)): ?>
<h3>Selected Restaurant:</h3>
<p><h2><b><?= htmlspecialchars($restaurant['name']) ?>&nbsp;<img src="images/arrow_sm.png"></img></b></h2></p>
<p><a href="<?= htmlspecialchars($restaurant['menu_link']) ?>" target="_blank">View Menu</a></p>
<?php
// Extract the base URL and the query parameters
$baseUrl = "https://www.google.com/maps/embed";
$queryString = parse_url($restaurant['google_map_link'], PHP_URL_QUERY);
// Encode the query string only
$encodedQuery = urlencode($queryString);
// Rebuild the final URL
$finalMapUrl = $baseUrl . "?pb=" . $encodedQuery;
?>
<p align="center">
<iframe
src="<?= htmlspecialchars($restaurant['google_map_link']) ?>"
width="600"
height="450"
style="border:0;"
allowfullscreen=""
loading="lazy">
</iframe>
<br />
<br />
</p>
<?php else: ?>
<p>No results found based on your criteria.</p>
<?php endif; ?>
<br />
</div>
</body>
</html>
+6
View File
@@ -0,0 +1,6 @@
<?php
session_start();
session_destroy();
header('Location: index.php');
exit;
?>
+69
View File
@@ -0,0 +1,69 @@
<?php
require 'db.php';
session_start();
if (!isset($_SESSION['admin_logged_in']) || !$_SESSION['admin_logged_in']) {
header('Location: admin_login.php');
exit;
}
// Handle Delete Request
if (isset($_GET['delete_id'])) {
$delete_id = $_GET['delete_id'];
$stmt = $pdo->prepare("DELETE FROM restaurants WHERE id = :id");
$stmt->execute(['id' => $delete_id]);
header('Location: admin_portal.php');
exit;
}
// Fetch Restaurants for Display
$restaurants = $pdo->query("SELECT * FROM restaurants")->fetchAll();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="/css/main.css">
<title>Admin Portal</title>
</head>
<body>
<div class="login">
<?php include "header.php"; ?>
<h2>Manage Restaurants</h2>
<?php if (!empty($success)): ?>
<p style="color: green;"><?= htmlspecialchars($success) ?></p>
<?php endif; ?>
<table border="1">
<tr>
<th>Name</th>
<th>Menu Link</th>
<th>Cost Category</th>
<th>Food Type</th>
<th>Subcategory</th>
<th>Actions</th>
</tr>
<?php foreach ($restaurants as $restaurant): ?>
<tr>
<td><?= htmlspecialchars($restaurant['name']) ?></td>
<td>
<?php if ($restaurant['menu_link']): ?>
<a href="<?= htmlspecialchars($restaurant['menu_link']) ?>" target="_blank">View Menu</a>
<?php else: ?>
N/A
<?php endif; ?>
</td>
<td><?= htmlspecialchars($restaurant['cost_category']) ?></td>
<td><?= htmlspecialchars($restaurant['food_type']) ?></td>
<td><?= htmlspecialchars($restaurant['food_type_subcategory']) ?></td>
<td>
<a href="edit_restaurant.php?id=<?= $restaurant['id'] ?>">Edit</a>
|
<a href="?delete_id=<?= $restaurant['id'] ?>" onclick="return confirm('Are you sure you want to delete this restaurant?');">Delete</a>
</td>
</tr>
<?php endforeach; ?>
</table>
</div>
</body>
</html>
+26
View File
@@ -0,0 +1,26 @@
<?php
require 'db.php';
$query = $_GET['q'] ?? '';
$suggestions = [];
if (!empty($query)) {
$stmt = $pdo->prepare("
SELECT DISTINCT food_type_subcategory
FROM restaurants
WHERE food_type_subcategory LIKE :query
");
$stmt->execute(['query' => "%$query%"]);
while ($row = $stmt->fetch()) {
$keywords = array_map('trim', explode(',', $row['food_type_subcategory']));
foreach ($keywords as $keyword) {
if (stripos($keyword, $query) !== false && !in_array($keyword, $suggestions)) {
$suggestions[] = $keyword;
}
}
}
}
header('Content-Type: application/json');
echo json_encode($suggestions);
+122
View File
@@ -0,0 +1,122 @@
<?php
require 'db.php';
session_start();
if (!isset($_SESSION['admin_logged_in']) || !$_SESSION['admin_logged_in']) {
header('Location: admin_login.php');
exit;
}
// Handle adding a new user
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'add_user') {
$username = $_POST['username'];
$password = $_POST['password_hash'];
// Hash the password for secure storage
$password_hash = password_hash($password, PASSWORD_BCRYPT);
try {
$stmt = $pdo->prepare("INSERT INTO admin_users (username, password_hash) VALUES (:username, :password_hash)");
$stmt->execute(['username' => $username, 'password_hash' => $password_hash]);
$message = "User added successfully!";
} catch (PDOException $e) {
$message = "Error: " . $e->getMessage();
}
}
// Handle deleting a user
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'delete_user') {
$user_id = $_POST['user_id'];
try {
$stmt = $pdo->prepare("DELETE FROM admin_users WHERE id = :id");
$stmt->execute(['id' => $user_id]);
$message = "User deleted successfully!";
} catch (PDOException $e) {
$message = "Error: " . $e->getMessage();
}
}
// Handle updating a user's password
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'update_password') {
$user_id = $_POST['user_id'];
$new_password = $_POST['new_password'];
// Hash the new password
$password_hash = password_hash($new_password, PASSWORD_BCRYPT);
try {
$stmt = $pdo->prepare("UPDATE admin_users SET password_hash = :password_hash WHERE id = :id");
$stmt->execute(['password_hash' => $password_hash, 'id' => $user_id]);
$message = "Password updated successfully!";
} catch (PDOException $e) {
$message = "Error: " . $e->getMessage();
}
}
// Fetch all users
$users = $pdo->query("SELECT id, username FROM admin_users")->fetchAll(PDO::FETCH_ASSOC);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="/css/main.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Admin - User Management</title>
</head>
<body>
<div class="login">
<?php include "header.php"; ?>
<h2>Admin - User Management</h2>
<?php if (isset($message)): ?>
<p style="color:green;"><?= htmlspecialchars($message) ?></p>
<?php endif; ?>
<h3>Add a New User</h3>
<form method="POST">
<input type="hidden" name="action" value="add_user">
<!-- <label>Username: <input type="text" name="username" required></label><br> -->
<input type="text" name="username" placeholder="Username" required /><br>
<!-- <label>Password: <input type="password" name="password" required></label><br> -->
<input type="password" name="password" placeholder="Password" required /><br>
<button class="btn btn-primary btn-block btn-large" type="submit">Add User</button>
</form>
<h3>Existing Users</h3>
<table width="800" border="1">
<tr>
<th width="17">ID</th>
<th width="82">Username</th>
<th width="66">Actions</th>
<th width="66">Password</th>
</tr>
<?php foreach ($users as $user): ?>
<tr>
<td><?= htmlspecialchars($user['id']) ?></td>
<td><?= htmlspecialchars($user['username']) ?></td>
<td>
<!-- Delete User -->
<form method="POST" style="display:inline;">
<input type="hidden" name="action" value="delete_user">
<input type="hidden" name="user_id" value="<?= $user['id'] ?>">
<button class="btn btn-primary btn-block btn-large" type="submit" style="color:red;" onclick="return confirm('Are you sure you want to delete this restaurant?');">Delete</button>
</form>
</td>
<td width="362">
<!-- Update Password -->
<form method="POST" style="display:inline;">
<input type="hidden" name="action" value="update_password">
<input type="hidden" name="user_id" value="<?= $user['id'] ?>">
<!-- <label>New Password: <input type="password" name="new_password" required></label> -->
<input type="password" name="new_password" placeholder="New Password" required /><br>
<button class="btn btn-primary btn-block btn-large" type="submit">Update Password</button>
</form>
</td>
</tr>
<?php endforeach; ?>
</table>
</div>
</body>
</html>