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

Commit aeb5779

Browse files
committed
New styled Month Picker component.
NoMatchingProfiles card uses custom role returned from server. Removed matching rate constant. Cleanup and documentation.
1 parent 64e0af5 commit aeb5779

File tree

13 files changed

+178
-38
lines changed

13 files changed

+178
-38
lines changed
+23
Loading

src/components/InformationTooltip/index.jsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -26,24 +26,24 @@ function InformationTooltip({ text, iconSize = "16px" }) {
2626
name: "offset",
2727
options: {
2828
// use offset to move the tooltip slightly up
29-
offset: [0, 10],
29+
offset: [0, 12],
3030
},
3131
},
3232
{
3333
name: "arrow",
3434
// padding should be equal to border-radius of the tooltip
35-
options: { element: arrowElement, padding: 8 },
35+
options: { element: arrowElement, padding: 5 },
3636
},
3737
],
3838
});
3939

4040
const showTooltip = useCallback(() => {
4141
setIsTooltipShown(true);
42-
}, [setIsTooltipShown]);
42+
}, []);
4343

4444
const hideTooltip = useCallback(() => {
4545
setIsTooltipShown(false);
46-
}, [setIsTooltipShown]);
46+
}, []);
4747

4848
const iconStyle = {
4949
width: iconSize,

src/components/MonthPicker/index.jsx

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* Month Picker
3+
* An styled input component for selecting date by month.
4+
* Compatible with react-final-form
5+
*/
6+
import React from "react";
7+
import PT from "prop-types";
8+
import DatePicker from "react-datepicker";
9+
import "./styles.module.scss";
10+
11+
function getCurrMonthYear() {
12+
const now = new Date();
13+
const year = now.getFullYear();
14+
const month = now.getMonth();
15+
return new Date(`${year}-${month + 1}`);
16+
}
17+
18+
function MonthPicker({ name, value, onChange, onBlur }) {
19+
return (
20+
<div styleName="month-picker">
21+
<DatePicker
22+
name={name}
23+
selected={value}
24+
onChange={onChange}
25+
dateFormat="MMM, yyyy"
26+
showMonthYearPicker
27+
showPopperArrow={false}
28+
onBlur={onBlur}
29+
popperPlacement="top-end"
30+
showFourColumnMonthYearPicker
31+
minDate={getCurrMonthYear()}
32+
/>
33+
</div>
34+
);
35+
}
36+
37+
MonthPicker.propTypes = {
38+
name: PT.string,
39+
value: PT.any,
40+
onChange: PT.func,
41+
onBlur: PT.func,
42+
};
43+
44+
export default MonthPicker;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
@import "styles/include";
2+
3+
.month-picker {
4+
input {
5+
width: 118px;
6+
background-image: url("../../assets/images/icon-thick-calendar.svg");
7+
background-repeat: no-repeat;
8+
background-position: 95px 7px;
9+
}
10+
11+
:global {
12+
.react-datepicker__header {
13+
@include font-barlow;
14+
font-size: 20px;
15+
color: #2a2a2a;
16+
font-weight: 600;
17+
padding-top: 14px;
18+
padding-bottom: 14px;
19+
background-color: transparent;
20+
border-bottom: 1px solid #d4d4d4;
21+
margin: 0 16px;
22+
}
23+
24+
.react-datepicker__month-text {
25+
@include font-roboto;
26+
font-size: 14px;
27+
font-weight: 400;
28+
line-height: 40px;
29+
width: 40px;
30+
height: 40px;
31+
margin: 8px;
32+
border-radius: 100%;
33+
}
34+
.react-datepicker__month--selected {
35+
border-radius: 100%;
36+
background-color: #0AB88A;
37+
}
38+
39+
.react-datepicker__navigation {
40+
top: 18px;
41+
border: 2px solid transparent;
42+
height: 12px;
43+
width: 12px;
44+
}
45+
.react-datepicker__navigation--next, .react-datepicker__navigation--previous {
46+
border-right-color: transparent;
47+
border-bottom-color: transparent;
48+
border-left-color: #137D60;
49+
border-top-color: #137D60;
50+
}
51+
.react-datepicker__navigation--next {
52+
right: 24px;
53+
transform: rotate(135deg);
54+
}
55+
.react-datepicker__navigation--previous {
56+
left: 24px;
57+
transform: rotate(-45deg);
58+
}
59+
}
60+
}

src/constants/index.js

-5
Original file line numberDiff line numberDiff line change
@@ -356,11 +356,6 @@ export const INTERVIEW_POPUP_MEDIA_URL =
356356

357357
export const MAX_ALLOWED_INTERVIEWS = 3;
358358

359-
/**
360-
* Matching rate to show in CreateNewTeam ResultCard
361-
*/
362-
export const MATCHING_RATE = "80";
363-
364359
/**
365360
* Custom role names to remove from RoleList component
366361
*/

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

+14-6
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44
*/
55
import React from "react";
66
import { Link } from "@reach/router";
7+
import PT from "prop-types";
78
import "./styles.module.scss";
89
import IconEarthX from "../../../../assets/images/icon-earth-x.svg";
910
import Curve from "../../../../assets/images/curve.svg";
1011
import Button from "components/Button";
12+
import { formatMoney } from "utils/format";
1113

12-
function NoMatchingProfilesResultCard() {
14+
function NoMatchingProfilesResultCard({ role }) {
1315
return (
1416
<div styleName="result-card">
1517
<div styleName="heading">
@@ -23,11 +25,13 @@ function NoMatchingProfilesResultCard() {
2325
We will be looking internally for members matching your requirements
2426
and be back at them in about 2 weeks.
2527
</p>
26-
<div styleName="niche-rate-box">
27-
<p>Niche Rate</p>
28-
<p styleName="cost">$1,200</p>
29-
<p>/Week</p>
30-
</div>
28+
{role && (
29+
<div styleName="niche-rate-box">
30+
<p>{role.name} Rate</p>
31+
<p styleName="cost">{formatMoney(role.rates[0].global)}</p>
32+
<p>/Week</p>
33+
</div>
34+
)}
3135
<Link to="/taas/myteams/createnewteam">
3236
<Button type="secondary" styleName="button">
3337
Modify Search Criteria
@@ -38,4 +42,8 @@ function NoMatchingProfilesResultCard() {
3842
);
3943
}
4044

45+
NoMatchingProfilesResultCard.propTypes = {
46+
role: PT.object,
47+
};
48+
4149
export default NoMatchingProfilesResultCard;

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

+5-6
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,8 @@ import SearchCard from "../SearchCard";
1515
import ResultCard from "../ResultCard";
1616
import NoMatchingProfilesResultCard from "../NoMatchingProfilesResultCard";
1717
import { searchRoles } from "services/teams";
18-
import { setCurrentStage } from "utils/helpers";
18+
import { isCustomRole, setCurrentStage } from "utils/helpers";
1919
import { addRoleSearchId, addSearchedRole } from "../../actions";
20-
import { CUSTOM_ROLE_NAMES } from "constants";
2120
import "./styles.module.scss";
2221

2322
function SearchContainer({
@@ -52,12 +51,12 @@ function SearchContainer({
5251
.then((res) => {
5352
const name = _.get(res, "data.name");
5453
const searchId = _.get(res, "data.roleSearchRequestId");
55-
if (name && !CUSTOM_ROLE_NAMES.includes(name.toLowerCase())) {
56-
setMatchingRole(res.data);
54+
if (name && !isCustomRole({ name })) {
5755
dispatch(addSearchedRole({ searchId, name }));
5856
} else if (searchId) {
5957
dispatch(addRoleSearchId(searchId));
6058
}
59+
setMatchingRole(res.data);
6160
})
6261
.catch((err) => {
6362
console.error(err);
@@ -71,8 +70,8 @@ function SearchContainer({
7170
const renderLeftSide = () => {
7271
if (!searchState) return toRender;
7372
if (searchState === "searching") return <SearchCard />;
74-
if (matchingRole) return <ResultCard role={matchingRole} />;
75-
return <NoMatchingProfilesResultCard />;
73+
if (!isCustomRole(matchingRole)) return <ResultCard role={matchingRole} />;
74+
return <NoMatchingProfilesResultCard role={matchingRole} />;
7675
};
7776

7877
const getPercentage = useCallback(() => {

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

+4
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ function SubmitContainer({
8282
key === "startMonth" ? val : parseInt(val, 10)
8383
);
8484

85+
if (position.startMonth === null) {
86+
delete position.startMonth;
87+
}
88+
8589
position.roleSearchRequestId = key;
8690
position.roleName = addedRoles.find((role) => role.searchId === key).name;
8791

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

+1-5
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import React from "react";
88
import { Link } from "@reach/router";
99
import IconEarthCheck from "../../../../assets/images/icon-earth-check.svg";
1010
import Curve from "../../../../assets/images/curve.svg";
11-
import { MATCHING_RATE } from "constants";
1211
import "./styles.module.scss";
1312
import Button from "components/Button";
1413

@@ -18,10 +17,7 @@ function SuccessCard() {
1817
<div styleName="heading">
1918
<IconEarthCheck />
2019
<h3>We have matching profiles</h3>
21-
<p>
22-
We have qualified candidates who match {MATCHING_RATE}% or more of
23-
your job requirements.
24-
</p>
20+
<p>We have qualified candidates who match your job requirements.</p>
2521
<Curve styleName="curve" />
2622
<IconEarthCheck styleName="transparent-icon" />
2723
</div>

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

+4-7
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ import BaseCreateModal from "../BaseCreateModal";
1111
import { FORM_FIELD_TYPE } from "constants/";
1212
import { formatPlural } from "utils/format";
1313
import Button from "components/Button";
14-
import "./styles.module.scss";
15-
import DatePicker from "react-datepicker";
14+
import MonthPicker from "components/MonthPicker";
1615
import InformationTooltip from "components/InformationTooltip";
16+
import "./styles.module.scss";
1717

1818
const Error = ({ name }) => {
1919
const {
@@ -201,13 +201,10 @@ function TeamDetailsModal({ open, onClose, submitForm, addedRoles }) {
201201
initialValue={Date.now()}
202202
>
203203
{(props) => (
204-
<DatePicker
204+
<MonthPicker
205205
name={props.input.name}
206-
selected={props.input.value}
206+
value={props.input.value}
207207
onChange={props.input.onChange}
208-
dateFormat="MMM, yyyy"
209-
showMonthYearPicker
210-
showPopperArrow={false}
211208
onBlur={props.input.onBlur}
212209
/>
213210
)}

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

+8-3
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,8 @@
5151
font-size: 14px;
5252
line-height: 22px;
5353
height: 34px;
54-
width: 98px;
55-
&[type="month"] {
56-
width: 170px;
54+
&[type="number"] {
55+
width: 98px;
5756
}
5857
}
5958
}
@@ -78,4 +77,10 @@
7877
textarea {
7978
height: 95px;
8079
}
80+
}
81+
82+
@media only screen and (max-width: 550px) {
83+
.modal-body {
84+
overflow-x: scroll;
85+
}
8186
}

src/routes/CreateNewTeam/pages/SelectRole/index.jsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ import React, { useCallback, useState } from "react";
88
import { useData } from "hooks/useData";
99
import RolesList from "./components/RolesList";
1010
import { getRoles } from "services/roles";
11-
import { CUSTOM_ROLE_NAMES } from "constants";
1211
import LoadingIndicator from "components/LoadingIndicator";
1312
import RoleDetailsModal from "../../components/RoleDetailsModal";
1413
import SearchAndSubmit from "../../components/SearchAndSubmit";
14+
import { isCustomRole } from "utils/helpers";
1515

1616
// Remove custom roles from role list
1717
const removeCustomRoles = (roles) =>
18-
roles.filter(({ name }) => !CUSTOM_ROLE_NAMES.includes(name.toLowerCase()));
18+
roles.filter((role) => !isCustomRole(role));
1919

2020
function SelectRole() {
2121
const [stages, setStages] = useState([

src/utils/helpers.js

+9
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* If there are multiple methods which could be grouped into a separate file by their meaning they should be extracted from here to not make this file too big.
66
*/
77
import _ from "lodash";
8+
import { CUSTOM_ROLE_NAMES } from "constants/";
89

910
/**
1011
* Delay code for some milliseconds using promise.
@@ -62,3 +63,11 @@ export const setCurrentStage = (currentStepIdx, stages, setStagesCallback) => {
6263
.map((s) => ({ ...s, completed: false, isCurrent: false })),
6364
]);
6465
};
66+
67+
/**
68+
* Checks if role is custom/niche
69+
* @param {Object} role role to check
70+
* @returns {boolean} whether the role is custom/niche
71+
*/
72+
export const isCustomRole = (role) =>
73+
!role.name || CUSTOM_ROLE_NAMES.includes(role.name.toLowerCase());

0 commit comments

Comments
 (0)