| USER_DETAILS_PAGE, | USER_DETAILS_PAGE, | ||||
| CANDIDATES_DETAILS_PAGE, | CANDIDATES_DETAILS_PAGE, | ||||
| USER_DETAILS_PAGE, | USER_DETAILS_PAGE, | ||||
| SELECTION_PROCESS_PAGE | |||||
| SELECTION_PROCESS_PAGE, | |||||
| SELECTION_PROCESS_OF_APPLICANT_PAGE | |||||
| } from "./constants/pages"; | } from "./constants/pages"; | ||||
| // import LoginPage from './pages/LoginPage/LoginPage'; | // import LoginPage from './pages/LoginPage/LoginPage'; | ||||
| import UserDetails from "./pages/UsersPage/UserDetails"; | import UserDetails from "./pages/UsersPage/UserDetails"; | ||||
| import CandidateDetailsPage from "./pages/CandidateDetailsPage/CandidateDetailsPage"; | import CandidateDetailsPage from "./pages/CandidateDetailsPage/CandidateDetailsPage"; | ||||
| import SelectionProcessPage from "./pages/SelectionProcessPage/SelectionProcessPage"; | import SelectionProcessPage from "./pages/SelectionProcessPage/SelectionProcessPage"; | ||||
| import SelectionProcessOfApplicantPage from "./pages/SelectionProcessPage/SelectionProcessOfApplicantPage"; | |||||
| const AppRoutes = () => ( | const AppRoutes = () => ( | ||||
| <Switch> | <Switch> | ||||
| <PrivateRoute exact path={CANDIDATES_PAGE} component={CandidatesPage} /> | <PrivateRoute exact path={CANDIDATES_PAGE} component={CandidatesPage} /> | ||||
| <PrivateRoute exact path={CANDIDATES_DETAILS_PAGE} component={CandidateDetailsPage} /> | <PrivateRoute exact path={CANDIDATES_DETAILS_PAGE} component={CandidateDetailsPage} /> | ||||
| <PrivateRoute exact path={SELECTION_PROCESS_PAGE} component={SelectionProcessPage} /> | <PrivateRoute exact path={SELECTION_PROCESS_PAGE} component={SelectionProcessPage} /> | ||||
| <PrivateRoute exact path={SELECTION_PROCESS_OF_APPLICANT_PAGE} component={SelectionProcessOfApplicantPage} /> | |||||
| <Redirect from="*" to={NOT_FOUND_PAGE} /> | <Redirect from="*" to={NOT_FOUND_PAGE} /> | ||||
| </Switch> | </Switch> | ||||
| ); | ); |
| .selections { | .selections { | ||||
| margin-top: 36px; | margin-top: 36px; | ||||
| padding-left: 72px;@include media-below($bp-xl) { | |||||
| padding-left: 72px; | |||||
| @include media-below($bp-xl) { | |||||
| padding-left: 36px !important; | padding-left: 36px !important; | ||||
| } | } | ||||
| } | } | ||||
| display: flex; | display: flex; | ||||
| justify-content: space-between; | justify-content: space-between; | ||||
| align-items: center; | align-items: center; | ||||
| @include media-below($bp-xl) { | @include media-below($bp-xl) { | ||||
| padding: 0 0.75rem !important; | padding: 0 0.75rem !important; | ||||
| } | } | ||||
| .selection-levels-processes-process { | .selection-levels-processes-process { | ||||
| padding-left: 81px; | padding-left: 81px; | ||||
| display: flex; | display: flex; | ||||
| @include media-below($bp-xl) { | @include media-below($bp-xl) { | ||||
| padding-left: 0; | padding-left: 0; | ||||
| } | } | ||||
| border-radius: 18px; | border-radius: 18px; | ||||
| gap: 18px; | gap: 18px; | ||||
| margin-right: 36px; | margin-right: 36px; | ||||
| @include media-below($bp-xl) { | @include media-below($bp-xl) { | ||||
| margin-right: 20px !important; | margin-right: 20px !important; | ||||
| padding: 36px !important; | padding: 36px !important; | ||||
| flex: none; | flex: none; | ||||
| order: 0; | order: 0; | ||||
| flex-grow: 0; | flex-grow: 0; | ||||
| } | |||||
| .active-process { | |||||
| scale: 1.05; | |||||
| border-color: $mainBlue !important; | |||||
| background-color: $mainBlueLight !important; | |||||
| } | |||||
| .active-process-card { | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| justify-content: start; | |||||
| align-items: flex-start; | |||||
| padding: 18px; | |||||
| background: #ffffff; | |||||
| border: 1px solid #e4e4e4; | |||||
| border-radius: 18px; | |||||
| gap: 18px; | |||||
| margin-right: 36px; | |||||
| @include media-below($bp-xl) { | |||||
| margin-right: 20px !important; | |||||
| padding: 36px !important; | |||||
| } | |||||
| } | |||||
| .active-process-card-header { | |||||
| display: flex; | |||||
| flex-direction: row; | |||||
| justify-content: start; | |||||
| align-items: flex-start; | |||||
| padding: 0px; | |||||
| gap: 18px; | |||||
| } | |||||
| .active-process-card-body { | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| justify-content: center; | |||||
| width: 100%; | |||||
| align-items: center; | |||||
| padding: 34px; | |||||
| gap: 18px; | |||||
| @include media-below($bp-xl) { | |||||
| margin-right: 20px !important; | |||||
| padding: 36px !important; | |||||
| } | |||||
| } | |||||
| .active-process-card-date p { | |||||
| font-family: 'Source Sans Pro'; | |||||
| font-style: normal; | |||||
| font-weight: 400; | |||||
| font-size: 16px; | |||||
| line-height: 20px; | |||||
| color: #272727; | |||||
| flex: none; | |||||
| order: 0; | |||||
| flex-grow: 0; | |||||
| z-index: 0; | |||||
| } | |||||
| .active-process-card-number p { | |||||
| font-family: 'Source Sans Pro'; | |||||
| font-style: normal; | |||||
| font-weight: 600; | |||||
| font-size: 16px; | |||||
| line-height: 20px; | |||||
| text-align: left; | |||||
| background: conic-gradient(from 73.66deg at 50% 50%, #226CB0 0deg, #BA6FB9 106.88deg, #5E9FDB 228.75deg, #226CB0 360deg); | |||||
| -webkit-background-clip: text; | |||||
| -webkit-text-fill-color: transparent; | |||||
| background-clip: text; | |||||
| text-fill-color: transparent; | |||||
| flex: none; | |||||
| order: 6; | |||||
| flex-grow: 0; | |||||
| z-index: 6; | |||||
| } | |||||
| .active-process-card-buttons { | |||||
| overflow: hidden; | |||||
| display: flex; | |||||
| flex-direction: row; | |||||
| align-items: flex-start; | |||||
| justify-content: center; | |||||
| padding: 0px; | |||||
| gap: 18px; | |||||
| flex: none; | |||||
| order: 4; | |||||
| flex-grow: 0; | |||||
| @include media-below($bp-xl) { | |||||
| gap: 9px !important; | |||||
| } | |||||
| } | |||||
| .active-process-card-buttons button { | |||||
| box-sizing: border-box; | |||||
| display: flex; | |||||
| flex-direction: row; | |||||
| justify-content: center; | |||||
| align-items: center; | |||||
| padding: 9px; | |||||
| gap: 10px; | |||||
| height: 38px; | |||||
| background: transparent; | |||||
| border: 1px solid #e4e4e4; | |||||
| border-radius: 9px; | |||||
| flex: none; | |||||
| order: 0; | |||||
| flex-grow: 0; | |||||
| } | |||||
| .active-process-card-link{ | |||||
| font-family: 'Source Sans Pro'; | |||||
| font-style: normal; | |||||
| font-weight: 400; | |||||
| font-size: 12px; | |||||
| text-decoration-line: underline; | |||||
| color: #226CB0; | |||||
| flex: none; | |||||
| order: 4; | |||||
| flex-grow: 0; | |||||
| z-index: 4; | |||||
| } | } |
| import React from "react"; | |||||
| import PropTypes from "prop-types"; | |||||
| import { formatDate } from "../../util/helpers/dateHelpers"; | |||||
| const ApplicantSelection = ({ | |||||
| levelNumber, | |||||
| levelName, | |||||
| schedguler, | |||||
| link, | |||||
| date, | |||||
| status, | |||||
| onShowAdDetails, | |||||
| className, | |||||
| }) => { | |||||
| return ( | |||||
| <div className={`active-process-card ${className}`} onClick={onShowAdDetails}> | |||||
| <div className="active-process-card-header"> | |||||
| <div className="active-process-card-number"> | |||||
| <p> | |||||
| {levelNumber} | |||||
| </p> | |||||
| </div> | |||||
| </div> | |||||
| <div className="active-process-card-body"> | |||||
| <div className="active-process-card-date"> | |||||
| <p> | |||||
| {date && date !== "" && formatDate(new Date(date))} | |||||
| </p> | |||||
| </div> | |||||
| <div className="ad-card-title"> | |||||
| <h3>{levelName}</h3> | |||||
| </div> | |||||
| <div className="active-process-card-date"> | |||||
| <p> | |||||
| {schedguler} | |||||
| </p> | |||||
| </div> | |||||
| <div className="active-process-card-buttons"> | |||||
| <button>{status}</button> | |||||
| </div> | |||||
| <div className="active-process-card-link"> | |||||
| <a href="#"> | |||||
| {(link && status === "Odrađen") ? "Detaljni izveštaj" : ""} | |||||
| {(link && status !== "Odrađen") ? "Link do Google Meet-a" : ""} | |||||
| </a> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| ); | |||||
| }; | |||||
| ApplicantSelection.propTypes = { | |||||
| id: PropTypes.number, | |||||
| levelNumber: PropTypes.number, | |||||
| levelName: PropTypes.string, | |||||
| schedguler: PropTypes.string, | |||||
| link: PropTypes.string, | |||||
| date: PropTypes.any, | |||||
| status: PropTypes.string, | |||||
| onShowAdDetails: PropTypes.func, | |||||
| className: PropTypes.any, | |||||
| }; | |||||
| export default ApplicantSelection; |
| import React from "react"; | import React from "react"; | ||||
| import PropTypes from "prop-types"; | import PropTypes from "prop-types"; | ||||
| import { selectDoneProcessError } from "../../store/selectors/processesSelectors"; | |||||
| import { setDoneProcessReq } from "../../store/actions/processes/processesAction"; | |||||
| import { selectDoneProcessError } from "../../store/selectors/processSelectors"; | |||||
| import { setDoneProcessReq } from "../../store/actions/processes/processAction"; | |||||
| import { useDispatch, useSelector } from "react-redux"; | import { useDispatch, useSelector } from "react-redux"; | ||||
| import { formatDateSrb, formatTimeSrb } from "../../util/helpers/dateHelpers"; | import { formatDateSrb, formatTimeSrb } from "../../util/helpers/dateHelpers"; | ||||
| import { SELECTION_PROCESS_OF_APPLICANT_PAGE } from "../../constants/pages"; | |||||
| const dragStart = (e, applicant) => { | |||||
| e.dataTransfer.setData("text/plain", JSON.stringify(applicant)); | |||||
| } | |||||
| const dragOver = (e) => { | |||||
| e.preventDefault(); | |||||
| } | |||||
| const Selection = (props) => { | const Selection = (props) => { | ||||
| const applicants = props.selection.selectionProcesses; | const applicants = props.selection.selectionProcesses; | ||||
| const errorMessage = useSelector(selectDoneProcessError); | const errorMessage = useSelector(selectDoneProcessError); | ||||
| const dispatch = useDispatch(); | const dispatch = useDispatch(); | ||||
| const dragStart = (e, applicant) => { | |||||
| e.dataTransfer.setData("text/plain",JSON.stringify(applicant)); | |||||
| } | |||||
| const dragOver = (e) => { | |||||
| e.preventDefault(); | |||||
| } | |||||
| const dropItem = (e,selId) =>{ | |||||
| const dropItem = (e, selId) => { | |||||
| var data = e.dataTransfer.getData("text/plain"); | var data = e.dataTransfer.getData("text/plain"); | ||||
| const selectionProcess = JSON.parse(data); | const selectionProcess = JSON.parse(data); | ||||
| console.log(selectionProcess) | |||||
| if(selectionProcess.selectionLevelId !== selId){ | |||||
| dispatch(setDoneProcessReq({id: selectionProcess.id})); | |||||
| if (selectionProcess.selectionLevelId !== selId) { | |||||
| dispatch(setDoneProcessReq({ id: selectionProcess.id })); | |||||
| } | } | ||||
| if(errorMessage) | |||||
| { | |||||
| if (errorMessage) { | |||||
| console.log(errorMessage) | console.log(errorMessage) | ||||
| } | } | ||||
| } | } | ||||
| const handleOpenDetails = (id) => { | |||||
| props.history.push(SELECTION_PROCESS_OF_APPLICANT_PAGE.replace(":id", id)) | |||||
| } | |||||
| const renderList = applicants?.map((item, index) => { | const renderList = applicants?.map((item, index) => { | ||||
| return <div draggable key={index} className="sel-item" onDragStart={e => dragStart(e,item)}> | |||||
| return <div draggable key={index} className="sel-item" onDragStart={e => dragStart(e, item)} | |||||
| onClick={() => handleOpenDetails(item.applicant.applicantId)}> | |||||
| <div className="status"> | <div className="status"> | ||||
| <button>{item.status}</button> | <button>{item.status}</button> | ||||
| </div> | </div> | ||||
| ); | ); | ||||
| return ( | return ( | ||||
| <div dropppable="true" id={props.selection.id} className="selection-card" | |||||
| onDragOver={e => dragOver(e)} | |||||
| onDrop={e => dropItem(e,props.selection.id)} | |||||
| <div dropppable="true" id={props.selection.id} className="selection-card" | |||||
| onDragOver={e => dragOver(e)} | |||||
| onDrop={e => dropItem(e, props.selection.id)} | |||||
| > | > | ||||
| <div className="selection-card-title"> | <div className="selection-card-title"> | ||||
| <h3>{props.selection.name}</h3> | <h3>{props.selection.name}</h3> | ||||
| {applicants.length > 0 && renderList} | {applicants.length > 0 && renderList} | ||||
| {applicants.length === 0 && <div className="sel-item"> | {applicants.length === 0 && <div className="sel-item"> | ||||
| <div className="date"> | <div className="date"> | ||||
| <p>Nema kandidata u selekciji</p> | |||||
| </div> | |||||
| </div>} | |||||
| <p>Nema kandidata u selekciji</p> | |||||
| </div> | |||||
| </div>} | |||||
| </div> | </div> | ||||
| ); | ); | ||||
| }; | }; | ||||
| Selection.propTypes = { | Selection.propTypes = { | ||||
| history: PropTypes.shape({ | |||||
| replace: PropTypes.func, | |||||
| push: PropTypes.func, | |||||
| location: PropTypes.shape({ | |||||
| pathname: PropTypes.string, | |||||
| }), | |||||
| }), | |||||
| selection: PropTypes.shape({ | selection: PropTypes.shape({ | ||||
| id: PropTypes.number, | |||||
| name : PropTypes.string, | |||||
| selectionProcesses: PropTypes.arrayOf(PropTypes.shape({ | |||||
| id: PropTypes.number, | |||||
| name: PropTypes.string, | |||||
| date: PropTypes.string, | |||||
| status: PropTypes.string, | |||||
| currentSelection: PropTypes.number, | |||||
| map: PropTypes.func, | |||||
| applicant: PropTypes.shape({ | |||||
| firstName: PropTypes.string, | |||||
| lastName: PropTypes.string | |||||
| }) | |||||
| })) | |||||
| }), | |||||
| }; | |||||
| id: PropTypes.number, | |||||
| name: PropTypes.string, | |||||
| selectionProcesses: PropTypes.arrayOf(PropTypes.shape({ | |||||
| id: PropTypes.number, | |||||
| name: PropTypes.string, | |||||
| date: PropTypes.string, | |||||
| status: PropTypes.string, | |||||
| currentSelection: PropTypes.number, | |||||
| map: PropTypes.func, | |||||
| applicant: PropTypes.shape({ | |||||
| firstName: PropTypes.string, | |||||
| lastName: PropTypes.string | |||||
| }) | |||||
| })) | |||||
| }), | |||||
| }; | |||||
| export default Selection; | export default Selection; |
| export const CANDIDATES_DETAILS_PAGE = '/candidates/:id'; | export const CANDIDATES_DETAILS_PAGE = '/candidates/:id'; | ||||
| export const FORGOT_PASSWORD_CONFIRMATION_PAGE = '/forgot-password-confirmation'; | export const FORGOT_PASSWORD_CONFIRMATION_PAGE = '/forgot-password-confirmation'; | ||||
| export const RESET_PASSWORD_PAGE = '/reset-password'; | export const RESET_PASSWORD_PAGE = '/reset-password'; | ||||
| export const SELECTION_PROCESS_PAGE = '/selectionFlow'; | |||||
| export const SELECTION_PROCESS_PAGE = '/selectionFlow'; | |||||
| export const SELECTION_PROCESS_OF_APPLICANT_PAGE = '/selectionflow/:id'; |
| import React, { useState, useEffect, useRef } from "react"; | |||||
| import arrow_left from "../../assets/images/arrow_left.png"; | |||||
| import arrow_right from "../../assets/images/arrow_right.png"; | |||||
| import { useParams } from "react-router-dom"; | |||||
| import { useTranslation } from "react-i18next"; | |||||
| import { Link } from "react-router-dom"; | |||||
| import AddAdModal from "../../components/Ads/AddAdModal"; | |||||
| import AdFilters from "../../components/Ads/AdFilters"; | |||||
| import { useDispatch } from "react-redux"; | |||||
| import { setApplicantProcessesReq } from "../../store/actions/processes/applicantProcessesAction"; | |||||
| import { useSelector } from "react-redux"; | |||||
| import { selectApplicantProcesses } from "../../store/selectors/applicantProcessesSelectors"; | |||||
| import FilterButton from "../../components/Button/FilterButton"; | |||||
| import Slider from "react-slick"; | |||||
| import "slick-carousel/slick/slick.css"; | |||||
| import "slick-carousel/slick/slick-theme.css"; | |||||
| import { useTheme } from "@emotion/react"; | |||||
| import { useMediaQuery } from "@mui/material"; | |||||
| import ApplicantSelection from "../../components/Selection/ApplicantSelection"; | |||||
| import { setProcessesReq } from "../../store/actions/processes/processesAction" | |||||
| import { selectProcesses } from "../../store/selectors/processesSelectors" | |||||
| const SelectionProcessOfApplicantPage = () => { | |||||
| const theme = useTheme(); | |||||
| const matches = useMediaQuery(theme.breakpoints.down("sm")); | |||||
| const [toggleFiltersDrawer, setToggleFiltersDrawer] = useState(false); | |||||
| const [toggleModal, setToggleModal] = useState(false); | |||||
| const processes = useSelector(selectApplicantProcesses); | |||||
| const levels = useSelector(selectProcesses) | |||||
| const { id } = useParams(); | |||||
| const activeAdsSliderRef = useRef(); | |||||
| const { t } = useTranslation(); | |||||
| const dispatch = useDispatch(); | |||||
| useEffect(() => { | |||||
| dispatch(setApplicantProcessesReq(id)); | |||||
| dispatch(setProcessesReq()); | |||||
| console.log(processes) | |||||
| }, []); | |||||
| const handleToggleFiltersDrawer = () => { | |||||
| setToggleFiltersDrawer((oldState) => !oldState); | |||||
| }; | |||||
| const handleToggleModal = () => { | |||||
| setToggleModal((oldState) => !oldState); | |||||
| }; | |||||
| var settings = { | |||||
| dots: false, | |||||
| infinite: false, | |||||
| speed: 500, | |||||
| initialSlide: 0, | |||||
| responsive: [ | |||||
| { | |||||
| breakpoint: 1024, | |||||
| settings: { | |||||
| slidesToShow: 4, | |||||
| slidesToScroll: 4, | |||||
| infinite: true, | |||||
| dots: false, | |||||
| }, | |||||
| }, | |||||
| { | |||||
| breakpoint: 900, | |||||
| settings: { | |||||
| slidesToShow: 3, | |||||
| slidesToScroll: 3, | |||||
| initialSlide: 0, | |||||
| }, | |||||
| }, | |||||
| { | |||||
| breakpoint: 480, | |||||
| settings: { | |||||
| slidesToShow: 1, | |||||
| slidesToScroll: 1, | |||||
| }, | |||||
| }, | |||||
| ], | |||||
| }; | |||||
| const activeAdsArrowLeftHandler = () => { | |||||
| activeAdsSliderRef.current.slickPrev(); | |||||
| }; | |||||
| const activeAdsArrowRightHandler = () => { | |||||
| activeAdsSliderRef.current.slickNext(); | |||||
| }; | |||||
| const concatLevels = () => { | |||||
| const applicantSelections = []; | |||||
| console.log(processes.length) | |||||
| console.log(levels.length) | |||||
| let i = processes.lengthdo | |||||
| for (let i = processes.length; i < levels.length; i++) { | |||||
| applicantSelections.push(<ApplicantSelection | |||||
| levelNumber={levels[i].id} | |||||
| levelName={levels[i].name} | |||||
| schedguler={""} | |||||
| date={""} | |||||
| status={"Čeka na zakazivanje"} | |||||
| key={i} />); | |||||
| } | |||||
| applicantSelections.push(<ApplicantSelection key={i} className="hiddenAd" | |||||
| date={""} />); | |||||
| return applicantSelections; | |||||
| }; | |||||
| return ( | |||||
| <> | |||||
| <div className="l-t-rectangle"></div> | |||||
| <div className="r-b-rectangle"></div> | |||||
| {/* <AdFilters /> */} | |||||
| <AdFilters | |||||
| open={toggleFiltersDrawer} | |||||
| handleClose={handleToggleFiltersDrawer} | |||||
| /> | |||||
| <AddAdModal open={toggleModal} handleClose={handleToggleModal} /> | |||||
| <div className="ads"> | |||||
| {processes && processes.length > 0 && ( | |||||
| <div className="active-ads"> | |||||
| <div className="active-ads-header"> | |||||
| <h1>{t("ads.activeAds")}</h1> | |||||
| <FilterButton onShowFilters={handleToggleFiltersDrawer} /> | |||||
| </div> | |||||
| <div className="active-ads-ads"> | |||||
| <div className="active-ads-ads-a"> | |||||
| {!matches && ( | |||||
| <div className="active-ads-ads-arrows"> | |||||
| <button onClick={activeAdsArrowLeftHandler}> | |||||
| <img src={arrow_left} alt="arrow-left" /> | |||||
| </button> | |||||
| <button onClick={activeAdsArrowRightHandler}> | |||||
| <img src={arrow_right} alt="arrow-right" /> | |||||
| </button> | |||||
| </div> | |||||
| )} | |||||
| </div> | |||||
| <div className="active-ads-ads-ad"> | |||||
| <Slider | |||||
| {...settings} | |||||
| slidesToShow={4} | |||||
| slidesToScroll={4} | |||||
| style={{ width: "100%" }} | |||||
| ref={activeAdsSliderRef} | |||||
| > | |||||
| {processes.map((process, index) => ( | |||||
| <ApplicantSelection | |||||
| levelNumber={index + 1} | |||||
| levelName={process.selectionLevel.name} | |||||
| schedguler={"SAfet Purkovic"} | |||||
| link={process.link} | |||||
| date={new Date(process.date)} | |||||
| status={process.status} | |||||
| key={index} | |||||
| className={index === processes.length - 1 ? "active-process" : ""} | |||||
| /> | |||||
| ))} | |||||
| {processes.length < levels.length && concatLevels()} | |||||
| </Slider> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| )} | |||||
| {matches && ( | |||||
| <div className="active-ads-ads-arrows"> | |||||
| <button onClick={activeAdsArrowLeftHandler}> | |||||
| <img src={arrow_left} alt="arrow-left" /> | |||||
| </button> | |||||
| <button onClick={activeAdsArrowRightHandler}> | |||||
| <img src={arrow_right} alt="arrow-right" /> | |||||
| </button> | |||||
| </div> | |||||
| )} | |||||
| </div> | |||||
| <div className="add-ad"> | |||||
| <Link className="ad-details-buttons-link" to="/selectionflow"> | |||||
| Nazad na sve kandidate | |||||
| </Link> | |||||
| </div> | |||||
| </> | |||||
| ); | |||||
| }; | |||||
| export default SelectionProcessOfApplicantPage; |
| import AddAdModal from "../../components/Ads/AddAdModal"; | import AddAdModal from "../../components/Ads/AddAdModal"; | ||||
| import { useDispatch } from "react-redux"; | import { useDispatch } from "react-redux"; | ||||
| import AdFilters from "../../components/Ads/AdFilters"; | import AdFilters from "../../components/Ads/AdFilters"; | ||||
| import { setDoneProcess } from "../../store/actions/processes/processAction"; | |||||
| import { setProcessesReq } from "../../store/actions/processes/processesAction"; | import { setProcessesReq } from "../../store/actions/processes/processesAction"; | ||||
| import { selectProcesses, selectDoneProcess } from "../../store/selectors/processesSelectors"; | |||||
| import { selectDoneProcess, selectDoneProcessError } from "../../store/selectors/processSelectors"; | |||||
| import { selectProcesses, selectProcessesError } from "../../store/selectors/processesSelectors" | |||||
| import PropTypes from "prop-types"; | |||||
| const SelectionProcessPage = () => { | |||||
| const SelectionProcessPage = ({history}) => { | |||||
| const [toggleFiltersDrawer, setToggleFiltersDrawer] = useState(false); | const [toggleFiltersDrawer, setToggleFiltersDrawer] = useState(false); | ||||
| const [toggleModal, setToggleModal] = useState(false); | const [toggleModal, setToggleModal] = useState(false); | ||||
| // const errorMessage = useSelector(selectProcessesError); | |||||
| const errorMessage = useSelector(selectProcessesError); | |||||
| const process = useSelector(selectDoneProcess); | |||||
| const processes = useSelector(selectProcesses); | const processes = useSelector(selectProcesses); | ||||
| // const doneErrorMessage = useSelector(selectDoneProcessError); | |||||
| const doneProcess = useSelector(selectDoneProcess); | |||||
| const doneErrorMessage = useSelector(selectDoneProcessError); | |||||
| const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
| const dispatch = useDispatch(); | const dispatch = useDispatch(); | ||||
| dispatch(setProcessesReq()); | dispatch(setProcessesReq()); | ||||
| }, []); | }, []); | ||||
| console.log(process) | |||||
| useEffect(() => { | useEffect(() => { | ||||
| dispatch(setProcessesReq()); | dispatch(setProcessesReq()); | ||||
| },[doneProcess]) | |||||
| dispatch(setDoneProcess(false)); | |||||
| },[process.process.doneProcess]) | |||||
| // console.log(errorMessage); | |||||
| // console.log(doneErrorMessage); | |||||
| console.log(errorMessage); | |||||
| console.log(doneErrorMessage); | |||||
| const handleToggleFiltersDrawer = () => { | const handleToggleFiltersDrawer = () => { | ||||
| setToggleFiltersDrawer((oldState) => !oldState); | setToggleFiltersDrawer((oldState) => !oldState); | ||||
| const renderList = processes.map((item, index) => { | const renderList = processes.map((item, index) => { | ||||
| return <Selection selection={item} key={index}/> | |||||
| return <Selection selection={item} key={index} history={history}/> | |||||
| } | } | ||||
| ); | ); | ||||
| ); | ); | ||||
| }; | }; | ||||
| SelectionProcessPage.propTypes = { | |||||
| history: PropTypes.shape({ | |||||
| replace: PropTypes.func, | |||||
| push: PropTypes.func, | |||||
| location: PropTypes.shape({ | |||||
| pathname: PropTypes.string, | |||||
| }), | |||||
| }), | |||||
| }; | |||||
| export default SelectionProcessPage; | export default SelectionProcessPage; |
| processes: { | processes: { | ||||
| allLevels: base + "/selectionlevels", | allLevels: base + "/selectionlevels", | ||||
| doneProcess: base + "/selectionprocesses", | doneProcess: base + "/selectionprocesses", | ||||
| getApplicantProcesses: base + "/applicants/processes", | |||||
| // allProcesses: base + "/selectionprocesses", | // allProcesses: base + "/selectionprocesses", | ||||
| }, | }, | ||||
| }; | }; |
| export const getAllLevels = () => getRequest(apiEndpoints.processes.allLevels); | export const getAllLevels = () => getRequest(apiEndpoints.processes.allLevels); | ||||
| export const doneProcess = (id) => getRequest(`${apiEndpoints.processes.doneProcess}/${id}`); | export const doneProcess = (id) => getRequest(`${apiEndpoints.processes.doneProcess}/${id}`); | ||||
| export const getProcessesOfApplicant = (id) => getRequest(`${apiEndpoints.processes.getApplicantProcesses}/${id}`); |
| import { | |||||
| FETCH_APPLICANT_PROCESSES_REQ, | |||||
| FETCH_APPLICANT_PROCESSES_ERR, | |||||
| FETCH_APPLICANT_PROCESSES_SUCCESS, | |||||
| } from "./processesActionConstants"; | |||||
| export const setApplicantProcessesReq = (payload) => ({ | |||||
| type: FETCH_APPLICANT_PROCESSES_REQ, | |||||
| payload | |||||
| }); | |||||
| export const setApplicantProcessesError = (payload) => ({ | |||||
| type: FETCH_APPLICANT_PROCESSES_ERR, | |||||
| payload, | |||||
| }); | |||||
| export const setApplicantProcesses = (payload) => ({ | |||||
| type: FETCH_APPLICANT_PROCESSES_SUCCESS, | |||||
| payload, | |||||
| }); |
| import { | |||||
| PUT_PROCESS_ERR, | |||||
| PUT_PROCESS_REQ, | |||||
| PUT_PROCESS_SUCCESS | |||||
| } from "./processesActionConstants"; | |||||
| export const setDoneProcessReq = (payload) => ({ | |||||
| type: PUT_PROCESS_REQ, | |||||
| payload | |||||
| }); | |||||
| export const setDoneProcessError = (payload) => ({ | |||||
| type: PUT_PROCESS_ERR, | |||||
| payload, | |||||
| }); | |||||
| export const setDoneProcess = (payload) => ({ | |||||
| type: PUT_PROCESS_SUCCESS, | |||||
| payload | |||||
| }); | |||||
| FETCH_PROCESSES_REQ, | FETCH_PROCESSES_REQ, | ||||
| FETCH_PROCESSES_ERR, | FETCH_PROCESSES_ERR, | ||||
| FETCH_PROCESSES_SUCCESS, | FETCH_PROCESSES_SUCCESS, | ||||
| PUT_PROCESS_ERR, | |||||
| PUT_PROCESS_REQ, | |||||
| PUT_PROCESS_SUCCESS | |||||
| } from "./processesActionConstants"; | } from "./processesActionConstants"; | ||||
| export const setProcessesReq = () => ({ | export const setProcessesReq = () => ({ | ||||
| export const setProcesses = (payload) => ({ | export const setProcesses = (payload) => ({ | ||||
| type: FETCH_PROCESSES_SUCCESS, | type: FETCH_PROCESSES_SUCCESS, | ||||
| payload, | payload, | ||||
| }); | |||||
| export const setDoneProcessReq = (payload) => ({ | |||||
| type: PUT_PROCESS_REQ, | |||||
| payload | |||||
| }); | |||||
| export const setDoneProcessError = (payload) => ({ | |||||
| type: PUT_PROCESS_ERR, | |||||
| payload, | |||||
| }); | |||||
| export const setDoneProcess = (payload) => ({ | |||||
| type: PUT_PROCESS_SUCCESS, | |||||
| payload | |||||
| }); | |||||
| }); |
| export const FETCH_PROCESSES_SUCCESS = 'FETCH_PROCESSES_SUCCESS'; | export const FETCH_PROCESSES_SUCCESS = 'FETCH_PROCESSES_SUCCESS'; | ||||
| export const PUT_PROCESS_REQ = 'PUT_PROCESS_REQ'; | export const PUT_PROCESS_REQ = 'PUT_PROCESS_REQ'; | ||||
| export const PUT_PROCESS_ERR = 'PUT_PROCESS_ERR'; | export const PUT_PROCESS_ERR = 'PUT_PROCESS_ERR'; | ||||
| export const PUT_PROCESS_SUCCESS = 'PUT_PROCESS_SUCCESS'; | |||||
| export const PUT_PROCESS_SUCCESS = 'PUT_PROCESS_SUCCESS'; | |||||
| export const FETCH_APPLICANT_PROCESSES_REQ = 'FETCH_APPLICANT_PROCESSES_REQ'; | |||||
| export const FETCH_APPLICANT_PROCESSES_ERR = 'FETCH_APPLICANT_PROCESSES_ERR'; | |||||
| export const FETCH_APPLICANT_PROCESSES_SUCCESS = 'FETCH_APPLICANT_PROCESSES_SUCCESS'; |
| import adReducer from "./ad/adReducer"; | import adReducer from "./ad/adReducer"; | ||||
| import archiveAdsReducer from "./ad/archiveAdsReducer"; | import archiveAdsReducer from "./ad/archiveAdsReducer"; | ||||
| import candidatesReducer from "./candidates/candidatesReducer"; | import candidatesReducer from "./candidates/candidatesReducer"; | ||||
| import candidatesReducer from './candidates/candidatesReducer'; | |||||
| import processesReducer from './processes/processesReducer'; | import processesReducer from './processes/processesReducer'; | ||||
| import processReducer from "./processes/processReducer"; | |||||
| import applicantProcessesReducer from "./processes/applicantProcessesReducer"; | |||||
| export default combineReducers({ | export default combineReducers({ | ||||
| login: loginReducer, | login: loginReducer, | ||||
| ad: adReducer, | ad: adReducer, | ||||
| archiveAds: archiveAdsReducer, | archiveAds: archiveAdsReducer, | ||||
| candidates: candidatesReducer, | candidates: candidatesReducer, | ||||
| processes: processesReducer | |||||
| processes: processesReducer, | |||||
| process: processReducer, | |||||
| applicantProcesses: applicantProcessesReducer | |||||
| }); | }); |
| import { | |||||
| FETCH_APPLICANT_PROCESSES_ERR, | |||||
| FETCH_APPLICANT_PROCESSES_SUCCESS | |||||
| } from "../../actions/processes/processesActionConstants"; | |||||
| import createReducer from "../../utils/createReducer"; | |||||
| const initialState = { | |||||
| applicantProcesses: [], | |||||
| errorMessage: "" | |||||
| }; | |||||
| export default createReducer( | |||||
| { | |||||
| [FETCH_APPLICANT_PROCESSES_SUCCESS]: setStateApplicantProcesses, | |||||
| [FETCH_APPLICANT_PROCESSES_ERR]: setApplicantProcessesErrorMessage, | |||||
| }, | |||||
| initialState | |||||
| ); | |||||
| function setStateApplicantProcesses(state, action) { | |||||
| return { | |||||
| ...state, | |||||
| applicantProcesses: action.payload, | |||||
| }; | |||||
| } | |||||
| function setApplicantProcessesErrorMessage(state, action) { | |||||
| return { | |||||
| ...state, | |||||
| errorMessage: action.payload, | |||||
| }; | |||||
| } |
| import { | |||||
| PUT_PROCESS_ERR, | |||||
| PUT_PROCESS_SUCCESS | |||||
| } from "../../actions/processes/processesActionConstants"; | |||||
| import createReducer from "../../utils/createReducer"; | |||||
| const initialState = { | |||||
| doneProcess: false, | |||||
| errorMessage: "", | |||||
| }; | |||||
| export default createReducer( | |||||
| { | |||||
| [PUT_PROCESS_SUCCESS]: setStateDoneProcess, | |||||
| [PUT_PROCESS_ERR]: setDoneProcessErrorMessage, | |||||
| }, | |||||
| initialState | |||||
| ); | |||||
| function setStateDoneProcess(state, action) { | |||||
| return { | |||||
| ...state, | |||||
| doneProcess: action.payload, | |||||
| }; | |||||
| } | |||||
| function setDoneProcessErrorMessage(state, action) { | |||||
| return { | |||||
| ...state, | |||||
| errorMessage: action.payload, | |||||
| }; | |||||
| } | |||||
| import { | import { | ||||
| FETCH_PROCESSES_ERR, | FETCH_PROCESSES_ERR, | ||||
| FETCH_PROCESSES_SUCCESS, | |||||
| PUT_PROCESS_ERR, | |||||
| PUT_PROCESS_SUCCESS | |||||
| FETCH_PROCESSES_SUCCESS | |||||
| } from "../../actions/processes/processesActionConstants"; | } from "../../actions/processes/processesActionConstants"; | ||||
| import createReducer from "../../utils/createReducer"; | import createReducer from "../../utils/createReducer"; | ||||
| const initialState = { | const initialState = { | ||||
| processes: [], | processes: [], | ||||
| doneProcess: false, | |||||
| errorMessage: "", | errorMessage: "", | ||||
| }; | }; | ||||
| { | { | ||||
| [FETCH_PROCESSES_SUCCESS]: setStateProcesses, | [FETCH_PROCESSES_SUCCESS]: setStateProcesses, | ||||
| [FETCH_PROCESSES_ERR]: setProcessesErrorMessage, | [FETCH_PROCESSES_ERR]: setProcessesErrorMessage, | ||||
| [PUT_PROCESS_SUCCESS]: setStateDoneProcess, | |||||
| [PUT_PROCESS_ERR]: setDoneProcessErrorMessage, | |||||
| }, | }, | ||||
| initialState | initialState | ||||
| ); | ); | ||||
| ...state, | ...state, | ||||
| errorMessage: action.payload, | errorMessage: action.payload, | ||||
| }; | }; | ||||
| } | |||||
| function setStateDoneProcess(state, action) { | |||||
| return { | |||||
| ...state, | |||||
| doneProcess: action.payload, | |||||
| }; | |||||
| } | |||||
| function setDoneProcessErrorMessage(state, action) { | |||||
| return { | |||||
| ...state, | |||||
| errorMessage: action.payload, | |||||
| }; | |||||
| } | |||||
| } |
| import { all, call, put, takeLatest } from "redux-saga/effects"; | import { all, call, put, takeLatest } from "redux-saga/effects"; | ||||
| import { getAllLevels, doneProcess } from "../../request/processesReguest"; | |||||
| import { setProcesses, setProcessesError, setDoneProcess, setDoneProcessError } from "../actions/processes/processesAction"; | |||||
| import { FETCH_PROCESSES_REQ, PUT_PROCESS_REQ } from "../actions/processes/processesActionConstants"; | |||||
| import { getAllLevels, doneProcess, getProcessesOfApplicant } from "../../request/processesReguest"; | |||||
| import { setProcesses, setProcessesError } from "../actions/processes/processesAction"; | |||||
| import { setDoneProcess, setDoneProcessError } from "../actions/processes/processAction"; | |||||
| import { setApplicantProcesses, setApplicantProcessesError } from "../actions/processes/applicantProcessesAction"; | |||||
| import { FETCH_PROCESSES_REQ, PUT_PROCESS_REQ, FETCH_APPLICANT_PROCESSES_REQ } from "../actions/processes/processesActionConstants"; | |||||
| export function* getProcesses() { | export function* getProcesses() { | ||||
| try { | try { | ||||
| export function* finishProcess(payload) { | export function* finishProcess(payload) { | ||||
| try { | try { | ||||
| const id = payload.payload.id; | const id = payload.payload.id; | ||||
| const done = yield call(doneProcess,id); | |||||
| yield put(setDoneProcess(done)); | |||||
| const result = yield call(doneProcess,id); | |||||
| yield put(setDoneProcess(result.data)); | |||||
| } catch (error) { | } catch (error) { | ||||
| yield put(setDoneProcessError(error)); | yield put(setDoneProcessError(error)); | ||||
| } | } | ||||
| } | } | ||||
| export function* getApplicantProcesses(payload) { | |||||
| try { | |||||
| console.log(payload) | |||||
| const id = payload.payload; | |||||
| const result = yield call(getProcessesOfApplicant,id); | |||||
| yield put(setApplicantProcesses(result.data.selectionProcesses)); | |||||
| } catch (error) { | |||||
| yield put(setApplicantProcessesError(error)); | |||||
| } | |||||
| } | |||||
| export default function* processesSaga() { | export default function* processesSaga() { | ||||
| yield all([takeLatest(FETCH_PROCESSES_REQ, getProcesses)]); | yield all([takeLatest(FETCH_PROCESSES_REQ, getProcesses)]); | ||||
| yield all([takeLatest(PUT_PROCESS_REQ, finishProcess)]); | yield all([takeLatest(PUT_PROCESS_REQ, finishProcess)]); | ||||
| yield all([takeLatest(FETCH_APPLICANT_PROCESSES_REQ, getApplicantProcesses)]); | |||||
| } | } |
| import { createSelector } from "@reduxjs/toolkit"; | |||||
| export const applicantProcessesSelector = (state) => state.applicantProcesses; | |||||
| export const selectApplicantProcesses = createSelector(applicantProcessesSelector, (state) => state.applicantProcesses); | |||||
| export const selectApplicantProcessesError = createSelector( | |||||
| applicantProcessesSelector, | |||||
| (state) => state.errorMessage | |||||
| ); |
| import { createSelector } from "@reduxjs/toolkit"; | |||||
| export const doneProcessSelector = (state) => state; | |||||
| export const selectDoneProcess = createSelector(doneProcessSelector, (state) => state); | |||||
| export const selectDoneProcessError = createSelector( | |||||
| doneProcessSelector, | |||||
| (state) => state.errorMessage | |||||
| ); |
| export const selectProcessesError = createSelector( | export const selectProcessesError = createSelector( | ||||
| processesSelector, | processesSelector, | ||||
| (state) => state.errorMessage | (state) => state.errorMessage | ||||
| ); | |||||
| export const doneProcessSelector = (state) => state.processes; | |||||
| export const selectDoneProcess = createSelector(doneProcessSelector, (state) => state.processes); | |||||
| export const selectDoneProcessError = createSelector( | |||||
| doneProcessSelector, | |||||
| (state) => state.errorMessage | |||||
| ); | |||||
| ); |