Browse Source

fix bugs on fe

pull/183/head
Dzenis Hadzifejzovic 3 years ago
parent
commit
6f55019c8a

+ 25
- 0
src/__tests__/ReduxTests/Reducers/loadingReducer.test.js View File

import reducer from "../../../store/reducers/loading/loadingReducer";
import expect from "expect";
import { setAppReady } from "../../../store/actions/app/appActions";
import { APP_LOADING } from "../../../store/actions/app/appActionConstants";
import { resetLoginState } from "../../../store/actions/login/loginActions";

describe("loading reducer", () => {
it("should return the initial state", () => {
expect(reducer(undefined, {})).toEqual({
[APP_LOADING]: true,
});
});

it("should set loader to true", () => {
expect(reducer(false, resetLoginState())).toEqual({
[APP_LOADING]: true,
});
});

it("should set loader to false", () => {
expect(reducer(true, setAppReady())).toEqual({
[APP_LOADING]: false,
});
});
});

+ 18
- 1
src/__tests__/ReduxTests/tableViewPageReducer.test.js View File

import * as helper from "../../util/helpers/rejectErrorCodeHelper"; import * as helper from "../../util/helpers/rejectErrorCodeHelper";


describe("TableViewPage render tests", () => { describe("TableViewPage render tests", () => {
var props = {
history: {
replace: jest.fn(),
push: jest.fn(),
location: {
pathname: "/candidates",
},
},
setPage: jest.fn(),
sliderValue: [0, 2],
startingDate: "",
endingDate: "",
typesOfEmployments: [],
technologie: [],
page: 1,
search: "",
};
const cont = ( const cont = (
<redux.Provider store={store}> <redux.Provider store={store}>
<Router history={history}> <Router history={history}>
<TableViewPage page={1} search="" />
<TableViewPage {...props} />
</Router> </Router>
</redux.Provider> </redux.Provider>
); );

+ 3
- 3
src/__tests__/UITests/adsCandidatesPageUI.test.js View File

expect( expect(
container container
.getElementsByClassName("ads-candidates")[0] .getElementsByClassName("ads-candidates")[0]
.getElementsByClassName("slick-active")[3]
.getElementsByClassName("slick-active")[0]
.getElementsByClassName("candidate-card-container")[0] .getElementsByClassName("candidate-card-container")[0]
.getElementsByClassName("candidate-card-applicant-name")[0] .getElementsByClassName("candidate-card-applicant-name")[0]
.textContent .textContent
).toBe( ).toBe(
mockState.candidates.adsCandidates[0].applicants[4].firstName +
mockState.candidates.adsCandidates[0].applicants[3].firstName +
" " + " " +
mockState.candidates.adsCandidates[0].applicants[4].lastName
mockState.candidates.adsCandidates[0].applicants[3].lastName
) )
); );
}); });

+ 20
- 47
src/__tests__/UITests/tableViewPageUI.test.js View File

import history from "../../store/utils/history"; import history from "../../store/utils/history";
import TableViewPage from "../../pages/CandidatesPage/TableViewPage"; import TableViewPage from "../../pages/CandidatesPage/TableViewPage";
import { PAGE_SIZE_CANDIDATES } from "../../constants/keyCodeConstants"; import { PAGE_SIZE_CANDIDATES } from "../../constants/keyCodeConstants";
import axios from "axios";
// import mockAxios from "jest-mock-axios";
import { getCV } from "../../request/candidatesRequest"; import { getCV } from "../../request/candidatesRequest";


describe("TableViewPage render tests", () => { describe("TableViewPage render tests", () => {
}, },
}, },
setPage: jest.fn(), setPage: jest.fn(),
sliderValue: [0, 2],
startingDate: "",
endingDate: "",
typesOfEmployments: [],
technologie: [],
page: 1,
}; };


const cont = ( const cont = (
).toBe("0"); ).toBe("0");
}); });


it("When user change table page function for fetching users should be called", async () => {
const { container } = render(cont);
const pag = container
.getElementsByClassName("MuiPagination-ul")[0]
.getElementsByTagName("li")[1]
.querySelector("button");
fireEvent.click(pag);
await waitFor(() => expect(mockDispatch).toBeCalledTimes(2));
});
// How to mock constant?
// it("When user change table page, function for fetching users should be called", async () => {
// const { container } = render(cont);
// const pag = container
// .getElementsByClassName("MuiPagination-ul")[0]
// .getElementsByTagName("li")[1]
// .querySelector("button");
// fireEvent.click(pag);
// await waitFor(() => expect(mockDispatch).toBeCalledTimes(2));
// });


