From e637725143b1000014a0813191c4b2bd625e87ec Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Tue, 18 Mar 2025 17:38:07 -0400 Subject: [PATCH 01/33] convert to typescript --- src/shared/hooks/page-navigation-hook.js | 15 --------------- src/shared/hooks/page-navigation-hook.ts | 22 ++++++++++++++++++++++ 2 files changed, 22 insertions(+), 15 deletions(-) delete mode 100644 src/shared/hooks/page-navigation-hook.js create mode 100644 src/shared/hooks/page-navigation-hook.ts diff --git a/src/shared/hooks/page-navigation-hook.js b/src/shared/hooks/page-navigation-hook.js deleted file mode 100644 index cd0e5dfd..00000000 --- a/src/shared/hooks/page-navigation-hook.js +++ /dev/null @@ -1,15 +0,0 @@ -import { useState } from "react"; - -const usePageNavigation = (views, activeView) => { - var [pages, setPages] = useState({ pages: views, activePage: activeView }); - - const switchPage = (view) => { - setPages(() => { - return { ...pages, activePage: view }; - }); - }; - - return [pages, switchPage]; -}; - -export default usePageNavigation; diff --git a/src/shared/hooks/page-navigation-hook.ts b/src/shared/hooks/page-navigation-hook.ts new file mode 100644 index 00000000..d910c4b7 --- /dev/null +++ b/src/shared/hooks/page-navigation-hook.ts @@ -0,0 +1,22 @@ +import { useState } from "react"; + +interface PagesState { + pages: string[]; + activePage: string; +} + +type SwitchPage = (view: string) => void; + +const usePageNavigation = (views: string[], activeView: string): [PagesState, SwitchPage] => { + const [pages, setPages] = useState({ pages: views, activePage: activeView }); + + const switchPage: SwitchPage = (view) => { + setPages(() => { + return { ...pages, activePage: view }; + }); + }; + + return [pages, switchPage]; +}; + +export default usePageNavigation; From 904dc2c138051684e85210195ca069ec74375992 Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Tue, 18 Mar 2025 17:38:31 -0400 Subject: [PATCH 02/33] Combine pages together for an opportunities page --- src/App.tsx | 8 +--- src/opportunities/pages/Jobs.tsx | 42 ------------------ src/opportunities/pages/opportunities.tsx | 54 ++++++++++++++++++++--- 3 files changed, 51 insertions(+), 53 deletions(-) delete mode 100644 src/opportunities/pages/Jobs.tsx diff --git a/src/App.tsx b/src/App.tsx index aad23375..550f2fee 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,12 +2,10 @@ import React from "react"; import { Routes, Route } from "react-router-dom"; import "./style/App.css"; -import Opportunities from "./opportunities/pages/opportunities.tsx"; - +import Opportunities from "./opportunities/pages/Opportunities.tsx"; import Home from "./shared/pages/Home.tsx"; import PageNotFound from "./shared/pages/404.tsx"; import MainNavigation from "./shared/components/Navigation/MainNavigation.tsx"; -import Jobs from "./opportunities/pages/Jobs.tsx"; import Departments from "./staff/pages/Departments.tsx"; import StaffPage from "./staff/pages/Staff.tsx"; import Department from "./staff/pages/Department.tsx"; @@ -37,10 +35,8 @@ function App() { } /> } /> } /> - - } /> - } /> + } /> } /> { - - // navigation bar - const [pages, switchPage] = usePageNavigation(["Search", "Saved"], "Search") as [ - PageNavigationType, - (page: string) => void - ]; - - // displaying opportunities list component - return ( -
-
-
- - - {pages.activePage === "Search" && } - -
-
- -
- - - ); -}; - -export default Jobs; diff --git a/src/opportunities/pages/opportunities.tsx b/src/opportunities/pages/opportunities.tsx index cd5c9b10..ee8ac970 100644 --- a/src/opportunities/pages/opportunities.tsx +++ b/src/opportunities/pages/opportunities.tsx @@ -1,14 +1,58 @@ import React from "react"; +import Posts from "../components/Posts"; +import usePageNavigation from "../../shared/hooks/page-navigation-hook.ts"; import OpportunitiesList from "../components/opportunitiesDetails.tsx"; +interface PageNavigationType { + activePage: string; + pages: string[]; +} -export default function Opportunities() { +const Opportunities: React.FC = () => { + // navigation bar + const [pages, switchPage] = usePageNavigation(["Search", "Saved"], "Search") as [ + PageNavigationType, + (page: string) => void + ]; - // returning opportunities component on (currently not in use) opportunities page + const activeLink = "active-link"; + const normalLink = "normal-link hover:border-b-2 hover:text-black"; + + // displaying opportunities list component return ( -
- -
+
+
+
+
+

Opportunities

+ + +
+ + {pages.activePage === "Search" && } + +
+
+ +
+ + ); }; + +export default Opportunities; From a246c87a77c28ab948d86b5d1e520cdb427ae0f6 Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Tue, 18 Mar 2025 17:39:10 -0400 Subject: [PATCH 03/33] cleaned up typescript stuff for filters --- src/opportunities/components/FiltersField.tsx | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/opportunities/components/FiltersField.tsx b/src/opportunities/components/FiltersField.tsx index fae9ab58..644921fe 100644 --- a/src/opportunities/components/FiltersField.tsx +++ b/src/opportunities/components/FiltersField.tsx @@ -5,10 +5,16 @@ import GroupedComponents from "../../shared/components/UIElements/GroupedCompone import HorizontalIconButton from "./HorizontalIconButton.tsx"; import { PiSlidersHorizontal } from "react-icons/pi"; import { MdCancel } from "react-icons/md"; -import PropTypes from "prop-types"; -const FiltersField = ({ resetFilters, deleteFilter, filters, setPopUpMenu }) => { - +interface FiltersFieldProps { + resetFilters: () => void; + deleteFilter: (filter: string) => void; + filters: string[][]; + setPopUpMenu: () => void; +} + +const FiltersField: React.FC = ({ resetFilters, deleteFilter, filters, setPopUpMenu }) => { + return (

