Browse Source

Renaming in order to solve AdBlocker problem

feature/solving_add_blocker_problem_fe
Dzenis Hadzifejzovic 2 years ago
parent
commit
0cf3c7f97f
50 changed files with 569 additions and 577 deletions
  1. 2
    2
      src/AppRoutes.js
  2. 2
    2
      src/__tests__/UITests/adDetailsCandidateCardUI.test.js
  3. 9
    9
      src/__tests__/UITests/adDetailsPageUI.test.js
  4. 6
    6
      src/__tests__/UITests/adsCandidatesPageUI.test.js
  5. 17
    17
      src/__tests__/UITests/adsPageUI.test.js
  6. 8
    8
      src/__tests__/UITests/applyForAdFirstStageUI.test.js
  7. 5
    5
      src/__tests__/UITests/applyForAdFourthStageUI.test.js
  8. 7
    7
      src/__tests__/UITests/applyForAdSecondStageUI.test.js
  9. 7
    7
      src/__tests__/UITests/applyForAdThirdStageUI.test.js
  10. 1
    1
      src/__tests__/UITests/candidateDetailsPageUI.test.js
  11. 8
    8
      src/__tests__/UITests/createAdPageUI.test.js
  12. 1
    1
      src/__tests__/UITests/patternDetailsPageUI.test.js
  13. 1
    1
      src/__tests__/UITests/patternsPageUI.test.js
  14. 4
    4
      src/__tests__/UITests/statsAdComponentUI.test.js
  15. 3
    3
      src/__tests__/UITests/statsPageUI.test.js
  16. 170
    178
      src/assets/styles/components/_ads.scss
  17. 9
    9
      src/assets/styles/components/_candidatePage.scss
  18. 17
    17
      src/assets/styles/components/_candidatesPage.scss
  19. 2
    2
      src/assets/styles/components/_statistics.scss
  20. 10
    10
      src/components/Ads/Ad.js
  21. 8
    8
      src/components/Ads/AdDetailsCandidateCard.js
  22. 18
    18
      src/components/Ads/AdFilters.js
  23. 7
    7
      src/components/Ads/ApplyForAd.js
  24. 13
    13
      src/components/Ads/ApplyForAdFirstStage.js
  25. 8
    8
      src/components/Ads/ApplyForAdFourthStage.js
  26. 16
    16
      src/components/Ads/ApplyForAdSecondStage.js
  27. 6
    6
      src/components/Ads/ApplyForAdThirdStage.js
  28. 8
    8
      src/components/Ads/ArchiveJob.js
  29. 6
    6
      src/components/Ads/StatsAd.js
  30. 1
    1
      src/components/Button/FilterButton.js
  31. 16
    16
      src/components/Candidates/CandidateFilters.js
  32. 1
    1
      src/components/MUI/NavbarComponent.js
  33. 3
    3
      src/components/Selection/ApplicantSelection.js
  34. 12
    12
      src/components/Selection/SelectionFilter.js
  35. 3
    3
      src/constants/pages.js
  36. 1
    1
      src/i18n/resources/en.js
  37. 30
    30
      src/pages/AdsPage/AdDetailsPage.js
  38. 47
    47
      src/pages/AdsPage/AdsPage.js
  39. 9
    9
      src/pages/AdsPage/CreateAdFirstStep.js
  40. 7
    7
      src/pages/AdsPage/CreateAdPage.js
  41. 13
    13
      src/pages/AdsPage/CreateAdSecondStep.js
  42. 4
    4
      src/pages/AdsPage/CreateAdThirdStep.js
  43. 8
    8
      src/pages/CandidatesPage/AdsCandidatesPage.js
  44. 5
    5
      src/pages/CandidatesPage/CandidateDetailsPage.js
  45. 3
    3
      src/pages/PatternsPage/PatternDetailsPage.js
  46. 1
    1
      src/pages/PatternsPage/PatternsPage.js
  47. 9
    9
      src/pages/SelectionProcessPage/SelectionProcessOfApplicantPage.js
  48. 10
    10
      src/pages/StatsPage/StatsPage.js
  49. 1
    1
      src/pages/UsersPage/UsersPage.js
  50. 6
    6
      src/request/apiEndpoints.js

+ 2
- 2
src/AppRoutes.js View File



import { import {
ADS_PAGE, ADS_PAGE,
AD_DETAILS_PAGE,
FORGOT_PASSWORD_PAGE, FORGOT_PASSWORD_PAGE,
FORGOT_PASSWORD_CONFIRMATION_PAGE, FORGOT_PASSWORD_CONFIRMATION_PAGE,
NOT_FOUND_PAGE, NOT_FOUND_PAGE,
STATS_PAGE, STATS_PAGE,
REGISTER_PAGE, REGISTER_PAGE,
CREATE_AD_PAGE, CREATE_AD_PAGE,
JOB_DETAILS_PAGE,
} from "./constants/pages"; } from "./constants/pages";


import LoginPage from "./pages/LoginPage/LoginPageMUI"; import LoginPage from "./pages/LoginPage/LoginPageMUI";
<Route exact path={REGISTER_PAGE} component={RegisterPage} /> <Route exact path={REGISTER_PAGE} component={RegisterPage} />
<Route path={RESET_PASSWORD_PAGE} component={ResetPasswordPage} /> <Route path={RESET_PASSWORD_PAGE} component={ResetPasswordPage} />
<PrivateRoute exact path={ADS_PAGE} component={AdsPage} /> <PrivateRoute exact path={ADS_PAGE} component={AdsPage} />
<PrivateRoute exact path={AD_DETAILS_PAGE} component={AdDetailsPage} />
<PrivateRoute exact path={JOB_DETAILS_PAGE} component={AdDetailsPage} />
<PrivateRoute exact path={USER_DETAILS_PAGE} component={UserDetails} /> <PrivateRoute exact path={USER_DETAILS_PAGE} component={UserDetails} />
<PrivateRoute exact path={USERS_PAGE} component={UsersPage} /> <PrivateRoute exact path={USERS_PAGE} component={UsersPage} />
<PrivateRoute exact path={CANDIDATES_PAGE} component={CandidatesPage} /> <PrivateRoute exact path={CANDIDATES_PAGE} component={CandidatesPage} />

+ 2
- 2
src/__tests__/UITests/adDetailsCandidateCardUI.test.js View File



it("Should load ad details candidate card component", () => { it("Should load ad details candidate card component", () => {
render(cont); render(cont);
expect(screen.getByTestId("ad-details-candidate")).toBeDefined();
expect(screen.getByTestId("job-details-candidate")).toBeDefined();
}); });


it("Should navigate on candidates page when button clicked", async () => { it("Should navigate on candidates page when button clicked", async () => {
render(cont); render(cont);
waitFor(() => { waitFor(() => {
fireEvent.click(screen.getByTestId("ad-details-candidate-title-link"));
fireEvent.click(screen.getByTestId("job-details-candidate-title-link"));
expect(props.history.push).toHaveBeenCalledWith("/candidates/1"); expect(props.history.push).toHaveBeenCalledWith("/candidates/1");
}); });
}); });

+ 9
- 9
src/__tests__/UITests/adDetailsPageUI.test.js View File



it("Should render AdDetailsPage", () => { it("Should render AdDetailsPage", () => {
render(cont); render(cont);
expect(screen.getByTestId("ad-details-page")).toBeDefined();
expect(screen.getByTestId("job-details-page")).toBeDefined();
}); });


it("Should render modal when click archive ad button", () => { it("Should render modal when click archive ad button", () => {
const { container } = render(cont); const { container } = render(cont);


fireEvent.click(container.getElementsByClassName("archive-ad-button")[0]);
fireEvent.click(container.getElementsByClassName("archive-job-button")[0]);


expect(screen.getByTestId("alert-container")).toBeDefined(); expect(screen.getByTestId("alert-container")).toBeDefined();
}); });
const { container } = render(cont); const { container } = render(cont);


waitFor(() => { waitFor(() => {
fireEvent.click(container.getElementsByClassName("archive-ad-button")[0]);
fireEvent.click(container.getElementsByClassName("archive-job-button")[0]);


fireEvent.click(container.getElementsByClassName("dialog-btn")[1]); fireEvent.click(container.getElementsByClassName("dialog-btn")[1]);


waitFor(() => expect(props.history.push).toHaveBeenCalledWith('/ads'));
waitFor(() => expect(props.history.push).toHaveBeenCalledWith('/jobs'));
}); });
}); });


it("Should render apply for ad button", () => { it("Should render apply for ad button", () => {
const { container } = render(cont); const { container } = render(cont);
expect( expect(
container.getElementsByClassName("apply-for-ad-button")[0]
container.getElementsByClassName("apply-for-job-button")[0]
).toBeDefined(); ).toBeDefined();
}); });


it("Should render apply for ad modal after click button", () => { it("Should render apply for ad modal after click button", () => {
const { container } = render(cont); const { container } = render(cont);


fireEvent.click(container.getElementsByClassName("apply-for-ad-button")[0]);
fireEvent.click(container.getElementsByClassName("apply-for-job-button")[0]);


const a = screen.getByTestId("custom-modal-test-id"); const a = screen.getByTestId("custom-modal-test-id");


it("Should render go back button", () => { it("Should render go back button", () => {
const { container } = render(cont); const { container } = render(cont);
expect( expect(
container.getElementsByClassName("ad-details-buttons-link")[0]
container.getElementsByClassName("job-details-buttons-link")[0]
).toBeDefined(); ).toBeDefined();
}); });


const { container } = render(cont); const { container } = render(cont);


fireEvent.click( fireEvent.click(
container.getElementsByClassName("ad-details-buttons-link")[0]
container.getElementsByClassName("job-details-buttons-link")[0]
); );


const arg = { pathname: "/ads" };
const arg = { pathname: "/jobs" };


waitFor(() => expect(props.history.push).toHaveBeenCalledWith(arg)); waitFor(() => expect(props.history.push).toHaveBeenCalledWith(arg));
}); });

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

it("Should render", () => { it("Should render", () => {
const { container } = render(cont); const { container } = render(cont);
expect( expect(
container.getElementsByClassName("ads-candidates-container")[0]
container.getElementsByClassName("jobs-candidates-container")[0]
).toBeDefined(); ).toBeDefined();
}); });


it("Number of sliders should be equal to length of our adsCandidates array", () => { it("Number of sliders should be equal to length of our adsCandidates array", () => {
const { container } = render(cont); const { container } = render(cont);
expect(container.getElementsByClassName("ads-candidates").length).toBe(
expect(container.getElementsByClassName("jobs-candidates").length).toBe(
mockState.candidates.adsCandidates.length mockState.candidates.adsCandidates.length
); );
}); });
const { container } = render(cont); const { container } = render(cont);
expect( expect(
container container
.getElementsByClassName("ads-candidates")[0]
.getElementsByClassName("jobs-candidates")[0]
.getElementsByClassName("slick-slide").length .getElementsByClassName("slick-slide").length
).toBe(mockState.candidates.adsCandidates[0].applicants.length); ).toBe(mockState.candidates.adsCandidates[0].applicants.length);
}); });
it("Number of arrows (left and right) should be 1 because there is more than 4 candidates which applied for ad", () => { it("Number of arrows (left and right) should be 1 because there is more than 4 candidates which applied for ad", () => {
const { container } = render(cont); const { container } = render(cont);
expect( expect(
container.getElementsByClassName("active-ads-ads-arrows").length
container.getElementsByClassName("active-jobs-jobs-arrows").length
).toBe(1); ).toBe(1);
}); });


const { container } = render(cont); const { container } = render(cont);
fireEvent.click( fireEvent.click(
container container
.getElementsByClassName("active-ads-ads-arrows")[0]
.getElementsByClassName("active-jobs-jobs-arrows")[0]
.getElementsByTagName("button")[1] .getElementsByTagName("button")[1]
); );


