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

main
Last change on this file was befb988, checked in by 223021 <daniel.ilievski.2@…>, 12 days 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: 5.7 KB
Line 
1import {useDispatch, useSelector} from "react-redux";
2import {useEffect, useState} from "react";
3import {useParams} from "react-router";
4import {ApplicationActions} from "../../redux/actions/applicationActions";
5import {ApplicationDetailsModal} from "./ApplicationDetailsModal";
6import "./Applications.css"
7import Select from "react-select";
8import {sortElementsBy} from "../../utils/utils";
9import {JobSeekerActions} from "../../redux/actions/JobSeekerActions";
10import {notifyAppStatusUpdate} from "../../utils/toastUtils";
11
12export const ApplicationsByJobAd = () => {
13
14 const dispatch = useDispatch();
15 let {advertisement_id} = useParams();
16
17 const [applicationsByJobAd, setApplicationsByJobAd] = useState([]);
18 let applicationsByJobAdState = useSelector(state => state.appl.applicationsByJobAdId)
19 const [dispatched, setDispatched] = useState(false);
20
21 const [profilePics, setProfilePics] = useState({});
22 let profilePicsState = useSelector(state => state.images.profilePictures)
23 const [profilePicsDispatched, setProfilePicsDispatched] = useState(false);
24
25 const [jobAdTitle, setJobAdTitle] = useState("");
26
27 useEffect(() => {
28 if(!dispatched && (applicationsByJobAdState.length === 0 || applicationsByJobAdState.length === 1)) {
29 dispatch(ApplicationActions.fetchApplicationsByJobAdId(advertisement_id, (success, reponse) => {
30 if (success && reponse.data.length > 0) {
31 setApplicationsByJobAd(sortElementsBy(reponse.data, "submittedOn"))
32 setJobAdTitle(reponse.data[0].jobAdTitle)
33 }
34 setDispatched(true)
35 console.log("Fetch applications by job ad GET")
36 }))
37 } else {
38 setApplicationsByJobAd(sortElementsBy(applicationsByJobAdState, "submittedOn"));
39 if(applicationsByJobAdState.length > 0) {
40 setJobAdTitle(applicationsByJobAdState[0].jobAdTitle)
41 }
42
43 }
44
45 }, [applicationsByJobAdState])
46
47 useEffect(() => {
48 if(dispatched && !profilePicsDispatched) {
49 applicationsByJobAd.forEach(app => {
50 if(app.jobSeekerId && !profilePics[app.jobSeekerId]) {
51 fetchProfilePic(app.jobSeekerId)
52 }
53 })
54 setProfilePicsDispatched(true);
55 console.log("Fetch all profile pics GET")
56 } else if(profilePicsDispatched) {
57 setProfilePics(profilePicsState)
58 console.log("Fetch all profile pics STATE")
59 }
60 }, [dispatched])
61
62 const fetchProfilePic = (jobSeekerId) => {
63 dispatch(JobSeekerActions.downloadProfilePic(jobSeekerId, (success, response) => {
64 if(success) {
65 setProfilePics(prevState => ({...prevState, [jobSeekerId]: response}))
66 }
67 }))
68 }
69
70
71 const options = [
72 {value: 'PROPOSED', label: <span><i className="fa-solid fa-paper-plane"></i> Proposed</span>},
73 {value: 'UNDER_REVIEW', label: <span><i className="fa-solid fa-file-pen"></i> Under Review</span>},
74 {value: 'ACCEPTED', label: <span><i className="fa-solid fa-user-check"></i> Accepted</span>},
75 {value: 'DENIED', label: <span><i className="fa-solid fa-user-slash"></i> Denied</span>}
76 ];
77
78 let handleDefaultStatus = (status) => {
79 return options.find(option => option.value === status);
80 }
81
82 let handleChangeStatus = (selectedOption, id) => {
83 dispatch(ApplicationActions.updateApplicationStatus(id, selectedOption.value, (success, response) => {
84 if(success) {
85 // console.log("Status updated.")
86 notifyAppStatusUpdate()
87 }
88 }))
89 }
90
91
92 return (<div className="custom-container">
93 <div className="application-title">
94 {jobAdTitle ?
95 <h3>Applications for <b>{jobAdTitle}</b></h3> :
96 <h1></h1>
97 }
98 </div>
99
100 {applicationsByJobAd && applicationsByJobAd.map((application, index) => (
101 <div className="application-card">
102 <div className="app-job-seeker-pic">
103 <img
104 // loading gif
105 src={profilePicsState[application.jobSeekerId]}
106 alt=""
107 width={75} height={75}
108 />
109 </div>
110 <div className="app-info">
111 <span>Submitted on <b>{new Date(application.submittedOn).toLocaleString('default', {
112 day: 'numeric',
113 month: 'long',
114 year: 'numeric'
115 })}</b></span>
116 <div className="contact-info">
117 <div className="contact-item">
118 <i className="fa-solid fa-user"></i> <span>{application.jobSeekerName}</span>
119 </div> <div className="contact-item">
120 <i className="fa-solid fa-envelope"></i> <span>{application.jobSeekerEmail}</span>
121 </div> <div className="contact-item">
122 <i className="fa-solid fa-phone"></i> <span>{application.jobSeekerPhoneNumber}</span>
123 </div>
124 </div>
125 </div>
126
127 <div className="app-status">
128 <ApplicationDetailsModal application={application}/>
129 <div className="select">
130 <Select options={options} onChange={(selectedOption) => handleChangeStatus(selectedOption, application.id)} defaultValue={handleDefaultStatus(application.status)}/>
131 </div>
132
133 </div>
134 </div>
135 ))}
136
137 </div>)
138}
Note: See TracBrowser for help on using the repository browser.