diff --git a/package-lock.json b/package-lock.json index 3b45dc08..c1150518 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,7 +24,7 @@ "glob": "^11.0.0", "lru-cache": "^11.0.1", "postcss-resolve-url": "^0.0.1", - "react": "^19.0.0", + "react": "^18.3.1", "react-cookie": "^7.2.2", "react-dom": "^18.3.1", "react-hook-form": "^7.53.2", @@ -14813,10 +14813,13 @@ } }, "node_modules/react": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz", - "integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, "engines": { "node": ">=0.10.0" } diff --git a/package.json b/package.json index 316999c0..85463313 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "glob": "^11.0.0", "lru-cache": "^11.0.1", "postcss-resolve-url": "^0.0.1", - "react": "^19.0.0", + "react": "^18.3.1", "react-cookie": "^7.2.2", "react-dom": "^18.3.1", "react-hook-form": "^7.53.2", diff --git a/src/App.tsx b/src/App.tsx index 935bbffb..00eb59de 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,12 +4,12 @@ import "./style/App.css"; 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.js"; +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"; import CreatePost from "./staff/pages/CreatePost.tsx"; -import IndividualPost from "./opportunities/pages/IndividualPost.js"; +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"; diff --git a/src/opportunities/components/FiltersField.js b/src/opportunities/components/FiltersField.js deleted file mode 100644 index 23533487..00000000 --- a/src/opportunities/components/FiltersField.js +++ /dev/null @@ -1,42 +0,0 @@ -import React from "react"; -import SmallTextButton from "./SmallTextButton"; -import SearchBar from "./SearchBar"; -import GroupedComponents from "../../shared/components/UIElements/GroupedComponents"; -import HorizontalIconButton from "./HorizontalIconButton"; -import { PiSlidersHorizontal } from "react-icons/pi"; -import { MdCancel } from "react-icons/md"; - -const FiltersField = ({ deleteFilter, filters }) => { - return ( -
-
-
-
- - - - {filters.map((filter) => { - return ( - } - key={filter} - > - {filter} - - ); - })} - -
- - - - All Filters - -
-
-
- ); -}; - -export default FiltersField; diff --git a/src/opportunities/components/FiltersField.tsx b/src/opportunities/components/FiltersField.tsx new file mode 100644 index 00000000..fae9ab58 --- /dev/null +++ b/src/opportunities/components/FiltersField.tsx @@ -0,0 +1,58 @@ +import React from "react"; +import SmallTextButton from "./SmallTextButton.tsx"; +import SearchBar from "./SearchBar.tsx"; +import GroupedComponents from "../../shared/components/UIElements/GroupedComponents"; +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 }) => { + + return ( +
+
+
+
+ + + + + Change Filters + + + + {/* Fix rendering with new filters = [ [],[],[] ]*/} + + {filters[1].map((filter) => { + return( + } + key={filter} + special={false} + > + {filter} + + ) + })} + +
+ + + Reset + +
+
+
+ ); +}; + +FiltersField.propTypes = { + resetFilters: PropTypes.func.isRequired, + deleteFilter: PropTypes.func.isRequired, + filters: PropTypes.arrayOf(PropTypes.array), + setPopUpMenu: PropTypes.func.isRequired, +}; + +export default FiltersField; diff --git a/src/opportunities/components/HorizontalIconButton.js b/src/opportunities/components/HorizontalIconButton.tsx similarity index 66% rename from src/opportunities/components/HorizontalIconButton.js rename to src/opportunities/components/HorizontalIconButton.tsx index 568211eb..001655fe 100644 --- a/src/opportunities/components/HorizontalIconButton.js +++ b/src/opportunities/components/HorizontalIconButton.tsx @@ -1,4 +1,5 @@ -import React, { Children } from "react"; +import React from "react"; +import PropTypes from "prop-types"; const HorizontalIconButton = ({ children, onClick, icon, special }) => { return ( @@ -20,4 +21,11 @@ const HorizontalIconButton = ({ children, onClick, icon, special }) => { ); }; +HorizontalIconButton.propTypes = { + children: PropTypes.node, + onClick: PropTypes.func.isRequired, + icon: PropTypes.node, + special: PropTypes.bool, +} + export default HorizontalIconButton; diff --git a/src/opportunities/components/Posts.js b/src/opportunities/components/Posts.js deleted file mode 100644 index 0c299149..00000000 --- a/src/opportunities/components/Posts.js +++ /dev/null @@ -1,89 +0,0 @@ -import React from "react"; -import FiltersField from "../components/FiltersField"; -import PostsField from "./PostsField"; -import { useReducer } from "react"; -import { useCallback } from "react"; -import { useEffect } from "react"; - -const Posts = () => { - const reducer = (state, action) => { - switch (action.type) { - case "REMOVE_FILTER": - if (action.filter) { - state.filters = state.filters.filter((item) => item != action.filter); - } - return { ...state }; - case "ADD_FILTER": - if (action.filter) { - state.filters.push(action.filter); - } - return { ...state }; - case "SET_ACTIVE_ID": - if (action.id) { - if (state.jobs.find((job) => job.id === action.id)) { - state.activeId = action.id; - } - } - return { ...state }; - case "SET_JOBS": - if (action.jobs) { - state.jobs = action.jobs; - } - return { ...state }; - default: - return state; - } - }; - - var [jobState, dispatch] = useReducer(reducer, { - filters: ["Fall", "Credit", "Remote"], - activeId: "", - jobs: [], - }); - - const removeFilter = useCallback((name) => { - dispatch({ type: "REMOVE_FILTER", filter: name }); - }); - - const addFilter = useCallback((name) => { - dispatch({ type: "ADD_FILTER", filter: name }); - }); - - const setActiveId = useCallback((val) => { - console.log(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); - - if (!response.ok) { - console.log("Error fetching opportunities"); - } else { - let data = await response.json(); - data = data.data; - // console.log(data); - dispatch({ type: "SET_JOBS", jobs: data }); - console.log(jobState.jobs); - } - }; - - useEffect(() => { - fetchOpportunities(); - }, []); - - return ( -
- - -
- ); -}; - -export default Posts; diff --git a/src/opportunities/components/Posts.tsx b/src/opportunities/components/Posts.tsx new file mode 100644 index 00000000..959c8ab7 --- /dev/null +++ b/src/opportunities/components/Posts.tsx @@ -0,0 +1,260 @@ +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 { useForm } from "react-hook-form"; +import CheckBox from "../../staff/components/Checkbox.tsx"; +import PropTypes from "prop-types"; +import Input from "../../staff/components/Input"; + +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, + 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

+
+ { majors.map((list, index) => ( +
+ +
+ )) } +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+
+ ); +} + +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 [popUpMenu, setPopUpMenu] = React.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(); + + 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); + }) + } + 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) + } + return { ...state }; + case "SET_ACTIVE_ID": + if (action.id) { + if (state.jobs.find((job) => job.id === action.id)) { + state.activeId = action.id; + } + } + return { ...state }; + case "SET_JOBS": + if (action.jobs) { + state.jobs = action.jobs; + } + return { ...state }; + default: + return state; + } + }; + + const [jobState, dispatch] = useReducer(reducer, { + filters: [[[currSem],[currYr],[],[],[]],[currSem, currYr]], + activeId: "", + jobs: [], + }); + + const clearFilters = useCallback(() => { + dispatch({ type: "CLEAR_FILTERS"}); + }, []); + + const resetFilters = useCallback(() => { + dispatch({ type: "RESET_FILTERS"}); + }, []); + + const removeFilter = useCallback((name) => { + dispatch({ type: "REMOVE_FILTER", filter: name }); + }, []); + + const addFilter = useCallback((name) => { + dispatch({ type: "ADD_FILTER", filter: name }); + }, []); + + 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); + + 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(() => { + fetchOpportunities(); + }, []); + + console.log() + return ( +
+ setPopUpMenu(!popUpMenu)} /> + {popUpMenu && setPopUpMenu(!popUpMenu)} validYears={years} clear={clearFilters} add={addFilter} reset={resetFilters}/>} + +
+ ); +}; + +Posts.propTypes = { + years: PropTypes.arrayOf(PropTypes.string), +}; + +export default Posts; diff --git a/src/opportunities/components/PostsField.js b/src/opportunities/components/PostsField.js deleted file mode 100644 index d23aaa69..00000000 --- a/src/opportunities/components/PostsField.js +++ /dev/null @@ -1,137 +0,0 @@ -import React, { useEffect } from "react"; -import { useState } from "react"; -import JobPost from "./JobPost"; -import JobDetails from "./JobDetails"; - -let DUMMY_JOBS = [ - { - title: "Software Engineer", - professor: "Turner", - id: "u1", - location: "CII", - season: "Spring", - year: 2024, - }, - { - title: "Biology Researcher", - professor: "Turner", - id: "u2", - location: "CII", - season: "Spring", - year: 2024, - }, -]; - -const DUMMY_DATA = [ - { - title: "Software Engineer", - description: "Lorem Ipsum", - author: "John Smith", - id: "u1", - authorProfile: - "https://thedailyq.org/wp-content/uploads/2018/02/H-Menge-Torsten-900x600.jpg", - department: "Computer Science", - aboutSection: [ - { - title: "Application Deadline", - description: "July 1, 2024, 12pm", - }, - { - title: "Application Deadline", - description: "July 1, 2024, 12pm", - }, - { - title: "Application Deadline", - description: "July 1, 2024, 12pm", - }, - { - title: "Application Deadline", - description: "July 1, 2024, 12pm", - }, - { - title: "Application Deadline", - description: "July 1, 2024, 12pm", - }, - ], - }, - { - title: "Biology Reseacher", - description: "Lorem Ipsum", - author: "Turner", - id: "u2", - authorProfile: - "https://thedailyq.org/wp-content/uploads/2018/02/H-Menge-Torsten-900x600.jpg", - department: "Biology", - aboutSection: [ - { - title: "Application Deadline", - description: "July 1, 2024, 12pm", - }, - { - title: "Application Deadline", - description: "July 1, 2024, 12pm", - }, - { - title: "Application Deadline", - description: "July 1, 2024, 12pm", - }, - { - title: "Application Deadline", - description: "July 1, 2024, 12pm", - }, - { - title: "Application Deadline", - description: "July 1, 2024, 12pm", - }, - ], - }, -]; - -const PostsField = ({ activeId, setActive, opportunities }) => { - const findJobDetails = (id) => { - return DUMMY_DATA.find((item) => item.id === id); - }; - - var [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."} -
- ); -}; - -export default PostsField; diff --git a/src/opportunities/components/PostsField.tsx b/src/opportunities/components/PostsField.tsx new file mode 100644 index 00000000..c155c3ef --- /dev/null +++ b/src/opportunities/components/PostsField.tsx @@ -0,0 +1,57 @@ +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; diff --git a/src/opportunities/components/SearchBar.js b/src/opportunities/components/SearchBar.tsx similarity index 84% rename from src/opportunities/components/SearchBar.js rename to src/opportunities/components/SearchBar.tsx index 55636fef..0fce79f6 100644 --- a/src/opportunities/components/SearchBar.js +++ b/src/opportunities/components/SearchBar.tsx @@ -3,7 +3,7 @@ import { CiSearch } from "react-icons/ci"; const SearchBar = () => { return ( -
+ diff --git a/src/opportunities/components/SmallTextButton.js b/src/opportunities/components/SmallTextButton.js deleted file mode 100644 index 53872ccb..00000000 --- a/src/opportunities/components/SmallTextButton.js +++ /dev/null @@ -1,18 +0,0 @@ -import React, { Children } from "react"; - -const SmallTextButton = ({ children, onClick, icon, special, className }) => { - return ( -
- -
- ); -}; - -export default SmallTextButton; diff --git a/src/opportunities/components/SmallTextButton.tsx b/src/opportunities/components/SmallTextButton.tsx new file mode 100644 index 00000000..2ac9f08a --- /dev/null +++ b/src/opportunities/components/SmallTextButton.tsx @@ -0,0 +1,26 @@ +import React from "react"; +import PropTypes from "prop-types"; + +const SmallTextButton = ({ children, onClick, special, className }) => { + return ( +
+ +
+ ); +}; + +SmallTextButton.propTypes = { + children: PropTypes.node, + onClick: PropTypes.func.isRequired, + special: PropTypes.bool, + className: PropTypes.string, +} + +export default SmallTextButton; diff --git a/src/opportunities/pages/IndividualPost.js b/src/opportunities/pages/IndividualPost.js deleted file mode 100644 index 8dd55bb1..00000000 --- a/src/opportunities/pages/IndividualPost.js +++ /dev/null @@ -1,108 +0,0 @@ -import React, { useState } from "react"; -import JobDetails from "../components/JobDetails"; -import { useParams } from "react-router"; -import { useEffect } from "react"; -import { set } from "react-hook-form"; - -const DUMMY_DATA = [ - { - title: "Software Engineer", - description: "Lorem Ipsum", - author: "John Smith", - id: "u1", - authorProfile: - "https://thedailyq.org/wp-content/uploads/2018/02/H-Menge-Torsten-900x600.jpg", - department: "Computer Science", - aboutSection: [ - { - title: "Application Deadline", - description: "July 1, 2024, 12pm", - }, - { - title: "Application Deadline", - description: "July 1, 2024, 12pm", - }, - { - title: "Application Deadline", - description: "July 1, 2024, 12pm", - }, - ], - }, - { - title: "Biology Reseacher", - description: "Lorem Ipsum", - author: "Turner", - id: "u2", - authorProfile: - "https://thedailyq.org/wp-content/uploads/2018/02/H-Menge-Torsten-900x600.jpg", - department: "Biology", - aboutSection: [ - { - title: "Application Deadline", - description: "July 1, 2024, 12pm", - }, - { - title: "Application Deadline", - description: "July 1, 2024, 12pm", - }, - { - title: "Application Deadline", - description: "July 1, 2024, 12pm", - }, - { - title: "Application Deadline", - description: "July 1, 2024, 12pm", - }, - { - title: "Application Deadline", - description: "July 1, 2024, 12pm", - }, - ], - }, -]; - -const IndividualPost = () => { - const { postID } = useParams(); - - var [details, setDetails] = useState("Searching"); - - const fetchOpportunities = async () => { - // Consider moving the base URL to a configuration - const baseURL = `${process.env.REACT_APP_BACKEND_SERVER}`; - const url = `${baseURL}/getOpportunity/${postID}`; - - const response = await fetch(url); - - if (!response.ok) { - return false; - } - - const data = await response.json(); - console.log(data); - return data["data"]; - }; - - async function findDetails() { - var data = await fetchOpportunities(); - details = data || "Nothing found"; - setDetails(details); - } - - useEffect(() => { - findDetails(); - }, []); - - return ( -
- {details === "Searching" ? ( - - ) : details === "Nothing found" ? ( -

No post found

- ) : ( - - )} -
- ); -}; - -export default IndividualPost; diff --git a/src/opportunities/pages/IndividualPost.tsx b/src/opportunities/pages/IndividualPost.tsx new file mode 100644 index 00000000..95eaef1d --- /dev/null +++ b/src/opportunities/pages/IndividualPost.tsx @@ -0,0 +1,50 @@ +import React, { useState } from "react"; +import JobDetails from "../components/JobDetails"; +import { useParams } from "react-router"; +import { useEffect } from "react"; + +const IndividualPost = () => { + const { postID } = useParams(); + + const [details, setDetails] = useState("Searching"); + + const fetchOpportunities = async () => { + // Consider moving the base URL to a configuration + const baseURL = `${process.env.REACT_APP_BACKEND_SERVER}`; + const url = `${baseURL}/getOpportunity/${postID}`; + + const response = await fetch(url); + + if (!response.ok) { + return false; + } + + const data = await response.json(); + console.log(data); + return data["data"]; + }; + + async function findDetails() { + const data = await fetchOpportunities(); + details = data || "Nothing found"; + setDetails(details); + } + + useEffect(() => { + findDetails(); + }, []); + + return ( +
+ {details === "Searching" ? ( + + ) : details === "Nothing found" ? ( +

No post found

+ ) : ( + + )} +
+ ); +}; + +export default IndividualPost; diff --git a/src/opportunities/pages/Jobs.js b/src/opportunities/pages/Jobs.js deleted file mode 100644 index 2d33cfb3..00000000 --- a/src/opportunities/pages/Jobs.js +++ /dev/null @@ -1,24 +0,0 @@ -import React, { useState } from "react"; -import JobsNavigation from "../components/JobsNavigation"; -import Posts from "../components/Posts"; -import SavedJobs from "../components/SavedJobs"; -import PageNavigation from "../../shared/components/Navigation/PageNavigation"; -import usePageNavigation from "../../shared/hooks/page-navigation-hook"; - -const Jobs = () => { - var [pages, switchPage] = usePageNavigation(["Search", "Saved"], "Search"); - - return ( -
-
-
- - - {pages.activePage === "Search" && } -
-
-
- ); -}; - -export default Jobs; diff --git a/src/opportunities/pages/Jobs.tsx b/src/opportunities/pages/Jobs.tsx new file mode 100644 index 00000000..c6319b27 --- /dev/null +++ b/src/opportunities/pages/Jobs.tsx @@ -0,0 +1,41 @@ +import React, { useState } from "react"; +import Posts from "../components/Posts.tsx"; +import PageNavigation from "../../shared/components/Navigation/PageNavigation"; +import usePageNavigation from "../../shared/hooks/page-navigation-hook"; + +const Jobs = () => { + const [loading, setLoading] = useState(false); + const [years, setYears] = useState([]); + + async function fetchYears() { + const response = await fetch(`${process.env.REACT_APP_BACKEND_SERVER}/years`); + + if (response.ok) { + const data = await response.json(); + setYears(data); + } else { + console.log("No response for years"); + setLoading("no response"); + } + } + fetchYears() + + const [pages, switchPage] = usePageNavigation(["Search", "Saved"], "Search"); + + return loading === false && years != null ? ( +
+
+
+ + {pages.activePage === "Search" && } +
+
+
+ ) : loading === "no response" ? ( +

There was no response

+ ) : ( +

Loading...

+ ); +}; + +export default Jobs; diff --git a/src/style/general.css b/src/style/general.css index 3fd7a061..9f9c55dd 100644 --- a/src/style/general.css +++ b/src/style/general.css @@ -16,9 +16,6 @@ .about-head {@apply flex flex-col gap-1;} .about-title {@apply text-gray-500 text-base;} .about-description {@apply font-extrabold;} -.filters-template { @apply px-3 overflow-x-scroll max-h-20 flex gap-3;} -.filters-search {@apply flex gap-2 w-full;} -.all-filters-btn {@apply justify-end w-full;} .horizontal-btn {@apply flex gap-1 align-items-center p-2 px-2.5 rounded-3xl border;} .job-desc-header {@apply flex flex-col gap-2;} .job-desc-title {@apply font-extrabold text-xl;}