await waitFor(() => await waitFor(() =>
expect( expect(
container container
.getElementsByClassName("ads-candidates")[0]
.getElementsByClassName("jobs-candidates")[0]
.getElementsByClassName("slick-active")[0] .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]

+ 17
- 17
src/__tests__/UITests/adsPageUI.test.js View File



it("Should render ads", () => { it("Should render ads", () => {
render(cont); render(cont);
expect(screen.getByTestId("ads-page")).toBeDefined();
expect(screen.getByTestId("jobs-page")).toBeDefined();
}); });


it("Should be rendered button which is used for showing input responsible for searching by name", () => { it("Should be rendered button which is used for showing input responsible for searching by name", () => {
const { container } = render(cont); const { container } = render(cont);
expect(container.getElementsByClassName("ads-page-btn")[0]).toBeDefined();
expect(container.getElementsByClassName("jobs-page-btn")[0]).toBeDefined();
}); });


it("Should be rendered button for toggling filters modal", () => { it("Should be rendered button for toggling filters modal", () => {
const { container } = render(cont); const { container } = render(cont);
expect(container.getElementsByClassName("ads-page-btn")[1]).toBeDefined();
expect(container.getElementsByClassName("jobs-page-btn")[1]).toBeDefined();
}); });


it("Should be rendered button for adding new ad", () => { it("Should be rendered button for adding new ad", () => {
const { container } = render(cont); const { container } = render(cont);
expect(container.getElementsByClassName("ads-page-btn")[2]).toBeDefined();
expect(container.getElementsByClassName("jobs-page-btn")[2]).toBeDefined();
}); });


it("Should render CreateAdPage when click Add Ad button", () => { it("Should render CreateAdPage when click Add Ad button", () => {
const { container } = render(cont); const { container } = render(cont);
fireEvent.click(container.getElementsByClassName("ads-page-btn")[2]);
fireEvent.click(container.getElementsByClassName("jobs-page-btn")[2]);


expect(props.history.push).toHaveBeenCalledWith("/create-ad"); expect(props.history.push).toHaveBeenCalledWith("/create-ad");
}); });
it("Input for searching by title should not be shown when component is initialy rendered", () => { it("Input for searching by title should not be shown when component is initialy rendered", () => {
const { container } = render(cont); const { container } = render(cont);
expect( expect(
container.getElementsByClassName("ads-page-search-by-title")[0].style
container.getElementsByClassName("jobs-page-search-by-title")[0].style
.visibility .visibility
).toBe("hidden"); ).toBe("hidden");
}); });


it("Should be rendered ad cards", () => { it("Should be rendered ad cards", () => {
const { container } = render(cont); const { container } = render(cont);
expect(container.getElementsByClassName("ad-card").length).toBeGreaterThan(
expect(container.getElementsByClassName("job-card").length).toBeGreaterThan(
0 0
); );
}); });


it("Should be rendered archive ad cards", () => { it("Should be rendered archive ad cards", () => {
const { container } = render(cont); const { container } = render(cont);
expect(container.getElementsByClassName("archive-ad").length).toBe(0);
expect(container.getElementsByClassName("archive-job").length).toBe(0);
}); });


it("Should render filter drawer after click filter button", () => { it("Should render filter drawer after click filter button", () => {
const { container } = render(cont); const { container } = render(cont);


fireEvent.click(container.getElementsByClassName("fltr-btn")[0]); fireEvent.click(container.getElementsByClassName("fltr-btn")[0]);
expect(screen.getByTestId("ad-filters-drawer")).toBeDefined();
expect(screen.getByTestId("job-filters-drawer")).toBeDefined();
}); });


it("Should render arrow buttons for active ads slider", () => { it("Should render arrow buttons for active ads slider", () => {
const { container } = render(cont); const { container } = render(cont);
expect( expect(
container.getElementsByClassName("active-ads-ads-arrows")
container.getElementsByClassName("active-jobs-jobs-arrows")
).toBeDefined(); ).toBeDefined();
}); });


it("Should render arrow buttons for archived ads slider", () => { it("Should render arrow buttons for archived ads slider", () => {
const { container } = render(cont); const { container } = render(cont);
expect( expect(
container.getElementsByClassName("archived-ads-ads-arrows")
container.getElementsByClassName("archived-jobs-jobs-arrows")
).toBeDefined(); ).toBeDefined();
}); });


fireEvent.click(container.getElementsByClassName("fltr-btn")[0]); fireEvent.click(container.getElementsByClassName("fltr-btn")[0]);


fireEvent.click( fireEvent.click(
container.getElementsByClassName("ad-filters-checkbox")[0]
container.getElementsByClassName("job-filters-checkbox")[0]
); );


fireEvent.click(container.getByTestId("ad-filters-submit")[0]);
fireEvent.click(container.getByTestId("job-filters-submit")[0]);


expect( expect(
container.getElementsByClassName("ad-card").length
container.getElementsByClassName("job-card").length
).toBeGreaterThan(0); ).toBeGreaterThan(0);
}); });
}); });
const { container } = render(cont); const { container } = render(cont);
waitFor(() => waitFor(() =>
expect( expect(
container.getElementsByClassName("ad-card").length
container.getElementsByClassName("job-card").length
).toBeGreaterThan(0) ).toBeGreaterThan(0)
); );
}); });


it("Should navigate to ad details when click on ad card", async () => { it("Should navigate to ad details when click on ad card", async () => {
const { container } = render(cont); const { container } = render(cont);
fireEvent.click(container.getElementsByClassName("ad-card")[0]);
fireEvent.click(container.getElementsByClassName("job-card")[0]);


expect(props.history.push).toHaveBeenCalledWith("/ads/1");
expect(props.history.push).toHaveBeenCalledWith("/jobs/1");
}); });
}); });

+ 8
- 8
src/__tests__/UITests/applyForAdFirstStageUI.test.js View File



it("Should render firstName input", () => { it("Should render firstName input", () => {
render(cont); render(cont);
expect(screen.getByTestId("apply-for-ad-modal-first-name-input")).toBeDefined();
expect(screen.getByTestId("apply-for-job-modal-first-name-input")).toBeDefined();
}); });


