[08f82ec] | 1 | import React, {useEffect, useState} from "react";
|
---|
| 2 |
|
---|
| 3 | import "../shared_css/Modal.css"
|
---|
| 4 |
|
---|
| 5 | import 'react-responsive-modal/styles.css';
|
---|
| 6 | import "./JobSeekerEditProfile.css"
|
---|
| 7 |
|
---|
| 8 | //Validation
|
---|
| 9 | import * as yup from "yup";
|
---|
| 10 | import {yupResolver} from "@hookform/resolvers/yup";
|
---|
| 11 | import {Controller, useForm} from "react-hook-form";
|
---|
| 12 |
|
---|
| 13 | import {useDispatch, useSelector} from "react-redux";
|
---|
| 14 | import {JobSeekerActions} from "../../redux/actions/JobSeekerActions";
|
---|
| 15 | import {notifyProfileEdit, notifyProfilePicChange} from "../../utils/toastUtils";
|
---|
| 16 |
|
---|
| 17 |
|
---|
| 18 | export const JobSeekerEditProfile = (props) => {
|
---|
| 19 |
|
---|
| 20 | const dispatch = useDispatch();
|
---|
| 21 | const auth = useSelector(state => state.auth.currentUser)
|
---|
| 22 |
|
---|
| 23 | const [seekerDetails, setSeekerDetails] = useState(null);
|
---|
| 24 |
|
---|
| 25 | const [profilePicFile, setProfilePicFile] = useState(null);
|
---|
| 26 |
|
---|
| 27 | let profilePicState = useSelector(state => state.images.profilePictures);
|
---|
| 28 |
|
---|
| 29 | const [profilePicPreview, setProfilePicPreview] = useState(null);
|
---|
| 30 | const [profilePicView, setProfilePicView] = useState(null);
|
---|
| 31 |
|
---|
| 32 |
|
---|
| 33 | useEffect(() => {
|
---|
| 34 | if(auth) {
|
---|
| 35 | dispatch(JobSeekerActions.fetchJobSeekerEditDetailsById(auth.id, (success, response) => {
|
---|
| 36 | if(success) {
|
---|
| 37 | setSeekerDetails(response.data);
|
---|
| 38 | console.log(response.data)
|
---|
| 39 | }
|
---|
| 40 | }))
|
---|
| 41 | }
|
---|
| 42 | }, [auth])
|
---|
| 43 |
|
---|
| 44 | useEffect(() => {
|
---|
| 45 | if (auth.id) {
|
---|
| 46 | if(!profilePicState[auth.id]) {
|
---|
| 47 | dispatch(JobSeekerActions.downloadProfilePic(auth.id, (success, response) => {
|
---|
| 48 | if (success) {
|
---|
| 49 | setProfilePicView(response)
|
---|
| 50 | //setDispatched(true)
|
---|
| 51 | }
|
---|
| 52 | }))
|
---|
| 53 | //console.log("LOGO FETCH")
|
---|
| 54 | } else {
|
---|
| 55 | setProfilePicView(profilePicState[auth.id])
|
---|
| 56 | //console.log("LOGO STATE")
|
---|
| 57 | }
|
---|
| 58 |
|
---|
| 59 | }
|
---|
| 60 |
|
---|
| 61 | }, [auth])
|
---|
| 62 | const schema = yup.object().shape({
|
---|
| 63 | email: yup.string().required("Please enter your email"),
|
---|
| 64 | firstName: yup.string().required("Please enter your first name"),
|
---|
| 65 | lastName: yup.string().required("Please enter your last name"),
|
---|
| 66 | phoneNumber: yup.string().required("Please enter your phone number"),
|
---|
| 67 |
|
---|
| 68 | })
|
---|
| 69 |
|
---|
| 70 |
|
---|
| 71 |
|
---|
| 72 | const {register, handleSubmit, formState: {errors}} = useForm({
|
---|
| 73 | resolver: yupResolver(schema),
|
---|
| 74 | });
|
---|
| 75 |
|
---|
| 76 | const editJobSeekerDetails = async (values) => {
|
---|
| 77 | try {
|
---|
| 78 | dispatch(JobSeekerActions.editJobSeekerDetailsById(
|
---|
| 79 | {
|
---|
| 80 | email: values.email,
|
---|
| 81 | firstName: values.firstName,
|
---|
| 82 | lastName: values.lastName,
|
---|
| 83 | phoneNumber: values.phoneNumber,
|
---|
| 84 |
|
---|
| 85 |
|
---|
| 86 | }, auth.id, (success, response) => {
|
---|
| 87 | if (success) {
|
---|
| 88 | // console.log("Recruiter details edited")
|
---|
| 89 | notifyProfileEdit()
|
---|
| 90 | setSeekerDetails(response.data)
|
---|
| 91 | }
|
---|
| 92 | }
|
---|
| 93 | ))
|
---|
| 94 | } catch (err) {
|
---|
| 95 | console.error(err)
|
---|
| 96 | }
|
---|
| 97 | }
|
---|
| 98 |
|
---|
| 99 | const handleButtonClick = () => {
|
---|
| 100 | document.getElementById('logo-upload-input').click();
|
---|
| 101 | };
|
---|
| 102 | const handleLogoChange = (event) => {
|
---|
| 103 | const file = event.target.files[0];
|
---|
| 104 | if (file && (file.type === 'image/png' || file.type === 'image/jpeg')) {
|
---|
| 105 | setProfilePicFile(file)
|
---|
| 106 | setProfilePicPreview(URL.createObjectURL(file));
|
---|
| 107 | }
|
---|
| 108 | event.target.value = null;
|
---|
| 109 | };
|
---|
| 110 | const handleLogoUpload = async () => {
|
---|
| 111 | try {
|
---|
| 112 | const formData = new FormData();
|
---|
| 113 | formData.append("jobSeekerId", auth.id);
|
---|
| 114 | formData.append("profilePicFile", profilePicFile);
|
---|
| 115 |
|
---|
| 116 | dispatch(JobSeekerActions.submitProfilePic(formData, (success, response) => {
|
---|
| 117 | if (success) {
|
---|
| 118 | // window.location.reload(); // MAYBE REMOVE
|
---|
| 119 | // console.log("Logo uploaded successfully")
|
---|
| 120 | notifyProfilePicChange()
|
---|
| 121 | setProfilePicPreview(null)
|
---|
| 122 | setProfilePicView(URL.createObjectURL(profilePicFile))
|
---|
| 123 |
|
---|
| 124 | }
|
---|
| 125 | }))
|
---|
| 126 |
|
---|
| 127 | } catch (error) {
|
---|
| 128 | console.error(error)
|
---|
| 129 | }
|
---|
| 130 | }
|
---|
| 131 |
|
---|
| 132 | const handleCancelUpload = () => {
|
---|
| 133 | setProfilePicFile(null)
|
---|
| 134 | setProfilePicPreview(null)
|
---|
| 135 | }
|
---|
| 136 |
|
---|
| 137 |
|
---|
| 138 | return (<div className="custom-container no-additional-margin">
|
---|
| 139 |
|
---|
| 140 | {profilePicPreview && (
|
---|
| 141 | <div className="confirmation-bar">
|
---|
| 142 | <div className="confirmation-bar-buttons">
|
---|
| 143 | <button className="cancel-changes" onClick={handleCancelUpload}>Cancel</button>
|
---|
| 144 | <button className="save-changes" onClick={handleLogoUpload}>Save changes</button>
|
---|
| 145 |
|
---|
| 146 | </div>
|
---|
| 147 | </div>
|
---|
| 148 | )}
|
---|
| 149 | <div className="photo-box">
|
---|
| 150 | <div>
|
---|
| 151 | <img
|
---|
| 152 | src="/images/mountains.png"
|
---|
| 153 | className="company-banner"
|
---|
| 154 | alt="Company Banner"
|
---|
| 155 | />
|
---|
| 156 | {profilePicPreview ? <>
|
---|
| 157 | <img
|
---|
| 158 | src={profilePicPreview}
|
---|
| 159 | className="profile-pic"
|
---|
| 160 | alt=""
|
---|
| 161 | width={200} height={200}
|
---|
| 162 | />
|
---|
| 163 | </> : <>
|
---|
| 164 | <img
|
---|
| 165 | // loading gif
|
---|
| 166 | src={profilePicView}
|
---|
| 167 | className="profile-pic"
|
---|
| 168 | alt=""
|
---|
| 169 | width={200} height={200}
|
---|
| 170 | />
|
---|
| 171 | </>}
|
---|
| 172 |
|
---|
| 173 | </div>
|
---|
| 174 |
|
---|
| 175 | <div className="info-tab">
|
---|
| 176 | {seekerDetails && <h3>{seekerDetails.firstName + " " + seekerDetails.lastName}</h3>}
|
---|
| 177 | {/*<p>Active job listings: <span>{activeJobListingsCount}</span></p>*/}
|
---|
| 178 | </div>
|
---|
| 179 |
|
---|
| 180 | <div className="edit-buttons">
|
---|
| 181 |
|
---|
| 182 | <input
|
---|
| 183 | type="file"
|
---|
| 184 | id="logo-upload-input"
|
---|
| 185 | accept="image/png, image/jpeg"
|
---|
| 186 | onChange={handleLogoChange}
|
---|
| 187 | style={{display: 'none'}}
|
---|
| 188 | />
|
---|
| 189 | <button onClick={handleButtonClick}>
|
---|
| 190 | <i className="fa-solid fa-camera"></i> Change profile picture
|
---|
| 191 | </button>
|
---|
| 192 | <button><i className="fa-solid fa-panorama"></i> Change cover photo</button>
|
---|
| 193 | </div>
|
---|
| 194 |
|
---|
| 195 | </div>
|
---|
| 196 |
|
---|
| 197 |
|
---|
| 198 |
|
---|
| 199 | {seekerDetails &&
|
---|
| 200 | <>
|
---|
| 201 | <div className="floating-wrap">
|
---|
| 202 | <h5>Personal details</h5>
|
---|
| 203 | <form onSubmit={handleSubmit(editJobSeekerDetails)}>
|
---|
| 204 | <div className="row">
|
---|
| 205 | <div className="col-md-12">
|
---|
| 206 |
|
---|
| 207 |
|
---|
| 208 | <div className="form-floating mb-3">
|
---|
| 209 | <input type="text" className="form-control" defaultValue={seekerDetails.email} {...register("email")}
|
---|
| 210 | placeholder="David"/>
|
---|
| 211 | <label htmlFor="floatingFirstName">Email address</label>
|
---|
| 212 | <p className="error-message">{errors.email?.message}</p>
|
---|
| 213 | </div>
|
---|
| 214 |
|
---|
| 215 | <div className="form-floating mb-3">
|
---|
| 216 | <input type="text" className="form-control" defaultValue={seekerDetails.firstName} {...register("firstName")}
|
---|
| 217 | placeholder="David"/>
|
---|
| 218 | <label htmlFor="floatingFirstName">First name</label>
|
---|
| 219 | <p className="error-message">{errors.firstName?.message}</p>
|
---|
| 220 | </div>
|
---|
| 221 |
|
---|
| 222 | <div className="form-floating mb-3">
|
---|
| 223 | <input type="text" className="form-control" defaultValue={seekerDetails.lastName} {...register("lastName")}
|
---|
| 224 | placeholder="David"/>
|
---|
| 225 | <label htmlFor="floatingFirstName">Last name</label>
|
---|
| 226 | <p className="error-message">{errors.lastName?.message}</p>
|
---|
| 227 | </div>
|
---|
| 228 |
|
---|
| 229 |
|
---|
| 230 | <div className="form-floating mb-3">
|
---|
| 231 | <input type="text" className="form-control" defaultValue={seekerDetails.phoneNumber} {...register("phoneNumber")}
|
---|
| 232 | placeholder="David"/>
|
---|
| 233 | <label htmlFor="floatingFirstName">Phone number</label>
|
---|
| 234 | <p className="error-message">{errors.phoneNumber?.message}</p>
|
---|
| 235 | </div>
|
---|
| 236 |
|
---|
| 237 |
|
---|
| 238 | </div>
|
---|
| 239 | </div>
|
---|
| 240 |
|
---|
| 241 | <div className="d-flex justify-content-end">
|
---|
| 242 | <button className="blue-submit-button" type="submit"> Save changes</button>
|
---|
| 243 | </div>
|
---|
| 244 |
|
---|
| 245 | </form>
|
---|
| 246 | </div>
|
---|
| 247 | </>
|
---|
| 248 | }
|
---|
| 249 |
|
---|
| 250 |
|
---|
| 251 | </div>)
|
---|
| 252 | } |
---|