| h1, | |||||
| h3 { | |||||
| margin: 0; | |||||
| padding: 0; | |||||
| } | |||||
| .ads { | |||||
| .selections { | |||||
| margin-top: 36px; | margin-top: 36px; | ||||
| padding-left: 3rem; | |||||
| padding-left: 72px; | |||||
| } | } | ||||
| .active-ads-header { | |||||
| .level-header { | |||||
| padding-left: 81px; | padding-left: 81px; | ||||
| display: flex; | display: flex; | ||||
| justify-content: space-between; | justify-content: space-between; | ||||
| align-items: center; | align-items: center; | ||||
| } | } | ||||
| .activee{ | |||||
| /* Blue 4 */ | |||||
| background : #E8F7FF; | |||||
| border : 1px solid #226CB0; | |||||
| } | |||||
| .active-ads | |||||
| { | |||||
| .selection-levels { | |||||
| overflow-x: scroll; | overflow-x: scroll; | ||||
| padding-bottom: 100px; | padding-bottom: 100px; | ||||
| } | } | ||||
| .active-ads-subheader { | |||||
| font-family: 'Source Sans Pro'; | |||||
| font-style: normal; | |||||
| font-weight: 600; | |||||
| font-size: 24px; | |||||
| line-height: 36px; | |||||
| padding-left: 0.3rem; | |||||
| /* identical to box height, or 100% */ | |||||
| color:#226CB0; | |||||
| letter-spacing: 0.02em; | |||||
| } | |||||
| .active-ads-subheader-spliter { | |||||
| .level-header-subheader { | |||||
| font-family: 'Source Sans Pro'; | font-family: 'Source Sans Pro'; | ||||
| font-style: normal; | |||||
| font-weight: 600; | |||||
| font-size: 24px; | |||||
| line-height: 36px; | |||||
| padding-left: 0.3rem; | |||||
| /* identical to box height, or 100% */ | |||||
| color:#272727; | |||||
| letter-spacing: 0.02em; | |||||
| font-style: normal; | |||||
| font-weight: 600; | |||||
| font-size: 24px; | |||||
| line-height: 36px; | |||||
| padding-left: 0.3rem; | |||||
| color: #226CB0; | |||||
| letter-spacing: 0.02em; | |||||
| } | } | ||||
| .filter-vector { | |||||
| margin-left: 0.5rem !important; | |||||
| .level-header-spliter { | |||||
| font-family: 'Source Sans Pro'; | |||||
| font-style: normal; | |||||
| font-weight: 600; | |||||
| font-size: 24px; | |||||
| line-height: 36px; | |||||
| padding-left: 0.3rem; | |||||
| color: #272727; | |||||
| letter-spacing: 0.02em; | |||||
| } | } | ||||
| .active-ads-ads { | |||||
| .selection-levels-processes { | |||||
| display: flex; | display: flex; | ||||
| margin-top: 39px; | margin-top: 39px; | ||||
| position: relative; | position: relative; | ||||
| } | } | ||||
| .active-ads-ads-ad { | |||||
| .selection-levels-processes-process { | |||||
| padding-left: 81px; | padding-left: 81px; | ||||
| display: flex; | display: flex; | ||||
| } | } | ||||
| .selection-card { | .selection-card { | ||||
| display: flex; | display: flex; | ||||
| flex-direction: column; | flex-direction: column; | ||||
| justify-content: start; | justify-content: start; | ||||
| align-items: left; | align-items: left; | ||||
| // width: 550px; | |||||
| height: fit-content; | height: fit-content; | ||||
| padding: 36px; | padding: 36px; | ||||
| background: #F4F4F4; | background: #F4F4F4; | ||||
| margin-right: 36px; | margin-right: 36px; | ||||
| } | } | ||||
| .bg-danger{ | |||||
| .bg-danger { | |||||
| background-color: #272727; | background-color: #272727; | ||||
| } | } | ||||
| .grey { | |||||
| color: #e4e4e4 | |||||
| } | |||||
| .selection-item { | .selection-item { | ||||
| display: flex; | display: flex; | ||||
| flex-direction: row; | flex-direction: row; | ||||
| vertical-align: top; | vertical-align: top; | ||||
| align-items: left; | align-items: left; | ||||
| width: 400px; | width: 400px; | ||||
| // height: 400px; | |||||
| padding: 18px 36px; | padding: 18px 36px; | ||||
| background: #FFFFFF; | background: #FFFFFF; | ||||
| border: 1px solid #e4e4e4; | border: 1px solid #e4e4e4; | ||||
| flex-grow: 0; | flex-grow: 0; | ||||
| } | } | ||||
| .ad-card-logo img { | |||||
| width: 61px; | |||||
| height: 49px; | |||||
| flex: none; | |||||
| order: 2; | |||||
| flex-grow: 0; | |||||
| } | |||||
| .selection-item-name, .selection-item-date{ | |||||
| margin: auto 0 !important; | |||||
| .selection-item-name, | |||||
| .selection-item-date { | |||||
| margin: auto 0 !important; | |||||
| } | } | ||||
| .selection-item-name p { | .selection-item-name p { | ||||
| height: 20px; | height: 20px; | ||||
| font-family: 'Source Sans Pro'; | |||||
| font-style: normal; | |||||
| font-weight: 600; | |||||
| font-size: 16px; | |||||
| line-height: 20px; | |||||
| text-align: right; | |||||
| color: #226CB0; | |||||
| flex: none; | |||||
| order: 2; | |||||
| flex-grow: 0; | |||||
| } | |||||
| .ad-card-buttons { | |||||
| display: flex; | |||||
| flex-direction: row; | |||||
| align-items: flex-start; | |||||
| justify-content: center; | |||||
| padding: 0px; | |||||
| gap: 18px; | |||||
| width: 281px; | |||||
| height: 38px; | |||||
| font-family: 'Source Sans Pro'; | |||||
| font-style: normal; | |||||
| font-weight: 600; | |||||
| font-size: 16px; | |||||
| line-height: 20px; | |||||
| text-align: right; | |||||
| color: #226CB0; | |||||
| flex: none; | flex: none; | ||||
| order: 0; | |||||
| order: 2; | |||||
| flex-grow: 0; | flex-grow: 0; | ||||
| } | } | ||||
| flex-grow: 0; | flex-grow: 0; | ||||
| } | } | ||||
| .add-ad { | |||||
| margin-top: 49px; | |||||
| display: flex; | |||||
| justify-content: flex-end; | |||||
| align-items: center; | |||||
| padding-right: 5rem !important; | |||||
| padding-bottom: 49px; | |||||
| } | |||||
| .add-ad-btn { | |||||
| .sel-item { | |||||
| display: flex; | display: flex; | ||||
| flex-direction: row; | flex-direction: row; | ||||
| justify-content: center; | |||||
| align-items: center; | align-items: center; | ||||
| padding: 18px 72px; | |||||
| gap: 10px; | |||||
| width: 201px; | |||||
| height: 51px; | |||||
| background: #226cb0; | |||||
| border-radius: 9px; | |||||
| } | |||||
| .ad-filters-header-container { | |||||
| display: flex; | |||||
| justify-content: space-between; | |||||
| } | |||||
| .ad-filters-header { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| } | |||||
| .ad-filters-header-close { | |||||
| cursor: pointer; | |||||
| } | |||||
| .ad-filters-header > * { | |||||
| margin-right: 0.25rem; | |||||
| } | |||||
| .ad-filters-header img { | |||||
| width: 18px; | |||||
| height: 15.75px; | |||||
| } | |||||
| .ad-filters-header sub { | |||||
| color: #226cb0; | |||||
| padding: 18px 36px; | |||||
| gap: 18px; | |||||
| width: 458px; | |||||
| background: #FFFFFF; | |||||
| border: 1px solid #E4E4E4; | |||||
| border-radius: 18px; | |||||
| } | } | ||||
| .ad-filters-sub-title { | |||||
| font-family: "Source Sans Pro"; | |||||
| .sel-item .status { | |||||
| font-family: 'Source Sans Pro'; | |||||
| font-style: normal; | font-style: normal; | ||||
| font-weight: 600; | |||||
| font-weight: 400; | |||||
| font-size: 16px; | font-size: 16px; | ||||
| line-height: 20px; | line-height: 20px; | ||||
| color: #272727; | color: #272727; | ||||
| flex: none; | |||||
| order: 0; | |||||
| flex-grow: 0; | |||||
| } | } | ||||
| .ad-filters-experience { | |||||
| margin-top: 18px; | |||||
| box-sizing: border-box; | |||||
| } | |||||
| .ad-filters-experience-slider { | |||||
| margin-top: 5px; | |||||
| } | |||||
| .ad-filters-technologies { | |||||
| margin-top: 18px; | |||||
| } | |||||
| .ad-filters-employment-type { | |||||
| display: flex; | |||||
| } | |||||
| .ad-filters-employment-type > button { | |||||
| margin-right: 0.5rem; | |||||
| margin-top: 18px; | |||||
| } | |||||
| .ad-filters-search { | |||||
| margin-top: 18px; | |||||
| padding-bottom: 18px; | |||||
| } | |||||
| .ad-filters-search > * { | |||||
| width: 100%; | |||||
| } | |||||
| .sel-item{ | |||||
| display: flex; | |||||
| flex-direction: row; | |||||
| justify-content: space-between; | |||||
| align-items: center; | |||||
| padding: 18px 36px; | |||||
| gap: 18px; | |||||
| width: 458px; | |||||
| /* White */ | |||||
| background: #FFFFFF; | |||||
| /* Gray E4 */ | |||||
| border: 1px solid #E4E4E4; | |||||
| border-radius: 18px; | |||||
| } | |||||
| .sel-item .p{ | |||||
| /* Paragraph */ | |||||
| font-family: 'Source Sans Pro'; | |||||
| font-style: normal; | |||||
| font-weight: 400; | |||||
| font-size: 16px; | |||||
| line-height: 20px; | |||||
| /* Main Black */ | |||||
| color: #272727; | |||||
| /* Inside auto layout */ | |||||
| flex: none; | |||||
| order: 0; | |||||
| flex-grow: 0; | |||||
| } | |||||
| .sel-item .date{ | |||||
| /* 22.07. | 14:10h */ | |||||
| /* Paragraph */ | |||||
| font-family: 'Source Sans Pro'; | |||||
| font-style: normal; | |||||
| font-weight: 400; | |||||
| font-size: 16px; | |||||
| line-height: 20px; | |||||
| /* Main Black */ | |||||
| color: #272727; | |||||
| .sel-item .date { | |||||
| font-family: 'Source Sans Pro'; | |||||
| font-style: normal; | |||||
| font-weight: 400; | |||||
| font-size: 16px; | |||||
| line-height: 20px; | |||||
| color: #272727; | |||||
| } | } | ||||
| .sel-item .rig{ | |||||
| height: 20px; | |||||
| /* Bold Paragraph */ | |||||
| font-family: 'Source Sans Pro'; | |||||
| font-style: normal; | |||||
| font-weight: 600; | |||||
| font-size: 16px; | |||||
| line-height: 20px; | |||||
| text-align: right; | |||||
| /* Main Blue */ | |||||
| color: #226CB0; | |||||
| /* Inside auto layout */ | |||||
| flex: none; | |||||
| order: 1; | |||||
| flex-grow: 0; | |||||
| .sel-item .full-name { | |||||
| height: 20px; | |||||
| font-family: 'Source Sans Pro'; | |||||
| font-style: normal; | |||||
| font-weight: 600; | |||||
| font-size: 16px; | |||||
| text-align: right; | |||||
| color: #226CB0; | |||||
| flex: 3 0 auto; | |||||
| order: 1; | |||||
| } | } | ||||
| .sel-item .p button { | |||||
| .sel-item .status button { | |||||
| box-sizing: border-box; | box-sizing: border-box; | ||||
| display: flex; | display: flex; | ||||
| flex-direction: row; | flex-direction: row; | ||||
| min-width: 76px; | min-width: 76px; | ||||
| height: 38px; | height: 38px; | ||||
| border: 1px solid #e4e4e4; | border: 1px solid #e4e4e4; | ||||
| background: white; | |||||
| border-radius: 9px; | border-radius: 9px; | ||||
| flex: none; | flex: none; | ||||
| order: 0; | order: 0; |
| 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 { useDispatch, useSelector } from "react-redux"; | |||||
| import { formatDateSrb, formatTimeSrb } from "../../util/helpers/dateHelpers"; | |||||
| const dragStart = (e, applicant) => { | |||||
| // e.dataTransfer.setData("applicant", applicant.id); | |||||
| e.dataTransfer.setData("text/plain",JSON.stringify(applicant)); | |||||
| } | |||||
| const dragOver = (e) => { | |||||
| e.preventDefault(); | |||||
| } | |||||
| const dropItem = (e,selId) =>{ | |||||
| var data = e.dataTransfer.getData("text/plain"); | |||||
| const applicant = JSON.parse(data); | |||||
| if(applicant.currentSelection !== selId){ | |||||
| // SEND REQUEST TO BACKEND TO STORE NEW SELECTION | |||||
| console.log('jup') | |||||
| } | |||||
| } | |||||
| const Selection = (props) => { | const Selection = (props) => { | ||||
| console.log(props.selection); | |||||
| const applicants = props.selection.applicants; | |||||
| const renderList = applicants.map((item, index) => { | |||||
| 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) =>{ | |||||
| 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(errorMessage) | |||||
| { | |||||
| console.log(errorMessage) | |||||
| } | |||||
| } | |||||
| 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)}> | ||||
| <div className="p"> | |||||
| <div className="status"> | |||||
| <button>{item.status}</button> | <button>{item.status}</button> | ||||
| </div> | </div> | ||||
| <div className="date"> | <div className="date"> | ||||
| <p>{item.date}</p> | |||||
| <p>{formatDateSrb(item.date)} <span className="grey">|</span> {formatTimeSrb(item.date)}</p> | |||||
| </div> | </div> | ||||
| <div className="rig"> | |||||
| <p>{item.name}</p> | |||||
| <div className="full-name"> | |||||
| <p>{item.applicant.firstName + " " + item.applicant.lastName}</p> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| } | } | ||||
| <h3>{props.selection.name}</h3> | <h3>{props.selection.name}</h3> | ||||
| </div> | </div> | ||||
| {renderList} | |||||
| {applicants.length > 0 && renderList} | |||||
| {applicants.length === 0 && <div className="sel-item"> | |||||
| <div className="date"> | |||||
| <p>Nema kandidata u selekciji</p> | |||||
| </div> | |||||
| </div>} | |||||
| </div> | </div> | ||||
| ); | ); | ||||
| }; | }; | ||||
| selection: PropTypes.shape({ | selection: PropTypes.shape({ | ||||
| id: PropTypes.number, | id: PropTypes.number, | ||||
| name : PropTypes.string, | name : PropTypes.string, | ||||
| applicants: PropTypes.arrayOf(PropTypes.shape({ | |||||
| selectionProcesses: PropTypes.arrayOf(PropTypes.shape({ | |||||
| id: PropTypes.number, | id: PropTypes.number, | ||||
| name: PropTypes.string, | name: PropTypes.string, | ||||
| date: PropTypes.string, | date: PropTypes.string, | ||||
| status: PropTypes.string, | status: PropTypes.string, | ||||
| currentSelection: PropTypes.number, | currentSelection: PropTypes.number, | ||||
| map: PropTypes.func | |||||
| map: PropTypes.func, | |||||
| applicant: PropTypes.shape({ | |||||
| firstName: PropTypes.string, | |||||
| lastName: PropTypes.string | |||||
| }) | |||||
| })) | })) | ||||
| }), | }), | ||||
| }; | }; |
| import React, { useState } from "react"; | |||||
| import React, { useState, useEffect } from "react"; | |||||
| import { useSelector} from 'react-redux'; | |||||
| import Selection from "../../components/Selection/Selection"; | import Selection from "../../components/Selection/Selection"; | ||||
| import IconButton from "../../components/IconButton/IconButton"; | import IconButton from "../../components/IconButton/IconButton"; | ||||
| import filterVector from "../../assets/images/filter_vector.png"; | import filterVector from "../../assets/images/filter_vector.png"; | ||||
| import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
| import AddAdModal from "../../components/Ads/AddAdModal"; | import AddAdModal from "../../components/Ads/AddAdModal"; | ||||
| import { useDispatch } from "react-redux"; | |||||
| import AdFilters from "../../components/Ads/AdFilters"; | import AdFilters from "../../components/Ads/AdFilters"; | ||||
| import { setProcessesReq } from "../../store/actions/processes/processesAction"; | |||||
| import { selectProcesses, selectDoneProcess } from "../../store/selectors/processesSelectors"; | |||||
| const SelectionProcessPage = () => { | const SelectionProcessPage = () => { | ||||
| 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 processes = useSelector(selectProcesses); | |||||
| // const doneErrorMessage = useSelector(selectDoneProcessError); | |||||
| const doneProcess = useSelector(selectDoneProcess); | |||||
| const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
| const dispatch = useDispatch(); | |||||
| useEffect(() => { | |||||
| dispatch(setProcessesReq()); | |||||
| }, []); | |||||
| useEffect(() => { | |||||
| dispatch(setProcessesReq()); | |||||
| },[doneProcess]) | |||||
| // console.log(errorMessage); | |||||
| // console.log(doneErrorMessage); | |||||
| const handleToggleFiltersDrawer = () => { | const handleToggleFiltersDrawer = () => { | ||||
| setToggleFiltersDrawer((oldState) => !oldState); | setToggleFiltersDrawer((oldState) => !oldState); | ||||
| setToggleModal((oldState) => !oldState); | setToggleModal((oldState) => !oldState); | ||||
| }; | }; | ||||
| const selections = [ | |||||
| { | |||||
| id: 1, | |||||
| name: "HR interview", | |||||
| applicants: [ | |||||
| { | |||||
| id: 1, | |||||
| name: "Stefan Petrovic", | |||||
| status: "Zakazan", | |||||
| date: "01.01.2022 11:00", | |||||
| currentSelection: 1 | |||||
| }, | |||||
| { | |||||
| id: 2, | |||||
| name: "Stefan Petrovic", | |||||
| status: "Otkazan", | |||||
| date: "01.01.2022 11:00", | |||||
| currentSelection: 1 | |||||
| }, | |||||
| { | |||||
| id: 3, | |||||
| name: "Stefan Petrovic", | |||||
| status: "Ceka na zakazivanje", | |||||
| currentSelection: 1 | |||||
| }] | |||||
| }, | |||||
| { | |||||
| id: 2, | |||||
| name: "Screening test", | |||||
| applicants: [ | |||||
| { | |||||
| id: 1, | |||||
| name: "Stefan Petrovic", | |||||
| status: "Zakazan", | |||||
| date: "01.01.2022 11:00", | |||||
| currentSelection: 2 | |||||
| }, | |||||
| { | |||||
| id: 2, | |||||
| name: "Stefan Petrovic", | |||||
| status: "Otkazan", | |||||
| date: "01.01.2022 11:00", | |||||
| currentSelection: 2 | |||||
| }] | |||||
| }, | |||||
| { | |||||
| id: 3, | |||||
| name: "Technical interview", | |||||
| applicants: [ | |||||
| { | |||||
| id: 1, | |||||
| name: "Stefan Petrovic", | |||||
| status: "Zakazan", | |||||
| date: "01.01.2022 11:00", | |||||
| currentSelection: 3 | |||||
| }, | |||||
| { | |||||
| id: 2, | |||||
| name: "Stefan Petrovic", | |||||
| status: "Otkazan", | |||||
| date: "01.01.2022 11:00", | |||||
| currentSelection: 3 | |||||
| }, | |||||
| { | |||||
| id: 3, | |||||
| name: "Stefan Petrovic", | |||||
| status: "Ceka na zakazivanje", | |||||
| currentSelection: 3 | |||||
| }] | |||||
| }, | |||||
| { | |||||
| id: 4, | |||||
| name: "Final decision", | |||||
| applicants: [ | |||||
| { | |||||
| id: 1, | |||||
| name: "Stefan Petrovic", | |||||
| status: "Zakazan", | |||||
| date: "01.01.2022 11:00", | |||||
| currentSelection: 4 | |||||
| }, | |||||
| { | |||||
| id: 2, | |||||
| name: "Stefan Petrovic", | |||||
| status: "Otkazan", | |||||
| date: "01.01.2022 11:00", | |||||
| currentSelection: 4 | |||||
| }] | |||||
| } | |||||
| ] | |||||
| const renderList = selections.map((item, index) => { | |||||
| const renderList = processes.map((item, index) => { | |||||
| return <Selection selection={item} key={index}/> | return <Selection selection={item} key={index}/> | ||||
| } | } | ||||
| ); | ); | ||||
| handleClose={handleToggleFiltersDrawer} | handleClose={handleToggleFiltersDrawer} | ||||
| /> | /> | ||||
| <AddAdModal open={toggleModal} handleClose={handleToggleModal} /> | <AddAdModal open={toggleModal} handleClose={handleToggleModal} /> | ||||
| <div className="ads"> | |||||
| <div className="active-ads"> | |||||
| <div className="active-ads-header"> | |||||
| <div className="selections"> | |||||
| <div className="selection-levels"> | |||||
| <div className="level-header"> | |||||
| <h1>{t("selection.title")} | <h1>{t("selection.title")} | ||||
| <span className="active-ads-subheader-spliter"> | |||||
| <span className="level-header-spliter"> | |||||
| | | | | ||||
| </span> | </span> | ||||
| <span className="active-ads-subheader"> | |||||
| <span className="level-header-subheader"> | |||||
| Svi kandidati | Svi kandidati | ||||
| </span> | </span> | ||||
| </h1> | </h1> | ||||
| <img src={filterVector} alt="filter" className="filter-vector" /> | <img src={filterVector} alt="filter" className="filter-vector" /> | ||||
| </IconButton> | </IconButton> | ||||
| </div> | </div> | ||||
| <div className="active-ads-ads"> | |||||
| <div className="active-ads-ads-ad"> | |||||
| <div className="selection-levels-processes"> | |||||
| <div className="selection-levels-processes-process"> | |||||
| {renderList} | {renderList} | ||||
| </div> | </div> | ||||
| </div> | </div> |
| }, | }, | ||||
| comments:{ | comments:{ | ||||
| addComment:base + '/comments' | addComment:base + '/comments' | ||||
| } | |||||
| }, | |||||
| processes: { | |||||
| allLevels: base + "/selectionlevels", | |||||
| doneProcess: base + "/selectionprocesses", | |||||
| // allProcesses: base + "/selectionprocesses", | |||||
| }, | |||||
| }; | }; |
| import { getRequest } from "."; | |||||
| import apiEndpoints from "./apiEndpoints"; | |||||
| export const getAllLevels = () => getRequest(apiEndpoints.processes.allLevels); | |||||
| export const doneProcess = (id) => getRequest(`${apiEndpoints.processes.doneProcess}/${id}`); |
| import { | |||||
| FETCH_PROCESSES_REQ, | |||||
| FETCH_PROCESSES_ERR, | |||||
| FETCH_PROCESSES_SUCCESS, | |||||
| PUT_PROCESS_ERR, | |||||
| PUT_PROCESS_REQ, | |||||
| PUT_PROCESS_SUCCESS | |||||
| } from "./processesActionConstants"; | |||||
| export const setProcessesReq = () => ({ | |||||
| type: FETCH_PROCESSES_REQ, | |||||
| }); | |||||
| export const setProcessesError = (payload) => ({ | |||||
| type: FETCH_PROCESSES_ERR, | |||||
| 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 | |||||
| }); |
| 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 PUT_PROCESS_REQ = 'PUT_PROCESS_REQ'; | |||||
| export const PUT_PROCESS_ERR = 'PUT_PROCESS_ERR'; | |||||
| export const PUT_PROCESS_SUCCESS = 'PUT_PROCESS_SUCCESS'; |
| import adsReducer from "./ad/adsReducer"; | import adsReducer from "./ad/adsReducer"; | ||||
| 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 processesReducer from './processes/processesReducer'; | |||||
| export default combineReducers({ | export default combineReducers({ | ||||
| login: loginReducer, | login: loginReducer, | ||||
| ads: adsReducer, | ads: adsReducer, | ||||
| ad: adReducer, | ad: adReducer, | ||||
| archiveAds: archiveAdsReducer, | archiveAds: archiveAdsReducer, | ||||
| candidates: candidatesReducer, | |||||
| processes: processesReducer | |||||
| }); | }); |
| import { | |||||
| FETCH_PROCESSES_ERR, | |||||
| FETCH_PROCESSES_SUCCESS, | |||||
| PUT_PROCESS_ERR, | |||||
| PUT_PROCESS_SUCCESS | |||||
| } from "../../actions/processes/processesActionConstants"; | |||||
| import createReducer from "../../utils/createReducer"; | |||||
| const initialState = { | |||||
| processes: [], | |||||
| doneProcess: false, | |||||
| errorMessage: "", | |||||
| }; | |||||
| export default createReducer( | |||||
| { | |||||
| [FETCH_PROCESSES_SUCCESS]: setStateProcesses, | |||||
| [FETCH_PROCESSES_ERR]: setProcessesErrorMessage, | |||||
| [PUT_PROCESS_SUCCESS]: setStateDoneProcess, | |||||
| [PUT_PROCESS_ERR]: setDoneProcessErrorMessage, | |||||
| }, | |||||
| initialState | |||||
| ); | |||||
| function setStateProcesses(state, action) { | |||||
| return { | |||||
| ...state, | |||||
| processes: action.payload, | |||||
| }; | |||||
| } | |||||
| function setProcessesErrorMessage(state, action) { | |||||
| return { | |||||
| ...state, | |||||
| errorMessage: action.payload, | |||||
| }; | |||||
| } | |||||
| function setStateDoneProcess(state, action) { | |||||
| return { | |||||
| ...state, | |||||
| doneProcess: action.payload, | |||||
| }; | |||||
| } | |||||
| function setDoneProcessErrorMessage(state, action) { | |||||
| return { | |||||
| ...state, | |||||
| errorMessage: action.payload, | |||||
| }; | |||||
| } |
| import candidatesSaga from './candidatesSaga'; | import candidatesSaga from './candidatesSaga'; | ||||
| import loginSaga from "./loginSaga"; | import loginSaga from "./loginSaga"; | ||||
| import usersSaga from "./usersSaga"; | import usersSaga from "./usersSaga"; | ||||
| import processesSaga from "./processSaga"; | |||||
| export default function* rootSaga() { | export default function* rootSaga() { | ||||
| yield all([ | yield all([ | ||||
| loginSaga(), | loginSaga(), | ||||
| usersSaga(), | usersSaga(), | ||||
| adsSaga(), | adsSaga(), | ||||
| candidatesSaga() | |||||
| candidatesSaga(), | |||||
| processesSaga(), | |||||
| ]); | ]); | ||||
| } | } |
| 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"; | |||||
| export function* getProcesses() { | |||||
| try { | |||||
| const result = yield call(getAllLevels); | |||||
| yield put(setProcesses(result.data)); | |||||
| } catch (error) { | |||||
| yield put(setProcessesError(error)); | |||||
| } | |||||
| } | |||||
| export function* finishProcess(payload) { | |||||
| try { | |||||
| const id = payload.payload.id; | |||||
| const done = yield call(doneProcess,id); | |||||
| yield put(setDoneProcess(done)); | |||||
| } catch (error) { | |||||
| yield put(setDoneProcessError(error)); | |||||
| } | |||||
| } | |||||
| export default function* processesSaga() { | |||||
| yield all([takeLatest(FETCH_PROCESSES_REQ, getProcesses)]); | |||||
| yield all([takeLatest(PUT_PROCESS_REQ, finishProcess)]); | |||||
| } |
| import { createSelector } from "@reduxjs/toolkit"; | |||||
| export const processesSelector = (state) => state.processes; | |||||
| export const selectProcesses = createSelector(processesSelector, (state) => state.processes); | |||||
| 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 | |||||
| ); |
| const end = formatDate(dates.end); | const end = formatDate(dates.end); | ||||
| return i18next.t('common.date.range', { start, end }); | return i18next.t('common.date.range', { start, end }); | ||||
| } | } | ||||
| export function formatDateSrb(date) { | |||||
| const dt = new Date(date); | |||||
| return format(dt, 'dd.MM.'); | |||||
| } | |||||
| export function formatTimeSrb(date) { | |||||
| const dt = new Date(date); | |||||
| return format(dt, 'HH.mm.'); | |||||
| } |