@@ -17,15 +23,15 @@ const FiltersField = ({ resetFilters, deleteFilter, filters, setPopUpMenu }) => - + Change Filters - + {/* Fix rendering with new filters = [ [],[],[] ]*/} {filters[1].map((filter) => { - return( + return ( } @@ -48,11 +54,4 @@ const FiltersField = ({ resetFilters, deleteFilter, filters, setPopUpMenu }) => ); }; -FiltersField.propTypes = { - resetFilters: PropTypes.func.isRequired, - deleteFilter: PropTypes.func.isRequired, - filters: PropTypes.arrayOf(PropTypes.array), - setPopUpMenu: PropTypes.func.isRequired, -}; - export default FiltersField; From 664359d6cf47d8f8006c9abc838ffa9ace6d9f27 Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Tue, 18 Mar 2025 17:39:18 -0400 Subject: [PATCH 04/33] remove uneeded page --- src/opportunities/components/SavedJobs.js | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 src/opportunities/components/SavedJobs.js diff --git a/src/opportunities/components/SavedJobs.js b/src/opportunities/components/SavedJobs.js deleted file mode 100644 index b3fe34c7..00000000 --- a/src/opportunities/components/SavedJobs.js +++ /dev/null @@ -1,8 +0,0 @@ -import React from "react"; - -const SavedJobs = () => { - - return

Saved Jobs

; -} - -export default SavedJobs; \ No newline at end of file From 43ea735f903feadcfb9e99762b46dbc2c72c5d53 Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Tue, 18 Mar 2025 17:39:30 -0400 Subject: [PATCH 05/33] Update to new opportunities page --- .../components/Navigation/MainNavigation.tsx | 2 +- .../components/Navigation/PageNavigation.js | 45 ------------------- .../components/Navigation/StickyFooter.tsx | 12 ++--- 3 files changed, 7 insertions(+), 52 deletions(-) delete mode 100644 src/shared/components/Navigation/PageNavigation.js diff --git a/src/shared/components/Navigation/MainNavigation.tsx b/src/shared/components/Navigation/MainNavigation.tsx index 62131eea..990494d6 100644 --- a/src/shared/components/Navigation/MainNavigation.tsx +++ b/src/shared/components/Navigation/MainNavigation.tsx @@ -11,7 +11,7 @@ export default function MainNavigation() { const location = useLocation().pathname; const routes = auth.isAuthenticated ? [ - { name: "Jobs", href: "/jobs", current: true }, + { name: "Opportunities", href: "/opportunities", current: true }, { name: "Create", href: "/create", current: false }, { name: "Staff", href: "/staff", current: false }, { name: "Profile", href: "/profile", current: false }, diff --git a/src/shared/components/Navigation/PageNavigation.js b/src/shared/components/Navigation/PageNavigation.js deleted file mode 100644 index 9441d69e..00000000 --- a/src/shared/components/Navigation/PageNavigation.js +++ /dev/null @@ -1,45 +0,0 @@ -import React from "react"; -/* -pages = { - pages: [Saved, Search] - active: "Saved" -} - -usePageNavigation([Saved, Search, Bookmarks], active) - -=> switchPage(string) - activePage - -*/ - -const PageNavigation = ({ title, pages, switchPage }) => { - const activeLink = "active-link"; - const normalLink = "normal-link hover:border-b-2 hover:text-black"; - - return ( -
-

{title}

- - -
- ); -}; - -export default PageNavigation; diff --git a/src/shared/components/Navigation/StickyFooter.tsx b/src/shared/components/Navigation/StickyFooter.tsx index 4ba8341b..444ba11d 100644 --- a/src/shared/components/Navigation/StickyFooter.tsx +++ b/src/shared/components/Navigation/StickyFooter.tsx @@ -8,12 +8,12 @@ export default function StickyFooter() { const routes = auth.isAuthenticated ? [ - { name: "Jobs", href: "/jobs", current: true }, - { name: "Create", href: "/create", current: false }, - { name: "Staff", href: "/staff", current: false }, - { name: "Profile", href: "/profile", current: false }, - { name: "Sign Out", href: "/signout", current: false }, - ] + { name: "Opportunities", href: "/opportunities", current: true }, + { name: "Create", href: "/create", current: false }, + { name: "Staff", href: "/staff", current: false }, + { name: "Profile", href: "/profile", current: false }, + { name: "Sign Out", href: "/signout", current: false }, + ] : [{ name: "Sign In", href: "/signin", current: false }]; return ( From d193f7bce03aadbd5d989daa006c017eec694785 Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Tue, 18 Mar 2025 17:39:40 -0400 Subject: [PATCH 06/33] update to new opportunities page --- src/shared/pages/Home.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/shared/pages/Home.tsx b/src/shared/pages/Home.tsx index 9e130c7f..f58fe1cb 100644 --- a/src/shared/pages/Home.tsx +++ b/src/shared/pages/Home.tsx @@ -5,7 +5,7 @@ import SEO from "../components/SEO.tsx"; const Home = () => { const aboutSectionRef = useRef(null); - + // State for the Contact Us form const [contactForm, setContactForm] = useState({ name: "", @@ -45,10 +45,10 @@ const Home = () => {

If you are a student, go to the{" "} - Jobs + Opportunities {" "} tab to view currently available research opportunities.
From 8d2d001d055ef7fe363b35ae947e8a078f38ec7f Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Tue, 18 Mar 2025 18:20:48 -0400 Subject: [PATCH 07/33] Make improvements to filtering by connecting majors --- src/opportunities/components/Posts.tsx | 202 ++++++++++++++----------- 1 file changed, 112 insertions(+), 90 deletions(-) diff --git a/src/opportunities/components/Posts.tsx b/src/opportunities/components/Posts.tsx index 959c8ab7..8aec73ed 100644 --- a/src/opportunities/components/Posts.tsx +++ b/src/opportunities/components/Posts.tsx @@ -1,22 +1,53 @@ -import React from "react"; import FiltersField from "./FiltersField.tsx"; -import PostsField from "./PostsField.tsx"; -import { useReducer } from "react"; -import { useCallback } from "react"; -import { useEffect } from "react"; +import React, { useReducer, useCallback, useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import CheckBox from "../../staff/components/Checkbox.tsx"; import PropTypes from "prop-types"; import Input from "../../staff/components/Input"; +import OpportunitiesList from "./OpportunitiesDetails.tsx"; + +interface Major { + code: string; + name: string; +} + +const PopUpMenu = ({ setFunction, clear, add, reset }) => { + const [majors, setMajors] = useState(); + const [validYears, setValidYears] = useState([]); + + const checkboxes: [string, string[], "semesters" | "years" | "credits"][] = [ + ["Semester", ["Summer", "Fall", "Spring"], "semesters"], + ["Eligible Years", validYears, "years"], + ["Credits", ["1", "2", "3", "4"], "credits"] + ]; + + useEffect(() => { + const fetchMajors = async () => { + const url = `${process.env.REACT_APP_BACKEND_SERVER}/majors`; + const response = await fetch(url); + if (!response.ok) { + console.log("Error fetching majors"); + } else { + const data = await response.json(); + setMajors(data); + console.log(data); + } + } + const fetchYears = async () => { + const url = `${process.env.REACT_APP_BACKEND_SERVER}/years`; + const response = await fetch(url); + if (!response.ok) { + console.log("Error fetching valid years"); + } else { + const data = await response.json(); + setValidYears(data); + console.log(data); + } + } + fetchMajors(); + fetchYears(); + }, []); -const PopUpMenu = ( {setFunction, validYears, clear, add, reset} ) => { - const checkboxes = [["Semester",["Summer","Fall","Spring"],"semesters"], - ["Eligible Years",validYears,"years"], - ["Credits", ["1","2","3","4"],"credits"]] - const majors = [["ARCH", "LGHT", "BMED", "CHME", "CIVL", "ECSE", "ENGR", "ENVE", "ECSI", "ISYE"], - ["MANE", "MTLE", "ARTS", "COMM", "IHSS", "INQR", "LANG", "LITR", "PHIL"], - ["STDO", "WRIT", "COGS", "ECON", "GSAS", "PSYC", "ITWS", "MGMT", "ASTR"], - ["BCBP", "BIOL", "CHEM", "CSCI", "ISCI", "ERTH", "MATH", "MATP", "PHYS"]] const { register, handleSubmit, @@ -40,7 +71,7 @@ const PopUpMenu = ( {setFunction, validYears, clear, add, reset} ) => { } function submitHandler(data: FormData) { - const { semesters, years, credits, hourlyPay, majors} = data; + const { semesters, years, credits, hourlyPay, majors } = data; clear(); add(semesters) add(years) @@ -62,30 +93,30 @@ const PopUpMenu = ( {setFunction, validYears, clear, add, reset} ) => {

Filters
-
-
{ - submitHandler(data); - })} - className="form-container" - >
{/* Added max-height and overflow-y-auto */} -
- { checkboxes.map((filter) => ( -
- -
- )) } -
-
- + { + submitHandler(data); + })} + className="form-container" + >
{/* Added max-height and overflow-y-auto */} +
+ {checkboxes.map((filter) => ( +
+ +
+ ))} +
+
+ { type="number" options={[]} placeHolder="Enter minimum hourly pay" - /> -
- -
-

Majors

-
- { majors.map((list, index) => ( -
- -
- )) } -
-
+ />
- -
-
- -
-
- -
-
- -
+ +
+

Majors

+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
- -
+ +
@@ -140,13 +172,12 @@ const PopUpMenu = ( {setFunction, validYears, clear, add, reset} ) => { PopUpMenu.propTypes = { setFunction: PropTypes.func.isRequired, - validYears: PropTypes.arrayOf(PropTypes.string), clear: PropTypes.func.isRequired, add: PropTypes.func.isRequired, reset: PropTypes.func.isRequired }; -const Posts = ( {years} ) => { +const Posts = () => { const [popUpMenu, setPopUpMenu] = React.useState(false); const date = new Date(); @@ -157,10 +188,10 @@ const Posts = ( {years} ) => { const reducer = (state, action) => { switch (action.type) { case "CLEAR_FILTERS": - state.filters = [[],[]]; + state.filters = [[], []]; return { ...state }; case "RESET_FILTERS": - state.filters = [[[currSem],[currYr],[],[],[]],[currSem, currYr]]; + state.filters = [[[currSem], [currYr], [], [], []], [currSem, currYr]]; return { ...state }; case "REMOVE_FILTER": if (action.filter) { @@ -195,17 +226,17 @@ const Posts = ( {years} ) => { }; const [jobState, dispatch] = useReducer(reducer, { - filters: [[[currSem],[currYr],[],[],[]],[currSem, currYr]], + filters: [[[currSem], [currYr], [], [], []], [currSem, currYr]], activeId: "", jobs: [], }); const clearFilters = useCallback(() => { - dispatch({ type: "CLEAR_FILTERS"}); + dispatch({ type: "CLEAR_FILTERS" }); }, []); const resetFilters = useCallback(() => { - dispatch({ type: "RESET_FILTERS"}); + dispatch({ type: "RESET_FILTERS" }); }, []); const removeFilter = useCallback((name) => { @@ -239,22 +270,13 @@ const Posts = ( {years} ) => { fetchOpportunities(); }, []); - console.log() return (
- setPopUpMenu(!popUpMenu)} /> - {popUpMenu && setPopUpMenu(!popUpMenu)} validYears={years} clear={clearFilters} add={addFilter} reset={resetFilters}/>} - + setPopUpMenu(!popUpMenu)} /> + {popUpMenu && setPopUpMenu(!popUpMenu)} clear={clearFilters} add={addFilter} reset={resetFilters} />} +
); }; -Posts.propTypes = { - years: PropTypes.arrayOf(PropTypes.string), -}; - export default Posts; From bec341adb116ab21eaa19b3160a8991e5c426825 Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Tue, 18 Mar 2025 18:21:09 -0400 Subject: [PATCH 08/33] move list --- src/opportunities/pages/opportunities.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/opportunities/pages/opportunities.tsx b/src/opportunities/pages/opportunities.tsx index ee8ac970..beb8f98f 100644 --- a/src/opportunities/pages/opportunities.tsx +++ b/src/opportunities/pages/opportunities.tsx @@ -1,7 +1,6 @@ import React from "react"; import Posts from "../components/Posts"; import usePageNavigation from "../../shared/hooks/page-navigation-hook.ts"; -import OpportunitiesList from "../components/opportunitiesDetails.tsx"; interface PageNavigationType { activePage: string; @@ -48,10 +47,7 @@ const Opportunities: React.FC = () => { - - - ); }; From 0a8c3f09d4ece4ebd79b9ed73d5f44230a5c7a6d Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Tue, 18 Mar 2025 18:21:22 -0400 Subject: [PATCH 09/33] remove uneeded file --- src/opportunities/components/PostsField.tsx | 57 --------------------- 1 file changed, 57 deletions(-) delete mode 100644 src/opportunities/components/PostsField.tsx diff --git a/src/opportunities/components/PostsField.tsx b/src/opportunities/components/PostsField.tsx deleted file mode 100644 index c155c3ef..00000000 --- a/src/opportunities/components/PostsField.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import React, { useEffect } from "react"; -import { useState } from "react"; -import JobPost from "./JobPost"; -import JobDetails from "./JobDetails"; -import PropTypes from "prop-types"; - - -const PostsField = ({ activeId, setActive, opportunities }) => { - const [activeOpportunity, setActiveOpportunity] = useState(null); - - const fetchOpportunity = async (id) => { - const url = `${process.env.REACT_APP_BACKEND_SERVER}/getOpportunity/${id}`; - const response = await fetch(url); - if (!response.ok) { - console.log("Error fetching opportunity"); - setActiveOpportunity(null); - } else { - let data = await response.json(); - data = data.data; - setActiveOpportunity(data); - } - }; - - useEffect(() => { - fetchOpportunity(activeId); - }, [activeId]); - - return ( -
-
- {opportunities && - opportunities.map((job) => { - return ( - - ); - })} -
- {activeId != "" && activeOpportunity && ( - - )} - {(activeId === "" || !activeOpportunity) && "Opportunity not found."} -
- ); -}; - -PostsField.propTypes = { - activeId: PropTypes.string, - setActive: PropTypes.func.isRequired, - opportunities: PropTypes.array, -} - -export default PostsField; From f63e846c7353c3f151e25eccb7e45e1277163c70 Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Tue, 18 Mar 2025 18:21:41 -0400 Subject: [PATCH 10/33] Show no results found if empty --- .../components/opportunitiesDetails.tsx | 38 +++++++++++-------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/src/opportunities/components/opportunitiesDetails.tsx b/src/opportunities/components/opportunitiesDetails.tsx index c2ca633a..6c18e3b5 100644 --- a/src/opportunities/components/opportunitiesDetails.tsx +++ b/src/opportunities/components/opportunitiesDetails.tsx @@ -110,23 +110,31 @@ const OpportunitiesList = () => { {/* Info about the opportunities */} - {sampleOpportunities.map((opportunity, index) => ( - - {opportunity.name} - {opportunity.description} - {opportunity.location} - ${opportunity.pay}/hr - {opportunity.professor} - - {opportunity.semester} {opportunity.year} - - - + {sampleOpportunities.length > 0 ? ( + sampleOpportunities.map((opportunity, index) => ( + + {opportunity.name} + {opportunity.description} + {opportunity.location} + ${opportunity.pay}/hr + {opportunity.professor} + + {opportunity.semester} {opportunity.year} + + + + + + )) + ) : ( + + + No results found. - ))} + )} From 8e4678b1d5de706cb63ca657362b45c63fd060e4 Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Tue, 25 Mar 2025 16:57:45 -0400 Subject: [PATCH 11/33] Move filter menu to it's own component --- src/opportunities/components/PopUpMenu.tsx | 175 ++++++++++++++++++ src/opportunities/components/Posts.tsx | 199 ++------------------- 2 files changed, 188 insertions(+), 186 deletions(-) create mode 100644 src/opportunities/components/PopUpMenu.tsx diff --git a/src/opportunities/components/PopUpMenu.tsx b/src/opportunities/components/PopUpMenu.tsx new file mode 100644 index 00000000..3bec7fa6 --- /dev/null +++ b/src/opportunities/components/PopUpMenu.tsx @@ -0,0 +1,175 @@ +import React, { useEffect, useState } from "react"; +import { useForm } from "react-hook-form"; +import CheckBox from "../../staff/components/Checkbox.tsx"; +import Input from "../../staff/components/Input"; + +interface PopUpMenuProps { + setFunction: () => void; + clear: () => void; + add: (filter: string[] | string) => void; + reset: () => void; +} + +interface Major { + code: string; + name: string; +} + +export default function PopUpMenu({ setFunction, clear, add, reset }: PopUpMenuProps) { + const [majors, setMajors] = useState(); + const [validYears, setValidYears] = useState([]); + + const checkboxes: [string, string[], "semesters" | "years" | "credits"][] = [ + ["Semester", ["Summer", "Fall", "Spring"], "semesters"], + ["Eligible Years", validYears, "years"], + ["Credits", ["1", "2", "3", "4"], "credits"] + ]; + + useEffect(() => { + const fetchMajors = async () => { + const url = `${process.env.REACT_APP_BACKEND_SERVER}/majors`; + const response = await fetch(url); + if (!response.ok) { + console.log("Error fetching majors"); + } else { + const data = await response.json(); + setMajors(data); + console.log(data); + } + } + const fetchYears = async () => { + const url = `${process.env.REACT_APP_BACKEND_SERVER}/years`; + const response = await fetch(url); + if (!response.ok) { + console.log("Error fetching valid years"); + } else { + const data = await response.json(); + setValidYears(data); + console.log(data); + } + } + fetchMajors(); + fetchYears(); + }, []); + + const { + register, + handleSubmit, + formState: { errors }, + } = useForm({ + defaultValues: { + semesters: [], + years: [], + credits: [], + hourlyPay: "0", + majors: [] + }, + }); + + interface FormData { + semesters: string[], + years: string[], + credits: string[], + hourlyPay: string, + majors: string[] + } + + function submitHandler(data: FormData) { + const { semesters, years, credits, hourlyPay, majors } = data; + clear(); + add(semesters) + add(years) + add(credits) + if (hourlyPay === "0") { + add([]) + } else { + add([hourlyPay]) + } + add(majors) + setFunction() + }; + + return ( +
+ +
+
+
+
+
Filters
+
+
{ + submitHandler(data); + })} + className="form-container" + >
{/* Added max-height and overflow-y-auto */} +
+ {checkboxes.map((filter) => ( +
+ +
+ ))} +
+
+ +
+ +
+

Majors

+
+ +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+
+ ); +} \ No newline at end of file diff --git a/src/opportunities/components/Posts.tsx b/src/opportunities/components/Posts.tsx index 8aec73ed..8ea3033d 100644 --- a/src/opportunities/components/Posts.tsx +++ b/src/opportunities/components/Posts.tsx @@ -1,181 +1,8 @@ import FiltersField from "./FiltersField.tsx"; import React, { useReducer, useCallback, useEffect, useState } from "react"; -import { useForm } from "react-hook-form"; -import CheckBox from "../../staff/components/Checkbox.tsx"; -import PropTypes from "prop-types"; -import Input from "../../staff/components/Input"; import OpportunitiesList from "./OpportunitiesDetails.tsx"; +import PopUpMenu from "./PopUpMenu.tsx"; -interface Major { - code: string; - name: string; -} - -const PopUpMenu = ({ setFunction, clear, add, reset }) => { - const [majors, setMajors] = useState(); - const [validYears, setValidYears] = useState([]); - - const checkboxes: [string, string[], "semesters" | "years" | "credits"][] = [ - ["Semester", ["Summer", "Fall", "Spring"], "semesters"], - ["Eligible Years", validYears, "years"], - ["Credits", ["1", "2", "3", "4"], "credits"] - ]; - - useEffect(() => { - const fetchMajors = async () => { - const url = `${process.env.REACT_APP_BACKEND_SERVER}/majors`; - const response = await fetch(url); - if (!response.ok) { - console.log("Error fetching majors"); - } else { - const data = await response.json(); - setMajors(data); - console.log(data); - } - } - const fetchYears = async () => { - const url = `${process.env.REACT_APP_BACKEND_SERVER}/years`; - const response = await fetch(url); - if (!response.ok) { - console.log("Error fetching valid years"); - } else { - const data = await response.json(); - setValidYears(data); - console.log(data); - } - } - fetchMajors(); - fetchYears(); - }, []); - - const { - register, - handleSubmit, - formState: { errors }, - } = useForm({ - defaultValues: { - semesters: [], - years: [], - credits: [], - hourlyPay: 0, - majors: [] - }, - }); - - interface FormData { - semesters: string[], - years: string[], - credits: string[], - hourlyPay: string, - majors: string[] - } - - function submitHandler(data: FormData) { - const { semesters, years, credits, hourlyPay, majors } = data; - clear(); - add(semesters) - add(years) - add(credits) - if (hourlyPay == "0") { - add([]) - } else { - add([hourlyPay]) - } - add(majors) - setFunction() - }; - - return ( -
- -
-
-
-
-
Filters
-
-
{ - submitHandler(data); - })} - className="form-container" - >
{/* Added max-height and overflow-y-auto */} -
- {checkboxes.map((filter) => ( -
- -
- ))} -
-
- -
- -
-

Majors

-
- -
-
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-
-
-
-
- ); -} - -PopUpMenu.propTypes = { - setFunction: PropTypes.func.isRequired, - clear: PropTypes.func.isRequired, - add: PropTypes.func.isRequired, - reset: PropTypes.func.isRequired -}; const Posts = () => { const [popUpMenu, setPopUpMenu] = React.useState(false); @@ -247,23 +74,23 @@ const Posts = () => { dispatch({ type: "ADD_FILTER", filter: name }); }, []); - const setActiveId = useCallback((val) => { - dispatch({ type: "SET_ACTIVE_ID", id: val }); - }, []); + // const setActiveId = useCallback((val) => { + // dispatch({ type: "SET_ACTIVE_ID", id: val }); + // }, []); const fetchOpportunities = async () => { const url = `${process.env.REACT_APP_BACKEND_SERVER}/getOpportunityCards`; - const response = await fetch(url); + // const response = await fetch(url); - if (!response.ok) { - console.log("Error fetching opportunities"); - } else { - let data = await response.json(); - data = data.data; - dispatch({ type: "SET_JOBS", jobs: data }); - console.log(jobState.jobs); - } + // if (!response.ok) { + // console.log("Error fetching opportunities"); + // } else { + // let data = await response.json(); + // data = data.data; + // dispatch({ type: "SET_JOBS", jobs: data }); + // console.log(jobState.jobs); + // } }; useEffect(() => { From 98d7accf13533b6d9e0e0e7f699eeb8b2e53756d Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Fri, 28 Mar 2025 16:37:23 -0400 Subject: [PATCH 12/33] Clean up filters fields to use new filters --- src/opportunities/components/FiltersField.tsx | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/opportunities/components/FiltersField.tsx b/src/opportunities/components/FiltersField.tsx index 644921fe..91b15ebf 100644 --- a/src/opportunities/components/FiltersField.tsx +++ b/src/opportunities/components/FiltersField.tsx @@ -9,12 +9,12 @@ import { MdCancel } from "react-icons/md"; interface FiltersFieldProps { resetFilters: () => void; deleteFilter: (filter: string) => void; - filters: string[][]; + filters: string[]; setPopUpMenu: () => void; } -const FiltersField: React.FC = ({ resetFilters, deleteFilter, filters, setPopUpMenu }) => { - +export default function FiltersField({ resetFilters, deleteFilter, filters, setPopUpMenu }: FiltersFieldProps) { + console.log("FiltersField", filters); return (

@@ -30,7 +30,7 @@ const FiltersField: React.FC = ({ resetFilters, deleteFilter, {/* Fix rendering with new filters = [ [],[],[] ]*/} - {filters[1].map((filter) => { + {filters.map((filter) => { return ( = ({ resetFilters, deleteFilter,
); }; - -export default FiltersField; From b5a5f58fdbfbda3c2f38a61f49bbb57a296d2849 Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Fri, 28 Mar 2025 23:18:05 -0400 Subject: [PATCH 13/33] clean up logging --- src/opportunities/components/FiltersField.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/opportunities/components/FiltersField.tsx b/src/opportunities/components/FiltersField.tsx index 91b15ebf..a8d02453 100644 --- a/src/opportunities/components/FiltersField.tsx +++ b/src/opportunities/components/FiltersField.tsx @@ -14,7 +14,6 @@ interface FiltersFieldProps { } export default function FiltersField({ resetFilters, deleteFilter, filters, setPopUpMenu }: FiltersFieldProps) { - console.log("FiltersField", filters); return (

From eed21f7aedad5cbd872815fc9ddee5828c12a862 Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Fri, 28 Mar 2025 23:19:06 -0400 Subject: [PATCH 14/33] Update filters and use effects --- src/opportunities/components/PopUpMenu.tsx | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/opportunities/components/PopUpMenu.tsx b/src/opportunities/components/PopUpMenu.tsx index 3bec7fa6..de808bc7 100644 --- a/src/opportunities/components/PopUpMenu.tsx +++ b/src/opportunities/components/PopUpMenu.tsx @@ -1,6 +1,6 @@ import React, { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; -import CheckBox from "../../staff/components/Checkbox.tsx"; +import CheckBox from "../../shared/components/Checkbox.tsx"; import Input from "../../staff/components/Input"; interface PopUpMenuProps { @@ -8,6 +8,13 @@ interface PopUpMenuProps { clear: () => void; add: (filter: string[] | string) => void; reset: () => void; + filters: { + semesters: string[]; + years: string[]; + credits: string[]; + hourlyPay: string; + majors: string[]; + }; } interface Major { @@ -15,7 +22,7 @@ interface Major { name: string; } -export default function PopUpMenu({ setFunction, clear, add, reset }: PopUpMenuProps) { +export default function PopUpMenu({ setFunction, clear, add, reset, filters }: PopUpMenuProps) { const [majors, setMajors] = useState(); const [validYears, setValidYears] = useState([]); @@ -34,9 +41,12 @@ export default function PopUpMenu({ setFunction, clear, add, reset }: PopUpMenuP } else { const data = await response.json(); setMajors(data); - console.log(data); } } + fetchMajors(); + }, []); + + useEffect(() => { const fetchYears = async () => { const url = `${process.env.REACT_APP_BACKEND_SERVER}/years`; const response = await fetch(url); @@ -45,10 +55,8 @@ export default function PopUpMenu({ setFunction, clear, add, reset }: PopUpMenuP } else { const data = await response.json(); setValidYears(data); - console.log(data); } } - fetchMajors(); fetchYears(); }, []); @@ -115,6 +123,7 @@ export default function PopUpMenu({ setFunction, clear, add, reset }: PopUpMenuP formHook={{ ...register(filter[2], {}) }} name={filter[2]} type="checkbox" + filters={filters} />
))} From 1fce2bfb914ec8fef2acf968f73098bbe6ae2470 Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Fri, 28 Mar 2025 23:19:59 -0400 Subject: [PATCH 15/33] move check box logic and add filters as an option for default check --- src/{staff => shared}/components/Checkbox.tsx | 44 ++++++++++++------- 1 file changed, 29 insertions(+), 15 deletions(-) rename src/{staff => shared}/components/Checkbox.tsx (55%) diff --git a/src/staff/components/Checkbox.tsx b/src/shared/components/Checkbox.tsx similarity index 55% rename from src/staff/components/Checkbox.tsx rename to src/shared/components/Checkbox.tsx index a43760ff..bd4bba42 100644 --- a/src/staff/components/Checkbox.tsx +++ b/src/shared/components/Checkbox.tsx @@ -1,7 +1,30 @@ import React from "react"; -import PropTypes from "prop-types"; +import { FieldErrors, UseFormRegisterReturn } from "react-hook-form"; -const CheckBox = ({ +interface CheckBoxProps { + formHook: UseFormRegisterReturn; + errors: FieldErrors<{ + semesters: never[]; + years: never[]; + credits: never[]; + hourlyPay: string; + majors: never[]; + }>; + errorMessage: string; + name: string; + label: string; + options: string[]; + type?: "checkbox" | "radio"; + filters?: { + semesters: string[]; + years: string[]; + credits: string[]; + hourlyPay: string; + majors: string[]; + }; +} + +export default function CheckBox({ formHook, errors, errorMessage, @@ -9,14 +32,15 @@ const CheckBox = ({ label, options, type, -}) => { + filters, +}: CheckBoxProps) { return (
{label}
- {errors && errors[name] && ( + {errors && errors[name as keyof typeof errors] && (

{errorMessage}

)} @@ -33,6 +57,7 @@ const CheckBox = ({ {...formHook} id={item} className={type === "radio" ? "radio" : "checkbox"} + defaultChecked={name === "semesters" && filters?.semesters?.includes(item) || name === "years" && filters?.years?.includes(item) || name === "credits" && filters?.credits?.includes(item) ? true : false} />
@@ -43,14 +68,3 @@ const CheckBox = ({
); }; -CheckBox.propTypes = { - formHook: PropTypes.object, - errors: PropTypes.object, - errorMessage: PropTypes.string, - name: PropTypes.string.isRequired, - label: PropTypes.string, - options: PropTypes.arrayOf(PropTypes.string), - type: PropTypes.string, -}; - -export default CheckBox; From c788ba61161c2e143c20585d6b00f277d8b44017 Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Fri, 28 Mar 2025 23:20:17 -0400 Subject: [PATCH 16/33] move checkbox component --- src/staff/components/CreationForms.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/staff/components/CreationForms.tsx b/src/staff/components/CreationForms.tsx index 1c516235..c6b3360d 100644 --- a/src/staff/components/CreationForms.tsx +++ b/src/staff/components/CreationForms.tsx @@ -1,7 +1,7 @@ import React, { useState } from "react"; import { useForm } from "react-hook-form"; import { useEffect } from "react"; -import CheckBox from "./Checkbox.tsx"; +import CheckBox from "../../shared/components/Checkbox.tsx"; import Input from "./Input"; import { useParams } from "react-router"; import { Locations } from "../../shared/data/locations.ts"; From 7678b19a0a4e06a57855ab9456121d08489dd4c0 Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Fri, 28 Mar 2025 23:22:44 -0400 Subject: [PATCH 17/33] Updates to the reducer and what was passed into components --- src/opportunities/components/Posts.tsx | 135 ++++++++++++++++++------- 1 file changed, 97 insertions(+), 38 deletions(-) diff --git a/src/opportunities/components/Posts.tsx b/src/opportunities/components/Posts.tsx index 8ea3033d..9f9e9a80 100644 --- a/src/opportunities/components/Posts.tsx +++ b/src/opportunities/components/Posts.tsx @@ -5,7 +5,7 @@ import PopUpMenu from "./PopUpMenu.tsx"; const Posts = () => { - const [popUpMenu, setPopUpMenu] = React.useState(false); + const [popUpMenu, setPopUpMenu] = useState(false); const date = new Date(); const month = date.getMonth(); @@ -14,50 +14,108 @@ const Posts = () => { const reducer = (state, action) => { switch (action.type) { - case "CLEAR_FILTERS": - state.filters = [[], []]; - return { ...state }; - case "RESET_FILTERS": - state.filters = [[[currSem], [currYr], [], [], []], [currSem, currYr]]; - return { ...state }; - case "REMOVE_FILTER": - if (action.filter) { - state.filters[1] = state.filters[1].filter((item) => item !== action.filter); - state.filters[0].map((list, index) => { - state.filters[0][index] = list.filter((item) => item !== action.filter); - }) + // case "CLEAR_FILTERS": + // return { + // ...state, + // filters: { + // activeFilters: [], + // filterMap: { + // semesters: currSem, + // years: currYr, + // credits: [], + // hourlyPay: "0", + // majors: [], + // }, + // }, + // }; + + case "RESET_FILTERS": { + const newFilterMap = { + semesters: [currSem], + years: [currYr], + credits: [], + hourlyPay: "0", + majors: [], + }; + + return { + ...state, + filters: { + activeFilters: [currSem, currYr], + filterMap: newFilterMap, + }, + }; + } + + case "REMOVE_FILTER": { + const newFilterMap = { ...state.filters.filterMap }; + let newActiveFilters = state.filters.activeFilters.filter((item) => item !== action.filter); + + Object.keys(newFilterMap).forEach((key) => { + newFilterMap[key] = newFilterMap[key].filter((item) => item !== action.filter); + if (newFilterMap[key].length === 0) { + delete newFilterMap[key]; // Remove empty categories + } + }); + + return { + ...state, + filters: { + activeFilters: newActiveFilters, + filterMap: newFilterMap, + }, + }; + } + + case "ADD_FILTER": { + if (!action.filter || !action.category) return state; + + const newFilterMap = { ...state.filters.filterMap }; + if (!newFilterMap[action.category]) { + newFilterMap[action.category] = []; } - return { ...state }; - case "ADD_FILTER": - if (action.filter) { - state.filters[0] = [...state.filters[0], action.filter]; - state.filters[1] = [...state.filters[1], ...action.filter]; - console.log(state.filters) + if (!newFilterMap[action.category].includes(action.filter)) { + newFilterMap[action.category] = [...newFilterMap[action.category], action.filter]; } - return { ...state }; + + return { + ...state, + filters: { + activeFilters: Array.from(new Set([...state.filters.activeFilters, action.filter])), + filterMap: newFilterMap, + }, + }; + } + case "SET_ACTIVE_ID": - if (action.id) { - if (state.jobs.find((job) => job.id === action.id)) { - state.activeId = action.id; - } - } - return { ...state }; + return state.jobs.some((job) => job.id === action.id) + ? { ...state, activeId: action.id } + : state; + case "SET_JOBS": - if (action.jobs) { - state.jobs = action.jobs; - } - return { ...state }; + return action.jobs ? { ...state, jobs: action.jobs } : state; + default: return state; } }; const [jobState, dispatch] = useReducer(reducer, { - filters: [[[currSem], [currYr], [], [], []], [currSem, currYr]], + filters: { + activeFilters: [currSem, currYr], + filterMap: { + semesters: [currSem], + years: [currYr], + credits: [], + hourlyPay: "0", + majors: [], + }, + }, activeId: "", jobs: [], }); + // Action dispatchers const clearFilters = useCallback(() => { dispatch({ type: "CLEAR_FILTERS" }); }, []); @@ -70,13 +128,14 @@ const Posts = () => { dispatch({ type: "REMOVE_FILTER", filter: name }); }, []); - const addFilter = useCallback((name) => { - dispatch({ type: "ADD_FILTER", filter: name }); + const addFilter = useCallback((name, category) => { + dispatch({ type: "ADD_FILTER", filter: name, category }); + }, []); + + const setActiveId = useCallback((val) => { + dispatch({ type: "SET_ACTIVE_ID", id: val }); }, []); - // const setActiveId = useCallback((val) => { - // dispatch({ type: "SET_ACTIVE_ID", id: val }); - // }, []); const fetchOpportunities = async () => { const url = `${process.env.REACT_APP_BACKEND_SERVER}/getOpportunityCards`; @@ -99,8 +158,8 @@ const Posts = () => { return (
- setPopUpMenu(!popUpMenu)} /> - {popUpMenu && setPopUpMenu(!popUpMenu)} clear={clearFilters} add={addFilter} reset={resetFilters} />} + setPopUpMenu(!popUpMenu)} /> + {popUpMenu && setPopUpMenu(!popUpMenu)} filters={jobState.filters.filterMap} clear={clearFilters} add={addFilter} reset={resetFilters} />}
); From ff9a1c7d899125bea7f02fdb10433105c308dfee Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Fri, 4 Apr 2025 23:48:57 -0400 Subject: [PATCH 18/33] add new types use for opportunities --- src/types/opportunities.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/types/opportunities.ts diff --git a/src/types/opportunities.ts b/src/types/opportunities.ts new file mode 100644 index 00000000..28d0d98c --- /dev/null +++ b/src/types/opportunities.ts @@ -0,0 +1,19 @@ +export type Filters = { + years: number[]; + credits: string[]; + hourlyPay: number; + majors: string[]; +}; + +export type OpportunityList = { + id: number; + name: string; + description: string; + recommended_experience: string; + pay: number; + semester: string; + year: number; + application_due: Date; + location: string; + professor: string +} \ No newline at end of file From 1cfa5a055f27f1082a20c2e60ba8eab15c57ff7c Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Fri, 4 Apr 2025 23:49:07 -0400 Subject: [PATCH 19/33] update Checkbox to use new type --- src/shared/components/Checkbox.tsx | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/shared/components/Checkbox.tsx b/src/shared/components/Checkbox.tsx index bd4bba42..605b625e 100644 --- a/src/shared/components/Checkbox.tsx +++ b/src/shared/components/Checkbox.tsx @@ -1,5 +1,6 @@ import React from "react"; import { FieldErrors, UseFormRegisterReturn } from "react-hook-form"; +import { Filters } from "../../types/opportunities.ts"; interface CheckBoxProps { formHook: UseFormRegisterReturn; @@ -15,14 +16,9 @@ interface CheckBoxProps { label: string; options: string[]; type?: "checkbox" | "radio"; - filters?: { - semesters: string[]; - years: string[]; - credits: string[]; - hourlyPay: string; - majors: string[]; - }; -} + filters?: Filters +}; + export default function CheckBox({ formHook, From b4ec3741dd240e7def15ed58d17c01468add7b7f Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Fri, 4 Apr 2025 23:49:21 -0400 Subject: [PATCH 20/33] move type to type file --- .../components/opportunitiesDetails.tsx | 32 ++++++------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/src/opportunities/components/opportunitiesDetails.tsx b/src/opportunities/components/opportunitiesDetails.tsx index 6c18e3b5..9d423670 100644 --- a/src/opportunities/components/opportunitiesDetails.tsx +++ b/src/opportunities/components/opportunitiesDetails.tsx @@ -1,26 +1,9 @@ import React from "react"; +import { OpportunityList } from "../../types/opportunities.ts"; - -//Created a new interface to make displaying an opportunity easier, contains 9 fields - -export interface Opportunity { - name: string; - description: string; - recommended_experience: string; - pay: number; - semester: string; - year: number; - application_due: Date; - location: string; - professor: string - // Add any other relevant information about an opportunity -} - - -// List of sample opportunities of type Opportunity - -const sampleOpportunities: Opportunity[] = [ +const sampleOpportunities: OpportunityList[] = [ { + id: 1, name: "Research Assistant - Machine Learning Lab", description: "Work on cutting-edge ML projects", recommended_experience: "Python, Machine Learning basics", @@ -32,6 +15,7 @@ const sampleOpportunities: Opportunity[] = [ professor: "Dr. Emily Chen" }, { + id: 2, name: "Data Visualization Intern - Data Science Center", description: "Create compelling visualizations for real-world datasets.", recommended_experience: "D3.js, Tableau, or Matplotlib", @@ -43,6 +27,7 @@ const sampleOpportunities: Opportunity[] = [ professor: "Dr. Alan Green" }, { + id: 3, name: "Undergraduate Researcher - Renewable Energy Lab", description: "Analyze energy efficiency of solar panel setups.", recommended_experience: "R, Excel, or energy systems knowledge", @@ -54,6 +39,7 @@ const sampleOpportunities: Opportunity[] = [ professor: "Dr. Maria Santos" }, { + id: 4, name: "AI in Healthcare Research Assistant", description: "Develop and test AI models for diagnostic tools.", recommended_experience: "Python, TensorFlow, basic healthcare knowledge", @@ -65,6 +51,7 @@ const sampleOpportunities: Opportunity[] = [ professor: "Dr. Raj Patel" }, { + id: 5, name: "Human-Computer Interaction (HCI) Researcher", description: "Study user interfaces to improve accessibility.", recommended_experience: "HTML, CSS, JavaScript, Usability Testing", @@ -76,6 +63,7 @@ const sampleOpportunities: Opportunity[] = [ professor: "Dr. Susan Miller" }, { + id: 6, name: "Climate Modeling Research Intern", description: "Simulate climate patterns using advanced modeling techniques.", recommended_experience: "Python, MATLAB, or climate science coursework", @@ -111,8 +99,8 @@ const OpportunitiesList = () => { {/* Info about the opportunities */} {sampleOpportunities.length > 0 ? ( - sampleOpportunities.map((opportunity, index) => ( - + sampleOpportunities.map((opportunity) => ( + {opportunity.name} {opportunity.description} {opportunity.location} From 3508cb2e4b5c99ec0640fa755cadc750e8fb325f Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Fri, 4 Apr 2025 23:49:46 -0400 Subject: [PATCH 21/33] Remove semester option and clean up on submit and credit formatting --- src/opportunities/components/PopUpMenu.tsx | 89 ++++++++++++++-------- 1 file changed, 58 insertions(+), 31 deletions(-) diff --git a/src/opportunities/components/PopUpMenu.tsx b/src/opportunities/components/PopUpMenu.tsx index de808bc7..d88aed34 100644 --- a/src/opportunities/components/PopUpMenu.tsx +++ b/src/opportunities/components/PopUpMenu.tsx @@ -2,19 +2,13 @@ import React, { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import CheckBox from "../../shared/components/Checkbox.tsx"; import Input from "../../staff/components/Input"; +import { Filters } from "../../types/opportunities.ts"; interface PopUpMenuProps { setFunction: () => void; - clear: () => void; - add: (filter: string[] | string) => void; reset: () => void; - filters: { - semesters: string[]; - years: string[]; - credits: string[]; - hourlyPay: string; - majors: string[]; - }; + filters: Filters; + setFilters: (activeFilters: string[], filterMap: Filters) => void; } interface Major { @@ -22,13 +16,12 @@ interface Major { name: string; } -export default function PopUpMenu({ setFunction, clear, add, reset, filters }: PopUpMenuProps) { +export default function PopUpMenu({ setFunction, reset, filters, setFilters }: PopUpMenuProps) { const [majors, setMajors] = useState(); const [validYears, setValidYears] = useState([]); - const checkboxes: [string, string[], "semesters" | "years" | "credits"][] = [ - ["Semester", ["Summer", "Fall", "Spring"], "semesters"], - ["Eligible Years", validYears, "years"], + const checkboxes: [string, string[], "years" | "credits"][] = [ + ["Class Year", validYears, "years"], ["Credits", ["1", "2", "3", "4"], "credits"] ]; @@ -66,43 +59,63 @@ export default function PopUpMenu({ setFunction, clear, add, reset, filters }: P formState: { errors }, } = useForm({ defaultValues: { - semesters: [], years: [], credits: [], - hourlyPay: "0", + hourlyPay: filters.hourlyPay ?? 0, majors: [] }, }); interface FormData { - semesters: string[], years: string[], credits: string[], - hourlyPay: string, + hourlyPay: number, majors: string[] } - function submitHandler(data: FormData) { - const { semesters, years, credits, hourlyPay, majors } = data; - clear(); - add(semesters) - add(years) - add(credits) - if (hourlyPay === "0") { - add([]) + function formatCredits(credits: string[]): string | null { + if (credits.length === 4) { + return "1-4 Credits"; + } else if (credits.length === 1) { + return `${credits[0]} ${credits[0] === "1" ? "Credit" : "Credits"}`; + } else if (JSON.stringify(credits) === JSON.stringify(["1", "2", "3"])) { + return "1-3 Credits"; + } else if (JSON.stringify(credits) === JSON.stringify(["2", "3", "4"])) { + return "2-4 Credits"; + } else if (credits.length === 0) { + return null; } else { - add([hourlyPay]) + return `${credits.join(", ")} Credits`; + } + } + + function submitHandler(data: FormData) { + const { years, credits, hourlyPay, majors } = data; + const newFilterMap: Filters = { + years: years.map(Number), + credits: credits, + hourlyPay: Number(hourlyPay), + majors: majors } - add(majors) + + const activeFilters: string[] = [ + ...years, + ...(formatCredits(credits) ? [formatCredits(credits)!] : []), + ...(Number(hourlyPay) > 0 ? [`$${Number(hourlyPay).toFixed(2)}/hr+`] : []), + ...majors + ]; + setFilters(activeFilters, newFilterMap); setFunction() }; + console.log("Filters: ", filters); + return (
-
+
Filters
@@ -111,7 +124,7 @@ export default function PopUpMenu({ setFunction, clear, add, reset, filters }: P submitHandler(data); })} className="form-container" - >
{/* Added max-height and overflow-y-auto */} + >
{/* Added max-height and overflow-y-auto */}
{checkboxes.map((filter) => (
@@ -134,7 +147,16 @@ export default function PopUpMenu({ setFunction, clear, add, reset, filters }: P label="Minimum Hourly Pay" name={"hourlyPay"} errorMessage={"Hourly pay must be at least 0"} - formHook={{ ...register("hourlyPay", {}) }} + formHook={{ + ...register("hourlyPay", { + required: "Hourly pay is required", + validate: value => value >= 0 || "Hourly pay must be greater or equal to 0", + pattern: { + value: /^[0-9]\d*$/, + message: "Hourly pay must be a positive integer" + } + }) + }} type="number" options={[]} placeHolder="Enter minimum hourly pay" @@ -152,7 +174,12 @@ export default function PopUpMenu({ setFunction, clear, add, reset, filters }: P > {majors && majors.map((major, index) => ( - ))} From c4f84cda12ec6b17ec053bb8169b8d78cb793dd1 Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Fri, 4 Apr 2025 23:50:03 -0400 Subject: [PATCH 22/33] Fix up reducer to work with popupmenu and interface as is --- src/opportunities/components/Posts.tsx | 132 +++++++++++-------------- 1 file changed, 56 insertions(+), 76 deletions(-) diff --git a/src/opportunities/components/Posts.tsx b/src/opportunities/components/Posts.tsx index 9f9e9a80..36c1ef47 100644 --- a/src/opportunities/components/Posts.tsx +++ b/src/opportunities/components/Posts.tsx @@ -2,61 +2,70 @@ import FiltersField from "./FiltersField.tsx"; import React, { useReducer, useCallback, useEffect, useState } from "react"; import OpportunitiesList from "./OpportunitiesDetails.tsx"; import PopUpMenu from "./PopUpMenu.tsx"; +import { Filters, OpportunityList } from "../../types/opportunities.ts"; const Posts = () => { const [popUpMenu, setPopUpMenu] = useState(false); const date = new Date(); - const month = date.getMonth(); - const currSem = (0 <= month && month <= 5) ? "Spring" : (5 < month && month <= 8) ? "Summer" : "Fall"; const currYr = date.getFullYear(); + // replace currYr with user year - const reducer = (state, action) => { + interface OpportunityState { + filters: { + activeFilters: string[]; + filterMap: Filters; + }; + activeId: string; + opportunities: OpportunityList[]; + } + + type OpportunityAction = + | { type: "SET_FILTERS"; activeFilters: string[]; filterMap: Filters } + | { type: "RESET_FILTERS" } + | { type: "REMOVE_FILTER"; filter: string } + | { type: "SET_OPPORTUNITIES"; opportunities: OpportunityList[] }; + + const reducer: React.Reducer = (state, action) => { switch (action.type) { - // case "CLEAR_FILTERS": - // return { - // ...state, - // filters: { - // activeFilters: [], - // filterMap: { - // semesters: currSem, - // years: currYr, - // credits: [], - // hourlyPay: "0", - // majors: [], - // }, - // }, - // }; + case "SET_FILTERS": + if (!action.activeFilters || !action.filterMap) return state; - case "RESET_FILTERS": { - const newFilterMap = { - semesters: [currSem], - years: [currYr], - credits: [], - hourlyPay: "0", - majors: [], + return { + ...state, + filters: { + activeFilters: action.activeFilters, + filterMap: action.filterMap, + }, }; + case "RESET_FILTERS": { return { ...state, filters: { - activeFilters: [currSem, currYr], - filterMap: newFilterMap, + activeFilters: [currYr.toString()], + filterMap: { + years: [currYr], + credits: [], + hourlyPay: 0, + majors: [], + }, }, }; } case "REMOVE_FILTER": { - const newFilterMap = { ...state.filters.filterMap }; - let newActiveFilters = state.filters.activeFilters.filter((item) => item !== action.filter); + if (!action.filter) return state; - Object.keys(newFilterMap).forEach((key) => { - newFilterMap[key] = newFilterMap[key].filter((item) => item !== action.filter); - if (newFilterMap[key].length === 0) { - delete newFilterMap[key]; // Remove empty categories - } - }); + const newActiveFilters = state.filters.activeFilters.filter((filter) => filter !== action.filter); + const newFilterMap = { + ...state.filters.filterMap, + years: state.filters.filterMap.years.filter((year) => year !== parseInt(action.filter)), + credits: action.filter.includes("Credit") ? [] : state.filters.filterMap.credits, + majors: state.filters.filterMap.majors.filter((major) => major !== action.filter), + hourlyPay: action.filter.includes("Hourly") ? 0 : state.filters.filterMap.hourlyPay, + }; return { ...state, @@ -67,73 +76,44 @@ const Posts = () => { }; } - case "ADD_FILTER": { - if (!action.filter || !action.category) return state; - - const newFilterMap = { ...state.filters.filterMap }; - if (!newFilterMap[action.category]) { - newFilterMap[action.category] = []; - } - if (!newFilterMap[action.category].includes(action.filter)) { - newFilterMap[action.category] = [...newFilterMap[action.category], action.filter]; - } + case "SET_OPPORTUNITIES": + if (!action.opportunities) return state; return { ...state, - filters: { - activeFilters: Array.from(new Set([...state.filters.activeFilters, action.filter])), - filterMap: newFilterMap, - }, + opportunities: action.opportunities, }; - } - - case "SET_ACTIVE_ID": - return state.jobs.some((job) => job.id === action.id) - ? { ...state, activeId: action.id } - : state; - - case "SET_JOBS": - return action.jobs ? { ...state, jobs: action.jobs } : state; default: return state; } }; - const [jobState, dispatch] = useReducer(reducer, { + const [opportunityState, dispatch] = useReducer(reducer, { filters: { - activeFilters: [currSem, currYr], + activeFilters: [currYr.toString()], filterMap: { - semesters: [currSem], years: [currYr], credits: [], - hourlyPay: "0", + hourlyPay: 0, majors: [], }, }, activeId: "", - jobs: [], + opportunities: [], }); // Action dispatchers - const clearFilters = useCallback(() => { - dispatch({ type: "CLEAR_FILTERS" }); - }, []); - const resetFilters = useCallback(() => { dispatch({ type: "RESET_FILTERS" }); }, []); - const removeFilter = useCallback((name) => { + const removeFilter = useCallback((name: string) => { dispatch({ type: "REMOVE_FILTER", filter: name }); }, []); - const addFilter = useCallback((name, category) => { - dispatch({ type: "ADD_FILTER", filter: name, category }); - }, []); - - const setActiveId = useCallback((val) => { - dispatch({ type: "SET_ACTIVE_ID", id: val }); + const setFilters = useCallback((activeFilters: string[], filterMap: Filters) => { + dispatch({ type: "SET_FILTERS", activeFilters, filterMap }); }, []); @@ -148,7 +128,7 @@ const Posts = () => { // let data = await response.json(); // data = data.data; // dispatch({ type: "SET_JOBS", jobs: data }); - // console.log(jobState.jobs); + // console.log(opportunityState.jobs); // } }; @@ -158,8 +138,8 @@ const Posts = () => { return (
- setPopUpMenu(!popUpMenu)} /> - {popUpMenu && setPopUpMenu(!popUpMenu)} filters={jobState.filters.filterMap} clear={clearFilters} add={addFilter} reset={resetFilters} />} + setPopUpMenu(!popUpMenu)} /> + {popUpMenu && setPopUpMenu(!popUpMenu)} filters={opportunityState.filters.filterMap} reset={resetFilters} setFilters={setFilters} />}
); From ff21dbf6d0d96e3e99c5b86c5ce981c040c8f1db Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Tue, 8 Apr 2025 19:16:32 -0400 Subject: [PATCH 23/33] add saved status --- src/types/opportunities.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/types/opportunities.ts b/src/types/opportunities.ts index 28d0d98c..f7585868 100644 --- a/src/types/opportunities.ts +++ b/src/types/opportunities.ts @@ -16,4 +16,5 @@ export type OpportunityList = { application_due: Date; location: string; professor: string + saved: boolean; } \ No newline at end of file From 165f4f4f3329907fc16f2df4d682d08ebf9e33ab Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Tue, 8 Apr 2025 19:16:48 -0400 Subject: [PATCH 24/33] connect to backend route --- src/opportunities/components/Posts.tsx | 41 +++++++++++++++++--------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/src/opportunities/components/Posts.tsx b/src/opportunities/components/Posts.tsx index 36c1ef47..cd5be576 100644 --- a/src/opportunities/components/Posts.tsx +++ b/src/opportunities/components/Posts.tsx @@ -118,29 +118,42 @@ const Posts = () => { const fetchOpportunities = async () => { - const url = `${process.env.REACT_APP_BACKEND_SERVER}/getOpportunityCards`; - - // const response = await fetch(url); - - // if (!response.ok) { - // console.log("Error fetching opportunities"); - // } else { - // let data = await response.json(); - // data = data.data; - // dispatch({ type: "SET_JOBS", jobs: data }); - // console.log(opportunityState.jobs); - // } + const nonEmptyFilters = Object.fromEntries( + Object.entries(opportunityState.filters.filterMap).filter(([_, value]) => { + if (Array.isArray(value)) { + return value.length > 0; + } + return value !== 0 && value !== null && value !== undefined; + }) + ); + + const response = await fetch(`${process.env.REACT_APP_BACKEND_SERVER}/opportunity/filter`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + credentials: "include", + body: JSON.stringify(nonEmptyFilters), + }); + + if (!response.ok) { + console.log("Error fetching opportunities"); + } else { + const data = await response.json(); + dispatch({ type: "SET_OPPORTUNITIES", opportunities: data }); + console.log(data); + } }; useEffect(() => { fetchOpportunities(); - }, []); + }, [opportunityState.filters]); return (
setPopUpMenu(!popUpMenu)} /> {popUpMenu && setPopUpMenu(!popUpMenu)} filters={opportunityState.filters.filterMap} reset={resetFilters} setFilters={setFilters} />} - +
); }; From 9b60971b2071988bd0f19d973578505af73177d9 Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Tue, 8 Apr 2025 19:17:20 -0400 Subject: [PATCH 25/33] update to include save status and view button --- .../components/opportunitiesDetails.tsx | 104 +++--------------- 1 file changed, 17 insertions(+), 87 deletions(-) diff --git a/src/opportunities/components/opportunitiesDetails.tsx b/src/opportunities/components/opportunitiesDetails.tsx index 9d423670..f2411073 100644 --- a/src/opportunities/components/opportunitiesDetails.tsx +++ b/src/opportunities/components/opportunitiesDetails.tsx @@ -1,85 +1,11 @@ import React from "react"; import { OpportunityList } from "../../types/opportunities.ts"; -const sampleOpportunities: OpportunityList[] = [ - { - id: 1, - name: "Research Assistant - Machine Learning Lab", - description: "Work on cutting-edge ML projects", - recommended_experience: "Python, Machine Learning basics", - pay: 15.00, - semester: "Fall", - year: 2024, - application_due: new Date("2024-08-01"), - location: "DCC", - professor: "Dr. Emily Chen" - }, - { - id: 2, - name: "Data Visualization Intern - Data Science Center", - description: "Create compelling visualizations for real-world datasets.", - recommended_experience: "D3.js, Tableau, or Matplotlib", - pay: 12.50, - semester: "Spring", - year: 2025, - application_due: new Date("2025-01-15"), - location: "EMPAC", - professor: "Dr. Alan Green" - }, - { - id: 3, - name: "Undergraduate Researcher - Renewable Energy Lab", - description: "Analyze energy efficiency of solar panel setups.", - recommended_experience: "R, Excel, or energy systems knowledge", - pay: 14.00, - semester: "Summer", - year: 2025, - application_due: new Date("2025-04-30"), - location: "Jonsson Engineering Center", - professor: "Dr. Maria Santos" - }, - { - id: 4, - name: "AI in Healthcare Research Assistant", - description: "Develop and test AI models for diagnostic tools.", - recommended_experience: "Python, TensorFlow, basic healthcare knowledge", - pay: 16.00, - semester: "Fall", - year: 2024, - application_due: new Date("2024-07-20"), - location: "Biotech Center", - professor: "Dr. Raj Patel" - }, - { - id: 5, - name: "Human-Computer Interaction (HCI) Researcher", - description: "Study user interfaces to improve accessibility.", - recommended_experience: "HTML, CSS, JavaScript, Usability Testing", - pay: 13.00, - semester: "Spring", - year: 2025, - application_due: new Date("2025-01-10"), - location: "Carnegie Building", - professor: "Dr. Susan Miller" - }, - { - id: 6, - name: "Climate Modeling Research Intern", - description: "Simulate climate patterns using advanced modeling techniques.", - recommended_experience: "Python, MATLAB, or climate science coursework", - pay: 14.50, - semester: "Summer", - year: 2025, - application_due: new Date("2025-03-15"), - location: "Troy Building", - professor: "Dr. John Reynolds" - } -]; +interface OpportunitiesListProps { + opportunities: OpportunityList[]; +} - -// This component returns a 'list' of all the opportunities - -const OpportunitiesList = () => { +export default function OpportunitiesList({ opportunities }: OpportunitiesListProps) { return (
@@ -93,32 +19,38 @@ const OpportunitiesList = () => { Pay Professor Term - Action + View + Save {/* Info about the opportunities */} - {sampleOpportunities.length > 0 ? ( - sampleOpportunities.map((opportunity) => ( + {opportunities.length > 0 ? ( + opportunities.map((opportunity) => ( {opportunity.name} {opportunity.description} {opportunity.location} - ${opportunity.pay}/hr + {opportunity.pay ? `$${opportunity.pay}/hr` : ""} {opportunity.professor} {opportunity.semester} {opportunity.year} + + + )) ) : ( - + No results found. @@ -128,6 +60,4 @@ const OpportunitiesList = () => {
); -}; - -export default OpportunitiesList; +}; \ No newline at end of file From 494263af51e980ecaab174633bf31875b28d42f9 Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Tue, 15 Apr 2025 00:03:55 -0400 Subject: [PATCH 26/33] add credits and rename to lab managers --- src/types/opportunities.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/types/opportunities.ts b/src/types/opportunities.ts index f7585868..229fd275 100644 --- a/src/types/opportunities.ts +++ b/src/types/opportunities.ts @@ -11,10 +11,11 @@ export type OpportunityList = { description: string; recommended_experience: string; pay: number; + credits: string; semester: string; year: number; application_due: Date; location: string; - professor: string + lab_managers: string saved: boolean; } \ No newline at end of file From e19b7bdd339d25f611b317fab9b79a226db4912d Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Tue, 15 Apr 2025 00:04:06 -0400 Subject: [PATCH 27/33] add lab managers and credits --- src/opportunities/components/opportunitiesDetails.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/opportunities/components/opportunitiesDetails.tsx b/src/opportunities/components/opportunitiesDetails.tsx index f2411073..a1f98282 100644 --- a/src/opportunities/components/opportunitiesDetails.tsx +++ b/src/opportunities/components/opportunitiesDetails.tsx @@ -17,7 +17,8 @@ export default function OpportunitiesList({ opportunities }: OpportunitiesListPr Description Location Pay - Professor + Credits + Lab Managers Term View Save @@ -32,7 +33,8 @@ export default function OpportunitiesList({ opportunities }: OpportunitiesListPr {opportunity.description} {opportunity.location} {opportunity.pay ? `$${opportunity.pay}/hr` : ""} - {opportunity.professor} + {opportunity.credits} + {opportunity.lab_managers} {opportunity.semester} {opportunity.year} @@ -50,7 +52,7 @@ export default function OpportunitiesList({ opportunities }: OpportunitiesListPr )) ) : ( - + No results found. From b8e6e3f8c17781d0dd38be4212c6a613f552589f Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Tue, 15 Apr 2025 00:04:18 -0400 Subject: [PATCH 28/33] fix remove hourly page from filter map --- src/opportunities/components/Posts.tsx | 57 +++++++++++++++----------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/src/opportunities/components/Posts.tsx b/src/opportunities/components/Posts.tsx index cd5be576..6b0c8357 100644 --- a/src/opportunities/components/Posts.tsx +++ b/src/opportunities/components/Posts.tsx @@ -64,7 +64,7 @@ const Posts = () => { years: state.filters.filterMap.years.filter((year) => year !== parseInt(action.filter)), credits: action.filter.includes("Credit") ? [] : state.filters.filterMap.credits, majors: state.filters.filterMap.majors.filter((major) => major !== action.filter), - hourlyPay: action.filter.includes("Hourly") ? 0 : state.filters.filterMap.hourlyPay, + hourlyPay: action.filter.includes("$") ? 0 : state.filters.filterMap.hourlyPay, }; return { @@ -118,36 +118,45 @@ const Posts = () => { const fetchOpportunities = async () => { - const nonEmptyFilters = Object.fromEntries( - Object.entries(opportunityState.filters.filterMap).filter(([_, value]) => { - if (Array.isArray(value)) { - return value.length > 0; - } - return value !== 0 && value !== null && value !== undefined; - }) + const queryParams = new URLSearchParams( + Object.entries(opportunityState.filters.filterMap) + .filter(([, value]) => { + if (Array.isArray(value)) return value.length > 0; + return value !== 0 && value !== null && value !== undefined; + }) + .reduce((acc, [key, value]) => { + if (Array.isArray(value)) { + acc[key] = value.join(","); + } else { + acc[key] = value.toString(); + } + return acc; + }, {} as Record) ); - const response = await fetch(`${process.env.REACT_APP_BACKEND_SERVER}/opportunity/filter`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - credentials: "include", - body: JSON.stringify(nonEmptyFilters), - }); - - if (!response.ok) { - console.log("Error fetching opportunities"); - } else { - const data = await response.json(); - dispatch({ type: "SET_OPPORTUNITIES", opportunities: data }); - console.log(data); + try { + const response = await fetch(`${process.env.REACT_APP_BACKEND_SERVER}/opportunity/filter?${queryParams.toString()}`, { + method: "GET", + credentials: "include", + }); + + if (!response.ok) { + console.log("Error fetching opportunities", response.status); + dispatch({ type: "SET_OPPORTUNITIES", opportunities: [] }); + } else { + const data = await response.json(); + dispatch({ type: "SET_OPPORTUNITIES", opportunities: data }); + console.log(data); + } + } catch (error) { + console.error("Error fetching opportunities:", error); + dispatch({ type: "SET_OPPORTUNITIES", opportunities: [] }); } }; useEffect(() => { fetchOpportunities(); - }, [opportunityState.filters]); + }, [opportunityState.filters.filterMap]); return (
From 5af05bce173115ba70e1c7f4cb16308bad1cdd3e Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Tue, 15 Apr 2025 00:25:53 -0400 Subject: [PATCH 29/33] adjust ordering of imports --- src/App.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 550f2fee..8b5f2eb2 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,20 +2,20 @@ import React from "react"; import { Routes, Route } from "react-router-dom"; import "./style/App.css"; -import Opportunities from "./opportunities/pages/Opportunities.tsx"; import Home from "./shared/pages/Home.tsx"; import PageNotFound from "./shared/pages/404.tsx"; import MainNavigation from "./shared/components/Navigation/MainNavigation.tsx"; +import StickyFooter from "./shared/components/Navigation/StickyFooter.tsx"; +import ProfilePage from "./shared/pages/Profile.tsx"; import Departments from "./staff/pages/Departments.tsx"; import StaffPage from "./staff/pages/Staff.tsx"; import Department from "./staff/pages/Department.tsx"; import CreatePost from "./staff/pages/CreatePost.tsx"; -import IndividualPost from "./opportunities/pages/IndividualPost.tsx"; -import ProfilePage from "./shared/pages/Profile.tsx"; import LoginRedirection from "./auth/Login.tsx"; import LogoutRedirection from "./auth/Logout.tsx"; -import StickyFooter from "./shared/components/Navigation/StickyFooter.tsx"; import Token from "./auth/Token.tsx"; +import Opportunities from "./opportunities/pages/Opportunities.tsx"; +import IndividualPost from "./opportunities/pages/IndividualPost.tsx"; import { HelmetProvider } from 'react-helmet-async'; import { AuthProvider } from './context/AuthContext.tsx'; From 899ed9eff4780a0d974216e30f3043d37be1a423 Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Tue, 15 Apr 2025 00:26:57 -0400 Subject: [PATCH 30/33] rename to temp --- .../components/{opportunitiesDetails.tsx => temp.tsx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/opportunities/components/{opportunitiesDetails.tsx => temp.tsx} (100%) diff --git a/src/opportunities/components/opportunitiesDetails.tsx b/src/opportunities/components/temp.tsx similarity index 100% rename from src/opportunities/components/opportunitiesDetails.tsx rename to src/opportunities/components/temp.tsx From 2797b1b758b6bbf037141a191ba22de3deb7701f Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Tue, 15 Apr 2025 00:27:19 -0400 Subject: [PATCH 31/33] rename files --- src/opportunities/pages/{opportunities.tsx => temp.tsx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/opportunities/pages/{opportunities.tsx => temp.tsx} (100%) diff --git a/src/opportunities/pages/opportunities.tsx b/src/opportunities/pages/temp.tsx similarity index 100% rename from src/opportunities/pages/opportunities.tsx rename to src/opportunities/pages/temp.tsx From 11a8df0f67d821547adb94720b238240903c9c7d Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Tue, 15 Apr 2025 00:27:46 -0400 Subject: [PATCH 32/33] rename file to proper capitlization --- .../components/{temp.tsx => OpportunitiesDetails.tsx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/opportunities/components/{temp.tsx => OpportunitiesDetails.tsx} (100%) diff --git a/src/opportunities/components/temp.tsx b/src/opportunities/components/OpportunitiesDetails.tsx similarity index 100% rename from src/opportunities/components/temp.tsx rename to src/opportunities/components/OpportunitiesDetails.tsx From 0bdb989d3788783917e245bbc8ef9b1aecafce96 Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Tue, 15 Apr 2025 00:28:08 -0400 Subject: [PATCH 33/33] rename file to proper capitlization --- src/opportunities/pages/{temp.tsx => Opportunities.tsx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/opportunities/pages/{temp.tsx => Opportunities.tsx} (100%) diff --git a/src/opportunities/pages/temp.tsx b/src/opportunities/pages/Opportunities.tsx similarity index 100% rename from src/opportunities/pages/temp.tsx rename to src/opportunities/pages/Opportunities.tsx