source: jobvista-frontend/src/views/dashboard/Dashboard.js@ befb988

main
Last change on this file since befb988 was befb988, checked in by 223021 <daniel.ilievski.2@…>, 2 weeks ago

Added an edit profile page for both job seekers and recruiters, where they can upload profile pictures/company logos and edit their profile data. Added profile page specifically for recruiters. Refactored existing code.

  • Property mode set to 100644
File size: 8.3 KB
Line 
1import "../shared_css/Random.css"
2
3import {useDispatch, useSelector} from "react-redux";
4import {useEffect, useState} from "react";
5import {JobAdvertisementActions} from "../../redux/actions/jobAdvertisementActions";
6import {formatRelativeTime, sortElementsBy} from "../../utils/utils";
7import {dataRangeOptions, industryOptions, industryOptionsFilter, sortOptions} from "../selectOptions";
8import Select from "react-select";
9import Roles from "../../enumerations/Roles";
10import {Link} from "react-router-dom";
11import JobType from "../../enumerations/JobType";
12import {AUTH_TOKEN} from "../../axios/axiosInstance";
13import {jwtDecode} from "jwt-decode";
14import {RecruiterActions} from "../../redux/actions/recruiterActions";
15
16export const Dashboard = () => {
17
18 const dispatch = useDispatch();
19
20 const [jobAdvertisements, setJobAdvertisements] = useState([]);
21 let jobAdvertisementsState = useSelector(state => state.jobAd.jobAdvertisements)
22 const [jobDispatched, setJobDispatched] = useState(false);
23
24 const [logos, setLogos] = useState({});
25 let logosState = useSelector(state => state.images.logos)
26 const [logoDispatched, setLogoDispatched] = useState(false);
27
28 const auth = useSelector(state => state.auth);
29
30 // const [role, setRole] = useState("");
31 const [selectedSortOrder, setSelectedSortOrder] = useState("date_newest");
32 const [selectedIndustry, setSelectedIndustry] = useState("all");
33 const [searchTerm, setSearchTerm] = useState("");
34
35
36
37 // const [user, setUser] = useState(null);
38 //
39 // useEffect(() => {
40 // const token = localStorage.getItem(AUTH_TOKEN);
41 // if (token!=null) {
42 // try {
43 // const decodedToken = jwtDecode(token);
44 // setUser({
45 // name: decodedToken.name,
46 // role: decodedToken.role,
47 // hasAccess: decodedToken.access,
48 // });
49 // } catch (error) {
50 // console.error('Failed to decode token', error);
51 // }
52 // }
53 // console.log(user)
54 // }, [auth]);
55
56 // useEffect(() => {
57 // if (auth) {
58 // setRole(auth.role);
59 // }
60 // console.log(props)
61 // }, [auth]);
62
63 useEffect(() => {
64 if (!jobDispatched && jobAdvertisementsState.length == 0) {
65 dispatch(JobAdvertisementActions.fetchJobAdvertisements((success, response) => {
66 if (success && response.data.length > 0) {
67 setJobAdvertisements(sortElementsBy(response.data, "postedOn"))
68 }
69 setJobDispatched(true)
70 console.log("Fetch all job advertisements GET")
71 }))
72
73 } else {
74 setJobAdvertisements(jobAdvertisementsState)
75 console.log("Fetch all job advertisements STATE")
76
77
78 }
79 }, [jobAdvertisementsState])
80
81 useEffect(() => {
82
83 if(jobDispatched && !logoDispatched) {
84 jobAdvertisements.forEach(jobAd => {
85 if(jobAd.recruiterId && !logos[jobAd.recruiterId]) {
86 fetchLogo(jobAd.recruiterId);
87 }
88 })
89 setLogoDispatched(true)
90 console.log("Fetch all logos GET")
91 } else {
92 setLogos(logosState)
93 console.log("Fetch all logos STATE")
94 }
95
96 }, [jobDispatched, logosState])
97
98 const fetchLogo = (recruiterId) => {
99 dispatch(RecruiterActions.downloadLogo(recruiterId, (success, response) => {
100 if(success) {
101 setLogos(prevLogos => ({...prevLogos, [recruiterId]: response}))
102 }
103 }));
104 };
105
106 let filterJobAdvertisements = () => {
107 JobAdvertisementActions.filterJobAdvertisements(
108 {
109 searchTerm: searchTerm,
110 industry: selectedIndustry,
111 sortOrder: selectedSortOrder
112 }, (success, response) => {
113 if (success) {
114 setJobAdvertisements(response.data);
115 }
116 }
117 )
118 }
119
120 return (
121
122 <div className="container">
123 <div className="filter-container">
124 <div className="row">
125 <div className="col-md-12 filter-box">
126 <div className="search-container">
127 <i className="fa-solid fa-magnifying-glass search-icon"></i>
128 <input
129 className="search-input"
130 type="text"
131 placeholder="Search job advertisement by title..."
132 value={searchTerm}
133 onChange={event => setSearchTerm(event.target.value)}
134 />
135 </div>
136 <div className="sort-section item">
137 <Select
138 defaultValue={{value: "all", label: "All industries"}}
139 value={selectedIndustry.value}
140 onChange={option => setSelectedIndustry(option.value)}
141 options={industryOptionsFilter}
142 className="sort-range sort"
143 />
144 </div>
145 <div className="sort-section item">
146 <Select
147 defaultValue={{value: "newest", label: "Date (Newest First)"}}
148 value={selectedSortOrder.value}
149 onChange={option => setSelectedSortOrder(option.value)}
150 options={sortOptions}
151 className="sort-range sort"
152 />
153 </div>
154 <button onClick={filterJobAdvertisements} className="blue-submit-button">Find jobs</button>
155 </div>
156 </div>
157 </div>
158 <div className="row row-cols-2 row-cols-md-4 g-4">
159 {jobAdvertisements &&
160 jobAdvertisements.map((jobAd, index) => (
161 <div key={index} className="col">
162 <div className="custom-card">
163 <div className="card-head">
164 <span className="hourly-salary"><b>${jobAd.startingSalary}/hr</b></span>
165 <span
166 className="job-type"> {jobAd.jobType === JobType.JOB ? "Job" : "Internship"}</span>
167 {!jobAd.active && <span className="expired">Expired</span>}
168 </div>
169 <div className="card-body">
170 <img
171 // loading gif
172 src={logos[jobAd.recruiterId]}
173 alt=""
174 width={100} height={100}
175 />
176 <h5 className="card-title">{jobAd.title}</h5>
177 <span>{jobAd.industry} • <span style={{
178 color: "black",
179 fontWeight: "bold"
180 }}>{formatRelativeTime(jobAd.postedOn)}</span></span>
181 <div className="card-info">
182 <span><i className="fa-solid fa-building"
183 style={{color: "#000000"}}></i> Company: <span style={{
184 color: "black",
185 fontWeight: "bold"
186 }}>{jobAd.recruiterName}</span></span> <br/>
187 </div>
188
189 <div className="aligned">
190 <Link to={`/job-advertisements/${jobAd.id}`} className="card-button">Read
191 more</Link>
192 </div>
193
194 </div>
195 </div>
196 </div>
197 ))}
198
199 </div>
200 </div>
201 )
202}
Note: See TracBrowser for help on using the repository browser.