diff --git a/app/Filter-Window/AllergyFilterPage.module.css b/app/Filter-Window/AllergyFilterPage.module.css
new file mode 100644
index 0000000..688a72b
--- /dev/null
+++ b/app/Filter-Window/AllergyFilterPage.module.css
@@ -0,0 +1,41 @@
+/* AllergyFilterPage.module.css */
+
+.container {
+ @apply flex flex-col justify-center items-center min-h-screen py-12;
+}
+
+.columns {
+ @apply flex justify-center items-start space-x-8;
+}
+
+.submitButtons {
+ @apply flex justify-center mt-8; /* Adjust the margin-top */
+}
+
+.submitButton {
+ @apply mx-2; /* Add margin to each button */
+}
+
+.filterText {
+ font-size: 3rem; /* Adjust the font size as needed */
+ color: #003c6c; /* Set the text color */
+ font-weight: 600; /* Set the font weight */
+ padding-top: 1.25rem; /* Match the py-5 padding top */
+ display: center; /* Match the flex display */
+ align-items: center; /* Match the items-center alignment */
+ justify-content: center; /* Match the justify-center alignment */
+}
+
+.filterTopLeft {
+ position: absolute;
+ align-items: center;
+ top: 10rem; /* Adjust the top position as needed */
+ left: 80 rem; /* Adjust the left position as needed */
+ margin: 0; /* Remove the margin */
+}
+
+.submitButton:hover {
+ text-decoration: underline;
+ text-underline-offset: 0.2em;
+ text-decoration-color: #ffea00;
+}
diff --git a/app/Filter-Window/page.tsx b/app/Filter-Window/page.tsx
new file mode 100644
index 0000000..e6426c1
--- /dev/null
+++ b/app/Filter-Window/page.tsx
@@ -0,0 +1,164 @@
+"use client";
+import React, { useState, useEffect } from "react";
+import styles from "./AllergyFilterPage.module.css";
+
+const AllergyFilterPage = () => {
+ const [selectedHideAllergies, setSelectedHideAllergies] = useState(() => {
+ const storedHideAllergies = localStorage.getItem("hideAllergies");
+ return storedHideAllergies ? JSON.parse(storedHideAllergies) : [];
+ });
+
+ const [selectedShowAllergies, setSelectedShowAllergies] = useState(() => {
+ const storedShowAllergies = localStorage.getItem("showAllergies");
+ return storedShowAllergies ? JSON.parse(storedShowAllergies) : [];
+ });
+
+ const hideAllergies = [
+ "milk",
+ "eggs",
+ "fish",
+ "shellfish",
+ "treenut",
+ "nuts",
+ "wheat",
+ "soy",
+ "gluten",
+ "sesame",
+ "alcohol",
+ ];
+ const showAllergies = [
+ "eggs",
+ "fish",
+ "gluten",
+ "milk",
+ "nuts",
+ "soy",
+ "vegan",
+ "veggie",
+ "pork",
+ "beef",
+ "halal",
+ "shellfish",
+ "treenut",
+ "alcohol",
+ "sesame",
+ ];
+
+ const handleReset = () => {
+ setSelectedHideAllergies([]);
+ setSelectedShowAllergies([]);
+ };
+
+ const handleCancel = () => {
+ setSelectedHideAllergies([]);
+ setSelectedShowAllergies([]);
+ window.location.href = "global_search";
+ };
+
+ const handleApply = () => {
+ localStorage.setItem(
+ "hideAllergies",
+ JSON.stringify(selectedHideAllergies),
+ );
+ localStorage.setItem(
+ "showAllergies",
+ JSON.stringify(selectedShowAllergies),
+ );
+ console.log("Hide Allergies:", selectedHideAllergies);
+ console.log("Show Allergies:", selectedShowAllergies);
+ window.location.href = "global_search";
+ };
+
+ const handleCheckboxChange = (allergy, type) => {
+ if (type === "hide") {
+ if (selectedHideAllergies.includes(allergy)) {
+ setSelectedHideAllergies(
+ selectedHideAllergies.filter((item) => item !== allergy),
+ );
+ } else {
+ setSelectedHideAllergies([...selectedHideAllergies, allergy]);
+ }
+ } else {
+ if (selectedShowAllergies.includes(allergy)) {
+ setSelectedShowAllergies(
+ selectedShowAllergies.filter((item) => item !== allergy),
+ );
+ } else {
+ setSelectedShowAllergies([...selectedShowAllergies, allergy]);
+ }
+ }
+ };
+
+ return (
+
+
Filter
+
+
+
+ Hide Items that contain:
+
+
+ {hideAllergies.map((allergy, index) => (
+
+
+
+ ))}
+
+
+
+
+
+ Show items that match:
+
+
+ {showAllergies.map((allergy, index) => (
+
+
+
+ ))}
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default AllergyFilterPage;
diff --git a/app/global_search/Search.module.css b/app/global_search/Search.module.css
new file mode 100644
index 0000000..edf7cf6
--- /dev/null
+++ b/app/global_search/Search.module.css
@@ -0,0 +1,17 @@
+.filterText {
+ font-size: 3rem; /* Adjust the font size as needed */
+ color: #003c6c; /* Set the text color */
+ font-weight: 600; /* Set the font weight */
+ padding-top: 1.25rem; /* Match the py-5 padding top */
+ display: center; /* Match the flex display */
+ align-items: center; /* Match the items-center alignment */
+ justify-content: center; /* Match the justify-center alignment */
+}
+
+.filterTopLeft {
+ position: absolute;
+ align-items: center;
+ top: 3rem; /* Adjust the top position as needed */
+ left: 80 rem; /* Adjust the left position as needed */
+ margin: 0; /* Remove the margin */
+}
diff --git a/app/global_search/page.tsx b/app/global_search/page.tsx
index 01563b2..eb58105 100644
--- a/app/global_search/page.tsx
+++ b/app/global_search/page.tsx
@@ -1,9 +1,11 @@
"use client";
import React, { useState, useEffect } from "react";
import axios from "axios";
+import styles from "./Search.module.css";
interface Food {
name: string;
+ restrictions: string[]; // Change to string array
}
interface subCategory {
@@ -18,8 +20,29 @@ interface Category {
interface DiningHall {
name: string;
- categories: Category[];
+ categories: Array;
}
+interface RestrictionImageMap {
+ [key: string]: string;
+}
+
+const restrictionImageMap = {
+ eggs: "/Images/egg.jpg",
+ vegan: "/Images/vegan.jpg",
+ fish: "/Images/fish.jpg",
+ veggie: "/Images/veggie.jpg",
+ gluten: "/Images/gluten.jpg",
+ pork: "/Images/pork.jpg",
+ milk: "/Images/milk.jpg",
+ beef: "/Images/beef.jpg",
+ nuts: "/Images/nuts.jpg",
+ halal: "/Images/halal.jpg",
+ soy: "/Images/soy.jpg",
+ shellfish: "/Images/shellfish.jpg",
+ treenut: "/Images/treenut.jpg",
+ sesame: "/Images/sesame.jpg",
+ alcohol: "/Images/alcohol.jpg",
+};
const BarebonesComponent = () => {
const [dhs, setDhs] = useState([]);
@@ -30,6 +53,21 @@ const BarebonesComponent = () => {
const [showSearchResults, setShowSearchResults] = useState(false);
const [noFoodsFound, setNoFoodsFound] = useState(false);
+ // Retrieve hide and show allergies from local storage
+ const [selectedHideAllergies, setSelectedHideAllergies] = useState(
+ () => {
+ const storedHideAllergies = localStorage.getItem("hideAllergies");
+ return storedHideAllergies ? JSON.parse(storedHideAllergies) : [];
+ },
+ );
+
+ const [selectedShowAllergies, setSelectedShowAllergies] = useState(
+ () => {
+ const storedShowAllergies = localStorage.getItem("showAllergies");
+ return storedShowAllergies ? JSON.parse(storedShowAllergies) : [];
+ },
+ );
+
useEffect(() => {
axios
.get("http://localhost:8000/myapi/locations/")
@@ -48,6 +86,10 @@ const BarebonesComponent = () => {
setSearchInput(event.target.value);
};
+ const handleFilter = () => {
+ window.location.href = "Filter-Window";
+ };
+
const handleSearch = () => {
const allFoods: { food: Food; dhName: string; categoryName: string }[] = [];
dhs.forEach((dh) => {
@@ -68,8 +110,28 @@ const BarebonesComponent = () => {
food.name.toLowerCase().includes(searchInput.toLowerCase()),
);
- setNoFoodsFound(filtered.length === 0);
- setFilteredFoods(filtered);
+ // Check if all boxes are unchecked
+ const allBoxesUnchecked =
+ selectedShowAllergies.length === 0 && selectedHideAllergies.length === 0;
+
+ let finalFilteredFoods = filtered;
+ if (!allBoxesUnchecked) {
+ // Filter foods based on selectedShowAllergies and selectedHideAllergies
+ finalFilteredFoods = filtered.filter(({ food }) => {
+ const hasShowAllergy =
+ selectedShowAllergies.length === 0 ||
+ selectedShowAllergies.every((allergy) =>
+ food.name.toLowerCase().includes(allergy.toLowerCase()),
+ );
+ const hasHideAllergy = selectedHideAllergies.some(
+ (allergy) => food.restrictions.includes(allergy.toLowerCase()), // Check if food's restrictions include the hide allergy
+ );
+ return hasShowAllergy && !hasHideAllergy;
+ });
+ }
+
+ setNoFoodsFound(finalFilteredFoods.length === 0);
+ setFilteredFoods(finalFilteredFoods);
setShowSearchResults(true);
};
@@ -77,20 +139,46 @@ const BarebonesComponent = () => {
- {/* Title */}
-
Welcome to Hungry Slugs!
- {/* Search bar */}
-
- {" "}
- {/* Adjust margin as needed */}
-
-
+ {/* Title and Search bar */}
+
+
+ Global Search
+
+
+
+
+ {/* Filter button */}
+
+ Filter
+
+
+
{/* Display search results if button clicked */}
{showSearchResults && (
@@ -99,6 +187,16 @@ const BarebonesComponent = () => {
{filteredFoods.map(({ food, dhName, categoryName }, index) => (
{food.name} - {categoryName} ({dhName})
+
+ {food.restrictions.map((restriction, index) => (
+

+ ))}
+
))}
diff --git a/app/locations/[location]/page.tsx b/app/locations/[location]/page.tsx
index 3cbb6d2..c659265 100644
--- a/app/locations/[location]/page.tsx
+++ b/app/locations/[location]/page.tsx
@@ -5,12 +5,12 @@ import LocationFood from "@/components/location/food";
interface Food {
name: string;
- restrictions: Array
;
+ restrictions: string[]; // Change to string array
}
interface SubCategory {
name: string;
- foods: Array;
+ foods: Food[]; // Update to use the Food interface
}
interface Category {
@@ -23,31 +23,65 @@ interface Location {
categories: Category[];
}
+interface RestrictionImageMap {
+ [key: string]: string;
+}
+
+const restrictionImageMap = {
+ eggs: "/Images/egg.jpg",
+ vegan: "/Images/vegan.jpg",
+ fish: "/Images/fish.jpg",
+ veggie: "/Images/veggie.jpg",
+ gluten: "/Images/gluten.jpg",
+ pork: "/Images/pork.jpg",
+ milk: "/Images/milk.jpg",
+ beef: "/Images/beef.jpg",
+ nuts: "/Images/nuts.jpg",
+ halal: "/Images/halal.jpg",
+ soy: "/Images/soy.jpg",
+ shellfish: "/Images/shellfish.jpg",
+ treenut: "/Images/treenut.jpg",
+ sesame: "/Images/sesame.jpg",
+ alcohol: "/Images/alcohol.jpg",
+};
+
export default function Page({ params }: { params: { location: number } }) {
- const [location, setLocation] = useState();
- const [showCategories, setShowCategories] = useState();
+ const [location, setLocation] = useState(null);
+ const [showCategories, setShowCategories] = useState([]);
- // fetch location data
useEffect(() => {
axios
- .get("http://localhost:8000/myapi/locations/")
+ .get("http://localhost:8000/myapi/locations/")
.then((response) => {
- // Fetch the locations data
const locations: Location[] = response.data["locations"];
-
- // get the location data
const location = locations[params.location];
-
- // Set the location
setLocation(location);
- // Set the show categories to array of booleans
- setShowCategories(new Array(location.categories.length).fill(true));
+ // Get current hour
+ const currentHour = new Date().getHours();
+
+ // Set showCategories based on the time of day
+ setShowCategories(
+ new Array(location.categories.length).fill(false).map((_, index) => {
+ switch (index) {
+ case 0: // Breakfast (6 AM - 11 AM)
+ return currentHour >= 6 && currentHour < 11;
+ case 1: // Lunch (11 AM - 1 PM)
+ return currentHour >= 11 && currentHour < 15;
+ case 2: // Dinner (6 PM - 9 PM)
+ return currentHour >= 15 && currentHour < 20;
+ case 3: // Late Night (9 PM - 12 AM)
+ return currentHour >= 20 && currentHour < 24;
+ default:
+ return false;
+ }
+ }),
+ );
})
.catch((error) => {
console.log(error);
});
- }, [params.location]); // params.location is a dependency
+ }, [params.location]);
const handleDiningHallSearch = () => {
@@ -86,7 +120,9 @@ export default function Page({ params }: { params: { location: number } }) {
{/* Icon for accordion that will face up on false and down on true */}
diff --git a/backend/webscraper/food.py b/backend/webscraper/food.py
index 3e9daa2..0a22f09 100644
--- a/backend/webscraper/food.py
+++ b/backend/webscraper/food.py
@@ -1,7 +1,27 @@
from bs4.element import Tag
+
class Food:
+
+ restriction_image_map = {
+ "eggs": "app/locations/Images/egg.jpg",
+ "vegan": "app/locations/Images/vegan.jpg",
+ "fish": "app/locations/Images/fish.jpg",
+ "veggie": "app/locations/Images/veggie.jpg",
+ "gluten": "app/locations/Images/gluten.jpg",
+ "pork": "app/locations/Images/pork.jpg",
+ "milk": "app/locations/Images/milk.jpg",
+ "beef": "app/locations/Images/beef.jpg",
+ "nuts": "app/locations/Images/nuts.jpg",
+ "halal": "app/locations/Images/halal.jpg",
+ "soy": "app/locations/Images/soy.jpg",
+ "shellfish": "app/locations/Images/shellfish.jpg",
+ "treenut": "app/locations/Images/treenut.jpg",
+ "sesame": "app/locations/Images/sesame.jpg",
+ "alcohol": "app/locations/Images/alcohol.jpg",
+ }
+
def __init__(self, html: Tag) -> None:
self.name = "Error: Food name not found"
self.allergies = []
@@ -26,4 +46,4 @@ def __str__(self) -> str:
def to_dict(self) -> dict:
# foodObj = {self.name: self.allergies}
- return {"name": self.name, "restrictions": self.allergies}
+ return {"name": self.name, "restrictions": self.allergies, "restriction_image_map": self.restriction_image_map}
diff --git a/components/location/food.tsx b/components/location/food.tsx
index 2fc9219..8e8f937 100644
--- a/components/location/food.tsx
+++ b/components/location/food.tsx
@@ -2,10 +2,10 @@ import Link from "next/link";
export default function LocationFood({
food_name,
- restrictions,
+ restriction_images,
}: {
food_name: string;
- restrictions: string[];
+ restriction_images: string[]; // Change the type to string array
}) {
return (
@@ -13,9 +13,10 @@ export default function LocationFood({
{food_name}
- {restrictions.map((restriction, l) => (
- -
- {restriction}
+ {restriction_images.map((image, index) => (
+
-
+
{" "}
+ {/* Display the image */}
))}
diff --git a/loader.js b/loader.js
new file mode 100644
index 0000000..0f0c13e
--- /dev/null
+++ b/loader.js
@@ -0,0 +1,5 @@
+function imageLoader({ src }) {
+ return `/images/${src}`; // REPLACE WITH YOUR IMAGE DIRECTORY
+}
+
+module.exports = imageLoader;