| @@ -16,7 +16,8 @@ import { | |||
| USER_DETAILS_PAGE, | |||
| CANDIDATES_DETAILS_PAGE, | |||
| USER_DETAILS_PAGE, | |||
| SELECTION_PROCESS_PAGE | |||
| SELECTION_PROCESS_PAGE, | |||
| SELECTION_PROCESS_OF_APPLICANT_PAGE | |||
| } from "./constants/pages"; | |||
| // import LoginPage from './pages/LoginPage/LoginPage'; | |||
| @@ -37,6 +38,7 @@ import AdDetailsPage from "./pages/AdsPage/AdDetailsPage"; | |||
| import UserDetails from "./pages/UsersPage/UserDetails"; | |||
| import CandidateDetailsPage from "./pages/CandidateDetailsPage/CandidateDetailsPage"; | |||
| import SelectionProcessPage from "./pages/SelectionProcessPage/SelectionProcessPage"; | |||
| import SelectionProcessOfApplicantPage from "./pages/SelectionProcessPage/SelectionProcessOfApplicantPage"; | |||
| const AppRoutes = () => ( | |||
| <Switch> | |||
| @@ -58,6 +60,7 @@ const AppRoutes = () => ( | |||
| <PrivateRoute exact path={CANDIDATES_PAGE} component={CandidatesPage} /> | |||
| <PrivateRoute exact path={CANDIDATES_DETAILS_PAGE} component={CandidateDetailsPage} /> | |||
| <PrivateRoute exact path={SELECTION_PROCESS_PAGE} component={SelectionProcessPage} /> | |||
| <PrivateRoute exact path={SELECTION_PROCESS_OF_APPLICANT_PAGE} component={SelectionProcessOfApplicantPage} /> | |||
| <Redirect from="*" to={NOT_FOUND_PAGE} /> | |||
| </Switch> | |||
| ); | |||
| @@ -1,6 +1,8 @@ | |||
| .selections { | |||
| margin-top: 36px; | |||
| padding-left: 72px;@include media-below($bp-xl) { | |||
| padding-left: 72px; | |||
| @include media-below($bp-xl) { | |||
| padding-left: 36px !important; | |||
| } | |||
| } | |||
| @@ -10,6 +12,7 @@ | |||
| display: flex; | |||
| justify-content: space-between; | |||
| align-items: center; | |||
| @include media-below($bp-xl) { | |||
| padding: 0 0.75rem !important; | |||
| } | |||
| @@ -51,6 +54,7 @@ | |||
| .selection-levels-processes-process { | |||
| padding-left: 81px; | |||
| display: flex; | |||
| @include media-below($bp-xl) { | |||
| padding-left: 0; | |||
| } | |||
| @@ -69,6 +73,7 @@ | |||
| border-radius: 18px; | |||
| gap: 18px; | |||
| margin-right: 36px; | |||
| @include media-below($bp-xl) { | |||
| margin-right: 20px !important; | |||
| padding: 36px !important; | |||
| @@ -232,4 +237,130 @@ | |||
| flex: none; | |||
| order: 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; | |||
| } | |||
| @@ -0,0 +1,69 @@ | |||
| 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; | |||
| @@ -1,42 +1,43 @@ | |||
| import React from "react"; | |||
| 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 { 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 applicants = props.selection.selectionProcesses; | |||
| const errorMessage = useSelector(selectDoneProcessError); | |||
| 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"); | |||
| 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) | |||
| } | |||
| } | |||
| const handleOpenDetails = (id) => { | |||
| props.history.push(SELECTION_PROCESS_OF_APPLICANT_PAGE.replace(":id", id)) | |||
| } | |||
| 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"> | |||
| <button>{item.status}</button> | |||
| </div> | |||
| @@ -51,9 +52,9 @@ const Selection = (props) => { | |||
| ); | |||
| 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"> | |||
| <h3>{props.selection.name}</h3> | |||
| @@ -62,30 +63,37 @@ const Selection = (props) => { | |||
| {applicants.length > 0 && renderList} | |||
| {applicants.length === 0 && <div className="sel-item"> | |||
| <div className="date"> | |||
| <p>Nema kandidata u selekciji</p> | |||
| </div> | |||
| </div>} | |||
| <p>Nema kandidata u selekciji</p> | |||
| </div> | |||
| </div>} | |||
| </div> | |||
| ); | |||
| }; | |||
| Selection.propTypes = { | |||
| history: PropTypes.shape({ | |||
| replace: PropTypes.func, | |||
| push: PropTypes.func, | |||
| location: PropTypes.shape({ | |||
| pathname: PropTypes.string, | |||
| }), | |||
| }), | |||
| 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; | |||
| @@ -11,4 +11,5 @@ export const CANDIDATES_PAGE = '/candidates'; | |||
| export const CANDIDATES_DETAILS_PAGE = '/candidates/:id'; | |||
| export const FORGOT_PASSWORD_CONFIRMATION_PAGE = '/forgot-password-confirmation'; | |||
| 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'; | |||
| @@ -0,0 +1,190 @@ | |||
| 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; | |||
| @@ -7,16 +7,19 @@ import { useTranslation } from "react-i18next"; | |||
| import AddAdModal from "../../components/Ads/AddAdModal"; | |||
| import { useDispatch } from "react-redux"; | |||
| import AdFilters from "../../components/Ads/AdFilters"; | |||
| import { setDoneProcess } from "../../store/actions/processes/processAction"; | |||
| 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 [toggleModal, setToggleModal] = useState(false); | |||
| // const errorMessage = useSelector(selectProcessesError); | |||
| const errorMessage = useSelector(selectProcessesError); | |||
| const process = useSelector(selectDoneProcess); | |||
| const processes = useSelector(selectProcesses); | |||
| // const doneErrorMessage = useSelector(selectDoneProcessError); | |||
| const doneProcess = useSelector(selectDoneProcess); | |||
| const doneErrorMessage = useSelector(selectDoneProcessError); | |||
| const { t } = useTranslation(); | |||
| const dispatch = useDispatch(); | |||
| @@ -24,12 +27,15 @@ const SelectionProcessPage = () => { | |||
| dispatch(setProcessesReq()); | |||
| }, []); | |||
| console.log(process) | |||
| useEffect(() => { | |||
| dispatch(setProcessesReq()); | |||
| },[doneProcess]) | |||
| dispatch(setDoneProcess(false)); | |||
| },[process.process.doneProcess]) | |||
| // console.log(errorMessage); | |||
| // console.log(doneErrorMessage); | |||
| console.log(errorMessage); | |||
| console.log(doneErrorMessage); | |||
| const handleToggleFiltersDrawer = () => { | |||
| setToggleFiltersDrawer((oldState) => !oldState); | |||
| @@ -41,7 +47,7 @@ const SelectionProcessPage = () => { | |||
| const renderList = processes.map((item, index) => { | |||
| return <Selection selection={item} key={index}/> | |||
| return <Selection selection={item} key={index} history={history}/> | |||
| } | |||
| ); | |||
| @@ -86,4 +92,14 @@ const SelectionProcessPage = () => { | |||
| ); | |||
| }; | |||
| SelectionProcessPage.propTypes = { | |||
| history: PropTypes.shape({ | |||
| replace: PropTypes.func, | |||
| push: PropTypes.func, | |||
| location: PropTypes.shape({ | |||
| pathname: PropTypes.string, | |||
| }), | |||
| }), | |||
| }; | |||
| export default SelectionProcessPage; | |||
| @@ -28,6 +28,7 @@ export default { | |||
| processes: { | |||
| allLevels: base + "/selectionlevels", | |||
| doneProcess: base + "/selectionprocesses", | |||
| getApplicantProcesses: base + "/applicants/processes", | |||
| // allProcesses: base + "/selectionprocesses", | |||
| }, | |||
| }; | |||
| @@ -3,3 +3,4 @@ import apiEndpoints from "./apiEndpoints"; | |||
| export const getAllLevels = () => getRequest(apiEndpoints.processes.allLevels); | |||
| export const doneProcess = (id) => getRequest(`${apiEndpoints.processes.doneProcess}/${id}`); | |||
| export const getProcessesOfApplicant = (id) => getRequest(`${apiEndpoints.processes.getApplicantProcesses}/${id}`); | |||
| @@ -0,0 +1,20 @@ | |||
| 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, | |||
| }); | |||
| @@ -0,0 +1,21 @@ | |||
| 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 | |||
| }); | |||
| @@ -2,9 +2,6 @@ import { | |||
| FETCH_PROCESSES_REQ, | |||
| FETCH_PROCESSES_ERR, | |||
| FETCH_PROCESSES_SUCCESS, | |||
| PUT_PROCESS_ERR, | |||
| PUT_PROCESS_REQ, | |||
| PUT_PROCESS_SUCCESS | |||
| } from "./processesActionConstants"; | |||
| export const setProcessesReq = () => ({ | |||
| @@ -19,19 +16,4 @@ export const setProcessesError = (payload) => ({ | |||
| export const setProcesses = (payload) => ({ | |||
| type: FETCH_PROCESSES_SUCCESS, | |||
| 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 | |||
| }); | |||
| }); | |||
| @@ -3,4 +3,7 @@ export const FETCH_PROCESSES_ERR = 'FETCH_PROCESSES_ERR'; | |||
| export const FETCH_PROCESSES_SUCCESS = 'FETCH_PROCESSES_SUCCESS'; | |||
| export const PUT_PROCESS_REQ = 'PUT_PROCESS_REQ'; | |||
| 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'; | |||
| @@ -10,8 +10,9 @@ import adsReducer from "./ad/adsReducer"; | |||
| import adReducer from "./ad/adReducer"; | |||
| import archiveAdsReducer from "./ad/archiveAdsReducer"; | |||
| import candidatesReducer from "./candidates/candidatesReducer"; | |||
| import candidatesReducer from './candidates/candidatesReducer'; | |||
| import processesReducer from './processes/processesReducer'; | |||
| import processReducer from "./processes/processReducer"; | |||
| import applicantProcessesReducer from "./processes/applicantProcessesReducer"; | |||
| export default combineReducers({ | |||
| login: loginReducer, | |||
| @@ -25,5 +26,7 @@ export default combineReducers({ | |||
| ad: adReducer, | |||
| archiveAds: archiveAdsReducer, | |||
| candidates: candidatesReducer, | |||
| processes: processesReducer | |||
| processes: processesReducer, | |||
| process: processReducer, | |||
| applicantProcesses: applicantProcessesReducer | |||
| }); | |||
| @@ -0,0 +1,32 @@ | |||
| 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, | |||
| }; | |||
| } | |||
| @@ -0,0 +1,33 @@ | |||
| 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, | |||
| }; | |||
| } | |||
| @@ -1,14 +1,11 @@ | |||
| import { | |||
| FETCH_PROCESSES_ERR, | |||
| FETCH_PROCESSES_SUCCESS, | |||
| PUT_PROCESS_ERR, | |||
| PUT_PROCESS_SUCCESS | |||
| FETCH_PROCESSES_SUCCESS | |||
| } from "../../actions/processes/processesActionConstants"; | |||
| import createReducer from "../../utils/createReducer"; | |||
| const initialState = { | |||
| processes: [], | |||
| doneProcess: false, | |||
| errorMessage: "", | |||
| }; | |||
| @@ -16,8 +13,6 @@ export default createReducer( | |||
| { | |||
| [FETCH_PROCESSES_SUCCESS]: setStateProcesses, | |||
| [FETCH_PROCESSES_ERR]: setProcessesErrorMessage, | |||
| [PUT_PROCESS_SUCCESS]: setStateDoneProcess, | |||
| [PUT_PROCESS_ERR]: setDoneProcessErrorMessage, | |||
| }, | |||
| initialState | |||
| ); | |||
| @@ -34,18 +29,4 @@ function setProcessesErrorMessage(state, action) { | |||
| ...state, | |||
| errorMessage: action.payload, | |||
| }; | |||
| } | |||
| function setStateDoneProcess(state, action) { | |||
| return { | |||
| ...state, | |||
| doneProcess: action.payload, | |||
| }; | |||
| } | |||
| function setDoneProcessErrorMessage(state, action) { | |||
| return { | |||
| ...state, | |||
| errorMessage: action.payload, | |||
| }; | |||
| } | |||
| } | |||
| @@ -1,7 +1,9 @@ | |||
| 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() { | |||
| try { | |||
| @@ -15,14 +17,26 @@ export function* getProcesses() { | |||
| export function* finishProcess(payload) { | |||
| try { | |||
| 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) { | |||
| 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() { | |||
| yield all([takeLatest(FETCH_PROCESSES_REQ, getProcesses)]); | |||
| yield all([takeLatest(PUT_PROCESS_REQ, finishProcess)]); | |||
| yield all([takeLatest(FETCH_APPLICANT_PROCESSES_REQ, getApplicantProcesses)]); | |||
| } | |||
| @@ -0,0 +1,10 @@ | |||
| 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 | |||
| ); | |||
| @@ -0,0 +1,10 @@ | |||
| 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 | |||
| ); | |||
| @@ -7,13 +7,4 @@ export const selectProcesses = createSelector(processesSelector, (state) => stat | |||
| export const selectProcessesError = createSelector( | |||
| processesSelector, | |||
| (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 | |||
| ); | |||
| ); | |||