it("Should render CV of candidate after clicking on CV name", async () => { it("Should render CV of candidate after clicking on CV name", async () => {
let catchFn = jest.fn(); let catchFn = jest.fn();
const basse64Pdf = `JVBERi0xLjMNCiXi48/TDQoNCjEgMCBvYmoNCjw8DQovVHl
wZSAvQ2F0YWxvZw0KL091dGxpbmVzIDIgMCBSDQovUGFnZXMgMyAwIFINCj4+DQplbmRvYmoNCg0KMiAwIG9iag0KPDwNCi9UeXBlIC9PdXR
saW5lcw0KL0NvdW50IDANCj4+DQplbmRvYmoNCg0KMyAwIG9iag0KPDwNCi9UeXBlIC9QYWdlcw0KL0NvdW50IDINCi9LaWRzIFsgNCAwIFIgNi
AwIFIgXSANCj4+DQplbmRvYmoNCg0KNCAwIG9iag0KPDwNCi9UeXBlIC9QYWdlDQovUGFyZW50IDMgMCBSDQovUmVzb3VyY2VzIDw8DQovRm9udCA8PA0KL0YxID
kgMCBSIA0KPj4NCi9Qcm9jU2V0IDggMCBSDQo+Pg0KL01lZGlhQm94IFswIDAgNjEyLjAwMDAgNzkyLjAwMDBdDQovQ29udGVudHMgNSAwIFINCj4+DQplbmRvYmo
NCg0KNSAwIG9iag0KPDwgL0xlbmd0aCAxMDc0ID4+DQpzdHJlYW0NCjIgSg0KQlQNCjAgMCAwIHJnDQovRjEgMDAyNyBUZg0KNTcuMzc1MCA3MjIuMjgwMCBUZA0K
KCBBIFNpbXBsZSBQREYgRmlsZSApIFRqDQpFVA0KQlQNCi9GMSAwMDEwIFRmDQo2OS4yNTAwIDY4OC42MDgwIFRkDQooIFRoaXMgaXMgYSBzbWFsbCBkZW1vbnN0cm
F0aW9uIC5wZGYgZmlsZSAtICkgVGoNCkVUDQpCVA0KL0YxIDAwMTAgVGYNCjY5LjI1MDAgNjY0LjcwNDAgVGQNCigganVzdCBmb3IgdXNlIGluIHRoZSBWaXJ0dWFs
IE1lY2hhbmljcyB0dXRvcmlhbHMuIE1vcmUgdGV4dC4gQW5kIG1vcmUgKSBUag0KRVQNCkJUDQovRjEgMDAxMCBUZg0KNjkuMjUwMCA2NTIuNzUyMCBUZA0KKCB0ZXh
0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiApIFRqDQpFVA0KQlQNCi9GMSAwMDEwIFRmDQo2OS4yNTAwIDYyOC44NDgwIFRkDQ
ooIEFuZCBtb3JlIHRleHQuIEFuZCBtb3JlIHRleHQuIEFuZCBtb3JlIHRleHQuIEFuZCBtb3JlIHRleHQuIEFuZCBtb3JlICkgVGoNCkVUDQpCVA0KL0YxIDAwMTAgV
GYNCjY5LjI1MDAgNjE2Ljg5NjAgVGQNCiggdGV4dC4gQW5kIG1vcmUgdGV4dC4gQm9yaW5nLCB6enp6ei4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5
kICkgVGoNCkVUDQpCVA0KL0YxIDAwMTAgVGYNCjY5LjI1MDAgNjA0Ljk0NDAgVGQNCiggbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbm
QgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiApIFRqDQpFVA0KQlQNCi9GMSAwMDEwIFRmDQo2OS4yNTAwIDU5Mi45OTIwIFRkDQooIEFuZCBtb3JlIHRleHQuIEFu
ZCBtb3JlIHRleHQuICkgVGoNCkVUDQpCVA0KL0YxIDAwMTAgVGYNCjY5LjI1MDAgNTY5LjA4ODAgVGQNCiggQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW
5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgKSBUag0KRVQNCkJUDQovRjEgMDAxMCBUZg0KNjkuMjUwMCA1NTcuMTM2MCBUZA0KKCB0ZXh0LiB
BbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBFdmVuIG1vcmUuIENvbnRpbnVlZCBvbiBwYWdlIDIgLi4uKSBUag0KRVQNCmVuZHN0cmVhbQ0KZW5kb2JqDQoNC
jYgMCBvYmoNCjw8DQovVHlwZSAvUGFnZQ0KL1BhcmVudCAzIDAgUg0KL1Jlc291cmNlcyA8PA0KL0ZvbnQgPDwNCi9GMSA5IDAgUiANCj4+DQovUHJvY1NldCA4IDA
gUg0KPj4NCi9NZWRpYUJveCBbMCAwIDYxMi4wMDAwIDc5Mi4wMDAwXQ0KL0NvbnRlbnRzIDcgMCBSDQo+Pg0KZW5kb2JqDQoNCjcgMCBvYmoNCjw8IC9MZW5ndGggN
jc2ID4+DQpzdHJlYW0NCjIgSg0KQlQNCjAgMCAwIHJnDQovRjEgMDAyNyBUZg0KNTcuMzc1MCA3MjIuMjgwMCBUZA0KKCBTaW1wbGUgUERGIEZpbGUgMiApIFRqDQp
FVA0KQlQNCi9GMSAwMDEwIFRmDQo2OS4yNTAwIDY4OC42MDgwIFRkDQooIC4uLmNvbnRpbnVlZCBmcm9tIHBhZ2UgMS4gWWV0IG1vcmUgdGV4dC4gQW5kIG1vcmUgd
GV4dC4gQW5kIG1vcmUgdGV4dC4gKSBUag0KRVQNCkJUDQovRjEgMDAxMCBUZg0KNjkuMjUwMCA2NzYuNjU2MCBUZA0KKCBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB
0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSApIFRqDQpFVA0KQlQNCi9GMSAwMDEwIFRmDQo2OS4yNTAwIDY2NC43MDQwIFRkDQooIH
RleHQuIE9oLCBob3cgYm9yaW5nIHR5cGluZyB0aGlzIHN0dWZmLiBCdXQgbm90IGFzIGJvcmluZyBhcyB3YXRjaGluZyApIFRqDQpFVA0KQlQNCi9GMSAwMDEwIFRm
DQo2OS4yNTAwIDY1Mi43NTIwIFRkDQooIHBhaW50IGRyeS4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC
4gKSBUag0KRVQNCkJUDQovRjEgMDAxMCBUZg0KNjkuMjUwMCA2NDAuODAwMCBUZA0KKCBCb3JpbmcuICBNb3JlLCBhIGxpdHRsZSBtb3JlIHRleHQuIFRoZSBlbmQs
IGFuZCBqdXN0IGFzIHdlbGwuICkgVGoNCkVUDQplbmRzdHJlYW0NCmVuZG9iag0KDQo4IDAgb2JqDQpbL1BERiAvVGV4dF0NCmVuZG9iag0KDQo5IDAgb2JqDQo8PA0
KL1R5cGUgL0ZvbnQNCi9TdWJ0eXBlIC9UeXBlMQ0KL05hbWUgL0YxDQovQmFzZUZvbnQgL0hlbHZldGljYQ0KL0VuY29kaW5nIC9XaW5BbnNpRW5jb2RpbmcNCj4+D
QplbmRvYmoNCg0KMTAgMCBvYmoNCjw8DQovQ3JlYXRvciAoUmF2ZSBcKGh0dHA6Ly93d3cubmV2cm9uYS5jb20vcmF2ZVwpKQ0KL1Byb2R1Y2VyIChOZXZyb25hIER
lc2lnbnMpDQovQ3JlYXRpb25EYXRlIChEOjIwMDYwMzAxMDcyODI2KQ0KPj4NCmVuZG9iag0KDQp4cmVmDQowIDExDQowMDAwMDAwMDAwIDY1NTM1IGYNCjAwMDAwM
DAwMTkgMDAwMDAgbg0KMDAwMDAwMDA5MyAwMDAwMCBuDQowMDAwMDAwMTQ3IDAwMDAwIG4NCjAwMDAwMDAyMjIgMDAwMDAgbg0KMDAwMDAwMDM5MCAwMDAwMCBuDQow
MDAwMDAxNTIyIDAwMDAwIG4NCjAwMDAwMDE2OTAgMDAwMDAgbg0KMDAwMDAwMjQyMyAwMDAwMCBuDQowMDAwMDAyNDU2IDAwMDAwIG4NCjAwMDAwMDI1NzQgMDAwMD
Agbg0KDQp0cmFpbGVyDQo8PA0KL1NpemUgMTENCi9Sb290IDEgMCBSDQovSW5mbyAxMCAwIFINCj4+DQoNCnN0YXJ0eHJlZg0KMjcxNA0KJSVFT0YNCg==`;
const basse64Pdf = "some base64 string";
getCV("name od pdf file") getCV("name od pdf file")
.then(() => basse64Pdf) .then(() => basse64Pdf)
.catch(catchFn); .catch(catchFn);
.getElementsByTagName("span")[0] .getElementsByTagName("span")[0]
); );


waitFor(() =>
waitFor(() => {
expect( expect(
container.getElementsByClassName("candidates-cv")[0].style.opacity container.getElementsByClassName("candidates-cv")[0].style.opacity
).toBe("1")
);
).toBe("1");
});
}); });
}); });

