| display: flex; | display: flex; | ||||
| } | } | ||||
| .pattern-details-card-sub-card-add-email input { | |||||
| .pattern-details-card-sub-card-add-email input, | |||||
| .pattern-details-card-sub-card-add-email select { | |||||
| margin-right: 18px; | margin-right: 18px; | ||||
| flex: 50; | flex: 50; | ||||
| box-sizing: border-box; | box-sizing: border-box; |
| import { useDispatch, useSelector } from "react-redux"; | import { useDispatch, useSelector } from "react-redux"; | ||||
| import { setPatternReq } from "../../store/actions/pattern/patternActions"; | import { setPatternReq } from "../../store/actions/pattern/patternActions"; | ||||
| import { selectPattern } from "../../store/selectors/patternSelectors"; | import { selectPattern } from "../../store/selectors/patternSelectors"; | ||||
| import { | |||||
| clearNotSentEmailsArray, | |||||
| scheduleAppointmentReq, | |||||
| } from "../../store/actions/scheduleAppointment/scheduleAppointmentActions"; | |||||
| import { selectNotSentEmails } from "../../store/selectors/scheduleAppointmentSelectors"; | |||||
| import { setPatternApplicantsReq } from "../../store/actions/patternApplicants/patternApplicantsActions"; | |||||
| import { selectPatternApplicants } from "../../store/selectors/patternApplicants"; | |||||
| import { PATTERNS_PAGE } from "../../constants/pages"; | |||||
| import { useHistory } from "react-router-dom"; | |||||
| const PatternDetailsPage = () => { | const PatternDetailsPage = () => { | ||||
| const [emails, setEmails] = useState([]); | const [emails, setEmails] = useState([]); | ||||
| const [email, setEmail] = useState(""); | const [email, setEmail] = useState(""); | ||||
| const pattern = useSelector(selectPattern); | const pattern = useSelector(selectPattern); | ||||
| const patternApplicants = useSelector(selectPatternApplicants); | |||||
| const notSentEmails = useSelector(selectNotSentEmails); | |||||
| const [selectedPatternApplicants, setSelectedPatternApplicants] = useState( | |||||
| [] | |||||
| ); | |||||
| const { id } = useParams(); | const { id } = useParams(); | ||||
| const dispatch = useDispatch(); | const dispatch = useDispatch(); | ||||
| const regex = /^[\w-.]+@([\w-]+\.)+[\w-]{2,4}$/ | |||||
| const history = useHistory(); | |||||
| const navigateToPatternsPage = () => { | |||||
| history.push(PATTERNS_PAGE); | |||||
| }; | |||||
| useEffect(() => { | |||||
| setSelectedPatternApplicants(patternApplicants); | |||||
| }, [patternApplicants]); | |||||
| useEffect(() => { | |||||
| dispatch(setPatternApplicantsReq({ id })); | |||||
| }, []); | |||||
| useEffect(() => { | useEffect(() => { | ||||
| dispatch(setPatternReq({ id })); | dispatch(setPatternReq({ id })); | ||||
| }, []); | }, []); | ||||
| useEffect(() => { | |||||
| if (patternApplicants.length > 0) { | |||||
| setEmail(patternApplicants[0].email); | |||||
| } | |||||
| }, [patternApplicants]); | |||||
| useEffect(() => { | |||||
| const arrOfApplicants = []; | |||||
| for (let i = 0; i < patternApplicants.length; i++) { | |||||
| let s = 0; | |||||
| for (let j = 0; j < emails.length; j++) { | |||||
| if (patternApplicants[i].email === emails[j]) s = 1; | |||||
| } | |||||
| if (s === 0) arrOfApplicants.push(patternApplicants[i]); | |||||
| } | |||||
| setSelectedPatternApplicants(arrOfApplicants); | |||||
| if (arrOfApplicants.length > 0) { | |||||
| setEmail(arrOfApplicants[0].email); | |||||
| } | |||||
| }, [emails]); | |||||
| useEffect(() => { | |||||
| dispatch(clearNotSentEmailsArray()); | |||||
| }, []); | |||||
| const addNewEmailHandler = () => { | const addNewEmailHandler = () => { | ||||
| if (email.length === 0) return; | |||||
| if(selectedPatternApplicants.length === 0) return; | |||||
| setEmails((oldState) => [...oldState, email]); | setEmails((oldState) => [...oldState, email]); | ||||
| setEmail(""); | setEmail(""); | ||||
| }; | }; | ||||
| const scheduleAppointmentHandler = () => { | |||||
| dispatch( | |||||
| scheduleAppointmentReq({ | |||||
| emails, | |||||
| patternId: id, | |||||
| handleApiResponseSuccess: navigateToPatternsPage, | |||||
| }) | |||||
| ); | |||||
| }; | |||||
| return ( | return ( | ||||
| <> | <> | ||||
| {!pattern && ( | {!pattern && ( | ||||
| </div> | </div> | ||||
| <div className="pattern-details-card-sub-card"> | <div className="pattern-details-card-sub-card"> | ||||
| <div className="pattern-details-card-sub-card-title"> | <div className="pattern-details-card-sub-card-title"> | ||||
| <p>Screening test</p> | |||||
| <p>{pattern.selectionLevel.name}</p> | |||||
| </div> | </div> | ||||
| <div className="pattern-details-card-sub-card-emails"> | <div className="pattern-details-card-sub-card-emails"> | ||||
| {emails && | {emails && | ||||
| <div className="pattern-details-card-sub-card"> | <div className="pattern-details-card-sub-card"> | ||||
| <div className="pattern-details-card-sub-card-title"> | <div className="pattern-details-card-sub-card-title"> | ||||
| <p>Screening test</p> | |||||
| <p>{pattern.selectionLevel.name}</p> | |||||
| </div> | </div> | ||||
| <div className="pattern-details-card-sub-card-add-email"> | <div className="pattern-details-card-sub-card-add-email"> | ||||
| <input | |||||
| type="text" | |||||
| onChange={(e) => setEmail(e.target.value)} | |||||
| value={email} | |||||
| placeholder="ex. petar.petrovic@mail.com" | |||||
| /> | |||||
| <button | |||||
| onClick={addNewEmailHandler} | |||||
| disabled={!regex.test(email)} | |||||
| > | |||||
| <select onChange={(e) => setEmail(e.target.value)}> | |||||
| {selectedPatternApplicants.length > 0 && | |||||
| selectedPatternApplicants.map((applicant) => ( | |||||
| <option | |||||
| key={applicant.applicantId} | |||||
| value={applicant.email} | |||||
| > | |||||
| {applicant.firstName + " " + applicant.lastName} | |||||
| </option> | |||||
| ))} | |||||
| </select> | |||||
| <button onClick={addNewEmailHandler}> | |||||
| <img src={plusIcon} alt="plus" /> | <img src={plusIcon} alt="plus" /> | ||||
| </button> | </button> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| {notSentEmails && notSentEmails.map((x) => <p key={x}>{x}</p>)} | |||||
| <div className="pattern-details-card-sub-card"> | <div className="pattern-details-card-sub-card"> | ||||
| <div className="pattern-details-card-sub-card-title"> | <div className="pattern-details-card-sub-card-title"> | ||||
| <p>Teskt poruke</p> | <p>Teskt poruke</p> | ||||
| </div> | </div> | ||||
| <div className="pattern-details-card-sub-card-message-pattern"> | <div className="pattern-details-card-sub-card-message-pattern"> | ||||
| <textarea | |||||
| disabled | |||||
| // value={`Postovani, | |||||
| // Ovom prilikom Vas obavestavamo da je datum Screening testa zakazan za [selected Date] | |||||
| // Srdacan pozdrav, | |||||
| // Diligent HR Team`} | |||||
| value={pattern.message} | |||||
| ></textarea> | |||||
| <textarea disabled value={pattern.message}></textarea> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <Link className="ad-details-buttons-link" to="/patterns"> | <Link className="ad-details-buttons-link" to="/patterns"> | ||||
| Nazad na sve šablone | Nazad na sve šablone | ||||
| </Link> | </Link> | ||||
| <IconButton className="c-btn c-btn--primary add-ad-btn"> | |||||
| <IconButton | |||||
| disabled={emails.length === 0} | |||||
| className="c-btn c-btn--primary add-ad-btn" | |||||
| onClick={scheduleAppointmentHandler} | |||||
| > | |||||
| <img | <img | ||||
| style={{ | style={{ | ||||
| marginRight: "5px", | marginRight: "5px", |
| patterns: { | patterns: { | ||||
| allPatterns: base + "/patterns", | allPatterns: base + "/patterns", | ||||
| patternById: base + "/patterns/:id", | patternById: base + "/patterns/:id", | ||||
| patternApplicantsById: base + "/patterns/corresponding-pattern-applicants/:id", | |||||
| filteredPatterns: base + "/patterns/filter", | filteredPatterns: base + "/patterns/filter", | ||||
| createPattern: base + "/patterns", | createPattern: base + "/patterns", | ||||
| updatePattern: base + "/patterns/:id", | updatePattern: base + "/patterns/:id", | ||||
| scheduleAppointment: base + "/patterns/schedule-interview" | |||||
| }, | }, | ||||
| stats: { | stats: { | ||||
| stats: base + "/stats", | stats: base + "/stats", |
| getRequest(apiEndpoints.patterns.allPatterns); | getRequest(apiEndpoints.patterns.allPatterns); | ||||
| export const getPatternById = (id) => | export const getPatternById = (id) => | ||||
| getRequest(apiEndpoints.patterns.patternById.replace(":id", id)); | getRequest(apiEndpoints.patterns.patternById.replace(":id", id)); | ||||
| export const getPatternApplicantsById = (id) => | |||||
| getRequest(apiEndpoints.patterns.patternApplicantsById.replace(":id", id)); | |||||
| export const getFilteredPatterns = (payload) => { | export const getFilteredPatterns = (payload) => { | ||||
| let selectionLevelsQuery = ""; | let selectionLevelsQuery = ""; | ||||
| for (let i = 0; i < payload.selectionLevels.length; i++) { | for (let i = 0; i < payload.selectionLevels.length; i++) { | ||||
| return getRequest( | return getRequest( | ||||
| apiEndpoints.patterns.filteredPatterns + | apiEndpoints.patterns.filteredPatterns + | ||||
| `?fromDate=${ | `?fromDate=${ | ||||
| payload.fromDate === null ? "" : new Date(payload.fromDate).toISOString() | |||||
| payload.fromDate === null | |||||
| ? "" | |||||
| : new Date(payload.fromDate).toISOString() | |||||
| }&toDate=${ | }&toDate=${ | ||||
| payload.toDate === null ? "" : new Date(payload.toDate).toISOString() | payload.toDate === null ? "" : new Date(payload.toDate).toISOString() | ||||
| }&${selectionLevelsQuery}` | }&${selectionLevelsQuery}` | ||||
| apiEndpoints.patterns.updatePattern.replace(":id", payload.id), | apiEndpoints.patterns.updatePattern.replace(":id", payload.id), | ||||
| payload | payload | ||||
| ); | ); | ||||
| export const scheduleAppointmentRequest = (payload) => | |||||
| postRequest(apiEndpoints.patterns.scheduleAppointment, payload); |
| import { | |||||
| createFetchType, | |||||
| createSuccessType, | |||||
| createErrorType, | |||||
| } from "../actionHelpers"; | |||||
| const FETCH_PATTERN_APPLICANTS_SCOPE = "FETCH_PATTERN_APPLICANTS"; | |||||
| export const FETCH_PATTERN_APPLICANTS_REQ = createFetchType( | |||||
| FETCH_PATTERN_APPLICANTS_SCOPE | |||||
| ); | |||||
| export const FETCH_PATTERN_APPLICANTS_ERR = createErrorType( | |||||
| FETCH_PATTERN_APPLICANTS_SCOPE | |||||
| ); | |||||
| export const FETCH_PATTERN_APPLICANTS_SUCCESS = createSuccessType( | |||||
| FETCH_PATTERN_APPLICANTS_SCOPE | |||||
| ); |
| import { | |||||
| FETCH_PATTERN_APPLICANTS_REQ, | |||||
| FETCH_PATTERN_APPLICANTS_ERR, | |||||
| FETCH_PATTERN_APPLICANTS_SUCCESS, | |||||
| } from "./patternApplicantsActionConstants"; | |||||
| export const setPatternApplicantsReq = (payload) => ({ | |||||
| type: FETCH_PATTERN_APPLICANTS_REQ, | |||||
| payload, | |||||
| }); | |||||
| export const setPatternApplicantsError = (payload) => ({ | |||||
| type: FETCH_PATTERN_APPLICANTS_ERR, | |||||
| payload, | |||||
| }); | |||||
| export const setPatternApplicants = (payload) => ({ | |||||
| type: FETCH_PATTERN_APPLICANTS_SUCCESS, | |||||
| payload, | |||||
| }); |
| import { | |||||
| createFetchType, | |||||
| createSuccessType, | |||||
| createErrorType, | |||||
| } from "../actionHelpers"; | |||||
| const SCHEDULE_APPOINTMENT_SCOPE = "SCHEDULE_APPOINTMENT"; | |||||
| export const SCHEDULE_APPOINTMENT_REQ = createFetchType(SCHEDULE_APPOINTMENT_SCOPE); | |||||
| export const SCHEDULE_APPOINTMENT_ERR = createErrorType(SCHEDULE_APPOINTMENT_SCOPE); | |||||
| export const SCHEDULE_APPOINTMENT_SUCCESS = createSuccessType(SCHEDULE_APPOINTMENT_SCOPE); | |||||
| export const CLEAR_NOT_SENT_EMAILS_ARRAY = "CLEAR_NOT_SENT_EMAILS_ARRAY"; | |||||
| import { | |||||
| SCHEDULE_APPOINTMENT_REQ, | |||||
| SCHEDULE_APPOINTMENT_ERR, | |||||
| SCHEDULE_APPOINTMENT_SUCCESS, | |||||
| CLEAR_NOT_SENT_EMAILS_ARRAY, | |||||
| } from "./scheduleAppointmentActionConstants"; | |||||
| export const scheduleAppointmentReq = (payload) => ({ | |||||
| type: SCHEDULE_APPOINTMENT_REQ, | |||||
| payload, | |||||
| }); | |||||
| export const scheduleAppointmentError = (payload) => ({ | |||||
| type: SCHEDULE_APPOINTMENT_ERR, | |||||
| payload, | |||||
| }); | |||||
| export const scheduleAppointment = (payload) => ({ | |||||
| type: SCHEDULE_APPOINTMENT_SUCCESS, | |||||
| payload, | |||||
| }); | |||||
| export const clearNotSentEmailsArray = () => ({ | |||||
| type: CLEAR_NOT_SENT_EMAILS_ARRAY, | |||||
| }); |
| import updatePatternReducer from "./pattern/updatePatternReducer"; | import updatePatternReducer from "./pattern/updatePatternReducer"; | ||||
| import statsReducer from "./stats/statsReducer"; | import statsReducer from "./stats/statsReducer"; | ||||
| import scheduleReducer from "./schedule/scheduleReducer"; | import scheduleReducer from "./schedule/scheduleReducer"; | ||||
| import scheduleAppointmentReducer from "./pattern/scheduleAppointmentReducer"; | |||||
| import patternApplicantsReducer from "./pattern/patternApplicantsReducer"; | |||||
| import archiveActiveAdReducer from "./ad/archiveActiveAdReducer"; | import archiveActiveAdReducer from "./ad/archiveActiveAdReducer"; | ||||
| import registerReducer from "./register/registerReducer"; | import registerReducer from "./register/registerReducer"; | ||||
| createPattern: createPatternReducer, | createPattern: createPatternReducer, | ||||
| updatePattern: updatePatternReducer, | updatePattern: updatePatternReducer, | ||||
| stats: statsReducer, | stats: statsReducer, | ||||
| schedule:scheduleReducer, | |||||
| register: registerReducer | |||||
| schedule: scheduleReducer, | |||||
| register: registerReducer, | |||||
| scheduleAppointment: scheduleAppointmentReducer, | |||||
| patternApplicants: patternApplicantsReducer, | |||||
| }); | }); |
| import createReducer from "../../utils/createReducer"; | |||||
| import { | |||||
| FETCH_PATTERN_APPLICANTS_SUCCESS, | |||||
| FETCH_PATTERN_APPLICANTS_ERR, | |||||
| } from "../../actions/patternApplicants/patternApplicantsActionConstants"; | |||||
| const initialState = { | |||||
| patternApplicants: [], | |||||
| errorMessage: "", | |||||
| }; | |||||
| export default createReducer( | |||||
| { | |||||
| [FETCH_PATTERN_APPLICANTS_SUCCESS]: setStatePatternApplicants, | |||||
| [FETCH_PATTERN_APPLICANTS_ERR]: setStateErrorMessage, | |||||
| }, | |||||
| initialState | |||||
| ); | |||||
| function setStatePatternApplicants(state, action) { | |||||
| return { ...state, patternApplicants: action.payload }; | |||||
| } | |||||
| function setStateErrorMessage(state, action) { | |||||
| return { ...state, errorMessage: action.payload }; | |||||
| } |
| import { | |||||
| SCHEDULE_APPOINTMENT_SUCCESS, | |||||
| SCHEDULE_APPOINTMENT_ERR, | |||||
| CLEAR_NOT_SENT_EMAILS_ARRAY, | |||||
| } from "../../actions/scheduleAppointment/scheduleAppointmentActionConstants"; | |||||
| import createReducer from "../../utils/createReducer"; | |||||
| const initialState = { | |||||
| notSentEmails: null, | |||||
| errorMessage: "", | |||||
| }; | |||||
| export default createReducer( | |||||
| { | |||||
| [SCHEDULE_APPOINTMENT_SUCCESS]: setStateScheduleAppointment, | |||||
| [SCHEDULE_APPOINTMENT_ERR]: setScheduleAppointmentErrorMessage, | |||||
| [CLEAR_NOT_SENT_EMAILS_ARRAY]: setNotSentEmailsArrayNull, | |||||
| }, | |||||
| initialState | |||||
| ); | |||||
| function setStateScheduleAppointment(state, action) { | |||||
| return { | |||||
| ...state, | |||||
| notSentEmails: action.payload ? [...action.payload.notSentEmails] : null, | |||||
| }; | |||||
| } | |||||
| function setScheduleAppointmentErrorMessage(state, action) { | |||||
| return { | |||||
| ...state, | |||||
| errorMessage: action.payload, | |||||
| }; | |||||
| } | |||||
| function setNotSentEmailsArrayNull(state) { | |||||
| return { | |||||
| ...state, | |||||
| notSentEmails: null, | |||||
| }; | |||||
| } |
| createPatternRequest, | createPatternRequest, | ||||
| getAllPatterns, | getAllPatterns, | ||||
| getFilteredPatterns, | getFilteredPatterns, | ||||
| getPatternApplicantsById, | |||||
| getPatternById, | getPatternById, | ||||
| scheduleAppointmentRequest, | |||||
| updatePatternRequest, | updatePatternRequest, | ||||
| } from "../../request/patternsRequest"; | } from "../../request/patternsRequest"; | ||||
| import { | import { | ||||
| import { JWT_TOKEN } from "../../constants/localStorage"; | import { JWT_TOKEN } from "../../constants/localStorage"; | ||||
| import { addHeaderToken } from "../../request"; | import { addHeaderToken } from "../../request"; | ||||
| import { rejectErrorCodeHelper } from "../../util/helpers/rejectErrorCodeHelper"; | import { rejectErrorCodeHelper } from "../../util/helpers/rejectErrorCodeHelper"; | ||||
| import { SCHEDULE_APPOINTMENT_REQ } from "../actions/scheduleAppointment/scheduleAppointmentActionConstants"; | |||||
| import { scheduleAppointment } from "../actions/scheduleAppointment/scheduleAppointmentActions"; | |||||
| import { FETCH_PATTERN_APPLICANTS_REQ } from "../actions/patternApplicants/patternApplicantsActionConstants"; | |||||
| import { setPatternApplicants } from "../actions/patternApplicants/patternApplicantsActions"; | |||||
| export function* getPatterns() { | export function* getPatterns() { | ||||
| try { | try { | ||||
| } | } | ||||
| } | } | ||||
| export function* getPatternApplicants({ payload }) { | |||||
| try { | |||||
| const JwtToken = yield call(authScopeStringGetHelper, JWT_TOKEN); | |||||
| yield call(addHeaderToken, JwtToken); | |||||
| const result = yield call(getPatternApplicantsById, payload.id); | |||||
| yield put(setPatternApplicants(result.data)); | |||||
| } catch (error) { | |||||
| const errorMessage = yield call(rejectErrorCodeHelper, error); | |||||
| yield put(setPatternError(errorMessage)); | |||||
| } | |||||
| } | |||||
| export function* filterPatterns({ payload }) { | export function* filterPatterns({ payload }) { | ||||
| try { | try { | ||||
| const JwtToken = yield call(authScopeStringGetHelper, JWT_TOKEN); | const JwtToken = yield call(authScopeStringGetHelper, JWT_TOKEN); | ||||
| } | } | ||||
| } | } | ||||
| export function* scheduleAppointmentSaga({ payload }) { | |||||
| try { | |||||
| const JwtToken = yield call(authScopeStringGetHelper, JWT_TOKEN); | |||||
| yield call(addHeaderToken, JwtToken); | |||||
| const { data } = yield call(scheduleAppointmentRequest, payload); | |||||
| yield put(scheduleAppointment(data)); | |||||
| if (payload.handleApiResponseSuccess) { | |||||
| yield call(payload.handleApiResponseSuccess); | |||||
| } | |||||
| } catch (error) { | |||||
| const errorMessage = yield call(rejectErrorCodeHelper, error); | |||||
| yield put(setFilteredPatternsError(errorMessage)); | |||||
| } | |||||
| } | |||||
| export default function* adsSaga() { | export default function* adsSaga() { | ||||
| yield all([ | yield all([ | ||||
| takeLatest(FETCH_PATTERNS_REQ, getPatterns), | takeLatest(FETCH_PATTERNS_REQ, getPatterns), | ||||
| takeLatest(FETCH_PATTERN_REQ, getPattern), | takeLatest(FETCH_PATTERN_REQ, getPattern), | ||||
| takeLatest(FETCH_PATTERN_APPLICANTS_REQ, getPatternApplicants), | |||||
| takeLatest(FETCH_FILTERED_PATTERNS_REQ, filterPatterns), | takeLatest(FETCH_FILTERED_PATTERNS_REQ, filterPatterns), | ||||
| takeLatest(CREATE_PATTERN_REQ, createPatternSaga), | takeLatest(CREATE_PATTERN_REQ, createPatternSaga), | ||||
| takeLatest(UPDATE_PATTERN_REQ, updatePatternSaga), | takeLatest(UPDATE_PATTERN_REQ, updatePatternSaga), | ||||
| takeLatest(SCHEDULE_APPOINTMENT_REQ, scheduleAppointmentSaga), | |||||
| ]); | ]); | ||||
| } | } |
| import { createSelector } from "@reduxjs/toolkit"; | |||||
| export const patternApplicantsSelector = (state) => state.patternApplicants; | |||||
| export const selectPatternApplicants = createSelector( | |||||
| patternApplicantsSelector, | |||||
| (state) => state.patternApplicants | |||||
| ); | |||||
| export const selectPatternApplicantsError = createSelector( | |||||
| patternApplicantsSelector, | |||||
| (state) => state.errorMessage | |||||
| ); |
| import { createSelector } from "@reduxjs/toolkit"; | |||||
| export const scheduleAppointmentSelector = (state) => state.scheduleAppointment; | |||||
| export const selectNotSentEmails = createSelector( | |||||
| scheduleAppointmentSelector, | |||||
| (state) => state.notSentEmails | |||||
| ); | |||||
| export const selectScheduleAppointmentError = createSelector( | |||||
| scheduleAppointmentSelector, | |||||
| (state) => state.errorMessage | |||||
| ); |