Skip to content
This repository was archived by the owner on Mar 13, 2025. It is now read-only.

Role & Skills Intake - Job Description Module #291

Merged
merged 1 commit into from
Jun 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/root.component.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import JobForm from "./routes/JobForm";
import TeamAccess from "./routes/TeamAccess";
import CreateNewTeam from "./routes/CreateNewTeam";
import InputSkills from "./routes/CreateNewTeam/pages/InputSkills";
import InputJobDescription from "./routes/CreateNewTeam/pages/InputJobDescription";
import SelectRole from "./routes/CreateNewTeam/pages/SelectRole";
import ReduxToastr from "react-redux-toastr";
import store from "./store";
Expand All @@ -33,6 +34,7 @@ export default function Root() {
<ResourceBookingForm path="/taas/myteams/:teamId/rb/:resourceBookingId/edit" />
<PositionDetails path="/taas/myteams/:teamId/positions/:positionId/candidates" />
<TeamAccess path="/taas/myteams/:teamId/access" />
<InputJobDescription path="/taas/myteams/createnewteam/jd" />
<InputSkills path="/taas/myteams/createnewteam/:projectId/skills" />
<SelectRole path="/taas/myteams/createnewteam/:projectId/role" />
</Router>
Expand Down
17 changes: 12 additions & 5 deletions src/routes/CreateNewTeam/components/Completeness/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import CompleteProgress from "../CompleteProgress";
import "./styles.module.scss";
import IconMultipleActionsCheck from "../../../../assets/images/icon-multiple-actions-check-2.svg";
import IconListQuill from "../../../../assets/images/icon-list-quill.svg";
import IconOfficeFileText from "../../../../assets/images/icon-office-file-text.svg";

function Completeness({
extraStyleName,
Expand All @@ -21,6 +22,16 @@ function Completeness({
stages,
percentage,
}) {

let backgroundIcon
if (extraStyleName === "input-skills") {
backgroundIcon= <IconListQuill styleName="transparent-icon" />
} else if (extraStyleName === "input-job-description") {
backgroundIcon= <IconOfficeFileText styleName="transparent-icon" />
} else {
backgroundIcon= <IconMultipleActionsCheck styleName="transparent-icon" />
}

return (
<div styleName={cn("completeness", extraStyleName)}>
<CompleteProgress percentDone={percentage} />
Expand All @@ -44,11 +55,7 @@ function Completeness({
>
{buttonLabel}
</Button>
{extraStyleName === "input-skills" ? (
<IconListQuill styleName="transparent-icon" />
) : (
<IconMultipleActionsCheck styleName="transparent-icon" />
)}
{backgroundIcon}
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
}
}

.input-job-description {
background-image: linear-gradient(135deg, #2984BD 0%, #0AB88A 100%);
}

.input-skills {
background-image: linear-gradient(221.5deg, #2c95d7 0%, #9d41c9 100%);
}
Expand Down
6 changes: 5 additions & 1 deletion src/routes/CreateNewTeam/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ function CreateNewTeam() {
});
};

const goToJobDescription = () => {
navigate(`/taas/myteams/createnewteam/jd`);
};

return (
<Page title="Create New Team">
<PageHeader title="Create New Team" />
Expand All @@ -55,7 +59,7 @@ function CreateNewTeam() {
description="You would like to use a description to explain what you need."
icon={<IconOfficeFileText />}
backgroundImage="linear-gradient(135deg, #2984BD 0%, #0AB88A 100%)"
isDisabled
onClick={goToJobDescription}
/>
</Page>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/**
* Temporary Popup for skill list
* show skill list
*/
import React from "react";
import _ from "lodash";
import PT from "prop-types";
import Modal from "react-responsive-modal";
import Button from "components/Button";
import IconCrossLight from "../../../../../../assets/images/icon-cross-light.svg";
import IconSingleManAdd from "../../../../../../assets/images/icon-single-man-add.svg";
import "./styles.module.scss";
import CenteredSpinner from "components/CenteredSpinner";

const modalStyle = {
borderRadius: "8px",
padding: "32px 32px 22px 32px",
maxWidth: "460px",
width: "100%",
margin: 0,
"overflow-x": "hidden",
};

const containerStyle = {
padding: "10px",
};

function SkillListPopup({ open, skills, onClose, isLoading, onContinueClick }) {
return (
<Modal
open={open}
center
onClose={onClose}
closeIcon={
<IconCrossLight height="18px" width="18px" styleName="cross" />
}
styles={{
modal: modalStyle,
modalContainer: containerStyle,
}}
>
<div styleName="modal-body">
{isLoading ? (
<>
<CenteredSpinner />
<h5>loading skills</h5>
</>
) : (
<>
<IconSingleManAdd />
<h5>skills</h5>
{_.map(skills, (s) => {
return <div>{s.tag}</div>;
})}
</>
)}
</div>
<div styleName="button-group">
<Button
type="primary"
size="medium"
disabled={isLoading}
onClick={onContinueClick}
>
Continue
</Button>
</div>
</Modal>
);
}

SkillListPopup.propTypes = {
open: PT.bool,
onClose: PT.func,
isLoading: PT.bool,
onContinueClick: PT.func,
skills: PT.arrayOf(PT.shape()),
};

export default SkillListPopup;
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
@import "styles/include";

.button-group {
display: flex;
flex-direction: row;
justify-content: center;
align-items: flex-end;
:first-child {
margin-right: 8px;
}
}

.modal-body {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
text-align: center;
margin-bottom: 80px;

svg {
width: 48px;
height: 48px;
margin-bottom: 16px;
}

h5 {
@include font-barlow-condensed;
font-size: 34px;
color: #1e94a3;
text-transform: uppercase;
font-weight: 500;
margin-bottom: 10px;
}

p {
@include font-roboto;
font-size: 16px;
color: #555555;
line-height: 26px;
}
}

.cross {
g {
stroke: #000;
}
}
150 changes: 150 additions & 0 deletions src/routes/CreateNewTeam/pages/InputJobDescription/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/**
* Input Job Description page
*
*/
import React, { useCallback, useEffect, useState } from "react";
import { useData } from "hooks/useData";
import { navigate } from "@reach/router";
import { toastr } from "react-redux-toastr";
import { setCurrentStage } from "utils/helpers";
import Page from "components/Page";
import PT from "prop-types";
import PageHeader from "components/PageHeader";
import LoadingIndicator from "components/LoadingIndicator";
import MarkdownEditor from "../../../../components/MarkdownEditor";
import { getSkillsByJobDescription } from "../../../../services/teams";
import Completeness from "../../components/Completeness";
import { getSkills } from "services/skills";
import SearchCard from "../../components/SearchCard";
import ResultCard from "../../components/ResultCard";
import AddAnotherModal from "../../components/AddAnotherModal";
import SkillListPopup from "./components/SkillListPopup";
import "./styles.module.scss";
import withAuthentication from "../../../../hoc/withAuthentication";
import IconOfficeFileText from "../../../../assets/images/icon-office-file-text.svg";

function InputJobDescription() {
const [stages, setStages] = useState([
{ name: "Input Job Desccription", isCurrent: true },
{ name: "Search Member" },
{ name: "Overview of the Results" },
]);
const [jdString, setJdString] = useState("");
const [searchState, setSearchState] = useState(null);
const [modalOpen, setModalOpen] = useState(false);
const [skillModalOpen, setSkillModalOpen] = useState(false);
const [submitDone, setSubmitDone] = useState(false);
const [skills, setSkills] = useState([]);
const [isLoadingSkills, setIsLoadingSkills] = useState(false);

const onSearch = useCallback(
(value) => {
setSkillModalOpen(true);
setIsLoadingSkills(true);
getSkillsByJobDescription(jdString)
.then((response) => {
setSkills(response.data);
setIsLoadingSkills(false);
setSkillModalOpen(true);
})
.catch(() => {
setIsLoadingSkills(false);
});
},
[jdString]
);

const onConfirationClick = useCallback(() => {
setSearchState("searching");
setCurrentStage(1, stages, setStages);
setTimeout(() => {
setCurrentStage(2, stages, setStages);
setSearchState("done");
}, 3000);
}, []);

const addAnother = useCallback(() => {
// navigate(`/taas/myteams/createnewteam/${projectId}/role`);
}, []);

const submitJob = () => {
setSubmitDone(false);
setModalOpen(true);
setTimeout(() => {
setSubmitDone(true);
}, 3000);
};

const onEditChange = useCallback((value) => {
setJdString(value);
}, []);

return (
<div>
{!searchState ? (
<div styleName="page">
<div styleName="edit-container">
<PageHeader
title="Input Job Description"
backTo="/taas/myteams/createnewteam"
/>
<MarkdownEditor
height="482px"
placeholder="input job description"
onChange={onEditChange}
/>
</div>
<Completeness
extraStyleName="input-job-description"
isDisabled={jdString.length < 10}
stages={stages}
onClick={onSearch}
buttonLabel="Search"
percentage="26"
/>
<SkillListPopup
open={skillModalOpen}
skills={skills}
onClose={() => setSkillModalOpen(false)}
isLoading={isLoadingSkills}
onContinueClick={onConfirationClick}
/>
</div>
) : searchState === "searching" ? (
<div styleName="page">
<SearchCard />
<Completeness
extraStyleName="input-job-description"
isDisabled
stages={stages}
buttonLabel="Submit Request"
percentage="52"
/>
</div>
) : (
<div styleName="page">
<ResultCard />
<Completeness
extraStyleName="input-job-description"
stages={stages}
buttonLabel="Submit Request"
percentage="92"
onClick={submitJob}
/>
<AddAnotherModal
open={modalOpen}
onClose={() => setModalOpen(false)}
submitDone={submitDone}
addAnother={addAnother}
/>
</div>
)}
</div>
);
}

InputJobDescription.propTypes = {
projectId: PT.string,
};

export default withAuthentication(InputJobDescription);
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.page {
display: flex;
flex-direction: row;
justify-content: center;
align-items: flex-start;
margin: 42px 35px;

.edit-container {
background-color: #ffffff;
border-radius: 8px;
max-width: 746px;
position: relative;
margin-right: 30px;
padding: 0 30px 30px;
flex: 1;
}
}
Loading