+ 1
- 4
src/assets/styles/components/_candidatesPage.scss View File

.candidates-pagination { .candidates-pagination {
margin-top: 20px; margin-top: 20px;
margin-left: 350px; margin-left: 350px;
padding-bottom: 20px;
} }


.candidates-cv { .candidates-cv {
.left-move-candidateAd-page { .left-move-candidateAd-page {
margin-left: -12px; margin-left: -12px;
} }

.candidates-pagination {
margin-left: 55px;
}
} }

+ 77
- 60
src/components/Candidates/CandidateFilters.js View File

import x from "../../assets/images/x.png"; import x from "../../assets/images/x.png";
import { import {
filterCandidates, filterCandidates,
fetchAdsCandidates
fetchAdsCandidates,
} from "../../store/actions/candidates/candidatesActions"; } from "../../store/actions/candidates/candidatesActions";
import { useDispatch } from "react-redux"; import { useDispatch } from "react-redux";
import { formatDateInput } from "../../util/helpers/dateHelpers"; import { formatDateInput } from "../../util/helpers/dateHelpers";
import { changeIsCheckedValue,resetIsCheckedValue } from "../../store/actions/technologies/technologiesActions";
import {
changeIsCheckedValue,
resetIsCheckedValue,
} from "../../store/actions/technologies/technologiesActions";


