diff --git a/app/global_search/Search.module.css b/app/global_search/Search.module.css index edf7cf6..a8cfc9a 100644 --- a/app/global_search/Search.module.css +++ b/app/global_search/Search.module.css @@ -1,17 +1,74 @@ -.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; +.container { + display: flex; + flex-direction: column; 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 */ +} + +.title { + font-size: 60px; + margin-bottom: 20px; + color: #003c6c; + font-weight: 600; + text-align: center; +} + +.searchBar { + display: flex; + align-items: center; + margin-top: 20px; +} + +.searchInput { + padding: 10px; + font-size: 16px; + border: 1px solid #ccc; + border-radius: 5px; + margin-right: 10px; +} + +.searchButton { + padding: 10px 20px; + background-color: #4caf50; + color: white; + border: none; + border-radius: 5px; + cursor: pointer; +} + +.filterButton { + margin-left: 10px; + padding: 10px 20px; + background-color: #4caf50; + color: white; + cursor: pointer; + border-radius: 5px; +} + +.results { + margin-top: 20px; +} + +.resultList { + list-style-type: none; + padding: 0; +} + +.resultItem { + margin-bottom: 10px; + font-size: 18px; +} + +.restrictionIcons { + display: flex; + flex-wrap: nowrap; +} + +.restrictionIcon { + margin: 5px; +} + +.noResults { + margin-top: 20px; + font-size: 18px; + color: red; } diff --git a/app/global_search/page.tsx b/app/global_search/page.tsx index da1dcab..0d5935e 100644 --- a/app/global_search/page.tsx +++ b/app/global_search/page.tsx @@ -3,9 +3,46 @@ import React, { useState, useEffect } from "react"; import axios from "axios"; import styles from "./Search.module.css"; import Image from "next/image"; - import { Location, Food } from "@/interfaces/Location"; + + + + +interface subCategory { + name: string; + foods: Array; +} + +interface Category { + name: string; + sub_categories: Array; +} + +interface DiningHall { + name: string; + categories: Array; +} + +const restrictionImageMap: { [key: string]: string } = { + 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([]); const [searchInput, setSearchInput] = useState(""); @@ -85,8 +122,10 @@ const BarebonesComponent = () => { 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 + + const hasHideAllergy = selectedHideAllergies.some((allergy) => + food.restrictions.includes(allergy.toLowerCase()) + ); return hasShowAllergy && !hasHideAllergy; }); @@ -98,64 +137,40 @@ const BarebonesComponent = () => { }; return ( -
- {/* Title and Search bar */} -
-

- Global Search -

-
- - - {/* Filter button */} -
- Filter -
+
+

Global Search

+
+ + +
+ Filter
- {/* Display search results if button clicked */} {showSearchResults && ( -
+

Search Results:

-
    +
      {filteredFoods.map(({ food, dhName, categoryName }, index) => ( -
    • +
    • {food.name} - {categoryName} ({dhName}) -
      +
      {food.restrictions.map((restriction, index) => ( {restriction} ))}
      @@ -166,8 +181,8 @@ const BarebonesComponent = () => { )} {noFoodsFound && ( -
      -

      No foods found at this dining hall.

      +
      +

      No foods found.

      )}
      diff --git a/app/locations/[location]/DH_Search/page.tsx b/app/locations/[location]/DH_Search/page.tsx index aa39c05..66df13d 100644 --- a/app/locations/[location]/DH_Search/page.tsx +++ b/app/locations/[location]/DH_Search/page.tsx @@ -1,23 +1,53 @@ "use client"; import { useEffect, useState } from "react"; import Image from "next/image"; +import Link from "next/link"; import { fetchLocations } from "@/app/db"; - import { Location, Food } from "@/interfaces/Location"; -import Link from "next/link"; interface FoodWithCategory { food: Food; category: string; } + +// Map of restriction images +const restrictionImageMap: { [key: string]: string } = { + 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(null); const [foods, setFoods] = useState([]); const [searchInput, setSearchInput] = useState(""); const [foundFoods, setFoundFoods] = useState([]); + const [selectedRestrictions, setSelectedRestrictions] = useState( + () => { + const storedRestrictions = localStorage.getItem("selectedRestrictions"); + return storedRestrictions ? JSON.parse(storedRestrictions) : []; + } + ); + const [isFilterPopupOpen, setIsFilterPopupOpen] = useState(false); + const [filterApplied, setFilterApplied] = useState(false); + + useEffect(() => { fetchLocations().then((locations: Location[]) => { if (params.location < 0 || params.location >= locations.length) { @@ -42,49 +72,129 @@ export default function Page({ params }: { params: { location: number } }) { return

      Loading...

      ; } - // const filterFoods = (foods: Food[], filters: IDK (a list of restriction that will be filtered) ) => {}; const searchForFood = (food_name: string) => { - // search for food - let foundFoods = foods.filter((foodWithCategory) => - foodWithCategory.food.name.toLowerCase().includes(food_name.toLowerCase()) + const foundFoods = foods.filter((foodWithCategory) => + foodWithCategory.food.name + .toLowerCase() + .includes(food_name.toLowerCase()) ); - // get the filters from local storage - // const filters = localStorage.getItem("filters"); // IDK or something like that + const filteredFoods = foundFoods.filter(({ food }) => + selectedRestrictions.every((restriction) => + food.restrictions.includes(restriction) + ) + ); - // apply filters - // foundFoods = filterFoods(foundFoods, filters); + setFoundFoods(filteredFoods); + }; + + const toggleFilterPopup = () => { + setIsFilterPopupOpen(!isFilterPopupOpen); + }; + + const handleRestrictionChange = (restriction: string, checked: boolean) => { + const newRestrictions = checked + ? [...selectedRestrictions, restriction] + : selectedRestrictions.filter((r) => r !== restriction); + setSelectedRestrictions(newRestrictions); + localStorage.setItem( + "selectedRestrictions", + JSON.stringify(newRestrictions) + ); + }; + + const applyFilter = () => { + setFilterApplied(true); + searchForFood(searchInput); + toggleFilterPopup(); - setFoundFoods(foundFoods); }; return (
      -
      + +
      +

      {location.name}

      -
      - setSearchInput(e.target.value)} - /> + +
      +
      + setSearchInput(e.target.value)} + /> + +
      + {isFilterPopupOpen && ( +
      +
      +

      Filter by Restrictions

      +
      + {Object.keys(restrictionImageMap).map((restriction) => ( +
      + + handleRestrictionChange(restriction, e.target.checked) + } + /> + +
      + ))} +
      + + +
      +
      + )} +
      - {foundFoods.length > 0 && + {filterApplied && foundFoods.length === 0 ? ( +

      No foods found with the specified allergy constraints

      + ) : ( + foundFoods.map((foodWithCategory, index) => (
      (
    • {restriction}
    • - ))} + + )) + )} +
      ); } + + + + + + + + + +// + + +// const HelloWorld: React.FC = () => { +// const [filteredFoods, setFilteredFoods] = useState< +// { food: Food; dhName: string; categoryName: string }[] +// >([]); +// const [showSearchResults, setShowSearchResults] = useState(false); +// const [noFoodsFound, setNoFoodsFound] = useState(false); +// const [diningHall, setDiningHall] = useState(null); +// const [searchInput, setSearchInput] = useState(""); +// const [searchResults, setSearchResults] = useState([]); + +// // Retrieve the dining hall name from localStorage when the component mounts +// useEffect(() => { +// const storedDiningHall = localStorage.getItem("diningHall"); +// setDiningHall(storedDiningHall); +// }, []); + +// // Handle search logic +// const handleSearch = () => { +// const currentDiningHallName = localStorage.getItem("diningHall"); + +// // Filter the dining halls to find the current one +// const currentDiningHall = dhs.find( +// (dh) => dh.name === currentDiningHallName +// ); + +// if (currentDiningHall) { +// const allFoods: { food: Food; dhName: string; categoryName: string }[] = +// []; + +// // Collect all foods from the current dining hall only +// currentDiningHall.categories.forEach((category) => { +// category.sub_categories.forEach((subCategory) => { +// subCategory.foods.forEach((food) => { +// allFoods.push({ +// food, +// dhName: currentDiningHall.name, +// categoryName: category.name, +// }); +// }); +// }); +// }); + +// // Filter the collected foods based on the search input +// const filtered = allFoods.filter(({ food }) => +// food.name.toLowerCase().includes(searchInput.toLowerCase()) +// ); + +// // 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; +// }); +// } + +// // Update the state based on the search results +// setNoFoodsFound(finalFilteredFoods.length === 0); +// setFilteredFoods(finalFilteredFoods); +// setShowSearchResults(true); +// } else { +// // Handle case where the current dining hall is not found +// setFilteredFoods([]); +// setShowSearchResults(false); +// setNoFoodsFound(true); +// } +// }; + +// return ( +//
      +//

      +// {diningHall ? diningHall : "Dining Hall not found"} +//

      +//
      +// setSearchInput(e.target.value)} +// className="border border-gray-400 p-2 rounded" +// /> +// +//
      +// {searchResults.length > 0 && ( +//
      +//

      {searchResults[0].categoryName}:

      +//
        +// {searchResults.map((food: any, index: number) => ( +//
      • +//
        +// +// {food.name} - {food.categoryName} ({diningHall}) +// +//
        +// {food.restrictions.map( +// (restriction: string, index: number) => ( +// {restriction} +// ) +// )} +//
        +//
        +//
      • +// ))} +//
      +//
      +// )} +//
      +// ); +// }; + +// const BarebonesComponent: React.FC = () => { +// const [dhs, setDhs] = useState([]); +// const [searchInput, setSearchInput] = useState(""); +// const [filteredFoods, setFilteredFoods] = useState< +// { food: Food; dhName: string; categoryName: string }[] +// >([]); +// 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) : []; +// } +// ); + +// // Fetch dining hall data from the API when the component mounts +// useInsertionEffect(() => { +// fetchLocations().then((locations: Location[]) => { +// setDhs(locations); +// }); +// }, []); + +// // Handle search input change +// const handleSearchInputChange = ( +// event: React.ChangeEvent +// ) => { +// setSearchInput(event.target.value); +// }; + +// // Handle filter button click +// const handleFilter = () => { +// window.location.href = "Filter-Window"; +// }; + +// // Handle search logic +// const handleSearch = () => { +// const currentDiningHallName = localStorage.getItem("diningHall"); + +// // Filter the dining halls to find the current one +// const currentDiningHall = dhs.find( +// (dh) => dh.name === currentDiningHallName +// ); + +// if (currentDiningHall) { +// const allFoods: { food: Food; dhName: string; categoryName: string }[] = +// []; + +// // Collect all foods from the current dining hall only +// currentDiningHall.categories.forEach((category) => { +// category.sub_categories.forEach((subCategory) => { +// subCategory.foods.forEach((food) => { +// allFoods.push({ +// food, +// dhName: currentDiningHall.name, +// categoryName: category.name, +// }); +// }); +// }); +// }); + +// // Filter the collected foods based on the search input +// const filtered = allFoods.filter(({ food }) => +// food.name.toLowerCase().includes(searchInput.toLowerCase()) +// ); + +// // 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; +// }); +// } + +// // Update the state based on the search results +// setNoFoodsFound(finalFilteredFoods.length === 0); +// setFilteredFoods(finalFilteredFoods); +// setShowSearchResults(true); +// } else { +// // Handle case where the current dining hall is not found +// setFilteredFoods([]); +// setShowSearchResults(false); +// setNoFoodsFound(true); +// } +// }; + +// return ( +//
      +// {/* Title and Search bar */} +//
      +//

      +// {localStorage.getItem("diningHall")} +//

      + +//
      +// +// +// {/* Filter button */} +//
      +// Filter +//
      +//
      +//
      + +// {/* Display search results if button clicked */} +// {showSearchResults && ( +//
      +//

      Search Results:

      +//
        +// {filteredFoods.map(({ food, dhName, categoryName }, index) => ( +//
      • +// {food.name} - {categoryName} ({dhName}) +//
        +// {food.restrictions.map((restriction, index) => ( +// {restriction} +// ))} +//
        +//
      • +// ))} +//
      +//
      +// )} + +// {noFoodsFound && ( +//
      +//

      No foods found at this dining hall.

      +//
      +// )} +//
      +// ); +// }; + +// export default BarebonesComponent; + +// import Link from "next/link"; + diff --git a/db.sqlite3 b/db.sqlite3 index 01261e4..21e0d33 100644 Binary files a/db.sqlite3 and b/db.sqlite3 differ