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

Commit 52c8fb6

Browse files
authored
Merge pull request #358 from mbaghel/dev
Roles Intake - Post-release functional tweaks in UI https://challenges.topcoder.com/projects/28117/challenges/90a05023-9d08-4644-8eb2-c8f6c9f93fd8/view
2 parents 6b04430 + 8f8971c commit 52c8fb6

File tree

12 files changed

+222
-119
lines changed

12 files changed

+222
-119
lines changed

src/routes/CreateNewTeam/actions/index.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const addMatchingRole = (matchingRole) => ({
3232
payload: matchingRole,
3333
});
3434

35-
const deleteMatchingRole = (matchingRole) => ({
35+
const deleteMatchingRole = () => ({
3636
type: ACTION_TYPE.DELETE_MATCHING_ROLE,
3737
});
3838

@@ -61,7 +61,7 @@ export const saveMatchingRole = (matchingRole) => (dispatch, getState) => {
6161
updateLocalStorage(getState().searchedRoles);
6262
};
6363

64-
export const clearMatchingRole = (matchingRole) => (dispatch, getState) => {
64+
export const clearMatchingRole = () => (dispatch, getState) => {
6565
dispatch(deleteMatchingRole());
6666
updateLocalStorage(getState().searchedRoles);
6767
};

src/routes/CreateNewTeam/components/AddedRolesAccordion/index.jsx

+12-2
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,16 @@
88
import React, { useState } from "react";
99
import PT from "prop-types";
1010
import cn from "classnames";
11+
import { useDispatch } from "react-redux";
12+
import { deleteSearchedRole } from "../../actions";
1113
import "./styles.module.scss";
14+
import IconCrossLight from "../../../../assets/images/icon-cross-light.svg";
1215

1316
function AddedRolesAccordion({ addedRoles }) {
1417
const [isOpen, setIsOpen] = useState(false);
1518

19+
const dispatch = useDispatch();
20+
1621
return addedRoles.length ? (
1722
<div styleName="accordion">
1823
<button onClick={() => setIsOpen(!isOpen)} styleName="button">
@@ -27,8 +32,13 @@ function AddedRolesAccordion({ addedRoles }) {
2732
</button>
2833
{isOpen && (
2934
<div styleName="panel">
30-
{addedRoles.map(({ name }) => (
31-
<div styleName="role-name">{name}</div>
35+
{addedRoles.map(({ name, searchId: id }) => (
36+
<div key={id} styleName="role-name">
37+
{name}
38+
<button onClick={() => dispatch(deleteSearchedRole(id))}>
39+
<IconCrossLight height="14px" width="14px" />
40+
</button>
41+
</div>
3242
))}
3343
</div>
3444
)}

src/routes/CreateNewTeam/components/AddedRolesAccordion/styles.module.scss

+16-1
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,12 @@
5555
.panel {
5656
padding: 12px 18px 14px 10px;
5757
.role-name {
58-
height: 40px;
58+
position: relative;
5959
width: 100%;
6060
background-color: #F4F4F4;
6161
border-radius: 6px;
6262
padding: 10px;
63+
padding-right: 30px;
6364
@include font-barlow;
6465
font-size: 16px;
6566
line-height: 20px;
@@ -68,5 +69,19 @@
6869
&:not(:first-child) {
6970
margin-top: 5px;
7071
}
72+
73+
>button {
74+
outline: none;
75+
border: none;
76+
background: none;
77+
position: absolute;
78+
top: 12px;
79+
right: 4px;
80+
&:hover {
81+
g {
82+
stroke: red;
83+
}
84+
}
85+
}
7186
}
7287
}

src/routes/CreateNewTeam/components/BaseCreateModal/index.jsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ function BaseCreateModal({
3535
loadingMessage,
3636
maxWidth = "680px",
3737
darkHeader,
38+
disableFocusTrap,
3839
children,
3940
}) {
4041
return (
@@ -51,8 +52,9 @@ function BaseCreateModal({
5152
modalContainer: containerStyle,
5253
closeButton: closeButtonStyle,
5354
}}
55+
focusTrapped={!disableFocusTrap}
5456
>
55-
<div styleName="modal-body">
57+
<div styleName="modal-body" tabIndex="-1">
5658
{isLoading ? (
5759
<div styleName={cn("modal-header", { "dark-header": darkHeader })}>
5860
<CenteredSpinner />
@@ -86,6 +88,7 @@ BaseCreateModal.propTypes = {
8688
loadingMessage: PT.string,
8789
maxWidth: PT.string,
8890
darkHeader: PT.bool,
91+
disableFocusTrap: PT.bool,
8992
children: PT.node,
9093
};
9194

src/routes/CreateNewTeam/components/InputContainer/index.jsx

+2-6
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,10 @@
55
* input pages. Contains logic and supporting
66
* components for selecting for roles.
77
*/
8-
import React, { useCallback } from "react";
8+
import React from "react";
99
import PT from "prop-types";
1010
import AddedRolesAccordion from "../AddedRolesAccordion";
1111
import Completeness from "../Completeness";
12-
import SearchCard from "../SearchCard";
13-
import ResultCard from "../ResultCard";
14-
import NoMatchingProfilesResultCard from "../NoMatchingProfilesResultCard";
15-
import { isCustomRole } from "utils/helpers";
1612
import "./styles.module.scss";
1713

1814
function InputContainer({
@@ -33,7 +29,7 @@ function InputContainer({
3329
isDisabled={isCompletenessDisabled}
3430
onClick={onClick ? onClick: search}
3531
extraStyleName={completenessStyle}
36-
buttonLabel={"Search"}
32+
buttonLabel="Search"
3733
stages={stages}
3834
percentage="26"
3935
/>

src/routes/CreateNewTeam/components/NoMatchingProfilesResultCard/index.jsx

+45-5
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,42 @@
22
* No Matching Profiles Result Card
33
* Card that appears when there are no matching profiles after searching.
44
*/
5-
import React from "react";
5+
import React, { useCallback, useMemo } from "react";
66
import { Link } from "@reach/router";
77
import PT from "prop-types";
8+
import { useDispatch, useSelector } from "react-redux";
9+
import { addSearchedRole } from "../../actions";
810
import "./styles.module.scss";
911
import IconEarthX from "../../../../assets/images/icon-earth-x.svg";
1012
import Curve from "../../../../assets/images/curve.svg";
1113
import Button from "components/Button";
1214
import { formatMoney } from "utils/format";
1315

1416
function NoMatchingProfilesResultCard({ role }) {
17+
const { addedRoles } = useSelector((state) => state.searchedRoles);
18+
19+
const alreadyAdded = useMemo(() => {
20+
if (
21+
addedRoles.find(
22+
(addedRole) => addedRole.searchId === role.roleSearchRequestId
23+
)
24+
) {
25+
return true;
26+
}
27+
return false;
28+
}, [addedRoles, role]);
29+
30+
const dispatch = useDispatch();
31+
32+
const addRole = useCallback(() => {
33+
const searchId = role.roleSearchRequestId;
34+
let name = "Custom Role";
35+
if (role.jobTitle && role.jobTitle.length) {
36+
name = role.jobTitle;
37+
}
38+
dispatch(addSearchedRole({ searchId, name }));
39+
}, [dispatch, role]);
40+
1541
return (
1642
<div styleName="result-card">
1743
<div styleName="heading">
@@ -21,6 +47,11 @@ function NoMatchingProfilesResultCard({ role }) {
2147
<IconEarthX styleName="transparent-icon" />
2248
</div>
2349
<div styleName="content">
50+
<h4 styleName="job-title">
51+
{role.jobTitle && role.jobTitle.length
52+
? role.jobTitle
53+
: "Custom Role"}
54+
</h4>
2455
<p styleName="info-txt">
2556
We will be looking internally for members matching your requirements
2657
and be back at them in about 2 weeks.
@@ -38,11 +69,20 @@ function NoMatchingProfilesResultCard({ role }) {
3869
<p>/Week</p>
3970
</div>
4071
)}
41-
<Link to="/taas/createnewteam">
42-
<Button type="secondary" styleName="button">
43-
Modify Search Criteria
72+
<div styleName="button-group">
73+
<Link to="/taas/createnewteam">
74+
<Button styleName="left" type="secondary">
75+
Modify Search Criteria
76+
</Button>
77+
</Link>
78+
<Button
79+
onClick={addRole}
80+
disabled={!role.roleSearchRequestId || alreadyAdded}
81+
type="primary"
82+
>
83+
{alreadyAdded ? "Added" : "Add Custom Role"}
4484
</Button>
45-
</Link>
85+
</div>
4686
</div>
4787
</div>
4888
);

src/routes/CreateNewTeam/components/NoMatchingProfilesResultCard/styles.module.scss

+20-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
justify-content: flex-start;
1414
align-items: center;
1515
padding: 30px 0 60px 0;
16-
margin-bottom: 30px;
16+
margin-bottom: 14px;
1717
color: #fff;
1818
background-image: linear-gradient(225deg, #555555 0%, #2A2A2A 100%);
1919
position: relative;
@@ -41,6 +41,17 @@
4141
flex-direction: column;
4242
align-items: center;
4343
padding-bottom: 61px;
44+
.job-title {
45+
@include font-barlow;
46+
font-size: 22px;
47+
margin-bottom: 18px;
48+
font-weight: 600;
49+
text-align: center;
50+
text-transform: uppercase;
51+
// position text over bottom of header image
52+
position: relative;
53+
z-index: 100;
54+
}
4455
p.info-txt {
4556
@include font-roboto;
4657
font-size: 14px;
@@ -82,8 +93,15 @@
8293
}
8394
}
8495

85-
.button {
96+
.button-group {
8697
margin-top: 62px;
98+
display: flex;
99+
flex-direction: row;
100+
align-items: center;
101+
102+
.left {
103+
margin-right: 30px;
104+
}
87105
}
88106
}
89107

src/routes/CreateNewTeam/components/SearchAndSubmit/index.jsx

+13-12
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@ import React, { useCallback, useState, useEffect } from "react";
44
import { useDispatch, useSelector } from "react-redux";
55
import { searchRoles } from "services/teams";
66
import { isCustomRole, setCurrentStage } from "utils/helpers";
7-
import { clearMatchingRole, saveMatchingRole, addRoleSearchId, addSearchedRole } from "../../actions";
7+
import {
8+
clearMatchingRole,
9+
saveMatchingRole,
10+
addRoleSearchId,
11+
addSearchedRole,
12+
} from "../../actions";
813
import InputContainer from "../InputContainer";
914
import SearchContainer from "../SearchContainer";
1015
import SubmitContainer from "../SubmitContainer";
@@ -14,19 +19,19 @@ function SearchAndSubmit(props) {
1419

1520
const [searchState, setSearchState] = useState(null);
1621

17-
const { matchingRole } = useSelector(
18-
(state) => state.searchedRoles
19-
);
22+
const { matchingRole } = useSelector((state) => state.searchedRoles);
2023

21-
useEffect(()=> {
22-
const isFromInputPage = searchObject.role || searchObject.skills && searchObject.skills.length
23-
|| searchObject.jobDescription
24+
useEffect(() => {
25+
const isFromInputPage =
26+
searchObject.role ||
27+
(searchObject.skills && searchObject.skills.length) ||
28+
searchObject.jobDescription;
2429
// refresh in search page directly
2530
if (matchingRole && !isFromInputPage) {
2631
setCurrentStage(2, stages, setStages);
2732
setSearchState("done");
2833
}
29-
}, [])
34+
}, []);
3035

3136
const dispatch = useDispatch();
3237

@@ -52,8 +57,6 @@ function SearchAndSubmit(props) {
5257
} else if (searchId) {
5358
dispatch(addRoleSearchId(searchId));
5459
}
55-
// setMatchingRole(res.data);
56-
5760
dispatch(saveMatchingRole(res.data));
5861
})
5962
.catch((err) => {
@@ -78,8 +81,6 @@ function SearchAndSubmit(props) {
7881
<SearchContainer
7982
path="search"
8083
addedRoles={addedRoles}
81-
previousSearchId={previousSearchId}
82-
search={search}
8384
searchState={searchState}
8485
matchingRole={matchingRole}
8586
{...props}

src/routes/CreateNewTeam/components/SearchContainer/index.jsx

+18-11
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,36 @@
55
* search pages. Contains logic and supporting
66
* components for searching for roles.
77
*/
8-
import React, { useCallback } from "react";
8+
import React, { useCallback, useState } from "react";
99
import PT from "prop-types";
1010
import AddedRolesAccordion from "../AddedRolesAccordion";
1111
import Completeness from "../Completeness";
1212
import SearchCard from "../SearchCard";
1313
import ResultCard from "../ResultCard";
1414
import NoMatchingProfilesResultCard from "../NoMatchingProfilesResultCard";
1515
import { isCustomRole } from "utils/helpers";
16+
import AddAnotherModal from "../AddAnotherModal";
1617
import "./styles.module.scss";
1718

1819
function SearchContainer({
1920
stages,
20-
isCompletenessDisabled,
21-
toRender,
22-
onClick,
23-
search,
2421
completenessStyle,
2522
navigate,
2623
addedRoles,
2724
searchState,
2825
matchingRole,
2926
}) {
27+
const [addAnotherOpen, setAddAnotherOpen] = useState(false);
28+
3029
const onSubmit = useCallback(() => {
30+
setAddAnotherOpen(false);
3131
navigate("../result");
3232
}, [navigate]);
3333

34+
const addAnother = useCallback(() => {
35+
navigate("/taas/createnewteam");
36+
}, [navigate]);
37+
3438
const renderLeftSide = () => {
3539
if (searchState === "searching") return <SearchCard />;
3640
if (!isCustomRole(matchingRole)) return <ResultCard role={matchingRole} />;
@@ -53,23 +57,26 @@ function SearchContainer({
5357
searchState === "searching" ||
5458
(searchState === "done" && (!addedRoles || !addedRoles.length))
5559
}
56-
onClick={searchState ? onSubmit : onClick ? onClick : search}
60+
onClick={() => setAddAnotherOpen(true)}
5761
extraStyleName={completenessStyle}
58-
buttonLabel={searchState ? "Submit Request" : "Search"}
62+
buttonLabel="Submit Request"
5963
stages={stages}
6064
percentage={getPercentage()}
6165
/>
6266
</div>
67+
<AddAnotherModal
68+
open={addAnotherOpen}
69+
onClose={() => setAddAnotherOpen(false)}
70+
submitDone={true}
71+
onContinueClick={onSubmit}
72+
addAnother={addAnother}
73+
/>
6374
</div>
6475
);
6576
}
6677

6778
SearchContainer.propTypes = {
6879
stages: PT.array,
69-
isCompletenessDisabled: PT.bool,
70-
onClick: PT.func,
71-
search: PT.func,
72-
toRender: PT.func,
7380
completenessStyle: PT.string,
7481
navigate: PT.func,
7582
addedRoles: PT.array,

0 commit comments

Comments
 (0)