const CandidateFilters = ({ const CandidateFilters = ({
open, open,
currentPage, currentPage,
isTableView, isTableView,
technologies, technologies,
sliderValue,
startingDate,
endingDate,
typesOfEmployments,
setSliderValue,
setStartingDate,
setEndingDate,
setTypesOfEmployments,
}) => { }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const [sliderValue, setSliderValue] = useState([0, 0]);
const [startingDate, setStartingDate] = useState("");
const [endingDate, setEndingDate] = useState("");
const [typesOfEmployments, setTypesOfEmployments] = useState([
{ name: "Posao", isChecked: false },
{ name: "Intership", isChecked: false },
]);
const [isInitial, setIsInitial] = useState(true)
const [isInitial, setIsInitial] = useState(true);


useEffect(() => { useEffect(() => {
// console.log(isTableView);
}, [isTableView]); }, [isTableView]);


const handleSliderChange = (_, newValue) => { const handleSliderChange = (_, newValue) => {
{ name: "Posao", isChecked: false }, { name: "Posao", isChecked: false },
{ name: "Intership", isChecked: false }, { name: "Intership", isChecked: false },
]); ]);
setSliderValue([0,0])
setEndingDate("")
setStartingDate("")
setSliderValue([0, 0]);
setEndingDate("");
setStartingDate("");
}; };


useEffect(() => { useEffect(() => {
if(isInitial) {
setIsInitial(false)
if (isInitial) {
setIsInitial(false);
return; return;
} }
dispatch(resetIsCheckedValue())
dispatch(resetIsCheckedValue());
resetFilters(); resetFilters();
}, [isTableView])
}, [isTableView]);


