| @@ -217,6 +217,24 @@ h3 { | |||
| } | |||
| } | |||
| .sel-item-no-data { | |||
| display: flex; | |||
| flex-direction: row; | |||
| align-items: center; | |||
| padding: 18px 36px; | |||
| gap: 18px; | |||
| width: 458px; | |||
| background: #FFFFFF; | |||
| border: 1px solid #E4E4E4; | |||
| border-radius: 18px; | |||
| transition: 0.3s; | |||
| @include media-below($bp-xl) { | |||
| justify-content: space-between; | |||
| padding: 18px; | |||
| width: 303px; | |||
| } | |||
| } | |||
| .sel-item .status { | |||
| font-family: 'Source Sans Pro'; | |||
| font-style: normal; | |||
| @@ -103,7 +103,7 @@ const AdFilters = ({ open, handleClose, technologies }) => { | |||
| </div> | |||
| <div className="ad-filters-technologies-checkboxes"> | |||
| <FormGroup> | |||
| {technologies.map((technology, index) => ( | |||
| {technologies?.map((technology, index) => ( | |||
| <FormControlLabel | |||
| key={index} | |||
| control={ | |||
| @@ -20,7 +20,7 @@ const dragOver = (e) => { | |||
| } | |||
| const Selection = (props) => { | |||
| const applicants = props.selection.selectionProcesses; | |||
| const allApplicants = props.selection.selectionProcesses; | |||
| const errorMessage = useSelector(selectDoneProcessError); | |||
| const dispatch = useDispatch(); | |||
| const user = useSelector(selectAuthUser); | |||
| @@ -49,7 +49,7 @@ const Selection = (props) => { | |||
| const handleOpenDetails = (id) => { | |||
| props.history.push(SELECTION_PROCESS_OF_APPLICANT_PAGE.replace(":id", id)) | |||
| } | |||
| const applicants = allApplicants?.filter(a => a.status !== "Odrađen"); | |||
| const renderList = applicants?.map((item, index) => { | |||
| return <div draggable key={index} className="sel-item" onDragStart={e => dragStart(e, item)} | |||
| onClick={() => handleOpenDetails(item.applicant.applicantId)}> | |||
| @@ -79,7 +79,7 @@ const Selection = (props) => { | |||
| <Backdrop position="absolute" isLoading={isLoading} /> | |||
| {applicants.length > 0 && renderList} | |||
| {applicants.length === 0 && <div className="sel-item"> | |||
| {applicants.length === 0 && <div className="sel-item-no-data"> | |||
| <div className="date"> | |||
| <p>Nema kandidata u selekciji</p> | |||
| </div> | |||
| @@ -0,0 +1,150 @@ | |||
| import React, { useState } from "react"; | |||
| import PropType from "prop-types"; | |||
| import Box from "@mui/material/Box"; | |||
| import Drawer from "@mui/material/Drawer"; | |||
| import FormGroup from "@mui/material/FormGroup"; | |||
| import FormControlLabel from "@mui/material/FormControlLabel"; | |||
| import Checkbox from "@mui/material/Checkbox"; | |||
| import filterIcon from "../../assets/images/filter_vector.png"; | |||
| import x from "../../assets/images/x.png"; | |||
| import { changeStatusIsCheckedValue } from "../../store/actions/processes/statusAction"; | |||
| import { useDispatch } from "react-redux"; | |||
| import { setFilteredProcessesReq } from "../../store/actions/processes/processesAction"; | |||
| import { useTranslation } from "react-i18next"; | |||
| const SelectionFilter = ({ open, handleClose, statuses }) => { | |||
| const [startAt, setStartAt] = useState(""); | |||
| const [endAt, setEndAt] = useState(""); | |||
| const { t } = useTranslation(); | |||
| const dispatch = useDispatch(); | |||
| const onSubmitFilters = () => { | |||
| const status = statuses | |||
| .filter((status) => status.isChecked === true) | |||
| .map((status) => status.name); | |||
| if (status.length === 0) { | |||
| return; | |||
| } | |||
| dispatch( | |||
| setFilteredProcessesReq({ | |||
| statuses: status, | |||
| startAt, | |||
| endAt | |||
| }) | |||
| ); | |||
| handleClose(); | |||
| }; | |||
| const handleCheckboxes = (e) => { | |||
| const { value } = e.target; | |||
| dispatch(changeStatusIsCheckedValue(value)); | |||
| }; | |||
| const list = () => ( | |||
| <Box | |||
| sx={{ | |||
| width: 360, | |||
| height: "100%", | |||
| borderRadius: "18px 0 0 18px", | |||
| padding: "36px", | |||
| }} | |||
| role="presentation" | |||
| // onClick={handleClose} | |||
| onKeyDown={handleClose} | |||
| > | |||
| <div> | |||
| <div className="ad-filters-header-container"> | |||
| <div className="ad-filters-header"> | |||
| <img src={filterIcon} alt="filter_icon" /> | |||
| <h3>{t("filter.title")}</h3> | |||
| <p> | |||
| <sub>| {t("selection.title")}</sub> | |||
| </p> | |||
| </div> | |||
| <div className="ad-filters-header-close" onClick={handleClose}> | |||
| <img src={x} alt="x" /> | |||
| </div> | |||
| </div> | |||
| <div className="ad-filters-technologies"> | |||
| <div className="ad-filters-sub-title"> | |||
| <p>{t("selection.filterStatus")}</p> | |||
| </div> | |||
| <div className="ad-filters-technologies-checkboxes"> | |||
| <FormGroup> | |||
| {statuses?.map((technology, index) => ( | |||
| <FormControlLabel | |||
| key={index} | |||
| control={ | |||
| <Checkbox | |||
| onChange={handleCheckboxes} | |||
| value={technology.name} | |||
| checked={technology.isChecked} | |||
| /> | |||
| } | |||
| label={technology.name} | |||
| /> | |||
| ))} | |||
| </FormGroup> | |||
| </div> | |||
| </div> | |||
| <div className="ad-filters-technologies"> | |||
| {/* <div className="ad-filters-sub-title"> | |||
| <p>Datum isteka oglasa</p> | |||
| </div> | |||
| <input | |||
| type="date" | |||
| placeholder="ex" | |||
| value={expiredAt} | |||
| onChange={(e) => setExpiredAt(e.target.value)} | |||
| /> */} | |||
| <div className="ad-filters-sub-title"> | |||
| <p>{t("selection.filterDate")}</p> | |||
| </div> | |||
| <div className="add-ad-modal-stage-sub-card"> | |||
| <label>{t("selection.filterFrom")}</label> | |||
| <input | |||
| type="date" | |||
| placeholder="ex" | |||
| value={startAt} | |||
| onChange={(e) => setStartAt(e.target.value)} | |||
| /> | |||
| </div> | |||
| <div className="add-ad-modal-stage-sub-card"> | |||
| <label>{t("selection.filterTo")}</label> | |||
| <input | |||
| type="date" | |||
| placeholder="ex" | |||
| value={endAt} | |||
| onChange={(e) => setEndAt(e.target.value)} | |||
| /> | |||
| </div> | |||
| </div> | |||
| <div className="ad-filters-search"> | |||
| <button onClick={onSubmitFilters} className="c-btn c-btn--primary"> | |||
| {t("selection.filterSubmit")} | |||
| </button> | |||
| </div> | |||
| </div> | |||
| </Box > | |||
| ); | |||
| return ( | |||
| <div> | |||
| <Drawer anchor="right" open={open} onClose={handleClose}> | |||
| {list()} | |||
| </Drawer> | |||
| </div> | |||
| ); | |||
| }; | |||
| SelectionFilter.propTypes = { | |||
| open: PropType.any, | |||
| handleClose: PropType.func, | |||
| statuses: PropType.any, | |||
| }; | |||
| export default SelectionFilter; | |||
| @@ -137,19 +137,27 @@ export default { | |||
| title: "Tok Selekcije", | |||
| subtitle: "Svi kandidati", | |||
| tipHeader: "Savet za uspešan Screening test", | |||
| tipBody: "Zapamtite da odeljenje za ljudske resurse u sebi sadrži reč „ljudski“. HR treba da vas vidi kakvi ste i da bi stekli osećaj za vašu stvarnu ličnost i postarali se da se dobro uklopite u kompaniju. Zato je bolje da se ponašate prirodno i opušteno. Važno je i pokazati da posedujete snažne međuljudske veštine i da se ponašate profesionalno. Na dan intervjua budite tačni, predstavite se pristojno i obucite se na odgovarajući način. To znači da razmislite o slici kompanije, ali i da se odevate na način koji vam je ugodan tokom dana." | |||
| tipBody: "Zapamtite da odeljenje za ljudske resurse u sebi sadrži reč „ljudski“. HR treba da vas vidi kakvi ste i da bi stekli osećaj za vašu stvarnu ličnost i postarali se da se dobro uklopite u kompaniju. Zato je bolje da se ponašate prirodno i opušteno. Važno je i pokazati da posedujete snažne međuljudske veštine i da se ponašate profesionalno. Na dan intervjua budite tačni, predstavite se pristojno i obucite se na odgovarajući način. To znači da razmislite o slici kompanije, ali i da se odevate na način koji vam je ugodan tokom dana.", | |||
| filterStatus: "Status", | |||
| filterDate: "Datum", | |||
| filterFrom: "Od", | |||
| filterTo: "Do", | |||
| filterSubmit: "Pretraži" | |||
| }, | |||
| users:{ | |||
| management: "Upravljanje korisnicima", | |||
| fullName: 'Ime i prezime', | |||
| position: 'Pozicija', | |||
| invite: 'Pozovi', | |||
| inviteUser: 'Pozovi korisnika', | |||
| regLink: 'Registracioni link', | |||
| receiver: 'Primalac', | |||
| user: 'Korisnik', | |||
| contact: 'Kontakt', | |||
| phone: 'Telefon', | |||
| socials: 'Društvene mreže', | |||
| } | |||
| users: { | |||
| management: "Upravljanje korisnicima", | |||
| fullName: 'Ime i prezime', | |||
| position: 'Pozicija', | |||
| invite: 'Pozovi', | |||
| inviteUser: 'Pozovi korisnika', | |||
| regLink: 'Registracioni link', | |||
| receiver: 'Primalac', | |||
| user: 'Korisnik', | |||
| contact: 'Kontakt', | |||
| phone: 'Telefon', | |||
| socials: 'Društvene mreže', | |||
| }, | |||
| filter: { | |||
| title: "Filteri" | |||
| } | |||
| }; | |||
| @@ -78,6 +78,7 @@ const SelectionProcessOfApplicantPage = () => { | |||
| const concatLevels = () => { | |||
| const applicantSelections = []; | |||
| for (var i = processes.length; i < levels.length; i++) { | |||
| applicantSelections.push(<ApplicantSelection | |||
| levelNumber={levels[i].id} | |||
| @@ -145,7 +146,7 @@ const SelectionProcessOfApplicantPage = () => { | |||
| className={index === processes.length - 1 ? "active-process" : ""} | |||
| /> | |||
| })} | |||
| {processes.length < levels.length && concatLevels()} | |||
| {processes.length <= levels.length && concatLevels()} | |||
| </Slider> | |||
| </div> | |||
| </div> | |||
| @@ -1,17 +1,18 @@ | |||
| import React, { useState, useEffect } from "react"; | |||
| import { useSelector} from 'react-redux'; | |||
| import Selection from "../../components/Selection/Selection"; | |||
| import IconButton from "../../components/IconButton/IconButton"; | |||
| import filterVector from "../../assets/images/filter_vector.png"; | |||
| import FilterButton from "../../components/Button/FilterButton"; | |||
| 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 { setStatuses } from "../../store/actions/processes/statusAction"; | |||
| import { selectDoneProcess } from "../../store/selectors/processSelectors"; | |||
| import { selectProcesses } from "../../store/selectors/processesSelectors" | |||
| import { selecStatuses } from "../../store/selectors/statusSelectors" | |||
| import PropTypes from "prop-types"; | |||
| import SelectionFilter from "../../components/Selection/SelectionFilter" | |||
| const SelectionProcessPage = ({history}) => { | |||
| const [toggleFiltersDrawer, setToggleFiltersDrawer] = useState(false); | |||
| @@ -22,9 +23,19 @@ const SelectionProcessPage = ({history}) => { | |||
| // const doneErrorMessage = useSelector(selectDoneProcessError); | |||
| const { t } = useTranslation(); | |||
| const dispatch = useDispatch(); | |||
| const statuses = useSelector(selecStatuses); | |||
| useEffect(() => { | |||
| dispatch(setProcessesReq()); | |||
| const s = [ | |||
| {"isChecked":false,"name":"Zakazan"}, | |||
| {"isChecked":false,"name":"Odrađen"}, | |||
| {"isChecked":false,"name":"Čeka na zakazivanje"}, | |||
| {"isChecked":false,"name":"Čeka se odgovor"}] | |||
| dispatch(setStatuses(s)); | |||
| }, []); | |||
| @@ -51,10 +62,11 @@ const SelectionProcessPage = ({history}) => { | |||
| <> | |||
| <div className="l-t-rectangle"></div> | |||
| <div className="r-b-rectangle"></div> | |||
| <AdFilters /> | |||
| <AdFilters | |||
| <SelectionFilter /> | |||
| <SelectionFilter | |||
| open={toggleFiltersDrawer} | |||
| handleClose={handleToggleFiltersDrawer} | |||
| statuses={statuses} | |||
| /> | |||
| <AddAdModal open={toggleModal} handleClose={handleToggleModal} /> | |||
| <div className="selections"> | |||
| @@ -68,16 +80,17 @@ const SelectionProcessPage = ({history}) => { | |||
| {t("selection.subtitle")} | |||
| </span> | |||
| </h1> | |||
| <FilterButton onShowFilters={handleToggleFiltersDrawer} /> | |||
| </div> | |||
| <div> | |||
| <IconButton | |||
| {/* <IconButton | |||
| sx={{ marginLeft: "15px" }} | |||
| className="c-btn c-btn--primary-outlined fixed-right" | |||
| onClick={handleToggleFiltersDrawer} | |||
| > | |||
| Filteri{" "} | |||
| <img src={filterVector} alt="filter" className="filter-vector" /> | |||
| </IconButton> | |||
| </IconButton> */} | |||
| <div className="selection-levels-processes"> | |||
| <div className="selection-levels-processes-process"> | |||
| {renderList} | |||
| @@ -33,6 +33,7 @@ export default { | |||
| }, | |||
| processes: { | |||
| allLevels: base + "/selectionlevels", | |||
| filteredLevels: base + "/selectionlevels/filtered", | |||
| doneProcess: base + "/selectionprocesses", | |||
| getApplicantProcesses: base + "/applicants/processes", | |||
| // allProcesses: base + "/selectionprocesses", | |||
| @@ -4,3 +4,23 @@ import apiEndpoints from "./apiEndpoints"; | |||
| export const getAllLevels = () => getRequest(apiEndpoints.processes.allLevels); | |||
| export const doneProcess = (data) => postRequest(apiEndpoints.processes.doneProcess,data); | |||
| export const getProcessesOfApplicant = (id) => getRequest(`${apiEndpoints.processes.getApplicantProcesses}/${id}`); | |||
| export const getAllFilteredProcessesReq = (payload) => { | |||
| let statusesQuery = ""; | |||
| for (let i = 0; i < payload.statuses.length; i++) { | |||
| statusesQuery += `statuses=${payload.statuses[i]}&`; | |||
| } | |||
| if(payload.startAt && payload.startAt !== null) | |||
| statusesQuery += `DateStart=${payload.startAt}`; | |||
| if(payload.endAt && payload.endAt !== null) | |||
| statusesQuery += `&DateEnd=${payload.endAt}`; | |||
| return getRequest( | |||
| apiEndpoints.processes.filteredLevels + | |||
| "?" + | |||
| `${statusesQuery}` | |||
| ); | |||
| }; | |||
| @@ -2,12 +2,18 @@ import { | |||
| FETCH_PROCESSES_REQ, | |||
| FETCH_PROCESSES_ERR, | |||
| FETCH_PROCESSES_SUCCESS, | |||
| FETCH_FILTERED_PROCESSES_REQ | |||
| } from "./processesActionConstants"; | |||
| export const setProcessesReq = () => ({ | |||
| type: FETCH_PROCESSES_REQ, | |||
| }); | |||
| export const setFilteredProcessesReq = (payload) => ({ | |||
| type: FETCH_FILTERED_PROCESSES_REQ, | |||
| payload, | |||
| }); | |||
| export const setProcessesError = (payload) => ({ | |||
| type: FETCH_PROCESSES_ERR, | |||
| payload, | |||
| @@ -9,6 +9,7 @@ import { | |||
| export const FETCH_PROCESSES_REQ = 'FETCH_PROCESSES_REQ'; | |||
| export const FETCH_PROCESSES_ERR = 'FETCH_PROCESSES_ERR'; | |||
| export const FETCH_PROCESSES_SUCCESS = 'FETCH_PROCESSES_SUCCESS'; | |||
| export const FETCH_FILTERED_PROCESSES_REQ = 'FETCH_FILTERED_PROCESSES_REQ'; | |||
| const PUT_PROCESS_SCOPE = 'PUT_PROCESS'; | |||
| export const PUT_PROCESS_REQ = createFetchType(PUT_PROCESS_SCOPE); | |||
| @@ -21,4 +22,9 @@ export const PUT_PROCESS_LOADING = createLoadingType(PUT_PROCESS_SCOPE); | |||
| 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'; | |||
| export const FETCH_APPLICANT_PROCESSES_SUCCESS = 'FETCH_APPLICANT_PROCESSES_SUCCESS'; | |||
| export const FETCH_STATUSES_REQ = 'FETCH_STATUSES_REQ'; | |||
| export const FETCH_STATUSES_ERR = 'FETCH_STATUSES_ERR'; | |||
| export const FETCH_STATUSES_SUCCESS = 'FETCH_STATUSES_SUCCESS'; | |||
| export const CHANGE_STATUS_ISCHECKED_VALUE = 'CHANGE_STATUS_ISCHECKED_VALUE'; | |||
| @@ -0,0 +1,25 @@ | |||
| import { | |||
| FETCH_STATUSES_ERR, | |||
| FETCH_STATUSES_SUCCESS, | |||
| FETCH_STATUSES_REQ, | |||
| CHANGE_STATUS_ISCHECKED_VALUE | |||
| } from "./processesActionConstants"; | |||
| export const setStatusesReq = () => ({ | |||
| type: FETCH_STATUSES_REQ, | |||
| }); | |||
| export const setStatusesError = (payload) => ({ | |||
| type: FETCH_STATUSES_ERR, | |||
| payload, | |||
| }); | |||
| export const setStatuses = (payload) => ({ | |||
| type: FETCH_STATUSES_SUCCESS, | |||
| payload, | |||
| }); | |||
| export const changeStatusIsCheckedValue = (payload) => ({ | |||
| type: CHANGE_STATUS_ISCHECKED_VALUE, | |||
| payload, | |||
| }); | |||
| @@ -17,6 +17,7 @@ import processReducer from "./processes/processReducer"; | |||
| import applicantWithProcessesReducer from "./processes/applicantWithProcessesReducer"; | |||
| import userDetailsReducer from "./user/userDetailsReducer"; | |||
| import inviteUserReducer from "./user/inviteUserReducer"; | |||
| import statusReducer from "./processes/statusReducer"; | |||
| export default combineReducers({ | |||
| login: loginReducer, | |||
| @@ -37,4 +38,5 @@ export default combineReducers({ | |||
| applicant: applicantWithProcessesReducer, | |||
| userDetails: userDetailsReducer, | |||
| invite: inviteUserReducer, | |||
| statuses: statusReducer, | |||
| }); | |||
| @@ -0,0 +1,45 @@ | |||
| import createReducer from "../../utils/createReducer"; | |||
| import { | |||
| FETCH_STATUSES_SUCCESS, | |||
| FETCH_STATUSES_ERR, | |||
| CHANGE_STATUS_ISCHECKED_VALUE, | |||
| } from "../../actions/processes/processesActionConstants"; | |||
| const initialState = { | |||
| statuses: [], | |||
| errorMessage: "", | |||
| }; | |||
| export default createReducer( | |||
| { | |||
| [FETCH_STATUSES_SUCCESS]: setStateStatuses, | |||
| [FETCH_STATUSES_ERR]: setStateErrorMessage, | |||
| [CHANGE_STATUS_ISCHECKED_VALUE]: setIsCheckedStatus, | |||
| }, | |||
| initialState | |||
| ); | |||
| function setStateStatuses(state, action) { | |||
| return { ...state, statuses: action.payload }; | |||
| } | |||
| function setStateErrorMessage(state, action) { | |||
| return { ...state, errorMessage: action.payload }; | |||
| } | |||
| function setIsCheckedStatus(state, action) { | |||
| const tmpIndex = state.statuses.findIndex( | |||
| (x) => x.name === action.payload | |||
| ); | |||
| if (tmpIndex === -1) { | |||
| return state; | |||
| } | |||
| return { | |||
| ...state, | |||
| statuses: state.statuses.map((status, index) => | |||
| tmpIndex === index ? { ...status, isChecked: !status.isChecked } : status | |||
| ), | |||
| }; | |||
| } | |||
| @@ -1,12 +1,12 @@ | |||
| import { all, call, put, takeLatest } from "redux-saga/effects"; | |||
| import { getAllLevels, doneProcess, getProcessesOfApplicant } from "../../request/processesReguest"; | |||
| import { getAllLevels, doneProcess, getProcessesOfApplicant, getAllFilteredProcessesReq } from "../../request/processesReguest"; | |||
| import { setProcesses, setProcessesError } from "../actions/processes/processesAction"; | |||
| import { addHeaderToken } from "../../request"; | |||
| import { authScopeStringGetHelper } from "../../util/helpers/authScopeHelpers"; | |||
| import { JWT_TOKEN } from "../../constants/localStorage"; | |||
| import { setDoneProcess, setDoneProcessError } from "../actions/processes/processAction"; | |||
| import { setApplicant, setApplicantError } from "../actions/processes/applicantAction"; | |||
| import { FETCH_PROCESSES_REQ, PUT_PROCESS_REQ, FETCH_APPLICANT_PROCESSES_REQ } from "../actions/processes/processesActionConstants"; | |||
| import { FETCH_PROCESSES_REQ, FETCH_FILTERED_PROCESSES_REQ ,PUT_PROCESS_REQ, FETCH_APPLICANT_PROCESSES_REQ } from "../actions/processes/processesActionConstants"; | |||
| export function* getProcesses() { | |||
| try { | |||
| @@ -19,6 +19,18 @@ export function* getProcesses() { | |||
| } | |||
| } | |||
| export function* getFilteredProcesses(payload) { | |||
| try { | |||
| // const JwtToken = yield call(authScopeStringGetHelper, JWT_TOKEN); | |||
| // yield call(addHeaderToken, JwtToken); | |||
| console.log(payload.payload) | |||
| const result = yield call(getAllFilteredProcessesReq, payload.payload); | |||
| yield put(setProcesses(result.data)); | |||
| } catch (error) { | |||
| yield put(setProcessesError(error)); | |||
| } | |||
| } | |||
| export function* finishProcess(payload) { | |||
| try { | |||
| const JwtToken = yield call(authScopeStringGetHelper, JWT_TOKEN); | |||
| @@ -45,6 +57,7 @@ export function* getApplicantProcesses(payload) { | |||
| export default function* processesSaga() { | |||
| yield all([takeLatest(FETCH_PROCESSES_REQ, getProcesses)]); | |||
| yield all([takeLatest(FETCH_FILTERED_PROCESSES_REQ, getFilteredProcesses)]); | |||
| yield all([takeLatest(PUT_PROCESS_REQ, finishProcess)]); | |||
| yield all([takeLatest(FETCH_APPLICANT_PROCESSES_REQ, getApplicantProcesses)]); | |||
| } | |||
| @@ -0,0 +1,13 @@ | |||
| import { createSelector } from "@reduxjs/toolkit"; | |||
| export const statusesSelector = (state) => state.statuses; | |||
| export const selecStatuses = createSelector( | |||
| statusesSelector, | |||
| (state) => state.statuses | |||
| ); | |||
| export const selecStatusesError = createSelector( | |||
| statusesSelector, | |||
| (state) => state.errorMessage | |||
| ); | |||