diff --git a/src/constants/index.js b/src/constants/index.js index f1c5b67c..f36d2868 100644 --- a/src/constants/index.js +++ b/src/constants/index.js @@ -264,6 +264,7 @@ export const ACTION_TYPE = { */ ADD_MATCHING_ROLE: "ADD_MATCHING_ROLE", DELETE_MATCHING_ROLE: "DELETE_MATCHING_ROLE", + EDIT_MATCHING_ROLE: "EDIT_MATCHING_ROLE", }; /** diff --git a/src/routes/CreateNewTeam/actions/index.js b/src/routes/CreateNewTeam/actions/index.js index 0a224017..62d6e04a 100644 --- a/src/routes/CreateNewTeam/actions/index.js +++ b/src/routes/CreateNewTeam/actions/index.js @@ -36,6 +36,11 @@ const deleteMatchingRole = () => ({ type: ACTION_TYPE.DELETE_MATCHING_ROLE, }); +const editMatchingRole = (role) => ({ + type: ACTION_TYPE.EDIT_MATCHING_ROLE, + payload: role, +}); + export const clearSearchedRoles = () => (dispatch, getState) => { dispatch(clearRoles()); updateLocalStorage(getState().searchedRoles); @@ -51,6 +56,11 @@ export const addRoleSearchId = (id) => (dispatch, getState) => { updateLocalStorage(getState().searchedRoles); }; +export const editRoleAction = (role) => (dispatch, getState) => { + dispatch(editMatchingRole(role)); + updateLocalStorage(getState().searchedRoles); +}; + export const deleteSearchedRole = (id) => (dispatch, getState) => { dispatch(deleteRole(id)); updateLocalStorage(getState().searchedRoles); diff --git a/src/routes/CreateNewTeam/components/EditRoleModal/index.jsx b/src/routes/CreateNewTeam/components/EditRoleModal/index.jsx new file mode 100644 index 00000000..fa8bdedb --- /dev/null +++ b/src/routes/CreateNewTeam/components/EditRoleModal/index.jsx @@ -0,0 +1,165 @@ +/** + * Edit Role Modal + * Popup form to enter details about current role + */ +import React, { useEffect, useState } from "react"; +import PT from "prop-types"; +import { Form, Field, useField } from "react-final-form"; +import FormField from "components/FormField"; +import BaseCreateModal from "../BaseCreateModal"; +import Button from "components/Button"; +import MonthPicker from "components/MonthPicker"; +import InformationTooltip from "components/InformationTooltip"; +import IconCrossLight from "../../../../assets/images/icon-cross-light.svg"; +import "./styles.module.scss"; +import NumberInput from "components/NumberInput"; +import { validator, validateExists, validateMin, composeValidators } from "./utils/validator"; + +const Error = ({ name }) => { + const { + meta: { dirty, error }, + } = useField(name, { subscription: { dirty: true, error: true } }); + return dirty && error ? {error} : null; +}; + +function EditRoleModal({ open, onClose, submitForm, role }) { + const [startMonthVisible, setStartMonthVisible] = useState(false); + + return ( +
+ ); +} + +EditRoleModal.propTypes = { + open: PT.bool, + onClose: PT.func, + submitForm: PT.func, + role: PT.object, +}; + +export default EditRoleModal; diff --git a/src/routes/CreateNewTeam/components/EditRoleModal/styles.module.scss b/src/routes/CreateNewTeam/components/EditRoleModal/styles.module.scss new file mode 100644 index 00000000..4d303148 --- /dev/null +++ b/src/routes/CreateNewTeam/components/EditRoleModal/styles.module.scss @@ -0,0 +1,98 @@ +@import "styles/include"; + +.toggle-button { + @include font-roboto; + outline: none; + border: none; + background: none; + font-size: 12px; + font-weight: 500; + color: #137D60; + padding: 1px 6px 0 6px; + + &.toggle-description { + margin-top: 12px; + > span { + font-size: 18px; + vertical-align: middle; + } + } +} + +.table { + margin-top: 40px; + width: 100%; + th { + @include font-roboto; + font-size: 12px; + color: #555; + padding-bottom: 7px; + border-bottom: 1px solid #d4d4d4; + + &.bold { + font-weight: 700; + } + } + + .role-row { + td { + padding: 18px 18px 18px 0; + vertical-align: top; + @include font-barlow; + font-weight: 600; + font-size: 16px; + color: #2a2a2a; + border-bottom: 1px solid #e9e9e9; + + &:last-child { + padding-right: 0; + } + + input { + @include font-roboto; + font-size: 14px; + line-height: normal; + height: 34px; + &[type="number"] { + width: 98px; + } + } + } + } +} + +.flex-container { + display: flex; + flex-direction: row; + align-items: center; + justify-content: flex-start; + width: 118px; + margin-top: 13px; +} + +.error { + font-size: 14px; + font-weight: 400; + color: red; + display: block; +} + +.delete-role { + border: none; + background: none; + + margin-top: 13px; + + &:hover { + g { + stroke: red; + } + } +} + +.modal-body { + overflow-x: auto; + textarea { + height: 95px; + } +} diff --git a/src/routes/CreateNewTeam/components/EditRoleModal/utils/validator.js b/src/routes/CreateNewTeam/components/EditRoleModal/utils/validator.js new file mode 100644 index 00000000..60cb16a8 --- /dev/null +++ b/src/routes/CreateNewTeam/components/EditRoleModal/utils/validator.js @@ -0,0 +1,56 @@ +const composeValidators = (...validators) => (value) => + validators.reduce((error, validator) => error || validator(value), undefined); + +const validateMin = (min) => (value) => + isNaN(value) || value >= min ? undefined : `Should be greater than ${min}`; + +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 validator = (role) => { + const roleErrors = {}; + roleErrors.numberOfResources = validateNumber(role.numberOfResources); + roleErrors.durationWeeks = validateNumber(role.durationWeeks); + if (role.startMonth) { + roleErrors.startMonth = validateMonth(role.startMonth); + } + + return roleErrors; +}; + +const validateExists = (value) => { + return value === undefined ? "Please enter a positive integer" : undefined; +}; + +export { validator, validateExists, validateMin, composeValidators }; diff --git a/src/routes/CreateNewTeam/components/ResultCard/index.jsx b/src/routes/CreateNewTeam/components/ResultCard/index.jsx index 07f21c13..cb56b8ee 100644 --- a/src/routes/CreateNewTeam/components/ResultCard/index.jsx +++ b/src/routes/CreateNewTeam/components/ResultCard/index.jsx @@ -78,10 +78,10 @@ function ResultCard({ role }) { {showRates && !isExternalMember && ( -- Hi {userHandle}, we have special rates for you as a Xeno User! + Hi {userHandle}, we have special rates for you as a Wipro User!
)}/Week
/Week
+/Week
@@ -124,8 +131,15 @@ function ResultCard({ role }) {/Week
/Week
+/Week
@@ -151,8 +165,16 @@ function ResultCard({ role }) {/Week
/Week
+/Week
diff --git a/src/routes/CreateNewTeam/components/ResultCard/styles.module.scss b/src/routes/CreateNewTeam/components/ResultCard/styles.module.scss index 6babd0a1..150884c0 100644 --- a/src/routes/CreateNewTeam/components/ResultCard/styles.module.scss +++ b/src/routes/CreateNewTeam/components/ResultCard/styles.module.scss @@ -138,7 +138,7 @@ padding-bottom: 50px; } -.xeno-rates { +.wipro-rates { display: flex; flex-direction: column; padding: 0 25px 50px 52px; @@ -180,7 +180,8 @@ } } .global, - .in-country, + .global-niche, + .offshore-niche, .offshore { display: flex; flex-direction: column; @@ -225,7 +226,12 @@ .global::before { background-color: #c99014; } - .in-country::before { + + .global-niche::before { + background-color: #0ab88a; + } + + .offshore-niche::before { background-color: #716d67; } .offshore::before { diff --git a/src/routes/CreateNewTeam/components/SearchAndSubmit/index.jsx b/src/routes/CreateNewTeam/components/SearchAndSubmit/index.jsx index bfefd418..e24ed940 100644 --- a/src/routes/CreateNewTeam/components/SearchAndSubmit/index.jsx +++ b/src/routes/CreateNewTeam/components/SearchAndSubmit/index.jsx @@ -14,10 +14,13 @@ import InputContainer from "../InputContainer"; import SearchContainer from "../SearchContainer"; import SubmitContainer from "../SubmitContainer"; +const SEARCHINGTIME = 1600; + function SearchAndSubmit(props) { const { stages, setStages, searchObject, onClick, page } = props; const [searchState, setSearchState] = useState(null); + const [isNewRole, setIsNewRole] = useState(false); const { matchingRole } = useSelector((state) => state.searchedRoles); @@ -48,12 +51,14 @@ function SearchAndSubmit(props) { if (previousSearchId) { searchObjectCopy.previousRoleSearchRequestId = previousSearchId; } + const searchingBegin = Date.now(); searchRoles(searchObjectCopy) .then((res) => { const name = _.get(res, "data.name"); const searchId = _.get(res, "data.roleSearchRequestId"); if (name && !isCustomRole({ name })) { - dispatch(addSearchedRole({ searchId, name })); + dispatch(addSearchedRole({ searchId, name, numberOfResources: 1, durationWeeks: 4 })); + setIsNewRole(true) } else if (searchId) { dispatch(addRoleSearchId(searchId)); } @@ -63,8 +68,13 @@ function SearchAndSubmit(props) { console.error(err); }) .finally(() => { - setCurrentStage(2, stages, setStages); - setSearchState("done"); + _.delay( + () => { + setCurrentStage(2, stages, setStages); + setSearchState("done"); + }, + Date.now() - searchingBegin > SEARCHINGTIME ? 0 : 1500 + ); }); // eslint-disable-next-line react-hooks/exhaustive-deps }, [dispatch, previousSearchId, searchObject]); @@ -80,9 +90,11 @@ function SearchAndSubmit(props) { />