ソースを参照

added pages

feature/selection_process_FE
Safet Purkovic 3年前
コミット
02d0a32fd9

+ 4
- 1
src/AppRoutes.js ファイルの表示

@@ -12,7 +12,8 @@ import {
BASE_PAGE,
RESET_PASSWORD_PAGE,
USERS_PAGE,
CANDIDATES_PAGE
CANDIDATES_PAGE,
SELECTION_PROCESS_PAGE
} from "./constants/pages";

// import LoginPage from './pages/LoginPage/LoginPage';
@@ -30,6 +31,7 @@ import ResetPasswordPage from "./pages/ForgotPasswordPage/ResetPasswordPageMUI";
import UsersPage from "./pages/UsersPage/UsersPage";
import CandidatesPage from './pages/CandidatesPage/CandidatesPage'
import AdDetailsPage from "./pages/AdsPage/AdDetailsPage";
import SelectionProcessPage from "./pages/SelectionProcessPage/SelectionProcessPage";

const AppRoutes = () => (
<Switch>
@@ -48,6 +50,7 @@ const AppRoutes = () => (
<PrivateRoute exact path={AD_DETAILS_PAGE} component={AdDetailsPage} />
<PrivateRoute exact path={USERS_PAGE} component={UsersPage} />
<PrivateRoute exact path={CANDIDATES_PAGE} component={CandidatesPage} />
<PrivateRoute exact path={SELECTION_PROCESS_PAGE} component={SelectionProcessPage} />
<Redirect from="*" to={NOT_FOUND_PAGE} />
</Switch>
);

+ 372
- 0
src/assets/styles/components/_selectionProcessPage.scss ファイルの表示

@@ -0,0 +1,372 @@
h1,
h3 {
margin: 0;
padding: 0;
}

.ads {
margin-top: 36px;
padding-left: 3rem;
}

.active-ads-header {
padding-left: 81px;
display: flex;
justify-content: space-between;
align-items: center;
}

.activee{
/* Blue 4 */

background : #E8F7FF;
border : 1px solid #226CB0;
}

.active-ads
{
overflow-x: scroll;
padding-bottom: 100px;
}

.active-ads-subheader {
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 600;
font-size: 24px;
line-height: 36px;
padding-left: 0.3rem;
/* identical to box height, or 100% */
color:#226CB0;
letter-spacing: 0.02em;
}
.active-ads-subheader-spliter {
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 600;
font-size: 24px;
line-height: 36px;
padding-left: 0.3rem;
/* identical to box height, or 100% */
color:#272727;
letter-spacing: 0.02em;
}

.filter-vector {
margin-left: 0.5rem !important;
}

.active-ads-ads {
display: flex;
margin-top: 39px;
position: relative;
}

.active-ads-ads-ad {
padding-left: 81px;
display: flex;
}

.selection-card {
display: flex;
flex-direction: column;
justify-content: start;
align-items: left;
// width: 550px;
height: fit-content;
padding: 36px;
background: #F4F4F4;
border: 1px solid #e4e4e4;
border-radius: 18px;
gap: 18px;
margin-right: 36px;
}

.bg-danger{
background-color: #272727;
}

.selection-item {
display: flex;
flex-direction: row;
justify-content: left;
vertical-align: top;
align-items: left;
width: 400px;
// height: 400px;
padding: 18px 36px;
background: #FFFFFF;
border: 1px solid #e4e4e4;
border-radius: 18px;
gap: 18px;
margin-right: 36px;
}

.selection-item-date p {
text-align: right;
font-family: "Source Sans Pro";
font-style: normal;
font-weight: 400;
font-size: 16px;
line-height: 15px;
color: #272727;
flex: none;
order: 4;
flex-grow: 0;
}

.selection-card-title h3 {
font-family: "Source Sans Pro";
font-style: normal;
font-weight: 600;
font-size: 32px;
line-height: 32px;
letter-spacing: 0.02em;
color: #272727;
flex: none;
order: 0;
flex-grow: 0;
}

.ad-card-logo img {
width: 61px;
height: 49px;
flex: none;
order: 2;
flex-grow: 0;
}
.selection-item-name, .selection-item-date{
margin: auto 0 !important;
}
.selection-item-name p {
height: 20px;
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 600;
font-size: 16px;
line-height: 20px;
text-align: right;
color: #226CB0;
flex: none;
order: 2;
flex-grow: 0;
}

.ad-card-buttons {
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: center;
padding: 0px;
gap: 18px;
width: 281px;
height: 38px;
flex: none;
order: 0;
flex-grow: 0;
}

.selection-item-buttons button {
box-sizing: border-box;
display: flex;
flex-direction: row;
justify-content: center;
font-size: 16px;
align-items: center;
padding: 9px;
gap: 10px;
min-width: 76px;
height: 38px;
border: 1px solid #e4e4e4;
border-radius: 9px;
flex: none;
order: 0;
flex-grow: 0;
}

.add-ad {
margin-top: 49px;
display: flex;
justify-content: flex-end;
align-items: center;
padding-right: 5rem !important;
padding-bottom: 49px;
}

.add-ad-btn {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
padding: 18px 72px;
gap: 10px;
width: 201px;
height: 51px;
background: #226cb0;
border-radius: 9px;
}

.ad-filters-header-container {
display: flex;
justify-content: space-between;
}

.ad-filters-header {
display: flex;
align-items: center;
}

.ad-filters-header-close {
cursor: pointer;
}

.ad-filters-header > * {
margin-right: 0.25rem;
}

.ad-filters-header img {
width: 18px;
height: 15.75px;
}

.ad-filters-header sub {
color: #226cb0;
}

.ad-filters-sub-title {
font-family: "Source Sans Pro";
font-style: normal;
font-weight: 600;
font-size: 16px;
line-height: 20px;
color: #272727;
}

.ad-filters-experience {
margin-top: 18px;
box-sizing: border-box;
}

.ad-filters-experience-slider {
margin-top: 5px;
}

.ad-filters-technologies {
margin-top: 18px;
}

.ad-filters-employment-type {
display: flex;
}

.ad-filters-employment-type > button {
margin-right: 0.5rem;
margin-top: 18px;
}

.ad-filters-search {
margin-top: 18px;
padding-bottom: 18px;
}

.ad-filters-search > * {
width: 100%;
}

.sel-item{
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
padding: 18px 36px;
gap: 18px;

width: 458px;

/* White */

background: #FFFFFF;
/* Gray E4 */

border: 1px solid #E4E4E4;
border-radius: 18px;
}

.sel-item .p{
/* Paragraph */

font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 400;
font-size: 16px;
line-height: 20px;

/* Main Black */
color: #272727;


/* Inside auto layout */

flex: none;
order: 0;
flex-grow: 0;
}

.sel-item .date{
/* 22.07. | 14:10h */

/* Paragraph */

font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 400;
font-size: 16px;
line-height: 20px;

/* Main Black */

color: #272727;
}

.sel-item .rig{
height: 20px;

/* Bold Paragraph */

font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 600;
font-size: 16px;
line-height: 20px;
text-align: right;

/* Main Blue */

color: #226CB0;


/* Inside auto layout */

flex: none;
order: 1;
flex-grow: 0;
}


.sel-item .p button {
box-sizing: border-box;
display: flex;
flex-direction: row;
justify-content: center;
font-size: 16px;
align-items: center;
padding: 9px;
gap: 10px;
min-width: 76px;
height: 38px;
border: 1px solid #e4e4e4;
border-radius: 9px;
flex: none;
order: 0;
flex-grow: 0;
}

+ 69
- 0
src/components/Selection/Selection.js ファイルの表示

@@ -0,0 +1,69 @@
import React from "react";
import PropTypes from "prop-types";

const dragStart = (e, applicant) => {
// e.dataTransfer.setData("applicant", applicant.id);
e.dataTransfer.setData("text/plain",JSON.stringify(applicant));
}

const dragOver = (e) => {
e.preventDefault();
}

const dropItem = (e,selId) =>{
var data = e.dataTransfer.getData("text/plain");
const applicant = JSON.parse(data);
if(applicant.currentSelection !== selId){
// SEND REQUEST TO BACKEND TO STORE NEW SELECTION
console.log('jup')
}
}

const Selection = (props) => {
console.log(props.selection);
const applicants = props.selection.applicants;
const renderList = applicants.map((item, index) => {
return <div draggable key={index} className="sel-item" onDragStart={e => dragStart(e,item)}>
<div className="p">
<button>{item.status}</button>
</div>
<div className="date">
<p>{item.date}</p>
</div>
<div className="rig">
<p>{item.name}</p>
</div>
</div>
}
);

return (
<div dropppable="true" id={props.selection.id} className="selection-card"
onDragOver={e => dragOver(e)}
onDrop={e => dropItem(e,props.selection.id)}
>
<div className="selection-card-title">
<h3>{props.selection.name}</h3>
</div>

{renderList}
</div>
);
};

Selection.propTypes = {
selection: PropTypes.shape({
id: PropTypes.number,
name : PropTypes.string,
applicants: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.number,
name: PropTypes.string,
date: PropTypes.string,
status: PropTypes.string,
currentSelection: PropTypes.number,
map: PropTypes.func
}))
}),
};

