diff --git a/src/constants/index.js b/src/constants/index.js index 46a60d98..f1c5b67c 100644 --- a/src/constants/index.js +++ b/src/constants/index.js @@ -258,6 +258,12 @@ export const ACTION_TYPE = { ADD_SEARCHED_ROLE: "ADD_SEARCHED_ROLE", ADD_ROLE_SEARCH_ID: "ADD_ROLE_SEARCH_ID", DELETE_SEARCHED_ROLE: "DELETE_SEARCHED_ROLE", + + /* + * matching role + */ + ADD_MATCHING_ROLE: "ADD_MATCHING_ROLE", + DELETE_MATCHING_ROLE: "DELETE_MATCHING_ROLE", }; /** diff --git a/src/routes/CreateNewTeam/actions/index.js b/src/routes/CreateNewTeam/actions/index.js index a67e6569..0a224017 100644 --- a/src/routes/CreateNewTeam/actions/index.js +++ b/src/routes/CreateNewTeam/actions/index.js @@ -27,6 +27,15 @@ const deleteRole = (id) => ({ payload: id, }); +const addMatchingRole = (matchingRole) => ({ + type: ACTION_TYPE.ADD_MATCHING_ROLE, + payload: matchingRole, +}); + +const deleteMatchingRole = () => ({ + type: ACTION_TYPE.DELETE_MATCHING_ROLE, +}); + export const clearSearchedRoles = () => (dispatch, getState) => { dispatch(clearRoles()); updateLocalStorage(getState().searchedRoles); @@ -46,3 +55,13 @@ export const deleteSearchedRole = (id) => (dispatch, getState) => { dispatch(deleteRole(id)); updateLocalStorage(getState().searchedRoles); }; + +export const saveMatchingRole = (matchingRole) => (dispatch, getState) => { + dispatch(addMatchingRole(matchingRole)); + updateLocalStorage(getState().searchedRoles); +}; + +export const clearMatchingRole = () => (dispatch, getState) => { + dispatch(deleteMatchingRole()); + updateLocalStorage(getState().searchedRoles); +}; diff --git a/src/routes/CreateNewTeam/components/AddedRolesAccordion/index.jsx b/src/routes/CreateNewTeam/components/AddedRolesAccordion/index.jsx index ece5e080..1618b2b3 100644 --- a/src/routes/CreateNewTeam/components/AddedRolesAccordion/index.jsx +++ b/src/routes/CreateNewTeam/components/AddedRolesAccordion/index.jsx @@ -8,11 +8,16 @@ import React, { useState } from "react"; import PT from "prop-types"; import cn from "classnames"; +import { useDispatch } from "react-redux"; +import { deleteSearchedRole } from "../../actions"; import "./styles.module.scss"; +import IconCrossLight from "../../../../assets/images/icon-cross-light.svg"; function AddedRolesAccordion({ addedRoles }) { const [isOpen, setIsOpen] = useState(false); + const dispatch = useDispatch(); + return addedRoles.length ? (
{isOpen && (
- {addedRoles.map(({ name }) => ( -
{name}
+ {addedRoles.map(({ name, searchId: id }) => ( +
+ {name} + +
))}
)} diff --git a/src/routes/CreateNewTeam/components/AddedRolesAccordion/styles.module.scss b/src/routes/CreateNewTeam/components/AddedRolesAccordion/styles.module.scss index 6478f1f0..67f7c05e 100644 --- a/src/routes/CreateNewTeam/components/AddedRolesAccordion/styles.module.scss +++ b/src/routes/CreateNewTeam/components/AddedRolesAccordion/styles.module.scss @@ -55,11 +55,12 @@ .panel { padding: 12px 18px 14px 10px; .role-name { - height: 40px; + position: relative; width: 100%; background-color: #F4F4F4; border-radius: 6px; padding: 10px; + padding-right: 30px; @include font-barlow; font-size: 16px; line-height: 20px; @@ -68,5 +69,19 @@ &:not(:first-child) { margin-top: 5px; } + + >button { + outline: none; + border: none; + background: none; + position: absolute; + top: 12px; + right: 4px; + &:hover { + g { + stroke: red; + } + } + } } } \ No newline at end of file diff --git a/src/routes/CreateNewTeam/components/BaseCreateModal/index.jsx b/src/routes/CreateNewTeam/components/BaseCreateModal/index.jsx index d7fcecbb..17528b3e 100644 --- a/src/routes/CreateNewTeam/components/BaseCreateModal/index.jsx +++ b/src/routes/CreateNewTeam/components/BaseCreateModal/index.jsx @@ -35,6 +35,7 @@ function BaseCreateModal({ loadingMessage, maxWidth = "680px", darkHeader, + disableFocusTrap, children, }) { return ( @@ -51,8 +52,9 @@ function BaseCreateModal({ modalContainer: containerStyle, closeButton: closeButtonStyle, }} + focusTrapped={!disableFocusTrap} > -
+
{isLoading ? (
@@ -86,6 +88,7 @@ BaseCreateModal.propTypes = { loadingMessage: PT.string, maxWidth: PT.string, darkHeader: PT.bool, + disableFocusTrap: PT.bool, children: PT.node, }; diff --git a/src/routes/CreateNewTeam/components/Completeness/styles.module.scss b/src/routes/CreateNewTeam/components/Completeness/styles.module.scss index 6e12427f..3438d020 100644 --- a/src/routes/CreateNewTeam/components/Completeness/styles.module.scss +++ b/src/routes/CreateNewTeam/components/Completeness/styles.module.scss @@ -2,6 +2,7 @@ .completeness { @include rounded-card; + overflow: hidden; padding: 12px; position: relative; width: 250px; @@ -25,12 +26,19 @@ .list { margin-bottom: 55px; + & + button[disabled] { + background-color: #E9E9E9; + color: #FFF; + opacity: 1; + filter: none; + } } .list-item { margin-bottom: 14px; font-size: 14px; line-height: 16px; + font-weight: 400; &:before { content: ""; @@ -45,14 +53,14 @@ } &.active { - font-weight: 700; + font-weight: 500; &:before { background-color: #fff; } } &.done { - font-weight: 700; + font-weight: 400; color: rgba(255, 255, 255, 0.6); &:before { content: "✓"; diff --git a/src/routes/CreateNewTeam/components/InputContainer/index.jsx b/src/routes/CreateNewTeam/components/InputContainer/index.jsx new file mode 100644 index 00000000..cebc1551 --- /dev/null +++ b/src/routes/CreateNewTeam/components/InputContainer/index.jsx @@ -0,0 +1,51 @@ +/** + * InputContainer + * + * A container component for the different + * input pages. Contains logic and supporting + * components for selecting for roles. + */ +import React from "react"; +import PT from "prop-types"; +import AddedRolesAccordion from "../AddedRolesAccordion"; +import Completeness from "../Completeness"; +import "./styles.module.scss"; + +function InputContainer({ + stages, + isCompletenessDisabled, + toRender, + search, + onClick, + completenessStyle, + addedRoles, +}) { + return ( +
+ {toRender(search)} +
+ + +
+
+ ); +} + +InputContainer.propTypes = { + stages: PT.array, + isCompletenessDisabled: PT.bool, + search: PT.func, + onClick: PT.func, + toRender: PT.func, + completenessStyle: PT.string, + addedRoles: PT.array, +}; + +export default InputContainer; diff --git a/src/routes/CreateNewTeam/components/InputContainer/styles.module.scss b/src/routes/CreateNewTeam/components/InputContainer/styles.module.scss new file mode 100644 index 00000000..99cec905 --- /dev/null +++ b/src/routes/CreateNewTeam/components/InputContainer/styles.module.scss @@ -0,0 +1,14 @@ +.page { + display: flex; + flex-direction: row; + justify-content: center; + align-items: flex-start; + margin: 42px 35px; + .right-side { + display: flex; + flex-direction: column; + & > div:not(:first-child) { + margin-top: 16px; + } + } +} \ No newline at end of file diff --git a/src/routes/CreateNewTeam/components/ItemList/index.jsx b/src/routes/CreateNewTeam/components/ItemList/index.jsx index 56b6496a..1305eae6 100644 --- a/src/routes/CreateNewTeam/components/ItemList/index.jsx +++ b/src/routes/CreateNewTeam/components/ItemList/index.jsx @@ -36,7 +36,7 @@ function ItemList({ return (
{title}
} backTo="/taas/createnewteam" aside={ <> diff --git a/src/routes/CreateNewTeam/components/ItemList/styles.module.scss b/src/routes/CreateNewTeam/components/ItemList/styles.module.scss index 6e41531e..cf201197 100644 --- a/src/routes/CreateNewTeam/components/ItemList/styles.module.scss +++ b/src/routes/CreateNewTeam/components/ItemList/styles.module.scss @@ -9,6 +9,9 @@ height: 80vh; overflow-y: auto; + .title { + font-weight: 500; + } > header { padding: 16px 24px; } @@ -67,4 +70,4 @@ input:not([type="checkbox"]).filter-input { justify-content: flex-start; flex-wrap: wrap; margin-right: 24px; -} \ No newline at end of file +} diff --git a/src/routes/CreateNewTeam/components/NoMatchingProfilesResultCard/index.jsx b/src/routes/CreateNewTeam/components/NoMatchingProfilesResultCard/index.jsx index 4daee929..2085ab7c 100644 --- a/src/routes/CreateNewTeam/components/NoMatchingProfilesResultCard/index.jsx +++ b/src/routes/CreateNewTeam/components/NoMatchingProfilesResultCard/index.jsx @@ -2,9 +2,11 @@ * No Matching Profiles Result Card * Card that appears when there are no matching profiles after searching. */ -import React from "react"; +import React, { useCallback, useMemo } from "react"; import { Link } from "@reach/router"; import PT from "prop-types"; +import { useDispatch, useSelector } from "react-redux"; +import { addSearchedRole } from "../../actions"; import "./styles.module.scss"; import IconEarthX from "../../../../assets/images/icon-earth-x.svg"; import Curve from "../../../../assets/images/curve.svg"; @@ -12,6 +14,30 @@ import Button from "components/Button"; import { formatMoney } from "utils/format"; function NoMatchingProfilesResultCard({ role }) { + const { addedRoles } = useSelector((state) => state.searchedRoles); + + const alreadyAdded = useMemo(() => { + if ( + addedRoles.find( + (addedRole) => addedRole.searchId === role.roleSearchRequestId + ) + ) { + return true; + } + return false; + }, [addedRoles, role]); + + const dispatch = useDispatch(); + + const addRole = useCallback(() => { + const searchId = role.roleSearchRequestId; + let name = "Custom Role"; + if (role.jobTitle && role.jobTitle.length) { + name = role.jobTitle; + } + dispatch(addSearchedRole({ searchId, name })); + }, [dispatch, role]); + return (
@@ -21,6 +47,11 @@ function NoMatchingProfilesResultCard({ role }) {
+

+ {role.jobTitle && role.jobTitle.length + ? role.jobTitle + : "Custom Role"} +

We will be looking internally for members matching your requirements and be back at them in about 2 weeks. @@ -38,11 +69,20 @@ function NoMatchingProfilesResultCard({ role }) {

/Week

)} - - + + - +
); diff --git a/src/routes/CreateNewTeam/components/NoMatchingProfilesResultCard/styles.module.scss b/src/routes/CreateNewTeam/components/NoMatchingProfilesResultCard/styles.module.scss index 7334e07f..b39ab76b 100644 --- a/src/routes/CreateNewTeam/components/NoMatchingProfilesResultCard/styles.module.scss +++ b/src/routes/CreateNewTeam/components/NoMatchingProfilesResultCard/styles.module.scss @@ -13,7 +13,7 @@ justify-content: flex-start; align-items: center; padding: 30px 0 60px 0; - margin-bottom: 30px; + margin-bottom: 14px; color: #fff; background-image: linear-gradient(225deg, #555555 0%, #2A2A2A 100%); position: relative; @@ -41,6 +41,17 @@ flex-direction: column; align-items: center; padding-bottom: 61px; + .job-title { + @include font-barlow; + font-size: 22px; + margin-bottom: 18px; + font-weight: 600; + text-align: center; + text-transform: uppercase; + // position text over bottom of header image + position: relative; + z-index: 100; + } p.info-txt { @include font-roboto; font-size: 14px; @@ -82,8 +93,15 @@ } } - .button { + .button-group { margin-top: 62px; + display: flex; + flex-direction: row; + align-items: center; + + .left { + margin-right: 30px; + } } } diff --git a/src/routes/CreateNewTeam/components/SearchAndSubmit/index.jsx b/src/routes/CreateNewTeam/components/SearchAndSubmit/index.jsx index 778fd984..bfefd418 100644 --- a/src/routes/CreateNewTeam/components/SearchAndSubmit/index.jsx +++ b/src/routes/CreateNewTeam/components/SearchAndSubmit/index.jsx @@ -1,29 +1,49 @@ -import { Router } from "@reach/router"; +import { Router, navigate } from "@reach/router"; import _ from "lodash"; -import React, { useCallback, useState } from "react"; +import React, { useCallback, useState, useEffect } from "react"; import { useDispatch, useSelector } from "react-redux"; import { searchRoles } from "services/teams"; import { isCustomRole, setCurrentStage } from "utils/helpers"; -import { addRoleSearchId, addSearchedRole } from "../../actions"; +import { + clearMatchingRole, + saveMatchingRole, + addRoleSearchId, + addSearchedRole, +} from "../../actions"; +import InputContainer from "../InputContainer"; import SearchContainer from "../SearchContainer"; import SubmitContainer from "../SubmitContainer"; function SearchAndSubmit(props) { - const { stages, setStages, searchObject, onClick } = props; + const { stages, setStages, searchObject, onClick, page } = props; const [searchState, setSearchState] = useState(null); - const [matchingRole, setMatchingRole] = useState(null); + + const { matchingRole } = useSelector((state) => state.searchedRoles); + + useEffect(() => { + const isFromInputPage = + searchObject.role || + (searchObject.skills && searchObject.skills.length) || + searchObject.jobDescription; + // refresh in search page directly + if (matchingRole && !isFromInputPage) { + setCurrentStage(2, stages, setStages); + setSearchState("done"); + } + }, []); + + const dispatch = useDispatch(); const { addedRoles, previousSearchId } = useSelector( (state) => state.searchedRoles ); - const dispatch = useDispatch(); - const search = useCallback(() => { + navigate(`${page}/search`); setCurrentStage(1, stages, setStages); setSearchState("searching"); - setMatchingRole(null); + dispatch(clearMatchingRole()); const searchObjectCopy = { ...searchObject }; if (previousSearchId) { searchObjectCopy.previousRoleSearchRequestId = previousSearchId; @@ -37,7 +57,7 @@ function SearchAndSubmit(props) { } else if (searchId) { dispatch(addRoleSearchId(searchId)); } - setMatchingRole(res.data); + dispatch(saveMatchingRole(res.data)); }) .catch((err) => { console.error(err); @@ -51,11 +71,16 @@ function SearchAndSubmit(props) { return ( - + { - navigate("result"); + setAddAnotherOpen(false); + navigate("../result"); + }, [navigate]); + + const addAnother = useCallback(() => { + navigate("/taas/createnewteam"); }, [navigate]); const renderLeftSide = () => { - if (!searchState) return toRender(search); if (searchState === "searching") return ; if (!isCustomRole(matchingRole)) return ; return ; }; const getPercentage = useCallback(() => { - if (!searchState) return "26"; if (searchState === "searching") return "52"; if (matchingRole) return "98"; return "88"; @@ -52,27 +54,29 @@ function SearchContainer({ setAddAnotherOpen(true)} extraStyleName={completenessStyle} - buttonLabel={searchState ? "Submit Request" : "Search"} + buttonLabel="Submit Request" stages={stages} percentage={getPercentage()} />
+ setAddAnotherOpen(false)} + submitDone={true} + onContinueClick={onSubmit} + addAnother={addAnother} + />
); } SearchContainer.propTypes = { stages: PT.array, - isCompletenessDisabled: PT.bool, - onClick: PT.func, - search: PT.func, - toRender: PT.func, completenessStyle: PT.string, navigate: PT.func, addedRoles: PT.array, diff --git a/src/routes/CreateNewTeam/components/SubmitContainer/index.jsx b/src/routes/CreateNewTeam/components/SubmitContainer/index.jsx index aacd05e4..b7bfdc40 100644 --- a/src/routes/CreateNewTeam/components/SubmitContainer/index.jsx +++ b/src/routes/CreateNewTeam/components/SubmitContainer/index.jsx @@ -26,7 +26,7 @@ import "./styles.module.scss"; import { isCustomRole, setCurrentStage } from "utils/helpers"; import { clearSearchedRoles } from "../../actions"; import { postTeamRequest } from "services/teams"; -import SuccessCard from "../SuccessCard"; +import NoMatchingProfilesResultCard from "../NoMatchingProfilesResultCard"; function SubmitContainer({ stages, @@ -35,8 +35,8 @@ function SubmitContainer({ matchingRole, addedRoles, }) { - const [addAnotherOpen, setAddAnotherOpen] = useState(true); - const [teamDetailsOpen, setTeamDetailsOpen] = useState(false); + const [addAnotherOpen, setAddAnotherOpen] = useState(false); + const [teamDetailsOpen, setTeamDetailsOpen] = useState(true); const [teamObject, setTeamObject] = useState(null); const [requestLoading, setRequestLoading] = useState(false); @@ -95,8 +95,11 @@ function SubmitContainer({ setRequestLoading(true); postTeamRequest(teamObject) .then(() => { - dispatch(clearSearchedRoles()); - navigate("/taas/myteams"); + setTimeout(() => { + dispatch(clearSearchedRoles()); + // Backend api create project has sync issue, so delay 2 seconds + navigate("/taas/myteams"); + }, 2000); }) .catch((err) => { setRequestLoading(false); @@ -109,7 +112,7 @@ function SubmitContainer({ {!isCustomRole(matchingRole) ? ( ) : ( - + )}
diff --git a/src/routes/CreateNewTeam/components/TeamDetailsModal/index.jsx b/src/routes/CreateNewTeam/components/TeamDetailsModal/index.jsx index 11802f60..30d89b08 100644 --- a/src/routes/CreateNewTeam/components/TeamDetailsModal/index.jsx +++ b/src/routes/CreateNewTeam/components/TeamDetailsModal/index.jsx @@ -3,7 +3,7 @@ * Popup form to enter details about the * team request before submitting. */ -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import PT from "prop-types"; import { Form, Field, useField } from "react-final-form"; import { useDispatch } from "react-redux"; @@ -18,6 +18,7 @@ import { deleteSearchedRole } from "../../actions"; import IconCrossLight from "../../../../assets/images/icon-cross-light.svg"; import "./styles.module.scss"; import NumberInput from "components/NumberInput"; +import { validator, validateExists } from "./utils/validator"; const Error = ({ name }) => { const { @@ -28,13 +29,23 @@ const Error = ({ name }) => { function TeamDetailsModal({ open, onClose, submitForm, addedRoles }) { const [showDescription, setShowDescription] = useState(false); - const [startMonthVisible, setStartMonthVisible] = useState(() => { - const roles = {}; - addedRoles.forEach(({ searchId }) => { - roles[searchId] = false; - }); - return roles; - }); + const [startMonthVisible, setStartMonthVisible] = useState({}); + + // Ensure role is removed from form state when it is removed from redux store + let getFormState; + let clearFormField; + useEffect(() => { + const values = getFormState().values; + for (let fieldName of Object.keys(values)) { + if (fieldName === "teamName" || fieldName === "teamDescription") { + continue; + } + if (addedRoles.findIndex((role) => role.searchId === fieldName) === -1) { + clearFormField(fieldName); + setStartMonthVisible((state) => ({ ...state, [fieldName]: false })); + } + } + }, [getFormState, addedRoles, clearFormField]); const dispatch = useDispatch(); @@ -42,64 +53,6 @@ function TeamDetailsModal({ open, onClose, submitForm, addedRoles }) { setShowDescription((prevState) => !prevState); }; - const validateName = (name) => { - if (!name || name.trim().length === 0) { - return "Please enter a team name."; - } - return undefined; - }; - - const validateNumber = (number) => { - const converted = Number(number); - - if ( - Number.isNaN(converted) || - converted !== Math.floor(converted) || - converted < 1 - ) { - return "Please enter a positive integer"; - } - return undefined; - }; - - const validateMonth = (monthString) => { - const then = new Date(monthString); - const now = new Date(); - const thenYear = then.getFullYear(); - const nowYear = now.getFullYear(); - const thenMonth = then.getMonth(); - const nowMonth = now.getMonth(); - - if (thenYear < nowYear || (thenYear === nowYear && thenMonth < nowMonth)) { - return "Start month may not be before current month"; - } - return undefined; - }; - - const validateRole = (role) => { - const roleErrors = {}; - roleErrors.numberOfResources = validateNumber(role.numberOfResources); - roleErrors.durationWeeks = validateNumber(role.durationWeeks); - if (role.startMonth) { - roleErrors.startMonth = validateMonth(role.startMonth); - } - - return roleErrors; - }; - - const validator = (values) => { - const errors = {}; - - errors.teamName = validateName(values.teamName); - - for (const key of Object.keys(values)) { - if (key === "teamDescription" || key === "teamName") continue; - errors[key] = validateRole(values[key]); - } - - return errors; - }; - return (
undefined); }, }} - initialValues={{ teamName: "My Great Team" }} validate={validator} > {({ @@ -116,8 +68,11 @@ function TeamDetailsModal({ open, onClose, submitForm, addedRoles }) { hasValidationErrors, form: { mutators: { clearField }, + getState, }, }) => { + getFormState = getState; + clearFormField = clearField; return ( } + disableFocusTrap >
{name} - + {({ input, meta }) => ( - + {({ input, meta }) => ( { - clearField(id); dispatch(deleteSearchedRole(id)); }} > diff --git a/src/routes/CreateNewTeam/components/TeamDetailsModal/styles.module.scss b/src/routes/CreateNewTeam/components/TeamDetailsModal/styles.module.scss index 80ced5a3..96193ed6 100644 --- a/src/routes/CreateNewTeam/components/TeamDetailsModal/styles.module.scss +++ b/src/routes/CreateNewTeam/components/TeamDetailsModal/styles.module.scss @@ -36,7 +36,7 @@ .role-row { td { padding: 18px 18px 18px 0; - vertical-align: middle; + vertical-align: top; @include font-barlow; font-weight: 600; font-size: 16px; @@ -66,6 +66,7 @@ align-items: center; justify-content: flex-start; width: 118px; + margin-top: 13px; } .error { @@ -79,6 +80,8 @@ border: none; background: none; + margin-top: 13px; + &:hover { g { stroke: red; diff --git a/src/routes/CreateNewTeam/components/TeamDetailsModal/utils/validator.js b/src/routes/CreateNewTeam/components/TeamDetailsModal/utils/validator.js new file mode 100644 index 00000000..9e1a9caf --- /dev/null +++ b/src/routes/CreateNewTeam/components/TeamDetailsModal/utils/validator.js @@ -0,0 +1,63 @@ +const validateName = (name) => { + if (!name || name.trim().length === 0) { + return "Please enter a team name."; + } + return undefined; +}; + +const validateNumber = (number) => { + const converted = Number(number); + + if ( + Number.isNaN(converted) || + converted !== Math.floor(converted) || + converted < 1 + ) { + return "Please enter a positive integer"; + } + return undefined; +}; + +const validateMonth = (monthString) => { + const then = new Date(monthString); + const now = new Date(); + const thenYear = then.getFullYear(); + const nowYear = now.getFullYear(); + const thenMonth = then.getMonth(); + const nowMonth = now.getMonth(); + + if (thenYear < nowYear || (thenYear === nowYear && thenMonth < nowMonth)) { + return "Start month may not be before current month"; + } + return undefined; +}; + +const validateRole = (role) => { + const roleErrors = {}; + roleErrors.numberOfResources = validateNumber(role.numberOfResources); + roleErrors.durationWeeks = validateNumber(role.durationWeeks); + if (role.startMonth) { + roleErrors.startMonth = validateMonth(role.startMonth); + } + + return roleErrors; +}; + +const validator = (values) => { + const errors = {}; + + errors.teamName = validateName(values.teamName); + + for (const key of Object.keys(values)) { + if (key === "teamDescription" || key === "teamName") continue; + errors[key] = validateRole(values[key]); + } + + return errors; +}; + +const validateExists = (value) => { + return value === undefined ? "Please enter a positive integer" : undefined; +}; + +export { validator, validateExists }; diff --git a/src/routes/CreateNewTeam/index.jsx b/src/routes/CreateNewTeam/index.jsx index 3ca8343d..7140a739 100644 --- a/src/routes/CreateNewTeam/index.jsx +++ b/src/routes/CreateNewTeam/index.jsx @@ -6,23 +6,28 @@ * or inputting a job description */ import React, { useEffect } from "react"; +import { useDispatch } from "react-redux"; import { navigate } from "@reach/router"; import _ from "lodash"; import Page from "components/Page"; import PageHeader from "components/PageHeader"; import LandingBox from "./components/LandingBox"; +import { clearMatchingRole } from "./actions"; 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"; +import "./styles.module.scss"; function CreateNewTeam() { + const dispatch = useDispatch(); const goToRoute = (path) => { + dispatch(clearMatchingRole()); navigate(path); }; return ( - + Create New Team
} />

Please select how you want to find members that match your requirements.

diff --git a/src/routes/CreateNewTeam/pages/InputJobDescription/index.jsx b/src/routes/CreateNewTeam/pages/InputJobDescription/index.jsx index 2ba16303..10e1809b 100644 --- a/src/routes/CreateNewTeam/pages/InputJobDescription/index.jsx +++ b/src/routes/CreateNewTeam/pages/InputJobDescription/index.jsx @@ -56,14 +56,15 @@ function InputJobDescription() { 255} + isCompletenessDisabled={jdString.length < 10 || jdString.length > 2000} completenessStyle="input-job-description" searchObject={searchObject} + page="jd" onClick={onClick} toRender={(searchFunc) => (
Input Job Description
} backTo="/taas/createnewteam" />
@@ -80,8 +81,8 @@ function InputJobDescription() { placeholder="input job description" onChange={onEditChange} errorMessage={ - jdString.length > 255 - ? "Maximum of 255 characters. Please reduce job description length." + jdString.length > 2000 + ? "Maximum of 2000 characters. Please reduce job description length." : "" } /> diff --git a/src/routes/CreateNewTeam/pages/InputJobDescription/styles.module.scss b/src/routes/CreateNewTeam/pages/InputJobDescription/styles.module.scss index 892befbe..6b3f1a38 100644 --- a/src/routes/CreateNewTeam/pages/InputJobDescription/styles.module.scss +++ b/src/routes/CreateNewTeam/pages/InputJobDescription/styles.module.scss @@ -8,6 +8,10 @@ flex: 1; } +.title { + font-weight: 500; +} + .job-title { margin-bottom: 15px; @@ -15,4 +19,4 @@ line-height: normal; padding: 8px 15px; } -} \ No newline at end of file +} diff --git a/src/routes/CreateNewTeam/pages/InputSkills/index.jsx b/src/routes/CreateNewTeam/pages/InputSkills/index.jsx index ac0a7b2b..5e520cb2 100644 --- a/src/routes/CreateNewTeam/pages/InputSkills/index.jsx +++ b/src/routes/CreateNewTeam/pages/InputSkills/index.jsx @@ -50,6 +50,7 @@ function InputSkills() { setStages={setStages} isCompletenessDisabled={selectedSkills.length < 1} searchObject={{ skills: selectedSkills }} + page="skills" completenessStyle="input-skills" toRender={() => ( ( diff --git a/src/routes/CreateNewTeam/reducers/index.js b/src/routes/CreateNewTeam/reducers/index.js index d90316bf..2180d81d 100644 --- a/src/routes/CreateNewTeam/reducers/index.js +++ b/src/routes/CreateNewTeam/reducers/index.js @@ -7,6 +7,7 @@ const loadState = () => { const defaultState = { previousSearchId: undefined, addedRoles: [], + matchingRole: undefined, }; try { const state = localStorage.getItem("rolesState"); @@ -38,6 +39,16 @@ const reducer = (state = initialState, action) => { addedRoles: [], }; + case ACTION_TYPE.ADD_MATCHING_ROLE: + return { + ...state, + matchingRole: action.payload, + }; + case ACTION_TYPE.DELETE_MATCHING_ROLE: + return { + ...state, + matchingRole: null, + }; case ACTION_TYPE.ADD_SEARCHED_ROLE: return { ...state, diff --git a/src/routes/CreateNewTeam/styles.module.scss b/src/routes/CreateNewTeam/styles.module.scss new file mode 100644 index 00000000..379eb6ff --- /dev/null +++ b/src/routes/CreateNewTeam/styles.module.scss @@ -0,0 +1,3 @@ +.title { + font-weight: 500; +} diff --git a/src/services/skills.js b/src/services/skills.js index 36a91af8..6d733350 100644 --- a/src/services/skills.js +++ b/src/services/skills.js @@ -37,6 +37,11 @@ function getAllSkills() { page++; loop(page); } else { + skills.sort((a, b) => { + if (a.name.toLowerCase() < b.name.toLowerCase()) return -1; + if (a.name.toLowerCase() > b.name.toLowerCase()) return 1; + return 0; + }); resolve({ data: skills, });