source: jobvista-frontend/src/views/applications/ApplicationsByJobSeeker.js

main
Last change on this file was 4d97b63, checked in by 223021 <daniel.ilievski.2@…>, 3 months ago

Implemented Google login, additional file uploads, response messages and email notifications

  • Property mode set to 100644
File size: 7.4 KB
Line 
1import {useDispatch, useSelector} from "react-redux";
2import {useEffect, useState} from "react";
3import {ApplicationActions} from "../../redux/actions/applicationActions";
4import {ApplicationDetailsModal} from "./ApplicationDetailsModal";
5import Select from "react-select";
6
7import {RecruiterActions} from "../../redux/actions/recruiterActions";
8import {sortElementsBy} from "../../utils/utils";
9import {Link} from "react-router-dom";
10
11export const ApplicationsByJobSeeker = () => {
12 const dispatch = useDispatch();
13 const auth = useSelector(state => state.auth.currentUser);
14
15 const [applicationsByJobSeeker, setApplicationsByJobSeeker] = useState([]);
16 let applicationsByJobSeekerState = useSelector(state => state.appl.applicationsByJobSeeker);
17 const [dispatched, setDispatched] = useState(false);
18
19 const [logos, setLogos] = useState({});
20 let logosState = useSelector(state => state.images.logos)
21 const [logoDispatched, setLogoDispatched] = useState(false);
22
23
24 useEffect(() => {
25 if (!dispatched && (applicationsByJobSeekerState.length === 0 || applicationsByJobSeekerState.length === 1)) {
26 dispatch(ApplicationActions.fetchApplicationsByJobSeeker(auth.id, (success, response) => {
27 if (success && response.data.length > 0) {
28 setApplicationsByJobSeeker(sortElementsBy(response.data, "submittedOn"));
29 }
30 setDispatched(true)
31 console.log("Fetch applications by job seeker GET")
32 }))
33
34 } else {
35 setApplicationsByJobSeeker(sortElementsBy(applicationsByJobSeekerState, "submittedOn"));
36 console.log("Fetch applications by job seeker STATE")
37 }
38 }, [applicationsByJobSeekerState])
39
40 useEffect(() => {
41
42 if (dispatched && !logoDispatched) {
43 applicationsByJobSeeker.forEach(jobAd => {
44 if (jobAd.recruiterId && !logos[jobAd.recruiterId]) {
45 fetchLogo(jobAd.recruiterId);
46 }
47 })
48 setLogoDispatched(true)
49 console.log("Fetch all logos GET")
50 } else if (logoDispatched) {
51 setLogos(logosState)
52 console.log("Fetch all logos STATE")
53
54 }
55
56 }, [dispatched, logosState])
57
58
59 const fetchLogo = (recruiterId) => {
60 dispatch(RecruiterActions.downloadLogo(recruiterId, (success, response) => {
61 if (success) {
62 setLogos(prevLogos => ({...prevLogos, [recruiterId]: response}))
63 }
64 }));
65 };
66
67 const options = [{
68 value: 'PROPOSED', label: <span className="status" style={{backgroundColor: '#4A90E2'}}><i
69 className="fa-solid fa-paper-plane"></i> Proposed</span>
70 }, {
71 value: 'UNDER_REVIEW', label: <span className="status" style={{backgroundColor: '#F5A623'}}><i
72 className="fa-solid fa-file-pen"></i> Under Review</span>
73 }, {
74 value: 'ACCEPTED', label: <span className="status" style={{backgroundColor: '#7ED321'}}><i
75 className="fa-solid fa-user-check"></i> Accepted</span>
76 }, {
77 value: 'DENIED', label: <span className="status" style={{backgroundColor: '#D0021B'}}><i
78 className="fa-solid fa-user-slash"></i> Denied</span>
79 }];
80
81 const [selectedFilter, setSelectedFilter] = useState('All');
82
83 const filters = [
84 { value: 'ALL', label: 'All', icon: 'fa-folder-open' },
85 { value: 'PROPOSED', label: 'Proposed', icon: 'fa-paper-plane' },
86 { value: 'UNDER_REVIEW', label: 'Under Review', icon: 'fa-file-pen' },
87 { value: 'ACCEPTED', label: 'Accepted', icon: 'fa-user-check' },
88 { value: 'DENIED', label: 'Denied', icon: 'fa-user-slash' },
89 ];
90
91 const filterApplicationsByJobSeeker= (filter) => {
92 dispatch(ApplicationActions.filterApplicationsByJobSeeker(auth.id, filter, (success, response) => {
93 if(success) {
94 //notify
95 }
96 }))
97 }
98
99 let handleDefaultValue = (status) => {
100 return options.find(option => option.value === status);
101 }
102
103
104 return (<div className="custom-container">
105
106 <div className="application-title">
107 <h3>Application history</h3>
108 </div>
109
110 <div className="application-filters d-inline-flex flex-row justify-content-start">
111 {
112 filters.map(filter => (
113 <span
114 key={filter.label}
115 className={selectedFilter === filter.label ? "selected" : ""}
116 onClick={() => {
117 setSelectedFilter(filter.label)
118 filterApplicationsByJobSeeker(filter.value)
119 }}
120 ><i className={`fa-solid ${filter.icon}`}></i> {filter.label}</span>
121 ))
122 }
123 </div>
124
125 {applicationsByJobSeeker && applicationsByJobSeeker.map((application, index) => (
126 <div className="application-card-wrapper">
127 <div key={index} className="application-card">
128 <div className="app-company-logo">
129 <img
130 // loading gif
131 src={logosState[application.recruiterId]}
132 alt=""
133 width={75} height={75}
134 />
135 </div>
136
137 <div className="app-info">
138 <Link to={`/job-advertisements/${application.jobAdId}`}
139 className="jobAd-title">{application.jobAdTitle}</Link>
140 {/*<h5 className="jobAd-title"></h5>*/}
141 <div className="contact-info">
142 <div className="contact-item">
143 <i className="fa-solid fa-building"></i> <span>{application.recruiterName}</span>
144 </div>
145 <div className="contact-item">
146 <i className="fa-solid fa-envelope"></i> <span>{application.recruiterEmail}</span>
147 </div>
148 <div className="contact-item">
149 <i className="fa-solid fa-phone"></i>
150 <span>{application.recruiterPhoneNumber}</span>
151 </div>
152 <span> • Submitted on <b>{new Date(application.submittedOn).toLocaleString('default', {
153 day: 'numeric', month: 'long', year: 'numeric'
154 })}</b></span>
155 </div>
156 </div>
157
158 <div className="app-status">
159 <ApplicationDetailsModal application={application}/>
160 <> {handleDefaultValue(application.status).label}</>
161 {/*<div className="select">*/}
162 {/* <Select isDisabled={true} options={options} />*/}
163 {/*</div>*/}
164
165 </div>
166 </div>
167 {application.response &&
168 <div className="response-message">
169 {application.response}
170 </div>
171 }
172
173 </div>
174
175 ))}
176
177 </div>)
178}
Note: See TracBrowser for help on using the repository browser.