export default Selection;

+ 2
- 1
src/constants/pages.js ファイルの表示

@@ -8,4 +8,5 @@ export const NOT_FOUND_PAGE = '/not-found';
export const USERS_PAGE = '/users';
export const CANDIDATES_PAGE = '/candidates';
export const FORGOT_PASSWORD_CONFIRMATION_PAGE = '/forgot-password-confirmation';
export const RESET_PASSWORD_PAGE = '/reset-password';
export const RESET_PASSWORD_PAGE = '/reset-password';
export const SELECTION_PROCESS_PAGE = '/selection-process';

+ 3
- 0
src/i18n/resources/rs.js ファイルの表示

@@ -118,5 +118,8 @@ nav:{
ads: {
activeAds: "Aktivni Oglasi",
archiveAds: "Arhiva"
},
selection:{
title: "Tok Selekcije"
}
};

+ 1
- 0
src/main.scss ファイルの表示

@@ -16,6 +16,7 @@
@import './assets/styles/components/user-profile';
@import './assets/styles/components/auth';
@import './assets/styles/components/login';
@import './assets/styles/components/selectionProcessPage';
@import './assets/styles/components/login-card';
@import './assets/styles/components/forgot-password';
@import './assets/styles/components/input';

+ 161
- 0
src/pages/SelectionProcessPage/SelectionProcessPage.js ファイルの表示