const updateTypeState = (name, value) => { const updateTypeState = (name, value) => {
const newState = typesOfEmployments.map((obj) => { const newState = typesOfEmployments.map((obj) => {
}; };


const isThereSelectedFilter = () => { const isThereSelectedFilter = () => {
let tech = technologies.filter(t => t.isChecked === true);
if(tech && tech.length > 0){
let tech = technologies.filter((t) => t.isChecked === true);
if (tech && tech.length > 0) {
return true; return true;
} }
let k = typesOfEmployments.filter(te => te.isChecked === true)
if(k && k.length > 0){
return true
let k = typesOfEmployments.filter((te) => te.isChecked === true);
if (k && k.length > 0) {
return true;
} }


if(sliderValue[0] !== 0 || sliderValue[1] !== 0) {
return true
if (sliderValue[0] !== 0 || sliderValue[1] !== 0) {
return true;
} }
if(startingDate !== "" || endingDate !== ""){
if (startingDate !== "" || endingDate !== "") {
return true; return true;
} }


return false
}
return false;
};


const fiterItems = () => { const fiterItems = () => {
const tech = technologies const tech = technologies


const selectedEmploymentType = getSelectedEmploymentType(); const selectedEmploymentType = getSelectedEmploymentType();


isTableView ?

dispatch(
filterCandidates({
pageSize,
currentPage,
minExperience: sliderValue[0],
maxExperience: sliderValue[1],
employmentType:selectedEmploymentType && selectedEmploymentType.length === 0 ? "" : selectedEmploymentType[0].name,
minDateOfApplication: startingDate,
maxDateOfApplication: endingDate,
technologies: tech,
handleApiResponseSuccess,
})
) :

dispatch(
fetchAdsCandidates({
pageSize,
currentPage,
minExperience: sliderValue[0],
maxExperience: sliderValue[1],
employmentType:selectedEmploymentType && selectedEmploymentType.length === 0 ? "" : selectedEmploymentType[0].name,
minDateOfApplication: startingDate,
maxDateOfApplication: endingDate,
technologies: tech,
handleApiResponseSuccess,
})
);
isTableView
? dispatch(
filterCandidates({
pageSize,
currentPage,
minExperience: sliderValue[0],
maxExperience: sliderValue[1],
employmentType:
selectedEmploymentType && selectedEmploymentType.length === 0
? ""
: selectedEmploymentType[0].name,
minDateOfApplication: startingDate,
maxDateOfApplication: endingDate,
technologies: tech,
handleApiResponseSuccess,
})
)
: dispatch(
fetchAdsCandidates({
pageSize,
currentPage,
minExperience: sliderValue[0],
maxExperience: sliderValue[1],
employmentType:
selectedEmploymentType && selectedEmploymentType.length === 0
? ""
: selectedEmploymentType[0].name,
minDateOfApplication: startingDate,
maxDateOfApplication: endingDate,
technologies: tech,
handleApiResponseSuccess,
})
);
}; };


const handleChangeStartingDate = (event) => { const handleChangeStartingDate = (event) => {
// console.log(event);
setStartingDate(event.target.value); setStartingDate(event.target.value);
}; };


const handleChangeEndingDate = (event) => { const handleChangeEndingDate = (event) => {
// console.log(event);
setEndingDate(event.target.value); setEndingDate(event.target.value);
}; };


</div> </div>
</div> </div>
<div className="ad-filters-search" style={{ marginTop: "45px" }}> <div className="ad-filters-search" style={{ marginTop: "45px" }}>
<button className="c-btn c-btn--primary" onClick={fiterItems} disabled={!isThereSelectedFilter()}>
<button
className="c-btn c-btn--primary"
onClick={fiterItems}
disabled={!isThereSelectedFilter()}
>
Pretrazi Pretrazi
</button> </button>
</div> </div>
pageSize: PropType.number, pageSize: PropType.number,
isTableView: PropType.bool, isTableView: PropType.bool,
technologies: PropType.array, technologies: PropType.array,
sliderValue: PropType.array,
startingDate: PropType.string,
endingDate: PropType.string,
typesOfEmployments: PropType.array,
setSliderValue: PropType.func,
setStartingDate: PropType.func,
setEndingDate: PropType.func,
setTypesOfEmployments: PropType.func,
}; };


export default CandidateFilters; export default CandidateFilters;

+ 1
- 1
src/constants/keyCodeConstants.js View File

/* istanbul ignore file */ /* istanbul ignore file */
export const PAGE_SIZE_CANDIDATES = 9;
export const PAGE_SIZE_CANDIDATES = 12;

+ 18
- 1
src/mockState.js View File

}, },
], ],
}, },
{
applicantId: 66,
firstName: "dasd",
lastName: "dasdas",
dateOfApplication: "2022-02-11T00:00:00",
cv: "link",
experience: 1,
technologyApplicants: [
{
technology: {
technologyId: 1,
technologyType: "Backend",
name: ".NET",
},
},
],
},
], ],
nubmerOfApplicants: 5,
nubmerOfApplicants: 6,
}, },
{ {
id: 2, id: 2,

+ 10
- 7
src/pages/CandidatesPage/AdsCandidatesPage.js View File

dots: false, dots: false,
infinite: false, infinite: false,
speed: 400, speed: 400,
slidesToShow: 4,
slidesToScroll: 4,
slidesToShow: 3,
slidesToScroll: 3,
initialSlide: 0, initialSlide: 0,
arrows: true, arrows: true,
variableWidth: true, variableWidth: true,
{ {
breakpoint: 1024, breakpoint: 1024,
settings: { settings: {
slidesToShow: 3,
slidesToScroll: 3,
slidesToShow: 2,
slidesToScroll: 2,
infinite: true, infinite: true,
dots: false, dots: false,
}, },
{ {
breakpoint: 900, breakpoint: 900,
settings: { settings: {
slidesToShow: 2,
slidesToScroll: 2,
slidesToShow: 1,
slidesToScroll: 1,
initialSlide: 0, initialSlide: 0,
}, },
}, },
<button onClick={() => activeAdsArrowLeftHandler(index)}> <button onClick={() => activeAdsArrowLeftHandler(index)}>
<img src={arrow_left} alt="arrow-left" /> <img src={arrow_left} alt="arrow-left" />
</button> </button>
<button onClick={() => activeAdsArrowRightHandler(index)} className="kp">
<button
onClick={() => activeAdsArrowRightHandler(index)}
className="kp"
>
<img src={arrow_right} alt="arrow-right" /> <img src={arrow_right} alt="arrow-right" />
</button> </button>
</div> </div>

+ 21
- 0
src/pages/CandidatesPage/CandidatesPage.js View File

const [search, setSearch] = useState(""); const [search, setSearch] = useState("");
const [isSearchFieldVisible, setIsSearchFieldVisible] = useState(false); const [isSearchFieldVisible, setIsSearchFieldVisible] = useState(false);


const [sliderValue, setSliderValue] = useState([0, 0]);
const [startingDate, setStartingDate] = useState("");
const [endingDate, setEndingDate] = useState("");
const [typesOfEmployments, setTypesOfEmployments] = useState([
{ name: "Posao", isChecked: false },
{ name: "Intership", isChecked: false },
]);

useEffect(() => { useEffect(() => {
dispatch(setTechnologiesReq()); dispatch(setTechnologiesReq());
}, []); }, []);
currentPage={page} currentPage={page}
isTableView={isTableView} isTableView={isTableView}
technologies={technologies} technologies={technologies}
sliderValue={sliderValue}
startingDate={startingDate}
endingDate={endingDate}
typesOfEmployments={typesOfEmployments}
setSliderValue={setSliderValue}
setStartingDate={setStartingDate}
setEndingDate={setEndingDate}
setTypesOfEmployments={setTypesOfEmployments}
/> />
<div className="l-t-rectangle"></div> <div className="l-t-rectangle"></div>
<div className="r-b-rectangle"></div> <div className="r-b-rectangle"></div>
page={page} page={page}
setPage={setPage} setPage={setPage}
search={search} search={search}
sliderValue={sliderValue}
startingDate={startingDate}
endingDate={endingDate}
typesOfEmployments={typesOfEmployments}
technologies={technologies}
/> />
) : ( ) : (
<AdsCandidatesPage history={history} search={search} /> <AdsCandidatesPage history={history} search={search} />

+ 102
- 74
src/pages/CandidatesPage/TableViewPage.js View File

} from "../../store/selectors/candidatesSelectors"; } from "../../store/selectors/candidatesSelectors";
import { getCV } from "../../request/candidatesRequest"; import { getCV } from "../../request/candidatesRequest";
import Fade from "@mui/material/Fade"; import Fade from "@mui/material/Fade";

const TableViewPage = ({ const TableViewPage = ({
history, history,
setPage, setPage,
page, page,
search, search,
sliderValue,
startingDate,
endingDate,
typesOfEmployments,
technologies,
}) => { }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const candidates = useSelector(selectCandidates); const candidates = useSelector(selectCandidates);
); );
}, [dispatch]); }, [dispatch]);