it("Should change firstName on changing input", async () => { it("Should change firstName on changing input", async () => {
render(cont); render(cont);
fireEvent.change( fireEvent.change(
screen.getByTestId("apply-for-ad-modal-first-name-input"),
screen.getByTestId("apply-for-job-modal-first-name-input"),
{ target: { value: "Ermin" } } { target: { value: "Ermin" } }
); );




it("Should change last on changing input", async () => { it("Should change last on changing input", async () => {
render(cont); render(cont);
fireEvent.change(screen.getByTestId("apply-for-ad-modal-last-name-input"), {
fireEvent.change(screen.getByTestId("apply-for-job-modal-last-name-input"), {
target: { value: "Bronja" }, target: { value: "Bronja" },
}); });


it("Should select male gender", async () => { it("Should select male gender", async () => {
const { container } = render(cont); const { container } = render(cont);
fireEvent.click( fireEvent.click(
container.getElementsByClassName("apply-for-ad-modal-gender-input")[0]
container.getElementsByClassName("apply-for-job-modal-gender-input")[0]
); );


waitFor(() => expect(props.setGender).toHaveBeenCalled()); waitFor(() => expect(props.setGender).toHaveBeenCalled());
it("Should select female gender", async () => { it("Should select female gender", async () => {
const { container } = render(cont); const { container } = render(cont);
fireEvent.click( fireEvent.click(
container.getElementsByClassName("apply-for-ad-modal-gender-input")[1]
container.getElementsByClassName("apply-for-job-modal-gender-input")[1]
); );


waitFor(() => expect(props.setGender).toHaveBeenCalled()); waitFor(() => expect(props.setGender).toHaveBeenCalled());


it("Should change date of birth", async () => { it("Should change date of birth", async () => {
render(cont); render(cont);
fireEvent.change(screen.getByTestId("apply-for-ad-modal-date-of-birth"), {
fireEvent.change(screen.getByTestId("apply-for-job-modal-date-of-birth"), {
target: { value: "1998-05-05" }, target: { value: "1998-05-05" },
}); });




it("Should change phone number", async () => { it("Should change phone number", async () => {
render(cont); render(cont);
fireEvent.change(screen.getByTestId("apply-for-ad-modal-phone-number"), { target: { value: "0000000000" } });
fireEvent.change(screen.getByTestId("apply-for-job-modal-phone-number"), { target: { value: "0000000000" } });


waitFor(() => expect(props.setPhoneNumber).toHaveBeenCalled()); waitFor(() => expect(props.setPhoneNumber).toHaveBeenCalled());
}); });


it("Should click go forward button", async () => { it("Should click go forward button", async () => {
render(cont); render(cont);
fireEvent.click(screen.getByTestId("apply-for-ad-modal-go-forward-button"));
fireEvent.click(screen.getByTestId("apply-for-job-modal-go-forward-button"));


waitFor(() => expect(props.onIncreaseStage).toHaveBeenCalled()); waitFor(() => expect(props.onIncreaseStage).toHaveBeenCalled());
}); });

+ 5
- 5
src/__tests__/UITests/applyForAdFourthStageUI.test.js View File



it("Should render apply for ad fourth stage modal", () => { it("Should render apply for ad fourth stage modal", () => {
render(cont); render(cont);
expect(screen.getByTestId("apply-for-ad-modal-fourth-stage")).toBeDefined();
expect(screen.getByTestId("apply-for-job-modal-fourth-stage")).toBeDefined();
}); });


it("Should change pdfFile", async () => { it("Should change pdfFile", async () => {
render(cont); render(cont);
fireEvent.change( fireEvent.change(
screen.getByTestId("apply-for-ad-modal-fourth-stage-pdf-input"),
screen.getByTestId("apply-for-job-modal-fourth-stage-pdf-input"),
{ target: { files: [file] } } { target: { files: [file] } }
); );


it("Should change coverLetter", async () => { it("Should change coverLetter", async () => {
render(cont); render(cont);
fireEvent.change( fireEvent.change(
screen.getByTestId("apply-for-ad-modal-fourth-stage-cover-letter-input"),
screen.getByTestId("apply-for-job-modal-fourth-stage-cover-letter-input"),
{ target: { value: "Cover Letter" } } { target: { value: "Cover Letter" } }
); );


it("Should go back on click button", async () => { it("Should go back on click button", async () => {
render(cont); render(cont);
fireEvent.click( fireEvent.click(
screen.getByTestId("apply-for-ad-modal-fourth-stage-go-back-button")
screen.getByTestId("apply-for-job-modal-fourth-stage-go-back-button")
); );


waitFor(() => expect(props.onDecreaseStage).toHaveBeenCalled()); waitFor(() => expect(props.onDecreaseStage).toHaveBeenCalled());
it("Should finish stages on click button", async () => { it("Should finish stages on click button", async () => {
render(cont); render(cont);
fireEvent.click( fireEvent.click(
screen.getByTestId("apply-for-ad-modal-fourth-stage-go-forward-button")
screen.getByTestId("apply-for-job-modal-fourth-stage-go-forward-button")
); );


waitFor(() => expect(props.onFinishedFourStages).toHaveBeenCalled()); waitFor(() => expect(props.onFinishedFourStages).toHaveBeenCalled());

+ 7
- 7
src/__tests__/UITests/applyForAdSecondStageUI.test.js View File



it("Should render apply for ad second stage", () => { it("Should render apply for ad second stage", () => {
render(cont); render(cont);
expect(screen.getByTestId("apply-for-ad-second-stage")).toBeDefined();
expect(screen.getByTestId("apply-for-job-second-stage")).toBeDefined();
}); });


it("Should change professional qualification input", () => { it("Should change professional qualification input", () => {
render(cont); render(cont);
fireEvent.change( fireEvent.change(
screen.getByTestId( screen.getByTestId(
"apply-for-ad-second-stage-professional-qualification"
"apply-for-job-second-stage-professional-qualification"
), ),
{ {
target: { value: "Faculty" }, target: { value: "Faculty" },
const { container } = render(cont); const { container } = render(cont);


expect( expect(
container.getElementsByClassName("apply-for-ad-second-stage-checkbox")[0]
container.getElementsByClassName("apply-for-job-second-stage-checkbox")[0]
).toBeDefined(); ).toBeDefined();
}); });


const { container } = render(cont); const { container } = render(cont);


expect( expect(
container.getElementsByClassName("apply-for-ad-second-stage-checkbox")[1]
container.getElementsByClassName("apply-for-job-second-stage-checkbox")[1]
).toBeDefined(); ).toBeDefined();
}); });


const { container } = render(cont); const { container } = render(cont);


expect( expect(
container.getElementsByClassName("apply-for-ad-second-stage-checkbox")[2]
container.getElementsByClassName("apply-for-job-second-stage-checkbox")[2]
).toBeDefined(); ).toBeDefined();
}); });


render(cont); render(cont);


fireEvent.change( fireEvent.change(
screen.getByTestId("apply-for-ad-second-stage-experience-input"),
screen.getByTestId("apply-for-job-second-stage-experience-input"),
{ target: { value: 2 } } { target: { value: 2 } }
); );


const { container } = render(cont); const { container } = render(cont);


fireEvent.click( fireEvent.click(
container.getElementsByClassName("apply-for-ad-second-stage-checkbox")[0]
container.getElementsByClassName("apply-for-job-second-stage-checkbox")[0]
); );


waitFor(() => expect(props.technologies[0]).toBe(true)); waitFor(() => expect(props.technologies[0]).toBe(true));

+ 7
- 7
src/__tests__/UITests/applyForAdThirdStageUI.test.js View File

it("Should change linkedin input", async () => { it("Should change linkedin input", async () => {
render(cont); render(cont);
fireEvent.change( fireEvent.change(
screen.getByTestId("apply-for-ad-modal-third-stage-linkedin-input"),
screen.getByTestId("apply-for-job-modal-third-stage-linkedin-input"),
{ target: { value: "https://linkedin" } } { target: { value: "https://linkedin" } }
); );


render(cont); render(cont);


expect( expect(
screen.getByTestId("apply-for-ad-modal-third-stage-linkedin-input")
screen.getByTestId("apply-for-job-modal-third-stage-linkedin-input")
).toBeDefined(); ).toBeDefined();
}); });


it("Should change github input", async () => { it("Should change github input", async () => {
render(cont); render(cont);
fireEvent.change( fireEvent.change(
screen.getByTestId("apply-for-ad-modal-third-stage-github-input"),
screen.getByTestId("apply-for-job-modal-third-stage-github-input"),
{ target: { value: "https://github" } } { target: { value: "https://github" } }
); );


it("Should change bitbucket input", async () => { it("Should change bitbucket input", async () => {
render(cont); render(cont);
fireEvent.change( fireEvent.change(
screen.getByTestId("apply-for-ad-modal-third-stage-bitbucket-input"),
screen.getByTestId("apply-for-job-modal-third-stage-bitbucket-input"),
{ target: { value: "https://bitbucket" } } { target: { value: "https://bitbucket" } }
); );


it("Should change email input", async () => { it("Should change email input", async () => {
render(cont); render(cont);
fireEvent.change( fireEvent.change(
screen.getByTestId("apply-for-ad-modal-third-stage-email-input"),
screen.getByTestId("apply-for-job-modal-third-stage-email-input"),
{ target: { value: "ermin.bronja@dilig.net" } } { target: { value: "ermin.bronja@dilig.net" } }
); );


it("Should go back when button clicked", async () => { it("Should go back when button clicked", async () => {
render(cont); render(cont);
fireEvent.click( fireEvent.click(
screen.getByTestId("apply-for-ad-modal-third-stage-go-back-button")
screen.getByTestId("apply-for-job-modal-third-stage-go-back-button")
); );


waitFor(() => expect(props.onDecreaseStage).toHaveBeenCalled()); waitFor(() => expect(props.onDecreaseStage).toHaveBeenCalled());
it("Should go forward when button clicked", async () => { it("Should go forward when button clicked", async () => {
render(cont); render(cont);
fireEvent.click( fireEvent.click(
screen.getByTestId("apply-for-ad-modal-third-stage-go-forward-button")
screen.getByTestId("apply-for-job-modal-third-stage-go-forward-button")
); );


waitFor(() => expect(props.onIncreaseStage).toHaveBeenCalled()); waitFor(() => expect(props.onIncreaseStage).toHaveBeenCalled());

+ 1
- 1
src/__tests__/UITests/candidateDetailsPageUI.test.js View File

it("Should render page with all candidates", () => { it("Should render page with all candidates", () => {
const { container } = render(cont); const { container } = render(cont);
fireEvent.click( fireEvent.click(
container.getElementsByClassName("applicant-ads-back-button")[0]
container.getElementsByClassName("applicant-jobs-back-button")[0]
); );
const arg = { pathname: "/candidates" }; const arg = { pathname: "/candidates" };
expect(props.history.push).toHaveBeenCalledWith(arg); expect(props.history.push).toHaveBeenCalledWith(arg);

+ 8
- 8
src/__tests__/UITests/createAdPageUI.test.js View File



it("Should render create ad page", () => { it("Should render create ad page", () => {
render(cont); render(cont);
expect(screen.getByTestId("create-ad-page")).toBeDefined();
expect(screen.getByTestId("create-job-page")).toBeDefined();
}); });


it("Should render go back button", () => { it("Should render go back button", () => {
const { container } = render(cont); const { container } = render(cont);
expect( expect(
container.getElementsByClassName("create-ad-buttons-back")[0]
container.getElementsByClassName("create-job-buttons-back")[0]
).toBeDefined(); ).toBeDefined();
}); });


it("Should render go forward button", () => { it("Should render go forward button", () => {
const { container } = render(cont); const { container } = render(cont);
expect( expect(
container.getElementsByClassName("create-ad-buttons-forward")[0]
container.getElementsByClassName("create-job-buttons-forward")[0]
).toBeDefined(); ).toBeDefined();
}); });


it("Should render create ad first step form", () => { it("Should render create ad first step form", () => {
render(cont); render(cont);
expect(screen.getByTestId("create-ad-first-step-form")).toBeDefined();
expect(screen.getByTestId("create-job-first-step-form")).toBeDefined();
}); });


it("Should render sercond step form", () => { it("Should render sercond step form", () => {
const { container } = render(cont); const { container } = render(cont);
const formControls = container.getElementsByClassName( const formControls = container.getElementsByClassName(
"create-ad-form-control-first-step-input"
"create-job-form-control-first-step-input"
); );


fireEvent.change(formControls[0], { target: { value: ".NET DEVELOPER" } }); fireEvent.change(formControls[0], { target: { value: ".NET DEVELOPER" } });
fireEvent.change(formControls[1], { target: { value: "2020-05-24" } }); fireEvent.change(formControls[1], { target: { value: "2020-05-24" } });


fireEvent.click( fireEvent.click(
container.getElementsByClassName("create-ad-buttons-forward")[0]
container.getElementsByClassName("create-job-buttons-forward")[0]
); );


fireEvent.click(container.getElementsByClassName("create-ad-second-step-checkbox")[0])
fireEvent.click(container.getElementsByClassName("create-job-second-step-checkbox")[0])


fireEvent.click( fireEvent.click(
container.getElementsByClassName("create-ad-buttons-forward")[0]
container.getElementsByClassName("create-job-buttons-forward")[0]
); );


expect(screen.getByTestId("create-ad-third-step-form")).toBeDefined(); expect(screen.getByTestId("create-ad-third-step-form")).toBeDefined();

+ 1
- 1
src/__tests__/UITests/patternDetailsPageUI.test.js View File

const { container } = render(cont); const { container } = render(cont);
waitFor(() => { waitFor(() => {
expect( expect(
container.getElementsByClassName("ad-details-buttons-link")[0]
container.getElementsByClassName("job-details-buttons-link")[0]
).toBeDefined(); ).toBeDefined();
}); });
}); });

+ 1
- 1
src/__tests__/UITests/patternsPageUI.test.js View File



it("Should render add pattern button", () => { it("Should render add pattern button", () => {
const { container } = render(cont); const { container } = render(cont);
expect(container.getElementsByClassName("add-ad-btn")[0]).toBeDefined();
expect(container.getElementsByClassName("add-job-btn")[0]).toBeDefined();
}); });


it("Should render add pattern modal", () => { it("Should render add pattern modal", () => {

+ 4
- 4
src/__tests__/UITests/statsAdComponentUI.test.js View File



it("Should render", () => { it("Should render", () => {
const { container } = render(cont); const { container } = render(cont);
expect(container.getElementsByClassName("stats-ad")[0]).toBeDefined();
expect(container.getElementsByClassName("stats-job")[0]).toBeDefined();
}); });


it("Should render title", () => { it("Should render title", () => {
const { container } = render(cont); const { container } = render(cont);
expect( expect(
container.getElementsByClassName("archive-ad-title")[0]
container.getElementsByClassName("archive-job-title")[0]
).toBeDefined(); ).toBeDefined();
}); });


it("Should render date", () => { it("Should render date", () => {
const { container } = render(cont); const { container } = render(cont);
expect( expect(
container.getElementsByClassName("archive-ad-date")[0]
container.getElementsByClassName("archive-job-date")[0]
).toBeDefined(); ).toBeDefined();
}); });


const { container } = render(cont); const { container } = render(cont);
expect( expect(
container container
.getElementsByClassName("archive-ad-experience")[0]
.getElementsByClassName("archive-job-experience")[0]
.getElementsByTagName("p")[0].textContent .getElementsByTagName("p")[0].textContent
).toBe("1+ common.experience"); ).toBe("1+ common.experience");
}); });

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



it("Should render ads because there is more than 0 ads", () => { it("Should render ads because there is more than 0 ads", () => {
const { container } = render(cont); const { container } = render(cont);
expect(container.getElementsByClassName("archived-ads")[0]).toBeDefined();
expect(container.getElementsByClassName("archived-jobs")[0]).toBeDefined();
}); });


it("Should render only one right arrow and that depends on screen size", () => { it("Should render only one right arrow and that depends on screen size", () => {


it("Should render all ads in slider", () => { it("Should render all ads in slider", () => {
const { container } = render(cont); const { container } = render(cont);
expect(container.getElementsByClassName("stats-ad").length).toBe(
expect(container.getElementsByClassName("stats-job").length).toBe(
mockState.stats.ads.length mockState.stats.ads.length
); );
}); });
container container
.getElementsByClassName("slick-list")[0] .getElementsByClassName("slick-list")[0]
.getElementsByClassName("slick-active")[4] .getElementsByClassName("slick-active")[4]
.getElementsByClassName("archive-ad-title")[0].textContent
.getElementsByClassName("archive-job-title")[0].textContent
).toBe("React") ).toBe("React")
); );
}); });

+ 170
- 178
src/assets/styles/components/_ads.scss
File diff suppressed because it is too large
View File


+ 9
- 9
src/assets/styles/components/_candidatePage.scss View File

color: #226cb0; color: #226cb0;
} }


.applicant-ads-container {
.applicant-jobs-container {
margin-top: 36px; margin-top: 36px;
} }


.applicant-ads-container > p {
.applicant-jobs-container > p {
font-family: "Source Sans Pro"; font-family: "Source Sans Pro";
font-weight: 600; font-weight: 600;
font-size: 24px; font-size: 24px;
color: #272727; color: #272727;
} }


.applicant-ads-sub-container {
.applicant-jobs-sub-container {
margin-top: 18px; margin-top: 18px;
display: flex; display: flex;
margin-left: -20px; margin-left: -20px;
text-decoration: none; text-decoration: none;
} }


.applicant-ads-back-button {
.applicant-jobs-back-button {
margin-right: 36px; margin-right: 36px;
font-family: "Source Sans Pro"; font-family: "Source Sans Pro";
font-weight: 400; font-weight: 400;
color: #272727; color: #272727;
} }


.applicant-ads-container-2 {
.applicant-jobs-container-2 {
display: flex; display: flex;
align-items: center; align-items: center;
margin-top: 18px; margin-top: 18px;
justify-content: initial; justify-content: initial;
} }


.applicant-ads-container-2 {
.applicant-jobs-container-2 {
flex-direction: column-reverse; flex-direction: column-reverse;
align-items: flex-start; align-items: flex-start;
} }
padding-left: 0 !important; padding-left: 0 !important;
} }


.applicant-ads-back-button {
.applicant-jobs-back-button {
font-size: 14px; font-size: 14px;
line-height: 18px; line-height: 18px;
margin-right: 0; margin-right: 0;
letter-spacing: 0.04em; letter-spacing: 0.04em;
} }


.active-ads-ads-arrows {
.active-jobs-jobs-arrows {
margin-left: -0.75rem; margin-left: -0.75rem;
} }


.applicant-ads-buttons-container{
.applicant-jobs-buttons-container{
margin-left: 36px; margin-left: 36px;
} }
} }

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

background-color: #226cb0; background-color: #226cb0;
} }


.ads-candidates-container {
.jobs-candidates-container {
max-height: 837px; max-height: 837px;
overflow-y: auto; overflow-y: auto;
overflow-x: hidden; overflow-x: hidden;
} }


.ads-candidates-slider {
.jobs-candidates-slider {
display: flex; display: flex;
margin-top: 31px; margin-top: 31px;
} }


.ads-candidates-slider .slick-track {
.jobs-candidates-slider .slick-track {
margin: 0 !important; margin: 0 !important;
} }


.ads-candidates-slider .slick-slider {
.jobs-candidates-slider .slick-slider {
width: 100% !important; width: 100% !important;
} }


.ads-candidates-top-container {
.jobs-candidates-top-container {
display: flex; display: flex;
align-items: center; align-items: center;
margin-left: 72px; margin-left: 72px;
} }


.ads-candidates-title {
.jobs-candidates-title {
font-family: Source Sans Pro; font-family: Source Sans Pro;
font-size: 24px; font-size: 24px;
font-weight: 600; font-weight: 600;
margin-left: 18px; margin-left: 18px;
} }


.ads-candidates-numberOfApplicants {
.jobs-candidates-numberOfApplicants {
font-family: Source Sans Pro; font-family: Source Sans Pro;
font-size: 16px; font-size: 16px;
font-weight: 600; font-weight: 600;
margin-left: 5px; margin-left: 5px;
} }


.ads-candidates-image {
.jobs-candidates-image {
width: 49px; width: 49px;
height: 39px; height: 39px;
} }
margin-left: 42px; margin-left: 42px;
} }


.ads-search-field-responsive {
.jobs-search-field-responsive {
min-width: 350px; min-width: 350px;
border: 1px solid #226cb0; border: 1px solid #226cb0;
border-radius: 10px; border-radius: 10px;
} }
} }


.ads-search-field-responsive::placeholder {
.jobs-search-field-responsive::placeholder {
font-size: 1rem; font-size: 1rem;
color: #9d9d9d; color: #9d9d9d;
font-style: italic; font-style: italic;
} }


.ads-search-field {
.jobs-search-field {
min-width: 700px !important; min-width: 700px !important;
border: 1px solid #226cb0; border: 1px solid #226cb0;
border-radius: 10px; border-radius: 10px;
z-index: 1000; z-index: 1000;
} }


.ads-search-field::placeholder {
.jobs-search-field::placeholder {
font-size: 1rem; font-size: 1rem;
color: #9d9d9d; color: #9d9d9d;
font-style: italic; font-style: italic;
} }


@media only screen and (max-width: 600px) { @media only screen and (max-width: 600px) {
.ads-candidates-title {
.jobs-candidates-title {
font-size: 18px; font-size: 18px;
margin-left: 10px; margin-left: 10px;
} }
.ads-candidates-image {
.jobs-candidates-image {
width: 40px; width: 40px;
height: 30px; height: 30px;
} }
.ads-candidates-numberOfApplicants {
.jobs-candidates-numberOfApplicants {
font-size: 14px; font-size: 14px;
} }
} }


@media only screen and (max-width: 361px) { @media only screen and (max-width: 361px) {
.ads-candidates-slider {
.jobs-candidates-slider {
flex-direction: column-reverse; flex-direction: column-reverse;
} }


margin-left: 36px; margin-left: 36px;
} }


.ads-candidates-top-container {
.jobs-candidates-top-container {
margin-left: 36px; margin-left: 36px;
} }



+ 2
- 2
src/assets/styles/components/_statistics.scss View File

padding: 20px 36px !important; padding: 20px 36px !important;
} }
} }
.ad-count {
.job-count {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: center; justify-content: center;
order: 0; order: 0;
flex-grow: 0; flex-grow: 0;
} }
.stat-ads {
.stat-jobs {
margin-bottom: 0 !important; margin-bottom: 0 !important;
padding-bottom: 0 !important; padding-bottom: 0 !important;
} }

+ 10
- 10
src/components/Ads/Ad.js View File

const { t } = useTranslation(); const { t } = useTranslation();


return ( return (
<div className={`ad-card ${className}`} onClick={onShowAdDetails}>
<div className="ad-card-date">
<div className={`job-card ${className}`} onClick={onShowAdDetails}>
<div className="job-card-date">
<p> <p>
{new Date(createdAt).toLocaleDateString()} -{" "} {new Date(createdAt).toLocaleDateString()} -{" "}
{new Date(expiredAt).toLocaleDateString()} {new Date(expiredAt).toLocaleDateString()}
</p> </p>
</div> </div>


<div className="ad-card-title">
<div className="job-card-title">
<h3>{title}</h3> <h3>{title}</h3>
</div> </div>


<div className="ad-card-logo">
<div className="job-card-logo">
<img src={selectLogo(title)} alt="logo-react" /> <img src={selectLogo(title)} alt="logo-react" />
</div> </div>


<div className="ad-card-experience">
<div className="job-card-experience">
<p> <p>
{minimumExperience}+ {t("common.experience")} {minimumExperience}+ {t("common.experience")}
</p> </p>
</div> </div>


{!matches && ( {!matches && (
<div className="ad-card-buttons">
<div className="job-card-buttons">
<button>LinkedIn</button> <button>LinkedIn</button>
<button>Facebook</button> <button>Facebook</button>
<button disabled>Instagram</button> <button disabled>Instagram</button>
</div> </div>
)} )}
{matches && ( {matches && (
<div className="ad-card-buttons">
<button className="ad-card-buttons-button">
<div className="job-card-buttons">
<button className="job-card-buttons-button">
<img src={linkedin} /> <img src={linkedin} />
</button> </button>
<button className="ad-card-buttons-button">
<button className="job-card-buttons-button">
<img src={facebook} /> <img src={facebook} />
</button> </button>
<button disabled className="ad-card-buttons-button">
<button disabled className="job-card-buttons-button">
<img src={instagram} /> <img src={instagram} />
</button> </button>
</div> </div>

+ 8
- 8
src/components/Ads/AdDetailsCandidateCard.js View File

const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<div <div
data-testid="ad-details-candidate"
className={`ad-details-candidate ${className}`}
data-testid="job-details-candidate"
className={`job-details-candidate ${className}`}
> >
<div className="ad-details-candidate-date">
<div className="job-details-candidate-date">
<p>{new Date().toLocaleDateString()}</p> <p>{new Date().toLocaleDateString()}</p>
</div> </div>
<div className="ad-details-candidate-title">
<div className="job-details-candidate-title">
<h3 <h3
data-testid="ad-details-candidate-title-link"
data-testid="job-details-candidate-title-link"
onClick={() => onClick={() =>
history.push(CANDIDATES_DETAILS_PAGE.replace(":id", id)) history.push(CANDIDATES_DETAILS_PAGE.replace(":id", id))
} }
{firstName} {lastName} {firstName} {lastName}
</h3> </h3>
</div> </div>
<div className="ad-details-candidate-experience">
<div className="job-details-candidate-experience">
{experience > 0 ? ( {experience > 0 ? (
<p> <p>
{experience}+ {t("common.experience")} {experience}+ {t("common.experience")}
<p>{t("common.noExperience")}</p> <p>{t("common.noExperience")}</p>
)} )}
</div> </div>
<div className="ad-details-candidate-buttons">
<div className="job-details-candidate-buttons">
<button>React</button> <button>React</button>
<button>.NET</button> <button>.NET</button>
<button>Angular</button> <button>Angular</button>
</div> </div>
<div className="ad-details-candidate-cv">
<div className="job-details-candidate-cv">
<a href="#">{cv}</a> <a href="#">{cv}</a>
</div> </div>
</div> </div>

+ 18
- 18
src/components/Ads/AdFilters.js View File

onKeyDown={handleClose} onKeyDown={handleClose}
> >
<div data-testid="ad-filters-drawer"> <div data-testid="ad-filters-drawer">
<div className="ad-filters-header-container">
<div className="ad-filters-header">
<div className="job-filters-header-container">
<div className="job-filters-header">
<img src={filterIcon} alt="filter_icon" /> <img src={filterIcon} alt="filter_icon" />
<h3>{t("filters.filters")}</h3> <h3>{t("filters.filters")}</h3>
<p> <p>
<sub>| {t("ads.ads")}</sub> <sub>| {t("ads.ads")}</sub>
</p> </p>
</div> </div>
<div className="ad-filters-header-close" onClick={handleClose}>
<div className="job-filters-header-close" onClick={handleClose}>
<img src={x} alt="x" /> <img src={x} alt="x" />
</div> </div>
</div> </div>
<div className="ad-filters-experience">
<div className="ad-filters-sub-title">
<div className="job-filters-experience">
<div className="job-filters-sub-title">
<p>{t("filters.experience")}</p> <p>{t("filters.experience")}</p>
</div> </div>
<div className="ad-filters-experience-slider">
<div className="job-filters-experience-slider">
<Slider <Slider
getAriaLabel={() => "Temperature range"} getAriaLabel={() => "Temperature range"}
value={sliderValue} value={sliderValue}
/> />
</div> </div>
</div> </div>
<div className="ad-filters-technologies">
<div className="ad-filters-sub-title">
<div className="job-filters-technologies">
<div className="job-filters-sub-title">
<p>{t("filters.tecnologies")}</p> <p>{t("filters.tecnologies")}</p>
</div> </div>
<div className="ad-filters-technologies-checkboxes">
<div className="job-filters-technologies-checkboxes">
<FormGroup> <FormGroup>
{technologies?.map((technology, index) => ( {technologies?.map((technology, index) => (
<FormControlLabel <FormControlLabel
onChange={handleCheckboxes} onChange={handleCheckboxes}
value={technology.name} value={technology.name}
checked={technology.isChecked} checked={technology.isChecked}
className="ad-filters-checkbox"
className="job-filters-checkbox"
/> />
} }
label={technology.name} label={technology.name}
</FormGroup> </FormGroup>
</div> </div>
</div> </div>
<div className="ad-filters-technologies">
<div className="ad-filters-sub-title">
<div className="job-filters-technologies">
<div className="job-filters-sub-title">
<p>{t("filters.employmentType")}</p> <p>{t("filters.employmentType")}</p>
</div> </div>
<div className="ad-filters-employment-type">
<div className="job-filters-employment-type">
<button <button
className={`c-btn ${ className={`c-btn ${
employmentType === "Intership" employmentType === "Intership"
</button> </button>
</div> </div>
</div> </div>
<div className="ad-filters-technologies">
<div className="ad-filters-sub-title">
<div className="job-filters-technologies">
<div className="job-filters-sub-title">
<p>{t("filters.workHour")}</p> <p>{t("filters.workHour")}</p>
</div> </div>
<div className="ad-filters-employment-type">
<div className="job-filters-employment-type">
<button <button
className={`c-btn ${ className={`c-btn ${
workHour === "PartTime" workHour === "PartTime"
</button> </button>
</div> </div>
</div> </div>
<div className="ad-filters-search">
<div className="job-filters-search">
<button <button
onClick={onSubmitFilters} onClick={onSubmitFilters}
className="c-btn c-btn--primary" className="c-btn c-btn--primary"
data-testid="ad-filters-submit"
data-testid="job-filters-submit"
> >
{t("filters.search")} {t("filters.search")}
</button> </button>

+ 7
- 7
src/components/Ads/ApplyForAd.js View File

}; };


return ( return (
<CustomModal open={open} onCloseModal={onCloseModal} classes="apply-for-ad">
<div className="apply-for-ad-header">
<div className="apply-for-ad-header-left">
<div className="apply-for-ad-header-left-image">
<CustomModal open={open} onCloseModal={onCloseModal} classes="apply-for-job">
<div className="apply-for-job-header">
<div className="apply-for-job-header-left">
<div className="apply-for-job-header-left-image">
<img src={briefcaseIcon} alt="plus" /> <img src={briefcaseIcon} alt="plus" />
</div> </div>
<div className="apply-for-ad-header-left-image-title">
<div className="apply-for-job-header-left-image-title">
<p>{t("ads.signUp")}</p> <p>{t("ads.signUp")}</p>
</div> </div>
<div className="apply-for-ad-header-left-image-title-sub">
<div className="apply-for-job-header-left-image-title-sub">
<sub> | {title}</sub> <sub> | {title}</sub>
</div> </div>
</div> </div>
<div className="apply-for-ad-header-right">
<div className="apply-for-job-header-right">
<button onClick={onCloseModal}> <button onClick={onCloseModal}>
<img src={xIcon} alt="x" /> <img src={xIcon} alt="x" />
</button> </button>

+ 13
- 13
src/components/Ads/ApplyForAdFirstStage.js View File



return ( return (
<div> <div>
<div className="apply-for-ad-modal-form-control">
<div className="apply-for-job-modal-form-control">
<label>{t("common.name")}</label> <label>{t("common.name")}</label>
<input <input
type="text" type="text"
placeholder="ex. Petar" placeholder="ex. Petar"
value={firstName} value={firstName}
data-testid="apply-for-ad-modal-first-name-input"
data-testid="apply-for-job-modal-first-name-input"
onChange={(e) => setFirstName(e.target.value)} onChange={(e) => setFirstName(e.target.value)}
/> />
</div> </div>
<div className="apply-for-ad-modal-form-control">
<div className="apply-for-job-modal-form-control">
<label>{t("common.lastName")}</label> <label>{t("common.lastName")}</label>
<input <input
type="text" type="text"
placeholder="ex. Petrovic" placeholder="ex. Petrovic"
value={lastName} value={lastName}
data-testid="apply-for-ad-modal-last-name-input"
data-testid="apply-for-job-modal-last-name-input"
onChange={(e) => setLastName(e.target.value)} onChange={(e) => setLastName(e.target.value)}
/> />
</div> </div>
<div className="apply-for-ad-modal-form-control">
<div className="apply-for-job-modal-form-control">
<label>{t("common.gender")}</label> <label>{t("common.gender")}</label>
<div style={{ display: "flex" }}> <div style={{ display: "flex" }}>
<div style={{ display: "flex" }}> <div style={{ display: "flex" }}>
type="radio" type="radio"
name="gender" name="gender"
value="Muski" value="Muski"
className="apply-for-ad-modal-gender-input"
className="apply-for-job-modal-gender-input"
checked={gender === "Muski"} checked={gender === "Muski"}
onChange={(e) => setGender(e.target.value)} onChange={(e) => setGender(e.target.value)}
/> />
type="radio" type="radio"
name="gender" name="gender"
value="Zenski" value="Zenski"
className="apply-for-ad-modal-gender-input"
className="apply-for-job-modal-gender-input"
checked={gender === "Zenski"} checked={gender === "Zenski"}
onChange={(e) => setGender(e.target.value)} onChange={(e) => setGender(e.target.value)}
/> />
</div> </div>
</div> </div>
</div> </div>
<div className="apply-for-ad-modal-form-control">
<div className="apply-for-job-modal-form-control">
<label>{t("common.dateOfBirth")}</label> <label>{t("common.dateOfBirth")}</label>
<input <input
type="date" type="date"
placeholder="ex. Datum rodjenja" placeholder="ex. Datum rodjenja"
data-testid="apply-for-ad-modal-date-of-birth"
data-testid="apply-for-job-modal-date-of-birth"
value={dateOfBirth} value={dateOfBirth}
onChange={(e) => setDateOfBirth(e.target.value)} onChange={(e) => setDateOfBirth(e.target.value)}
/> />
</div> </div>
<div className="apply-for-ad-modal-form-control">
<div className="apply-for-job-modal-form-control">
<label>{t("common.phoneNumber")}</label> <label>{t("common.phoneNumber")}</label>
<input <input
type="text" type="text"
placeholder="ex. +381/60/000/0000" placeholder="ex. +381/60/000/0000"
data-testid="apply-for-ad-modal-phone-number"
data-testid="apply-for-job-modal-phone-number"
value={phoneNumber} value={phoneNumber}
onChange={(e) => setPhoneNumber(e.target.value)} onChange={(e) => setPhoneNumber(e.target.value)}
/> />
</div> </div>
<div className="apply-for-ad-buttons">
<div className="apply-for-job-buttons">
<button disabled>{t("common.back")}</button> <button disabled>{t("common.back")}</button>
<button <button
disabled={disabled} disabled={disabled}
data-testid="apply-for-ad-modal-go-forward-button"
data-testid="apply-for-job-modal-go-forward-button"
onClick={() => onIncreaseStage()} onClick={() => onIncreaseStage()}
> >
{t("common.continue")} {t("common.continue")}

+ 8
- 8
src/components/Ads/ApplyForAdFourthStage.js View File

}; };


return ( return (
<div data-testid="apply-for-ad-modal-fourth-stage">
<div className="apply-for-ad-modal-form-control">
<div data-testid="apply-for-job-modal-fourth-stage">
<div className="apply-for-job-modal-form-control">
<label>CV</label> <label>CV</label>
<div <div
className="uploadCV-input" className="uploadCV-input"
id="upload-file" id="upload-file"
style={{ display: "none", zIndex: -1 }} style={{ display: "none", zIndex: -1 }}
value={pdfFile} value={pdfFile}
data-testid="apply-for-ad-modal-fourth-stage-pdf-input"
data-testid="apply-for-job-modal-fourth-stage-pdf-input"
onChange={(e) => { onChange={(e) => {
console.log("Ovde smo"); console.log("Ovde smo");
setPdfFile(e.target.files[0]); setPdfFile(e.target.files[0]);
</div> </div>
</div> </div>
</div> </div>
<div className="apply-for-ad-modal-form-control">
<div className="apply-for-job-modal-form-control">
<label>{t("ads.coverLetter")}</label> <label>{t("ads.coverLetter")}</label>
<textarea <textarea
value={coverLetter} value={coverLetter}
onChange={(e) => setCoverLetter(e.target.value)} onChange={(e) => setCoverLetter(e.target.value)}
data-testid="apply-for-ad-modal-fourth-stage-cover-letter-input"
data-testid="apply-for-job-modal-fourth-stage-cover-letter-input"
placeholder="ex. Kao student Elektronskog fakulteta u Nišu..." placeholder="ex. Kao student Elektronskog fakulteta u Nišu..."
rows={5} rows={5}
></textarea> ></textarea>
</div> </div>
<div className="apply-for-ad-buttons">
<div className="apply-for-job-buttons">
<button <button
onClick={onDecreaseStage} onClick={onDecreaseStage}
data-testid="apply-for-ad-modal-fourth-stage-go-back-button"
data-testid="apply-for-job-modal-fourth-stage-go-back-button"
> >
{t("common.back")} {t("common.back")}
</button> </button>
<button <button
disabled={disabled} disabled={disabled}
data-testid="apply-for-ad-modal-fourth-stage-go-forward-button"
data-testid="apply-for-job-modal-fourth-stage-go-forward-button"
onClick={onFinishedFourStages} onClick={onFinishedFourStages}
> >
{t("ads.signUp")} {t("ads.signUp")}

+ 16
- 16
src/components/Ads/ApplyForAdSecondStage.js View File

}; };


return ( return (
<div data-testid="apply-for-ad-second-stage">
<div className="apply-for-ad-header-title">
<div data-testid="apply-for-job-second-stage">
<div className="apply-for-job-header-title">
<p>{t("ads.professionalQualification")}</p> <p>{t("ads.professionalQualification")}</p>
</div> </div>
<div className="apply-for-ad-modal-form-control">
<div className="apply-for-job-modal-form-control">
<input <input
type="text" type="text"
placeholder="ex. Elektrotehnicki fakultet" placeholder="ex. Elektrotehnicki fakultet"
onChange={(e) => setProfessionalQualification(e.target.value)} onChange={(e) => setProfessionalQualification(e.target.value)}
/> />
</div> </div>
<div className="apply-for-ad-header-title">
<div className="apply-for-job-header-title">
<p>{t("ads.technologies")}</p> <p>{t("ads.technologies")}</p>
</div> </div>
<div className="apply-for-ad-header-sub">
<div className="apply-for-ad-header-sub-group">
<div className="apply-for-job-header-sub">
<div className="apply-for-job-header-sub-group">
<label>Back-End</label> <label>Back-End</label>
<div className="apply-for-ad-header-sub-group-checkboxes">
<div className="apply-for-job-header-sub-group-checkboxes">
{technologies {technologies
.filter((x) => x.technologyType === "Backend") .filter((x) => x.technologyType === "Backend")
.map((x) => ( .map((x) => (
key={x.technologyId} key={x.technologyId}
control={ control={
<Checkbox <Checkbox
className="apply-for-ad-second-stage-checkbox"
className="apply-for-job-second-stage-checkbox"
value={x.name} value={x.name}
checked={x.isChecked} checked={x.isChecked}
onChange={handleCheckboxes.bind(this, x.technologyId)} onChange={handleCheckboxes.bind(this, x.technologyId)}
))} ))}
</div> </div>
</div> </div>
<div className="apply-for-ad-header-sub-group">
<div className="apply-for-job-header-sub-group">
<label>Front-End</label> <label>Front-End</label>
<div className="apply-for-ad-header-sub-group-checkboxes">
<div className="apply-for-job-header-sub-group-checkboxes">
{technologies {technologies
.filter((x) => x.technologyType === "Frontend") .filter((x) => x.technologyType === "Frontend")
.map((x) => ( .map((x) => (
key={x.technologyId} key={x.technologyId}
control={ control={
<Checkbox <Checkbox
className="apply-for-ad-second-stage-checkbox"
className="apply-for-job-second-stage-checkbox"
value={x.name} value={x.name}
checked={x.isChecked} checked={x.isChecked}
onChange={handleCheckboxes.bind(this, x.technologyId)} onChange={handleCheckboxes.bind(this, x.technologyId)}
))} ))}
</div> </div>
</div> </div>
<div className="apply-for-ad-header-sub-group">
<div className="apply-for-job-header-sub-group">
<label>{t("ads.others")}</label> <label>{t("ads.others")}</label>
<div className="apply-for-ad-header-sub-group-checkboxes">
<div className="apply-for-job-header-sub-group-checkboxes">
{technologies {technologies
.filter((x) => x.technologyType === "Other") .filter((x) => x.technologyType === "Other")
.map((x) => ( .map((x) => (
key={x.technologyId} key={x.technologyId}
control={ control={
<Checkbox <Checkbox
className="apply-for-ad-second-stage-checkbox"
className="apply-for-job-second-stage-checkbox"
value={x.name} value={x.name}
checked={x.isChecked} checked={x.isChecked}
onChange={handleCheckboxes.bind(this, x.technologyId)} onChange={handleCheckboxes.bind(this, x.technologyId)}
</div> </div>
</div> </div>
</div> </div>
<div className="apply-for-ad-modal-form-control">
<div className="apply-for-job-modal-form-control">
<label>{t("filters.experience")}</label> <label>{t("filters.experience")}</label>
<input <input
type="number" type="number"
onChange={(e) => setExperience(e.target.value)} onChange={(e) => setExperience(e.target.value)}
/> />
</div> </div>
<div className="apply-for-ad-buttons">
<div className="apply-for-job-buttons">
<button onClick={onDecreaseStage}>{t("common.back")}</button> <button onClick={onDecreaseStage}>{t("common.back")}</button>
<button onClick={onIncreaseStage} disabled={disabled}> <button onClick={onIncreaseStage} disabled={disabled}>
{t("common.continue")} {t("common.continue")}

+ 6
- 6
src/components/Ads/ApplyForAdThirdStage.js View File



return ( return (
<div> <div>
<div className="apply-for-ad-header-title">
<div className="apply-for-job-header-title">
<p>{t("common.socialNetwork")}</p> <p>{t("common.socialNetwork")}</p>
</div> </div>
<div className="apply-for-ad-modal-form-control">
<div className="apply-for-job-modal-form-control">
<label>LinkedIn</label> <label>LinkedIn</label>
<input <input
type="text" type="text"
placeholder="ex. https://www.linkedin.com/in/petar-petrovic" placeholder="ex. https://www.linkedin.com/in/petar-petrovic"
/> />
</div> </div>
<div className="apply-for-ad-modal-form-control">
<div className="apply-for-job-modal-form-control">
<label>GitHub</label> <label>GitHub</label>
<input <input
type="text" type="text"
placeholder="ex. https://www.github.com/petarpetrovic" placeholder="ex. https://www.github.com/petarpetrovic"
/> />
</div> </div>
<div className="apply-for-ad-modal-form-control">
<div className="apply-for-job-modal-form-control">
<label>BitBucket</label> <label>BitBucket</label>
<input <input
type="text" type="text"
placeholder="ex. https://developer.atlassian.com/user/petarapetrovic" placeholder="ex. https://developer.atlassian.com/user/petarapetrovic"
/> />
</div> </div>
<div className="apply-for-ad-modal-form-control">
<div className="apply-for-job-modal-form-control">
<label>Email</label> <label>Email</label>
<input <input
type="email" type="email"
placeholder="ex. petar.petrovic@dilig.net" placeholder="ex. petar.petrovic@dilig.net"
/> />
</div> </div>
<div className="apply-for-ad-buttons">
<div className="apply-for-job-buttons">
<button <button
onClick={onDecreaseStage} onClick={onDecreaseStage}
data-testid="apply-for-ad-modal-third-stage-go-back-button" data-testid="apply-for-ad-modal-third-stage-go-back-button"

src/components/Ads/ArchiveAd.js → src/components/Ads/ArchiveJob.js View File

import { selectLogo } from "../../util/helpers/technologiesLogos"; import { selectLogo } from "../../util/helpers/technologiesLogos";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";


const ArchiveAd = ({
const ArchiveJob = ({
className, className,
title, title,
minimumExperience, minimumExperience,
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<div className={`archive-ad ${className}`} onClick={onShowAdDetails}>
<div className="archive-ad-date">
<div className={`archive-job ${className}`} onClick={onShowAdDetails}>
<div className="archive-job-date">
<p> <p>
{new Date(createdAt).toLocaleDateString()} -{" "} {new Date(createdAt).toLocaleDateString()} -{" "}
{new Date(expiredAt).toLocaleDateString()} {new Date(expiredAt).toLocaleDateString()}
</p> </p>
</div> </div>
<div className="archive-ad-title">
<div className="archive-job-title">
<h3>{title}</h3> <h3>{title}</h3>
</div> </div>
<div className="archive-ad-image">
<div className="archive-job-image">
<img src={selectLogo(title)} alt=".net icon" /> <img src={selectLogo(title)} alt=".net icon" />
</div> </div>
<div className="archive-ad-experience">
<div className="archive-job-experience">
{minimumExperience > 0 ? ( {minimumExperience > 0 ? (
<p> <p>
{minimumExperience}+ {t("common.experience")} {minimumExperience}+ {t("common.experience")}
); );
}; };


ArchiveAd.propTypes = {
ArchiveJob.propTypes = {
id: PropTypes.number, id: PropTypes.number,
title: PropTypes.string, title: PropTypes.string,
minimumExperience: PropTypes.number, minimumExperience: PropTypes.number,
className: PropTypes.any, className: PropTypes.any,
}; };


export default ArchiveAd;
export default ArchiveJob;

+ 6
- 6
src/components/Ads/StatsAd.js View File

}) => { }) => {
const {t} = useTranslation() const {t} = useTranslation()
return ( return (
<div className={`archive-ad stats-ad ${className}`} onClick={onShowAdDetails}>
<div className="ad-count">
<div className={`archive-job stats-job ${className}`} onClick={onShowAdDetails}>
<div className="job-count">
{count} {t("ads.registered")} {count} {t("ads.registered")}
</div> </div>
<div className="archive-ad-date">
<div className="archive-job-date">
<p> <p>
{new Date(createdAt).toLocaleDateString()} -{" "} {new Date(createdAt).toLocaleDateString()} -{" "}
{new Date(expiredAt).toLocaleDateString()} {new Date(expiredAt).toLocaleDateString()}
</p> </p>
</div> </div>
<div className="archive-ad-title">
<div className="archive-job-title">
<h3>{title}</h3> <h3>{title}</h3>
</div> </div>
<div className="archive-ad-image">
<div className="archive-job-image">
<img src={selectLogo(title)} alt=".net icon" /> <img src={selectLogo(title)} alt=".net icon" />
</div> </div>
<div className="archive-ad-experience">
<div className="archive-job-experience">
{minimumExperience > 0 ? ( {minimumExperience > 0 ? (
<p>{minimumExperience}+ {t("common.experience")}</p> <p>{minimumExperience}+ {t("common.experience")}</p>
) : ( ) : (

+ 1
- 1
src/components/Button/FilterButton.js View File

return ( return (
<IconButton <IconButton
className={ className={
"c-btn--primary-outlined ads-page-btn fltr-btn c-btn userPageBtn ml-20px no-padding custom-filter-button"
"c-btn--primary-outlined jobs-page-btn fltr-btn c-btn userPageBtn ml-20px no-padding custom-filter-button"
} }
onClick={onShowFilters} onClick={onShowFilters}
> >

+ 16
- 16
src/components/Candidates/CandidateFilters.js View File

onKeyDown={handleClose} onKeyDown={handleClose}
> >
<div> <div>
<div className="ad-filters-header-container">
<div className="ad-filters-header">
<div className="job-filters-header-container">
<div className="job-filters-header">
<img src={filterIcon} alt="filter_icon" /> <img src={filterIcon} alt="filter_icon" />
<h3>{t("filters.filters")}</h3> <h3>{t("filters.filters")}</h3>
<p> <p>
<sub>| {t("candidates.candidates")}</sub> <sub>| {t("candidates.candidates")}</sub>
</p> </p>
</div> </div>
<div className="ad-filters-header-close" onClick={handleClose}>
<div className="job-filters-header-close" onClick={handleClose}>
<img src={x} alt="x" /> <img src={x} alt="x" />
</div> </div>
</div> </div>
<div className="ad-filters-experience">
<div className="ad-filters-sub-title">
<div className="job-filters-experience">
<div className="job-filters-sub-title">
<p>{t("filters.experience")}</p> <p>{t("filters.experience")}</p>
</div> </div>
<div className="ad-filters-experience-slider">
<div className="job-filters-experience-slider">
<Slider <Slider
getAriaLabel={() => "Temperature range"} getAriaLabel={() => "Temperature range"}
value={sliderValue} value={sliderValue}
/> />
</div> </div>
</div> </div>
<div className="ad-filters-technologies">
<div className="ad-filters-sub-title">
<div className="job-filters-technologies">
<div className="job-filters-sub-title">
<p>{t("filters.technologies")}</p> <p>{t("filters.technologies")}</p>
</div> </div>
<div className="ad-filters-technologies-checkboxes">
<div className="job-filters-technologies-checkboxes">
<FormGroup> <FormGroup>
{technologies.map((technology, index) => ( {technologies.map((technology, index) => (
<FormControlLabel <FormControlLabel
<Checkbox <Checkbox
checked={technology.isChecked} checked={technology.isChecked}
name={technology.name} name={technology.name}
className="ad-filters-technologies-checkboxes-checkbox"
className="job-filters-technologies-checkboxes-checkbox"
onChange={handleTechologiesChange} onChange={handleTechologiesChange}
/> />
} }
</FormGroup> </FormGroup>
</div> </div>
</div> </div>
<div className="ad-filters-technologies">
<div className="ad-filters-sub-title">
<div className="job-filters-technologies">
<div className="job-filters-sub-title">
<p>{t("filters.employmentType")}</p> <p>{t("filters.employmentType")}</p>
</div> </div>
<div className="ad-filters-employment-type">
<div className="job-filters-employment-type">
{typesOfEmployments.map((type, index) => ( {typesOfEmployments.map((type, index) => (
<button <button
key={index} key={index}
))} ))}
</div> </div>
</div> </div>
<div className="ad-filters-technologies" style={{ marginTop: "35px" }}>
<div className="ad-filters-sub-title">
<div className="job-filters-technologies" style={{ marginTop: "35px" }}>
<div className="job-filters-sub-title">
<p>{t("filters.dateOfApplication")}</p> <p>{t("filters.dateOfApplication")}</p>
<div className="filter-date-container"> <div className="filter-date-container">
<p>{t("common.from")}</p> <p>{t("common.from")}</p>
</div> </div>
</div> </div>
</div> </div>
<div className="ad-filters-search" style={{ marginTop: "45px" }}>
<div className="job-filters-search" style={{ marginTop: "45px" }}>
<button <button
className="c-btn c-btn--primary" className="c-btn c-btn--primary"
onClick={fiterItems} onClick={fiterItems}

+ 1
- 1
src/components/MUI/NavbarComponent.js View File



const NavbarComponent = () => { const NavbarComponent = () => {
const navItems = [ const navItems = [
"ads",
"jobs",
"selectionFlow", "selectionFlow",
"candidates", "candidates",
"schedule", "schedule",

+ 3
- 3
src/components/Selection/ApplicantSelection.js View File

<p>{date && date !== "" && formatDate(new Date(date))}</p> <p>{date && date !== "" && formatDate(new Date(date))}</p>
</div> </div>


<div className="ad-card-title">
<div className="job-card-title">
<h3>{levelName}</h3> <h3>{levelName}</h3>
</div> </div>




<div className="active-process-card-link"> <div className="active-process-card-link">
{status === "Odrađen" && ( {status === "Odrađen" && (
<Link className="ad-details-buttons-link" to={"/candidates/" + id}>
<Link className="job-details-buttons-link" to={"/candidates/" + id}>
{t("selection.report")} {t("selection.report")}
</Link> </Link>
)} )}
{link && status !== "Odrađen" && ( {link && status !== "Odrađen" && (
<a href={link} className="ad-details-buttons-link">
<a href={link} className="job-details-buttons-link">
{t("selection.link")} {t("selection.link")}
</a> </a>
)} )}

+ 12
- 12
src/components/Selection/SelectionFilter.js View File

onKeyDown={handleClose} onKeyDown={handleClose}
> >
<div> <div>
<div className="ad-filters-header-container">
<div className="ad-filters-header">
<div className="job-filters-header-container">
<div className="job-filters-header">
<img src={filterIcon} alt="filter_icon" /> <img src={filterIcon} alt="filter_icon" />
<h3>{t("filters.filters")}</h3> <h3>{t("filters.filters")}</h3>
<p> <p>
<sub>| {t("selection.title")}</sub> <sub>| {t("selection.title")}</sub>
</p> </p>
</div> </div>
<div className="ad-filters-header-close" onClick={handleClose}>
<div className="job-filters-header-close" onClick={handleClose}>
<img src={x} alt="x" /> <img src={x} alt="x" />
</div> </div>
</div> </div>
<div className="ad-filters-technologies">
<div className="ad-filters-sub-title">
<div className="job-filters-technologies">
<div className="job-filters-sub-title">
<p>Status</p> <p>Status</p>
</div> </div>
<div className="ad-filters-technologies-checkboxes">
<div className="job-filters-technologies-checkboxes">
<FormGroup> <FormGroup>
{statuses?.map((technology, index) => ( {statuses?.map((technology, index) => (
<FormControlLabel <FormControlLabel
</FormGroup> </FormGroup>
</div> </div>
</div> </div>
<div className="ad-filters-technologies">
{/* <div className="ad-filters-sub-title">
<div className="job-filters-technologies">
{/* <div className="job-filters-sub-title">
<p>Datum isteka oglasa</p> <p>Datum isteka oglasa</p>
</div> </div>
<input <input
value={expiredAt} value={expiredAt}
onChange={(e) => setExpiredAt(e.target.value)} onChange={(e) => setExpiredAt(e.target.value)}
/> */} /> */}
<div className="ad-filters-sub-title">
<div className="job-filters-sub-title">
<p>{t("selection.filterDate")}</p> <p>{t("selection.filterDate")}</p>
</div> </div>
<div className="add-ad-modal-stage-sub-card">
<div className="add-job-modal-stage-sub-card">
<label>{t("common.from")}</label> <label>{t("common.from")}</label>
<input <input
type="date" type="date"
onChange={(e) => setStartAt(e.target.value)} onChange={(e) => setStartAt(e.target.value)}
/> />
</div> </div>
<div className="add-ad-modal-stage-sub-card">
<div className="add-job-modal-stage-sub-card">
<label>{t("common.to")}</label> <label>{t("common.to")}</label>
<input <input
type="date" type="date"
/> />
</div> </div>
</div> </div>
<div className="ad-filters-search">
<div className="job-filters-search">
<button onClick={onSubmitFilters} className="c-btn c-btn--primary"> <button onClick={onSubmitFilters} className="c-btn c-btn--primary">
{t("common.search")} {t("common.search")}
</button> </button>

+ 3
- 3
src/constants/pages.js View File

export const BASE_PAGE = '/'; export const BASE_PAGE = '/';
export const FORGOT_PASSWORD_PAGE = '/forgot-password'; export const FORGOT_PASSWORD_PAGE = '/forgot-password';
export const HOME_PAGE = '/home'; export const HOME_PAGE = '/home';
export const ADS_PAGE = '/ads';
export const AD_DETAILS_PAGE = '/ads/:id';
export const ADS_PAGE = '/jobs';
export const JOB_DETAILS_PAGE = '/jobs/:id';
export const ERROR_PAGE = '/error-page'; export const ERROR_PAGE = '/error-page';
export const NOT_FOUND_PAGE = '/not-found'; export const NOT_FOUND_PAGE = '/not-found';
export const USERS_PAGE = '/users'; export const USERS_PAGE = '/users';
export const SCHEDULE_PAGE = '/schedule' export const SCHEDULE_PAGE = '/schedule'
export const STATS_PAGE = '/statistics'; export const STATS_PAGE = '/statistics';
export const REGISTER_PAGE = '/register'; export const REGISTER_PAGE = '/register';
export const CREATE_AD_PAGE = '/create-ad';
export const CREATE_AD_PAGE = '/create-job';

+ 1
- 1
src/i18n/resources/en.js View File

}, },
nav: { nav: {
navigation: "Navigation", navigation: "Navigation",
ads: "Ads",
jobs: "Ads",
selectionFlow: "Selection flow", selectionFlow: "Selection flow",
candidates: "Candidates", candidates: "Candidates",
planer: "Planer", planer: "Planer",

+ 30
- 30
src/pages/AdsPage/AdDetailsPage.js View File

<> <>
{!ad && <p>Radi</p>} {!ad && <p>Radi</p>}
{ad && ( {ad && (
<div data-testid="ad-details-page">
<div data-testid="job-details-page">
<ApplyForAd <ApplyForAd
open={applyForAdOpenModal} open={applyForAdOpenModal}
title={ad.title} title={ad.title}
adId={id} adId={id}
onCloseModal={handleCloseApplyForAdModal} onCloseModal={handleCloseApplyForAdModal}
/> />
<div className="ad-details">
<div className="job-details">
{matches && ( {matches && (
<div className="ad-details-tech-logo-date">
<div className="job-details-tech-logo-date">
<p> <p>
<span>{t("ads.adDetailsExpiredAt")}: </span> <span>{t("ads.adDetailsExpiredAt")}: </span>
{new Date(ad.expiredAt).toLocaleDateString()} {new Date(ad.expiredAt).toLocaleDateString()}
</p> </p>
</div> </div>
)} )}
<div className="ad-details-tech-logo">
<div className="ad-details-tech-logo-title">
<div className="ad-details-tech-logo-title-img">
<div className="job-details-tech-logo">
<div className="job-details-tech-logo-title">
<div className="job-details-tech-logo-title-img">
<img src={selectLogo(ad.title)} alt="asp-net-icon" /> <img src={selectLogo(ad.title)} alt="asp-net-icon" />
</div> </div>
<div className="ad-details-tech-logo-title-title">
<div className="job-details-tech-logo-title-title">
<h1>{ad.title}</h1> <h1>{ad.title}</h1>
</div> </div>
<div className="ad-details-tech-logo-title-sub">
<div className="job-details-tech-logo-title-sub">
<sub> <sub>
| {ad.totalApplicants} {t("ads.registered")} | {ad.totalApplicants} {t("ads.registered")}
</sub> </sub>
{!(new Date(ad.expiredAt) < new Date()) && ( {!(new Date(ad.expiredAt) < new Date()) && (
<IconButton <IconButton
onClick={() => setShowArchiveAdDialog(true)} onClick={() => setShowArchiveAdDialog(true)}
className={`c-btn--primary-outlined editEnableBtn c-btn userPageBtn archive-ad-button
className={`c-btn--primary-outlined editEnableBtn c-btn userPageBtn archive-job-button
}`} }`}
> >
{!matches && "Arhiviraj"} {!matches && "Arhiviraj"}
}} }}
onConfirm={() => archiveAdHandler()} onConfirm={() => archiveAdHandler()}
/> />
<div className="ad-details-content">
<div className="ad-details-content-experience">
<div className="job-details-content">
<div className="job-details-content-experience">
<p> <p>
{ad.minimumExperience}+ {t("ads.adDetailsExperience")} {ad.minimumExperience}+ {t("ads.adDetailsExperience")}
</p> </p>
</div> </div>
<div className="ad-details-content-work-time">
<div className="job-details-content-work-time">
<button>{t("filters.work")}</button> <button>{t("filters.work")}</button>
<button>{t("filters.fullTime")}</button> <button>{t("filters.fullTime")}</button>
</div> </div>
<div className="ad-details-content-content">
<div className="ad-details-content-conten-description">
<div className="job-details-content-content">
<div className="job-details-content-conten-description">
<p>{t("ads.adDetailsDescription")}</p> <p>{t("ads.adDetailsDescription")}</p>
</div> </div>
<div className="ad-details-content-conten-description">
<div className="job-details-content-conten-description">
<h3>{t("ads.adDetailsKeyResponsibilities")}</h3> <h3>{t("ads.adDetailsKeyResponsibilities")}</h3>
{parse(ad.keyResponsibilities)} {parse(ad.keyResponsibilities)}
</div> </div>
<div className="ad-details-content-conten-description">
<div className="job-details-content-conten-description">
<h3>{t("ads.adDetailsRequirements")}</h3> <h3>{t("ads.adDetailsRequirements")}</h3>
{parse(ad.requirements)} {parse(ad.requirements)}
</div> </div>
<div className="ad-details-content-conten-description">
<div className="job-details-content-conten-description">
<h3>{t("ads.adDetailsOffer")}</h3> <h3>{t("ads.adDetailsOffer")}</h3>
{parse(ad.offer)} {parse(ad.offer)}
</div> </div>
</div> </div>
</div> </div>
{ad.applicants && ad.applicants.length > 0 && ( {ad.applicants && ad.applicants.length > 0 && (
<div className="ad-details-applicants">
<div className="ad-details-applicants-header">
<div className="job-details-applicants">
<div className="job-details-applicants-header">
<h2>{t("ads.archiveAdsCandidates")}</h2> <h2>{t("ads.archiveAdsCandidates")}</h2>
</div> </div>
<div className="ad-details-applicants-applicants">
<div className="job-details-applicants-applicants">
{!matches && ( {!matches && (
<div className="ad-details-applicants-applicants-a">
<div className="ad-details-applicants-applicants-arrows">
<div className="job-details-applicants-applicants-a">
<div className="job-details-applicants-applicants-arrows">
<button onClick={archiveAdsArrowLeftHandler}> <button onClick={archiveAdsArrowLeftHandler}>
<img src={arrow_left} alt="arrow-left" /> <img src={arrow_left} alt="arrow-left" />
</button> </button>
</div> </div>
</div> </div>
)} )}
<div className="ad-details-applicants-applicants-applicant">
<div className="job-details-applicants-applicants-applicant">
<Slider <Slider
ref={archiveAdsSliderRef} ref={archiveAdsSliderRef}
{...settings} {...settings}
</div> </div>
</div> </div>
{matches && ( {matches && (
<div className="active-ads-ads-arrows">
<div className="active-jobs-jobs-arrows">
<button onClick={archiveAdsArrowLeftHandler}> <button onClick={archiveAdsArrowLeftHandler}>
<img src={arrow_left} alt="arrow-left" /> <img src={arrow_left} alt="arrow-left" />
</button> </button>
)} )}
</div> </div>
)} )}
<div className="ad-details-actions">
<div className="job-details-actions">
{!matches && ( {!matches && (
<div className="ad-details-expired-at">
<div className="ad-details-tech-logo-date">
<div className="job-details-expired-at">
<div className="job-details-tech-logo-date">
<p> <p>
<span>{t("ads.adDetailsExpiredAt")}: </span> <span>{t("ads.adDetailsExpiredAt")}: </span>
{new Date(ad.expiredAt).toLocaleDateString()} {new Date(ad.expiredAt).toLocaleDateString()}
</div> </div>
</div> </div>
)} )}
<div className="ad-details-buttons">
<div className="job-details-buttons">
<button <button
className="ad-details-buttons-link"
className="job-details-buttons-link"
onClick={() => history.push({ pathname: ADS_PAGE })} onClick={() => history.push({ pathname: ADS_PAGE })}
> >
{t("ads.backToAds")} {t("ads.backToAds")}


{!(new Date(ad.expiredAt) < new Date()) && ( {!(new Date(ad.expiredAt) < new Date()) && (
<IconButton <IconButton
className="c-btn c-btn--primary add-ad-btn apply-for-ad-button"
className="c-btn c-btn--primary add-job-btn apply-for-job-button"
onClick={() => setApplyForAdOpenModal(true)} onClick={() => setApplyForAdOpenModal(true)}
> >
{t("ads.signUp").toUpperCase()} {t("ads.signUp").toUpperCase()}

+ 47
- 47
src/pages/AdsPage/AdsPage.js View File

import React, { useState, useEffect, useRef } from "react"; import React, { useState, useEffect, useRef } from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import Ad from "../../components/Ads/Ad"; import Ad from "../../components/Ads/Ad";
import ArchiveAd from "../../components/Ads/ArchiveAd";
import IconButton from "../../components/IconButton/IconButton"; import IconButton from "../../components/IconButton/IconButton";
import arrow_left from "../../assets/images/arrow_left.png"; import arrow_left from "../../assets/images/arrow_left.png";
import arrow_right from "../../assets/images/arrow_right.png"; import arrow_right from "../../assets/images/arrow_right.png";
} from "../../store/actions/ads/adsAction"; } from "../../store/actions/ads/adsAction";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import { selectAds } from "../../store/selectors/adsSelectors"; import { selectAds } from "../../store/selectors/adsSelectors";
import { AD_DETAILS_PAGE, CREATE_AD_PAGE } from "../../constants/pages";
import { JOB_DETAILS_PAGE, CREATE_AD_PAGE } from "../../constants/pages";
import FilterButton from "../../components/Button/FilterButton"; import FilterButton from "../../components/Button/FilterButton";
import Slider from "react-slick"; import Slider from "react-slick";
import "slick-carousel/slick/slick.css"; import "slick-carousel/slick/slick.css";
import Fade from "@mui/material/Fade"; import Fade from "@mui/material/Fade";
import { FETCH_ADS_LOADING } from "../../store/actions/ads/adsActionConstants"; import { FETCH_ADS_LOADING } from "../../store/actions/ads/adsActionConstants";
import { selectIsLoadingByActionType } from "../../store/selectors/loadingSelectors"; import { selectIsLoadingByActionType } from "../../store/selectors/loadingSelectors";
import ArchiveJob from '../../components/Ads/ArchiveJob'


const AdsPage = ({ history }) => { const AdsPage = ({ history }) => {
const theme = useTheme(); const theme = useTheme();
const [tmp, setTmp] = useState(null); const [tmp, setTmp] = useState(null);
const ads = useSelector(selectAds); const ads = useSelector(selectAds);
const technologies = useSelector(selectTechnologies); const technologies = useSelector(selectTechnologies);
const archiveAds = useSelector(selectArchiveAds);
const archiveJobs = useSelector(selectArchiveAds);
const activeAdsSliderRef = useRef(); const activeAdsSliderRef = useRef();
const archiveAdsSliderRef = useRef();
const archiveJobsSliderRef = useRef();
const { t } = useTranslation(); const { t } = useTranslation();
const dispatch = useDispatch(); const dispatch = useDispatch();
const { search } = useLocation(); const { search } = useLocation();
dispatch(setArchiveAdsReq()); dispatch(setArchiveAdsReq());
}, []); }, []);


var slider1 = document.querySelector(".active-ads-ads-ad .slick-track");
var slider2 = document.querySelector(".archived-ads-ads-ad .slick-track");
var slider1 = document.querySelector(".active-jobs-jobs-job .slick-track");
var slider2 = document.querySelector(".archived-jobs-jobs-job .slick-track");


useEffect(() => { useEffect(() => {
if (slider1 && slider2) { if (slider1 && slider2) {
}; };


const archiveAdsArrowLeftHandler = () => { const archiveAdsArrowLeftHandler = () => {
archiveAdsSliderRef.current.slickPrev();
archiveJobsSliderRef.current.slickPrev();
}; };


const archiveAdsArrowRightHandler = () => { const archiveAdsArrowRightHandler = () => {
archiveAdsSliderRef.current.slickNext();
archiveJobsSliderRef.current.slickNext();
}; };


// const deleteFiltersHandler = () => { // const deleteFiltersHandler = () => {
return ads; return ads;
}; };


const getDummyArchiveAds = (len) => {
const getDummyArchiveJobs = (len) => {
const ads = []; const ads = [];


for (let i = 0; i < 5 - len + 1; i++) { for (let i = 0; i < 5 - len + 1; i++) {
ads.push(<ArchiveAd key={i} className="hiddenAd" />);
ads.push(<ArchiveJob key={i} className="hiddenAd" />);
} }


return ads; return ads;
placeholder="Pretrazi..." placeholder="Pretrazi..."
value={searchInput} value={searchInput}
onChange={(e) => setSearchInput(e.target.value)} onChange={(e) => setSearchInput(e.target.value)}
className="ads-search-field"
className="jobs-search-field"
onClick={stopPropagation} onClick={stopPropagation}
style={{ zIndex: 1000 }} style={{ zIndex: 1000 }}
/> />
placeholder="Pretrazi..." placeholder="Pretrazi..."
value={searchInput} value={searchInput}
onChange={(e) => setSearchInput(e.target.value)} onChange={(e) => setSearchInput(e.target.value)}
className="ads-search-field-responsive smaller"
className="jobs-search-field-responsive smaller"
onClick={stopPropagation} onClick={stopPropagation}
style={{ zIndex: 1000 }} style={{ zIndex: 1000 }}
/> />
</div> </div>
</div> </div>
) : ( ) : (
<div data-testid="ads-page">
<div data-testid="jobs-page">
<div className="l-t-rectangle"></div> <div className="l-t-rectangle"></div>
<div className="r-b-rectangle"></div> <div className="r-b-rectangle"></div>
{/* <AdFilters /> */} {/* <AdFilters /> */}
<Fade <Fade
in={isSearchFieldVisible} in={isSearchFieldVisible}
timeout={500} timeout={500}
className="ads-page-search-by-title"
className="jobs-page-search-by-title"
> >
{inputNormal} {inputNormal}
</Fade> </Fade>
</> </>
)} )}
</div> </div>
<div className="ads" onClick={() => handleChangeVisibility(false)}>
<div className="jobs" onClick={() => handleChangeVisibility(false)}>
{ads && ads.length > 0 && ( {ads && ads.length > 0 && (
<div className="active-ads">
<div className="active-ads-header">
<div className="active-jobs">
<div className="active-jobs-header">
<h1>{t("ads.activeAds")}</h1> <h1>{t("ads.activeAds")}</h1>
<div className="active-ads-header-buttons">
<div className="active-jobs-header-buttons">
<IconButton <IconButton
className={ className={
"c-btn--primary-outlined c-btn ads-page-btn userPageBtn ml-20px no-padding" "c-btn--primary-outlined c-btn ads-page-btn userPageBtn ml-20px no-padding"
<FilterButton onShowFilters={handleToggleFiltersDrawer} /> <FilterButton onShowFilters={handleToggleFiltersDrawer} />
</div> </div>
</div> </div>
<div className="active-ads-ads">
<div className="active-ads-ads-a">
<div className="active-jobs-jobs">
<div className="active-jobs-jobs-a">
{!matches && ( {!matches && (
<div className="active-ads-ads-arrows">
<div className="active-jobs-jobs-arrows">
<button onClick={activeAdsArrowLeftHandler}> <button onClick={activeAdsArrowLeftHandler}>
<img src={arrow_left} alt="arrow-left" /> <img src={arrow_left} alt="arrow-left" />
</button> </button>
</div> </div>
)} )}
</div> </div>
<div className="active-ads-ads-ad">
<div className="active-jobs-jobs-job">
<Slider <Slider
{...settings} {...settings}
slidesToShow={3} slidesToShow={3}
.map((ad, index) => ( .map((ad, index) => (
<Ad <Ad
onShowAdDetails={() => onShowAdDetails={() =>
history.push(AD_DETAILS_PAGE.replace(":id", ad.id))
history.push(JOB_DETAILS_PAGE.replace(":id", ad.id))
} }
key={index} key={index}
title={ad.title} title={ad.title}
</div> </div>
)} )}
{ads && ads.length > 0 && matches && ( {ads && ads.length > 0 && matches && (
<div className="active-ads-ads-arrows">
<div className="active-jobs-jobs-arrows">
<button onClick={activeAdsArrowLeftHandler}> <button onClick={activeAdsArrowLeftHandler}>
<img src={arrow_left} alt="arrow-left" /> <img src={arrow_left} alt="arrow-left" />
</button> </button>
</div> </div>
)} )}
{(!ads || ads.length === 0) && ( {(!ads || ads.length === 0) && (
<div className="active-ads-ads-no-ads">
<div className="active-ads-ads-no-ads-filters">
<div className="active-jobs-jobs-no-jobs">
<div className="active-jobs-jobs-no-jobs-filters">
<FilterButton onShowFilters={handleToggleFiltersDrawer} /> <FilterButton onShowFilters={handleToggleFiltersDrawer} />
</div> </div>
<img src={noActiveAds} alt="noActiveAds" /> <img src={noActiveAds} alt="noActiveAds" />
<h1>{t("ads.thereIsNoAds")}</h1> <h1>{t("ads.thereIsNoAds")}</h1>
<p>{t("ads.addAd")}</p> <p>{t("ads.addAd")}</p>
<div className="add-ad add-ad-no-ads">
<div className="add-job add-job-no-jobs">
<IconButton <IconButton
className="c-btn ads-page-btn c-btn--primary add-ad-btn"
className="c-btn jobs-page-btn c-btn--primary add-job-btn"
onClick={() => history.push(CREATE_AD_PAGE)} onClick={() => history.push(CREATE_AD_PAGE)}
> >
{t("ads.adNewAd")} {t("ads.adNewAd")}
</div> </div>
</div> </div>
)} )}
{archiveAds && archiveAds.length > 0 && (
<div className="archived-ads">
<div className="archived-ads-header">
{archiveJobs && archiveJobs.length > 0 && (
<div className="archived-jobs">
<div className="archived-jobs-header">
<h2>{t("ads.archiveAds")}</h2> <h2>{t("ads.archiveAds")}</h2>
</div> </div>
<div className="archived-ads-ads">
<div className="archived-jobs-jobs">
{!matches && ( {!matches && (
<div className="archived-ads-ads-a">
<div className="archived-ads-ads-arrows">
<div className="archived-jobs-jobs-a">
<div className="archived-jobs-jobs-arrows">
<button onClick={archiveAdsArrowLeftHandler}> <button onClick={archiveAdsArrowLeftHandler}>
<img src={arrow_left} alt="arrow-left" /> <img src={arrow_left} alt="arrow-left" />
</button> </button>
{archiveAds.length > 5 && (
{archiveJobs.length > 5 && (
<button onClick={archiveAdsArrowRightHandler}> <button onClick={archiveAdsArrowRightHandler}>
<img src={arrow_right} alt="arrow-right" /> <img src={arrow_right} alt="arrow-right" />
</button> </button>
</div> </div>
</div> </div>
)} )}
<div className="archived-ads-ads-ad">
<div className="archived-jobs-jobs-job">
<Slider <Slider
ref={archiveAdsSliderRef}
ref={archiveJobsSliderRef}
{...settings} {...settings}
slidesToShow={5} slidesToShow={5}
slidesToScroll={5} slidesToScroll={5}
style={{ width: "100%" }} style={{ width: "100%" }}
> >
{archiveAds
{archiveJobs
.filter((ad) => .filter((ad) =>
ad.title.toLowerCase().includes(searchInput.toLowerCase()) ad.title.toLowerCase().includes(searchInput.toLowerCase())
) )
.map((ad, index) => ( .map((ad, index) => (
<ArchiveAd
<ArchiveJob
key={index} key={index}
title={ad.title} title={ad.title}
minimumExperience={ad.minimumExperience} minimumExperience={ad.minimumExperience}
createdAt={ad.createdAt} createdAt={ad.createdAt}
expiredAt={ad.expiredAt} expiredAt={ad.expiredAt}
onShowAdDetails={() => onShowAdDetails={() =>
history.push(AD_DETAILS_PAGE.replace(":id", ad.id))
history.push(JOB_DETAILS_PAGE.replace(":id", ad.id))
} }
/> />
))} ))}
{archiveAds.length <= 5 &&
getDummyArchiveAds(archiveAds.length)}
{archiveJobs.length <= 5 &&
getDummyArchiveJobs(archiveJobs.length)}
</Slider> </Slider>
</div> </div>
</div> </div>
{matches && ( {matches && (
<div className="active-ads-ads-arrows">
<div className="active-jobs-jobs-arrows">
<button onClick={archiveAdsArrowLeftHandler}> <button onClick={archiveAdsArrowLeftHandler}>
<img src={arrow_left} alt="arrow-left" /> <img src={arrow_left} alt="arrow-left" />
</button> </button>
{archiveAds.length > 5 && (
{archiveJobs.length > 5 && (
<button onClick={archiveAdsArrowRightHandler}> <button onClick={archiveAdsArrowRightHandler}>
<img src={arrow_right} alt="arrow-right" /> <img src={arrow_right} alt="arrow-right" />
</button> </button>
</div> </div>
)} )}


<div className="archive-ads-no-active-ads"></div>
<div className="archive-jobs-no-active-jobs"></div>
</div> </div>
)} )}
</div> </div>


{ads && ads.length > 0 && ( {ads && ads.length > 0 && (
<div className="add-ad">
<div className="add-job">
<IconButton <IconButton
className="c-btn ads-page-btn c-btn--primary add-ad-btn"
className="c-btn ads-page-btn c-btn--primary add-job-btn"
onClick={createAd} onClick={createAd}
> >
+ {t("ads.ad")} + {t("ads.ad")}

+ 9
- 9
src/pages/AdsPage/CreateAdFirstStep.js View File

}; };


return ( return (
<div data-testid="create-ad-first-step-form">
<div className="create-ad-form-control">
<div data-testid="create-job-first-step-form">
<div className="create-job-form-control">
<label>{t("common.title")}</label> <label>{t("common.title")}</label>
<input <input
type="text" type="text"
className="create-ad-form-control-first-step-input"
className="create-job-form-control-first-step-input"
onChange={(e) => setTitle(e.target.value)} onChange={(e) => setTitle(e.target.value)}
value={title} value={title}
placeholder="ex. Medior React Developer" placeholder="ex. Medior React Developer"
/> />
</div> </div>
<div className="create-ad-form-control">
<div className="create-job-form-control">
<label>{t("filters.employmentType")}</label> <label>{t("filters.employmentType")}</label>
<div className="create-ad-form-control-buttons">
<div className="create-job-form-control-buttons">
<button <button
className={`c-btn ${ className={`c-btn ${
employmentType === "Work" employmentType === "Work"
</button> </button>
</div> </div>
</div> </div>
<div className="create-ad-form-control">
<div className="create-job-form-control">
<label>{t("filters.workHour")}</label> <label>{t("filters.workHour")}</label>
<div className="create-ad-form-control-buttons">
<div className="create-job-form-control-buttons">
<button <button
className={`c-btn ${ className={`c-btn ${
workHour === "PartTime" workHour === "PartTime"
</button> </button>
</div> </div>
</div> </div>
<div className="create-ad-form-control">
<div className="create-job-form-control">
<label>{t("ads.expirationDate")}</label> <label>{t("ads.expirationDate")}</label>
<input <input
type="date" type="date"
className="create-ad-form-control-first-step-input"
className="create-job-form-control-first-step-input"
onChange={(e) => setExpiredAt(e.target.value)} onChange={(e) => setExpiredAt(e.target.value)}
value={expiredAt} value={expiredAt}
/> />

+ 7
- 7
src/pages/AdsPage/CreateAdPage.js View File

}; };


return ( return (
<div className="create-ad-page" data-testid="create-ad-page">
<div className="create-ad-page-content">
<div className="create-ad-page-content-header">
<div className="create-job-page" data-testid="create-job-page">
<div className="create-job-page-content">
<div className="create-job-page-content-header">
<img <img
src={plusIcon} src={plusIcon}
alt="plus" alt="plus"
<sub> | {t("ads.ad")}</sub> <sub> | {t("ads.ad")}</sub>
</h2> </h2>
</div> </div>
<div className="create-ad-steps">
<div className="create-job-steps">
{stage === 1 && ( {stage === 1 && (
<CreateAdFirstStep <CreateAdFirstStep
title={title} title={title}
)} )}
{stage === 3 && <CreateAdThirdStep childRef={childRef} />} {stage === 3 && <CreateAdThirdStep childRef={childRef} />}
</div> </div>
<div className="create-ad-buttons" style={{ marginBottom: "2rem" }}>
<div className="create-job-buttons" style={{ marginBottom: "2rem" }}>
<button <button
className="create-ad-buttons-back"
className="create-job-buttons-back"
disabled={stage === 1} disabled={stage === 1}
onClick={backClickHandler} onClick={backClickHandler}
> >
{t("common.back")} {t("common.back")}
</button> </button>
<button <button
className="create-ad-buttons-forward"
className="create-job-buttons-forward"
onClick={forwardClickHandler} onClick={forwardClickHandler}
> >
{t("common.continue")} {t("common.continue")}

+ 13
- 13
src/pages/AdsPage/CreateAdSecondStep.js View File

}; };


return ( return (
<div data-testid="create-ad-second-step-form">
<div className="create-ad-form-control">
<div data-testid="create-job-second-step-form">
<div className="create-job-form-control">
<label>{t("filters.advancedTechnologies")}</label> <label>{t("filters.advancedTechnologies")}</label>
</div> </div>
<div className="add-ad-modal-stage-sub-card">
<div className="add-ad-modal-stage-sub-card-checkboxes-group">
<div className="add-job-modal-stage-sub-card">
<div className="add-job-modal-stage-sub-card-checkboxes-group">
<label>Front-End</label> <label>Front-End</label>
<div className="add-ad-modal-stage-sub-card-checkboxes">
<div className="add-job-modal-stage-sub-card-checkboxes">
{technologies {technologies
.filter((x) => x.technologyType === "Frontend") .filter((x) => x.technologyType === "Frontend")
.map((x) => ( .map((x) => (
value={x.name} value={x.name}
checked={x.isChecked} checked={x.isChecked}
onChange={handleCheckboxes.bind(this, x.technologyId)} onChange={handleCheckboxes.bind(this, x.technologyId)}
className="create-ad-second-step-checkbox"
className="create-job-second-step-checkbox"
/> />
} }
label={x.name} label={x.name}
</div> </div>
</div> </div>


<div className="add-ad-modal-stage-sub-card-checkboxes-group">
<div className="add-job-modal-stage-sub-card-checkboxes-group">
<label>Back-End</label> <label>Back-End</label>
<div className="add-ad-modal-stage-sub-card-checkboxes">
<div className="add-job-modal-stage-sub-card-checkboxes">
{technologies {technologies
.filter((x) => x.technologyType === "Backend") .filter((x) => x.technologyType === "Backend")
.map((x) => ( .map((x) => (
value={x.name} value={x.name}
checked={x.isChecked} checked={x.isChecked}
onChange={handleCheckboxes.bind(this, x.technologyId)} onChange={handleCheckboxes.bind(this, x.technologyId)}
className="create-ad-second-step-checkbox"
className="create-job-second-step-checkbox"
/> />
} }
label={x.name} label={x.name}
</div> </div>
</div> </div>


<div className="add-ad-modal-stage-sub-card-checkboxes-group">
<div className="add-job-modal-stage-sub-card-checkboxes-group">
<label>{t("ads.others")}</label> <label>{t("ads.others")}</label>
<div className="add-ad-modal-stage-sub-card-checkboxes">
<div className="add-job-modal-stage-sub-card-checkboxes">
{technologies {technologies
.filter((x) => x.technologyType === "Other") .filter((x) => x.technologyType === "Other")
.map((x) => ( .map((x) => (
value={x.name} value={x.name}
checked={x.isChecked} checked={x.isChecked}
onChange={handleCheckboxes.bind(this, x.technologyId)} onChange={handleCheckboxes.bind(this, x.technologyId)}
className="create-ad-second-step-checkbox"
className="create-job-second-step-checkbox"
/> />
} }
label={x.name} label={x.name}
</div> </div>
</div> </div>
</div> </div>
<div className="create-ad-form-control">
<div className="create-job-form-control">
<label>{t("filters.experience")}</label> <label>{t("filters.experience")}</label>
<input <input
type="number" type="number"

+ 4
- 4
src/pages/AdsPage/CreateAdThirdStep.js View File

} }


return ( return (
<div data-testid="create-ad-third-step-form">
<div className="create-ad-form-control">
<div data-testid="create-job-third-step-form">
<div className="create-job-form-control">
<label>{t("ads.duties")}</label> <label>{t("ads.duties")}</label>
<Editor <Editor
onInit={(evt, editor) => onInit={(evt, editor) =>
style={{ height: "1rem !important" }} style={{ height: "1rem !important" }}
/> />
</div> </div>
<div className="create-ad-form-control">
<div className="create-job-form-control">
<label>{t("ads.conditions")}</label> <label>{t("ads.conditions")}</label>
<Editor <Editor
onInit={(evt, editor) => (editorRequirementsRef.current = editor)} onInit={(evt, editor) => (editorRequirementsRef.current = editor)}
style={{ height: "1rem !important" }} style={{ height: "1rem !important" }}
/> />
</div> </div>
<div className="create-ad-form-control">
<div className="create-job-form-control">
<label>{t("ads.offer")}</label> <label>{t("ads.offer")}</label>
<Editor <Editor
onInit={(evt, editor) => (editorOfferRef.current = editor)} onInit={(evt, editor) => (editorOfferRef.current = editor)}

+ 8
- 8
src/pages/CandidatesPage/AdsCandidatesPage.js View File

}; };


return ( return (
<div className="ads-candidates-container top-cnd">
<div className="jobs-candidates-container top-cnd">
{adsCandidates.map((adCandidates, index) => ( {adsCandidates.map((adCandidates, index) => (
<div className="ads-candidates" key={index}>
<div className="ads-candidates-top-container">
<img src={adImage} className="ads-candidates-image" />
<p className="ads-candidates-title">{adCandidates.title}</p>
<p className="ads-candidates-numberOfApplicants">
<div className="jobs-candidates" key={index}>
<div className="jobs-candidates-top-container">
<img src={adImage} className="jobs-candidates-image" />
<p className="jobs-candidates-title">{adCandidates.title}</p>
<p className="jobs-candidates-numberOfApplicants">
| {adCandidates.nubmerOfApplicants} {t("ads.registered")} | {adCandidates.nubmerOfApplicants} {t("ads.registered")}
</p> </p>
</div> </div>
<div className="ads-candidates-slider">
<div className="jobs-candidates-slider">
{filterByName(adCandidates).length > 4 && ( {filterByName(adCandidates).length > 4 && (
<div <div
className="active-ads-ads-arrows"
className="active-jobs-jobs-arrows"
style={matches ? { marginLeft: 36 } : { marginLeft: 0 }} style={matches ? { marginLeft: 36 } : { marginLeft: 0 }}
> >
<button onClick={() => activeAdsArrowLeftHandler(index)}> <button onClick={() => activeAdsArrowLeftHandler(index)}>

+ 5
- 5
src/pages/CandidatesPage/CandidateDetailsPage.js View File

</div> </div>
</div> </div>
</div> </div>
<div className="applicant-ads-container">
<div className="applicant-jobs-container">
<p style={{ marginLeft: matches ? 36 : 144 }}> <p style={{ marginLeft: matches ? 36 : 144 }}>
{t("candidates.allApplications")} {t("candidates.allApplications")}
</p> </p>
<div className="applicant-ads-container-2">
<div className="applicant-jobs-container-2">
<div <div
style={{ style={{
marginLeft: matches ? 36 : candidate.ads.length < 5 ? 108 : 72, marginLeft: matches ? 36 : candidate.ads.length < 5 ? 108 : 72,
? candidate.ads.length > 1 ? candidate.ads.length > 1
: candidate.ads.length > 5) && ( : candidate.ads.length > 5) && (
<div <div
className="active-ads-ads-arrows"
className="active-jobs-jobs-arrows"
data-testid="candidate-ad-responsive-arrows" data-testid="candidate-ad-responsive-arrows"
> >
<button onClick={activeAdsArrowLeftHandler}> <button onClick={activeAdsArrowLeftHandler}>
</Slider> </Slider>
</div> </div>
</div> </div>
<div className="applicant-ads-buttons-container">
<div className="applicant-jobs-buttons-container">
<p <p
to="/candidates" to="/candidates"
className="applicant-ads-back-button"
className="applicant-jobs-back-button"
onClick={goToPageWithAllCandidates} onClick={goToPageWithAllCandidates}
> >
{t("candidates.backToCandidates")} {t("candidates.backToCandidates")}

+ 3
- 3
src/pages/PatternsPage/PatternDetailsPage.js View File



<div className="pattern-details-card-buttons"> <div className="pattern-details-card-buttons">
<button <button
className="ad-details-buttons-link"
data-testid="ad-details-buttons-link"
className="job-details-buttons-link"
data-testid="job-details-buttons-link"
onClick={() => history.push(PATTERNS_PAGE)} onClick={() => history.push(PATTERNS_PAGE)}
> >
{t("ads.backToAds")} {t("ads.backToAds")}
</button> </button>
<IconButton <IconButton
disabled={emails && emails.length === 0} disabled={emails && emails.length === 0}
className="c-btn c-btn--primary add-ad-btn"
className="c-btn c-btn--primary add-job-btn"
data-testid="pattern-details-send-email" data-testid="pattern-details-send-email"
onClick={scheduleAppointmentHandler} onClick={scheduleAppointmentHandler}
> >

+ 1
- 1
src/pages/PatternsPage/PatternsPage.js View File

</div> </div>
<div className="patterns-button"> <div className="patterns-button">
<IconButton <IconButton
className="c-btn c-btn--primary add-ad-btn add-pattern-btn"
className="c-btn c-btn--primary add-job-btn add-pattern-btn"
onClick={() => setOpenAddPatternModal(true)} onClick={() => setOpenAddPatternModal(true)}
> >
{t("patterns.addPattern")} {t("patterns.addPattern")}

+ 9
- 9
src/pages/SelectionProcessPage/SelectionProcessOfApplicantPage.js View File

<div className="l-t-rectangle"></div> <div className="l-t-rectangle"></div>
<div className="r-b-rectangle"></div> <div className="r-b-rectangle"></div>
{/* <AdFilters /> */} {/* <AdFilters /> */}
<div data-testid="appl-sel" className="ads">
<div data-testid="appl-sel" className="jobs">
{processes && processes.length > 0 && ( {processes && processes.length > 0 && (
<div className="active-ads">
<div className="active-ads-header">
<div className="active-jobs">
<div className="active-jobs-header">
<h1> <h1>
{t("selection.title")} {t("selection.title")}
<span className="level-header-spliter">|</span> <span className="level-header-spliter">|</span>
</h1> </h1>
</div> </div>


<div className="active-ads-ads">
<div className="active-ads-ads-a">
<div className="active-jobs-jobs">
<div className="active-jobs-jobs-a">
{!matches && ( {!matches && (
<div className="active-ads-ads-arrows">
<div className="active-jobs-jobs-arrows">
<button onClick={activeAdsArrowLeftHandler}> <button onClick={activeAdsArrowLeftHandler}>
<img src={arrow_left} alt="arrow-left" /> <img src={arrow_left} alt="arrow-left" />
</button> </button>
</div> </div>
)} )}
</div> </div>
<div className="active-ads-ads-ad">
<div className="active-jobs-jobs-job">
<Slider <Slider
{...settings} {...settings}
slidesToShow={4} slidesToShow={4}
</div> </div>
)} )}
{matches && ( {matches && (
<div className="active-ads-ads-arrows">
<div className="active-jobs-jobs-arrows">
<button onClick={activeAdsArrowLeftHandler}> <button onClick={activeAdsArrowLeftHandler}>
<img src={arrow_left} alt="arrow-left" /> <img src={arrow_left} alt="arrow-left" />
</button> </button>
</p> </p>
</div> </div>
</div> </div>
<div className="add-ad">
<div className="add-job">
<Link className="ad-details-buttons-link" to="/selectionFlow"> <Link className="ad-details-buttons-link" to="/selectionFlow">
{t("candidates.backToCandidates")} {t("candidates.backToCandidates")}
</Link> </Link>

+ 10
- 10
src/pages/StatsPage/StatsPage.js View File

import arrow_left from "../../assets/images/arrow_left.png"; import arrow_left from "../../assets/images/arrow_left.png";
import arrow_right from "../../assets/images/arrow_right.png"; import arrow_right from "../../assets/images/arrow_right.png";
import Slider from "react-slick"; import Slider from "react-slick";
import { AD_DETAILS_PAGE } from "../../constants/pages";
import { JOB_DETAILS_PAGE } from "../../constants/pages";
import StatsAd from "../../components/Ads/StatsAd"; import StatsAd from "../../components/Ads/StatsAd";
import { useDispatch } from "react-redux"; import { useDispatch } from "react-redux";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
<div className="stats-section"> <div className="stats-section">
<h2 className="section-header">{t("stats.registered")}</h2> <h2 className="section-header">{t("stats.registered")}</h2>
</div> </div>
<div className="ads stat-ads">
<div className="jobs stat-jobs">
{stats.ads && stats.ads.length > 0 && ( {stats.ads && stats.ads.length > 0 && (
<div className="archived-ads">
{/* <div className="archived-ads-header">
<div className="archived-jobs">
{/* <div className="archived-jobs-header">
<h2>{t("ads.archiveAds")}</h2> <h2>{t("ads.archiveAds")}</h2>
</div> */} </div> */}
<div className="archived-ads-ads">
<div className="archived-jobs-jobs">
{!matches && ( {!matches && (
<div className="archived-ads-ads-a">
<div className="archived-ads-ads-arrows">
<div className="archived-jobs-jobs-a">
<div className="archived-jobs-jobs-arrows">
<button onClick={arrowLeftHandler} data-testid="left-arrow"> <button onClick={arrowLeftHandler} data-testid="left-arrow">
<img src={arrow_left} alt="arrow-left" /> <img src={arrow_left} alt="arrow-left" />
</button> </button>
</div> </div>
</div> </div>
)} )}
<div className="archived-ads-ads-ad">
<div className="archived-jobs-jobs-job">
<Slider <Slider
ref={sliderRef} ref={sliderRef}
{...settings} {...settings}
createdAt={ad.createdAt} createdAt={ad.createdAt}
expiredAt={ad.expiredAt} expiredAt={ad.expiredAt}
onShowAdDetails={() => onShowAdDetails={() =>
history.push(AD_DETAILS_PAGE.replace(":id", ad.id))
history.push(JOB_DETAILS_PAGE.replace(":id", ad.id))
} }
/> />
))} ))}
</div> </div>
</div> </div>
{matches && ( {matches && (
<div className="active-ads-ads-arrows">
<div className="active-jobs-jobs-arrows">
<button onClick={arrowLeftHandler} data-testid="left-arrow"> <button onClick={arrowLeftHandler} data-testid="left-arrow">
<img src={arrow_left} alt="arrow-left" /> <img src={arrow_left} alt="arrow-left" />
</button> </button>

+ 1
- 1
src/pages/UsersPage/UsersPage.js View File

<Fade <Fade
in={isSearchFieldVisible} in={isSearchFieldVisible}
timeout={500} timeout={500}
className="ads-page-search-by-title"
className="jobs-page-search-by-title"
> >
{inputNormal} {inputNormal}
</Fade> </Fade>

+ 6
- 6
src/request/apiEndpoints.js View File

initProcess: base + "/applicants/selection-init", initProcess: base + "/applicants/selection-init",
}, },
ads: { ads: {
allAds: base + "/ads",
createAd: base + "/ads",
allFilteredAds: base + "/ads/filtered",
allArchiveAds: base + "/ads/archive",
adDetails: base + "/ads/details",
archiveActiveAd: base + "/ads/archive-active-ad/:id",
allAds: base + "/jobs",
createAd: base + "/jobs",
allFilteredAds: base + "/jobs/filtered",
allArchiveAds: base + "/jobs/archive",
adDetails: base + "/jobs/details",
archiveActiveAd: base + "/jobs/archive-active-job/:id",
}, },
technologies: { technologies: {
allTechnologies: base + "/technologies", allTechnologies: base + "/technologies",

Loading…
Cancel
Save