Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added local storage for saved searches and moved search content to be… #8

Merged
merged 1 commit into from
Jul 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions src/components/SavedSearches.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,37 @@
import React, { useState } from "react";
import { RxCross1 } from "react-icons/rx";

type ButtonClickHandler = (value:string) => void;

interface ButtonComponentProps {
content: string;
clickStay: boolean;
textSize: string;
clearSingleSavedItems: ButtonClickHandler;
buttonClicked?: boolean;
}

const SavedSearchBtn: React.FC<ButtonComponentProps> = ({ content, clickStay, textSize, buttonClicked }) => {
const SavedSearchBtn: React.FC<ButtonComponentProps> = ({ content, clickStay, textSize, clearSingleSavedItems, buttonClicked }) => {

Check failure on line 14 in src/components/SavedSearches.tsx

View workflow job for this annotation

GitHub Actions / build (20.x)

'buttonClicked' is defined but never used

Check failure on line 14 in src/components/SavedSearches.tsx

View workflow job for this annotation

GitHub Actions / build (20.x)

'buttonClicked' is defined but never used
const [displayx, setDisplayx] = useState(true);
const [greenBg, setGreenBg] = useState(true);

const handleXClick = () => {
// setDisplayx(false);
// setGreenBg(false);
clearSingleSavedItems(content);
}

const handleMainClick = () => {
setDisplayx(true);
setGreenBg(!greenBg);
}

return (
<button className={`rounded-full border border-teal px-4 py-1 flex items-center gap-1 ${textSize} ${
clickStay ? "bg-teal text-white" : ""}`}>
<span>{content}</span>
<RxCross1 className="h-4 w-3 text-gray-200 ml-3 mr-0.5" />
(clickStay && greenBg) ? "bg-teal text-white" : ""} `}>
<span onClick={handleMainClick}>{content}</span>
{displayx && <RxCross1 onClick={handleXClick} className={`h-4 w-3 ${greenBg? "text-gray-200" : ""} ml-3 mr-0.5`} />}

</button>
)

Expand Down
180 changes: 43 additions & 137 deletions src/components/Search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
// search input
import { IoSearch } from "react-icons/io5";
import { RxCross1 } from "react-icons/rx";
import { SearchCard } from "./SearchCard";
import Fuse from 'fuse.js'
import DropInData from "../../backend/scraper/drop_in.json";
// saved searches
import { saveArrayToLocalStorage, getArrayFromLocalStorage } from "../utils/localStorageUtil";
// for date picker
import dayjs, { Dayjs } from 'dayjs';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
Expand All @@ -19,19 +18,12 @@
import Checkbox from '@mui/material/Checkbox';
import { categoryListAcademics, categoryListClubs, categoryListCareer } from "../types";
// selectable dropdown
// import { Dropdown } from "./Dropdown";
import { Button } from "./Button";

import "react-dropdown/style.css";
import "./Search.css";
import { SavedSearchBtn } from "./SavedSearches";
// import useSearch from "../../utils/hooks/useSearch";
import DITData from "../../backend/scraper/drop_in.json";
import PTData from "../../backend/scraper/peer_tutoring.json";
import SIData from "../../backend/scraper/si.json";
import ClubsData from "../../backend/scraper/tartanconnect.json";
import CareerData from "../../backend/scraper/handshake.json";

import SearchContent from "./SearchContent";

// https://plainenglish.io/blog/how-to-implement-a-search-bar-in-react-js

Expand All @@ -44,6 +36,7 @@
// Chang name to search bar
const [searchInput, setSearchInput] = useState("");
const [categoryName, setCategoryName] = useState<string[]>([]);
const [savedItems, setSavedItems] = useState<string[]>([]);
// search results
// const [data, setData] = useState(null)
// date picker
Expand All @@ -52,16 +45,36 @@
const showDatePicker = true;


useEffect(()=> {
// const [data, setData] = useState([]);
useEffect(() => {
// Load the array from local storage when the component mounts
const storedItems = getArrayFromLocalStorage<string>('savedSearches');
setSavedItems(storedItems);
// clearSavedItems();
console.log(savedItems);
}, [searchInput]);

const clearSavedItems = () => {

Check failure on line 56 in src/components/Search.tsx

View workflow job for this annotation

GitHub Actions / build (20.x)

'clearSavedItems' is assigned a value but never used

Check failure on line 56 in src/components/Search.tsx

View workflow job for this annotation

GitHub Actions / build (20.x)

'clearSavedItems' is assigned a value but never used
setSavedItems([]);
localStorage.removeItem('savedSearches');
};

// const fuse = new Fuse(SIData, {
// keys: ["course_id", "course_name"],
// });
const clearSingleSavedItems = (value:string) => {
const index:number = savedItems.indexOf(value);
const newArray = savedItems.slice(0,index).concat(savedItems.slice(index+1,-1));
setSavedItems(newArray);
saveArrayToLocalStorage('savedSearches', newArray);
// localStorage.removeItem('savedSearches');
};

const addSavedItem = () => {
if (!savedItems.includes(searchInput)) {
const newItems = [...savedItems, searchInput];
setSavedItems(newItems);
saveArrayToLocalStorage('savedSearches', newItems);
}
console.log(savedItems);
};

// setData([fuse.search(searchInput)]);
getCategoryData(page);
},[categoryName])


// search
Expand All @@ -82,68 +95,6 @@
);
};

const inDateRange = (date: string) => {
const startDateObj = startDate.toDate();
const endDateObj = endDate.toDate();
const eventDate = new Date(date);
return eventDate >= startDateObj && eventDate <= endDateObj;
}

const getCategoryData = (currPage:string) => {
// console.log("running category data");
switch(currPage) {
case "academics":
const optionsAcademics = { keys: ['resource_type', 'course_id', 'course_name'] }
let combinedData = [...DITData, ...SIData, ...PTData];
const fuseAcademics = new Fuse(combinedData, optionsAcademics);
// const fuse = new Fuse(SIData, options);
if (categoryName.length == 0 || categoryName.length==4) {
return fuseAcademics.search(searchInput);
} else {
if (!categoryName.includes("Supplemental Instructions")) {
fuseAcademics.remove((doc) => {
return doc.resource_type === 'SI';
})
}
if (!categoryName.includes("Drop-in Tutoring")) {
fuseAcademics.remove((doc) => {
return doc.resource_type === 'DIT';
})
}
if (!categoryName.includes("Peer Tutoring")) {
fuseAcademics.remove((doc) => {
return doc.resource_type === 'PT'
})
}
return fuseAcademics.search(searchInput);
}
break;
case "clubs":
const optionsClubs = { keys: ['resource_type', 'event_name', 'event_host', 'categories'] }
const fuseClubs = new Fuse(ClubsData, optionsClubs);
return fuseClubs.search(searchInput);
break;
case "career":
const optionsCareer = { keys: ['resource_type', 'event_name', 'event_host', 'categories'] }
const fuseCareer = new Fuse(CareerData, optionsCareer);
return fuseCareer.search(searchInput);
break;
}
}

const getWeekday = (weekday: number) => {
const today = new Date();
const dayOfWeekToday = today.getDay(); // 0 (Sunday) to 6 (Saturday)
const offSet = dayOfWeekToday - weekday;
if (offSet === 0 || offSet === 7) {
return today.toDateString();
} else {
const targetDay = new Date(today);
targetDay.setDate(today.getDate() - offSet);
return targetDay.toDateString();
}
}

const getNumCategories = () => {
if (page==="academics") {
return categoryListAcademics.length;
Expand Down Expand Up @@ -254,26 +205,17 @@
);
}

// bogus values
const eventName1 = "Office Hours";
const orgName1 = "15-122 Course Staff";
const startDate1 = "06/17"
const startTime1 = "3PM"
const endDate1 = "06/17"
const endTime1 = "5PM"
const location1 = "POS 146";
// const eventCategory1 = "academic";
// const eventSubcategory1 = "OfficeHour";
return (
<div className="bg-[#F5F5F5] relative -top-2 w-full min-h-screen pl-8 pt-7 text-sans">
<div className="flex flex-col w-11/12 gap-y-2.5">
<div className="no-scroll-bar flex flex-nowrap flex-row gap-x-1.5 overflow-scroll">
<SavedSearchBtn content="15122" clickStay={true} textSize="text-xs"/>
<SavedSearchBtn content="programming" clickStay={true} textSize="text-xs"/>
<SavedSearchBtn content="15122" clickStay={true} textSize="text-xs"/>
<SavedSearchBtn content="15122" clickStay={true} textSize="text-xs"/>
<SavedSearchBtn content="15122" clickStay={true} textSize="text-xs"/>
<SavedSearchBtn content="15122" clickStay={true} textSize="text-xs"/>
{savedItems && savedItems.map((item, index) => {
return (
<SavedSearchBtn key={index} content={item} clickStay={true} clearSingleSavedItems={clearSingleSavedItems} textSize="text-xs"/>
)
})}
{/* <SavedSearchBtn content="15122" clickStay={true} textSize="text-xs"/>
<SavedSearchBtn content="programming" clickStay={true} textSize="text-xs"/> */}
</div>
<div className="bg-gray-200 relative h-12 w-full rounded-md border border-black border-[1.5] flex items-center justify-center">
<input
Expand All @@ -283,23 +225,24 @@
value={searchInput}
className="bg-gray-200 flex-grow px-4 focus:outline-none"
/>
{/* Search icon. Add onClick function in the future */}
{/* Search icon */}
{searchInput?
<RxCross1 onClick = {()=> setSearchInput("")} className="h-6 w-6 text-gray-500 mr-2" /> :
<IoSearch className="h-6 w-6 text-gray-500 mr-2" />
}

</div>

{/* drop down filter */}
<div className="mt-3 flex w-full items-baseline justify-between">
<div className="w-3/5 items-center flex flex-row justify-between space-x-2">{dateContent}</div>
{/* drop down filter */}
{(page === "academics" || page === "clubs" || page==="career") ? (
<div className="w-2/6">{categoryContent}</div>
) : (
<></>
)}
</div>

{/* <div className="w-full mt-2">{actionsMenuComp}</div> */}
<div className="w-full mt-2 flex justify-between">
{/* <Dropdown/> */}
Expand All @@ -308,45 +251,8 @@
</div>

<div className="overflow-scroll" style={{height: '70vh'}}>
{searchInput && page==="academics" && getCategoryData(page)?.map( (result) => {
for (let i = 0; i<result.item.events.length; i++) {
if (inDateRange(getWeekday(result.item.events[i].weekday))) {
return (
<SearchCard
key={result.refIndex}
eventName={`${result.item.resource_type} for ${result.item.course_name}`}
orgName={`${result.item.course_id} Staff`}
startDate={getWeekday(result.item.events[i].weekday) || `null`}
startTime={result.item.events[i].start_time}
endDate={getWeekday(result.item.events[i].weekday) || `null`}
endTime={result.item.events[i].end_time}
location={result.item.events[i].location}
/>
)
}
}
})}
{searchInput && (page==="clubs" || page==="career") && getCategoryData(page)?.map( (result) => {
for (let i = 0; i<result.item.events.length; i++) {
if (inDateRange(getWeekday(result.item.events[i].weekday))) {
return (
<SearchCard
key={result.refIndex}
eventName={`${result.item.event_name}`}
orgName={`${result.item.event_host}`}
startDate={getWeekday(result.item.events[i].weekday) || `null`}
startTime={result.item.events[i].start_time}
endDate={getWeekday(result.item.events[i].weekday) || `null`}
endTime={result.item.events[i].end_time}
location={result.item.events[i].location}
/>
)
}
}
})}
{ searchInput && <SearchContent searchInput={searchInput} page={page} categoryName={categoryName} startDate={startDate} endDate={endDate} addToSavedItems={addSavedItem}/>}
</div>



</div>
</div>
Expand Down
11 changes: 10 additions & 1 deletion src/components/SearchCard.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import React, { useState } from "react";
import React, { useEffect, useState } from "react";

Check failure on line 1 in src/components/SearchCard.tsx

View workflow job for this annotation

GitHub Actions / build (20.x)

'useEffect' is defined but never used

Check failure on line 1 in src/components/SearchCard.tsx

View workflow job for this annotation

GitHub Actions / build (20.x)

'useEffect' is defined but never used
import { IoLocationSharp, IoAdd } from "react-icons/io5";
import { FaRegClock, FaCheck } from "react-icons/fa";
import { saveArrayToLocalStorage, getArrayFromLocalStorage } from "../utils/localStorageUtil";

Check failure on line 4 in src/components/SearchCard.tsx

View workflow job for this annotation

GitHub Actions / build (20.x)

'saveArrayToLocalStorage' is defined but never used

Check failure on line 4 in src/components/SearchCard.tsx

View workflow job for this annotation

GitHub Actions / build (20.x)

'saveArrayToLocalStorage' is defined but never used

type ButtonClickHandler = () => void;

interface SearchCardProps {
eventName: string;
Expand All @@ -10,6 +13,7 @@
endDate: string;
endTime: string;
location: string;
addToSavedItems: ButtonClickHandler;
// eventCategory: string;
// eventSubcategory: string;
}
Expand All @@ -22,15 +26,20 @@
endDate,
endTime,
location,
addToSavedItems,
// eventCategory,
// eventSubcategory,
}) => {
const [buttonClicked, setButtonClicked] = useState(false);
const [cardClicked, setCardClicked] = useState(false);

// const [savedItems, setSavedItems] = useState<string[]>([]);


const handleAddToCalendar = () => {
setButtonClicked((prevClicked) => !prevClicked);
// Logic for calling GCal
addToSavedItems();
};

const handleCardClicked = () => {
Expand Down
Loading
Loading