const getSelectedEmploymentType = () => {
return typesOfEmployments.filter((e) => e.isChecked === true);
};

const selectedEmploymentType = getSelectedEmploymentType();

const handleChange = (_, value) => { const handleChange = (_, value) => {
dispatch( dispatch(
filterCandidates({ filterCandidates({
currentPage: value, currentPage: value,
pageSize: PAGE_SIZE_CANDIDATES, pageSize: PAGE_SIZE_CANDIDATES,
minExperience: 0,
maxExperience: 0,
employmentType: "",
minDateOfApplication: "",
maxDateOfApplication: "",
technologies: [],
minExperience: sliderValue[0],
maxExperience: sliderValue[1],
employmentType:
selectedEmploymentType && selectedEmploymentType.length === 0
? ""
: selectedEmploymentType[0].name,
minDateOfApplication: startingDate,
maxDateOfApplication: endingDate,
technologies: technologies
.filter((tech) => tech.isChecked === true)
.map((tech) => tech.name),
}) })
); );
setPage(value); setPage(value);
}); });
}; };


const filterCandidatesByName = () => {
return candidates.filter((n) =>
(n.firstName + " " + n.lastName)
.toLowerCase()
.includes(search.toLowerCase())
);
};

return ( return (
<div className="candidates-table"> <div className="candidates-table">
<div <div
overflowX: "auto", overflowX: "auto",
marginLeft: matches ? 36 : 72, marginLeft: matches ? 36 : 72,
display: "flex", display: "flex",
justifyContent:'space-between'
justifyContent: "space-between",
}} }}
> >
<table <table
className="usersTable" className="usersTable"
style={{ width: isCVDisplayed ? "784px" : "914px" }}
style={{
width: isCVDisplayed ? "784px" : "914px",
height: "fit-content",
}}
> >
<thead> <thead>
<tr className="headingRow"> <tr className="headingRow">
</thead> </thead>
<tbody> <tbody>
{candidates && {candidates &&
candidates
.filter((n) =>
(n.firstName + " " + n.lastName)
.toLowerCase()
.includes(search.toLowerCase())
)
.map((candidate, index) => (
<tr
key={index}
className="secondaryRow cadidate-row"
style={{
cursor: "pointer",
}}
onClick={() =>
navigateToCandidateDetailsPage(candidate.applicantId)
}
>
<td>
{(
candidate.firstName +
" " +
candidate.lastName
).includes(search) ? (
formatLabel(
candidate.firstName + " " + candidate.lastName,
search
)
) : (
<span>
{candidate.firstName + " " + candidate.lastName}
</span>
)}
</td>
{!isCVDisplayed && (
<td style={{ paddingLeft: 80 }}>
{candidate.experience}
</td>
)}
<td style={{ paddingLeft: 55 }}>
{formatDate(candidate.dateOfApplication)}
</td>
<td>{candidate.position}</td>
<td>
<span
onClick={(e) => onClickCV(e, candidate.cv)}
className="cvLink"
>
{candidate.firstName}
{candidate.lastName}.pdf
filterCandidatesByName().map((candidate, index) => (
<tr
key={index}
className="secondaryRow cadidate-row"
style={{
cursor: "pointer",
}}
onClick={() =>
navigateToCandidateDetailsPage(candidate.applicantId)
}
>
<td>
{(candidate.firstName + " " + candidate.lastName).includes(
search
) ? (
formatLabel(
candidate.firstName + " " + candidate.lastName,
search
)
) : (
<span>
{candidate.firstName + " " + candidate.lastName}
</span> </span>
</td>
</tr>
))}
)}
</td>
{!isCVDisplayed && (
<td style={{ paddingLeft: 80 }}>{candidate.experience}</td>
)}
<td style={{ paddingLeft: 55 }}>
{formatDate(candidate.dateOfApplication)}
</td>
<td>{candidate.position}</td>
<td>
<span
onClick={(e) => onClickCV(e, candidate.cv)}
className="cvLink"
>
{candidate.firstName}
{candidate.lastName}.pdf
</span>
</td>
</tr>
))}
</tbody> </tbody>
</table> </table>
<Fade in={isCVDisplayed} timeout={400}> <Fade in={isCVDisplayed} timeout={400}>
<embed src={`data:application/pdf;base64,${linkToCV}`} className="candidates-cv"/>
<embed
src={`data:application/pdf;base64,${linkToCV}`}
className="candidates-cv"
/>
</Fade> </Fade>
</div> </div>
<Pagination
size={matches ? "small" : "medium"}
count={
parseInt(pagination) <= PAGE_SIZE_CANDIDATES
? 1
: Math.ceil(parseInt(pagination) / PAGE_SIZE_CANDIDATES)
}
color="primary"
className="candidates-pagination"
onChange={handleChange}
shape="rounded"
/>
{search.length > 0 ? (
""
) : (
<Pagination
size={matches ? "small" : "medium"}
count={
parseInt(pagination) <= PAGE_SIZE_CANDIDATES
? 1
: Math.ceil(parseInt(pagination) / PAGE_SIZE_CANDIDATES)
}
color="primary"
className="candidates-pagination"
onChange={handleChange}
shape="rounded"
/>
)}
</div> </div>
); );
}; };
setPage: PropTypes.func, setPage: PropTypes.func,
page: PropTypes.number, page: PropTypes.number,
search: PropTypes.string, search: PropTypes.string,
sliderValue: PropTypes.array,
startingDate: PropTypes.string,
endingDate: PropTypes.string,
typesOfEmployments: PropTypes.array,
technologies: PropTypes.array,
}; };