@@ -0,0 +1,161 @@
import React, { useState } from "react";
import Selection from "../../components/Selection/Selection";
import IconButton from "../../components/IconButton/IconButton";
import filterVector from "../../assets/images/filter_vector.png";
import { useTranslation } from "react-i18next";
import AddAdModal from "../../components/Ads/AddAdModal";
import AdFilters from "../../components/Ads/AdFilters";

const SelectionProcessPage = () => {
const [toggleFiltersDrawer, setToggleFiltersDrawer] = useState(false);
const [toggleModal, setToggleModal] = useState(false);
const { t } = useTranslation();

const handleToggleFiltersDrawer = () => {
setToggleFiltersDrawer((oldState) => !oldState);
};

const handleToggleModal = () => {
setToggleModal((oldState) => !oldState);
};

const selections = [
{
id: 1,
name: "HR interview",
applicants: [
{
id: 1,
name: "Stefan Petrovic",
status: "Zakazan",
date: "01.01.2022 11:00",
currentSelection: 1
},
{
id: 2,
name: "Stefan Petrovic",
status: "Otkazan",
date: "01.01.2022 11:00",
currentSelection: 1
},
{
id: 3,
name: "Stefan Petrovic",
status: "Ceka na zakazivanje",
currentSelection: 1
}]
},
{
id: 2,
name: "Screening test",
applicants: [
{
id: 1,
name: "Stefan Petrovic",
status: "Zakazan",
date: "01.01.2022 11:00",
currentSelection: 2
},
{
id: 2,
name: "Stefan Petrovic",
status: "Otkazan",
date: "01.01.2022 11:00",
currentSelection: 2
}]
},
{
id: 3,
name: "Technical interview",
applicants: [
{
id: 1,
name: "Stefan Petrovic",
status: "Zakazan",
date: "01.01.2022 11:00",
currentSelection: 3
},
{
id: 2,
name: "Stefan Petrovic",
status: "Otkazan",
date: "01.01.2022 11:00",
currentSelection: 3
},
{
id: 3,
name: "Stefan Petrovic",
status: "Ceka na zakazivanje",
currentSelection: 3
}]
},
{
id: 4,
name: "Final decision",
applicants: [
{
id: 1,
name: "Stefan Petrovic",
status: "Zakazan",
date: "01.01.2022 11:00",
currentSelection: 4
},
{
id: 2,
name: "Stefan Petrovic",
status: "Otkazan",
date: "01.01.2022 11:00",
currentSelection: 4
}]
}
]


const renderList = selections.map((item, index) => {
return <Selection selection={item} key={index}/>
}
);

return (
<>
<div className="l-t-rectangle"></div>
<div className="r-b-rectangle"></div>
<AdFilters />
<AdFilters
open={toggleFiltersDrawer}
handleClose={handleToggleFiltersDrawer}
/>
<AddAdModal open={toggleModal} handleClose={handleToggleModal} />
<div className="ads">
<div className="active-ads">
<div className="active-ads-header">
<h1>{t("selection.title")}
<span className="active-ads-subheader-spliter">
|
</span>
<span className="active-ads-subheader">
Svi kandidati
</span>
</h1>
<IconButton
sx={{ marginLeft: "15px" }}
className="c-btn c-btn--primary-outlined"
onClick={handleToggleFiltersDrawer}
>
Filteri{" "}
<img src={filterVector} alt="filter" className="filter-vector" />
</IconButton>
</div>
<div className="active-ads-ads">
<div className="active-ads-ads-ad">
{renderList}
</div>
</div>
</div>
</div>
</>
);
};

export default SelectionProcessPage;

読み込み中…
キャンセル
保存