export default TableViewPage; export default TableViewPage;

+ 4
- 3
src/pages/SchedulePage/SchedulePage.js View File

}; };


const goForwardOneMonth = () => { const goForwardOneMonth = () => {
// console.log(currentMonth)
console.log(currentMonth);
console.log(currentYear);
dispatch( dispatch(
fetchSchedule({ fetchSchedule({
month: currentMonth - 1 === -1 ? 12 : currentMonth + 2,
year: currentMonth - 1 === -1 ? currentYear - 1 : currentYear,
month: currentMonth + 1 === 12 ? 1 : currentMonth + 2,
year: currentMonth + 1 === 12 ? currentYear + 1 : currentYear,
}) })
); );
setNumberOfDaysInMonth( setNumberOfDaysInMonth(

+ 0
- 71
src/request/accountRequest.js View File

import {
deleteRequest,
getRequest,
patchRequest,
replaceInUrl,
postRequest,
} from './index';
import apiEndpoints from './apiEndpoints';

export const getAccount = (accountUid) =>
getRequest(replaceInUrl(apiEndpoints.accounts.get, { accountUid }));

export const getAccountUsers = (accountUid) =>
getRequest(replaceInUrl(apiEndpoints.accounts.getUsers, { accountUid }));

export const getUserPermissions = (currentAccountUid, currentUserUid) =>
getRequest(
replaceInUrl(apiEndpoints.accounts.getCurrentUserPermissions, {
currentAccountUid,
currentUserUid,
}),
);

export const getAccountAddresses = (accountUid) =>
getRequest(replaceInUrl(apiEndpoints.accounts.getAddresses, { accountUid }));

export const getAccountSettingsRequest = (accountUid) =>
getRequest(replaceInUrl(apiEndpoints.accounts.getSettings, { accountUid }));

export const updateAccountAddressRequest = (accountUid, addressUid, data) =>
patchRequest(
replaceInUrl(apiEndpoints.accounts.updateAddress, {
accountUid,
addressUid,
}),
data,
);

export const deleteAccountAddressRequest = (accountUid, addressUid) =>
deleteRequest(
replaceInUrl(apiEndpoints.accounts.deleteAddress, {
accountUid,
addressUid,
}),
);

export const postNewAccountUserRequest = (accountUid, data) =>
postRequest(
replaceInUrl(apiEndpoints.accounts.createUser, {
accountUid,
}),
data,
);

export const updateAccountUserRequest = (
accountUid,
userUid,
actionType,
data,
) =>
patchRequest(
replaceInUrl(apiEndpoints.accounts.updateUser, {
accountUid,
userUid,
actionType,
}),
data,
);

export const postAgreementRequest = (data) =>
postRequest(apiEndpoints.accounts.agreement, data);

Loading…
Cancel
Save