Skip to content

Commit 28d72bb

Browse files
committed
poc-recommender-sub-2
1 parent 32b14e3 commit 28d72bb

File tree

12 files changed

+295
-37
lines changed

12 files changed

+295
-37
lines changed

__tests__/shared/components/challenge-listing/__snapshots__/index.jsx.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ exports[`Matches shallow shapshot 1 shapshot 1 1`] = `
4040
loadMoreOnGoing={null}
4141
loadMoreOpenForRegistration={null}
4242
loadMorePast={null}
43+
loadMoreRecommended={null}
4344
loadMoreReviewOpportunities={null}
4445
loadingPastChallenges={false}
4546
newChallengeDetails={false}
@@ -96,6 +97,7 @@ exports[`Matches shallow shapshot 2 shapshot 2 1`] = `
9697
loadMoreOnGoing={null}
9798
loadMoreOpenForRegistration={null}
9899
loadMorePast={null}
100+
loadMoreRecommended={null}
99101
loadMoreReviewOpportunities={null}
100102
loadingPastChallenges={false}
101103
newChallengeDetails={false}

src/shared/actions/challenge-listing/index.js

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ const REVIEW_OPPORTUNITY_PAGE_SIZE = 1000;
5353
*/
5454
function getChallengeTypesDone() {
5555
return getService()
56-
.getChallengeTypes()
57-
.then(res => res.sort((a, b) => a.name.localeCompare(b.name)));
56+
.getChallengeTypes();
5857
}
5958

6059
/**
@@ -91,6 +90,10 @@ function getAllChallengesInit(uuid, page, frontFilter) {
9190
return { uuid, page, frontFilter };
9291
}
9392

93+
function getRecommendedChallengesInit(uuid, page, frontFilter) {
94+
return { uuid, page, frontFilter };
95+
}
96+
9497
function getMyPastChallengesInit(uuid, page, frontFilter) {
9598
return { uuid, page, frontFilter };
9699
}
@@ -231,6 +234,7 @@ function getActiveChallengesDone(uuid, page, backendFilter, tokenV3, frontFilter
231234
function getOpenForRegistrationChallengesDone(uuid, page, backendFilter,
232235
tokenV3, frontFilter = {}) {
233236
const { sorts } = frontFilter;
237+
const sortOrder = SORT[sorts[BUCKETS.OPEN_FOR_REGISTRATION]];
234238
const filter = {
235239
backendFilter,
236240
frontFilter: {
@@ -240,7 +244,7 @@ function getOpenForRegistrationChallengesDone(uuid, page, backendFilter,
240244
perPage: PAGE_SIZE,
241245
page: page + 1,
242246
sortBy: sorts[BUCKETS.OPEN_FOR_REGISTRATION],
243-
sortOrder: SORT[sorts[BUCKETS.OPEN_FOR_REGISTRATION]].order,
247+
sortOrder: sortOrder ? sortOrder.order : 'asc',
244248
},
245249
};
246250
delete filter.frontFilter.sorts;
@@ -301,6 +305,17 @@ function getAllChallengesDone(uuid, page, backendFilter, tokenV3, frontFilter =
301305
}));
302306
}
303307

308+
function getRecommendedChallengesDone(uuid, tokenV3, sort, filter) {
309+
const service = getService(tokenV3);
310+
return service.getRecommendedChallenges(sort, filter).then(ch => ({
311+
uuid,
312+
recommendedChallenges: ch.challenges,
313+
meta: {
314+
allRecommendedChallengesCount: ch.meta,
315+
},
316+
}));
317+
}
318+
304319
function getMyPastChallengesDone(uuid, page, backendFilter, tokenV3, frontFilter = {}) {
305320
const userId = decodeToken(tokenV3).userId.toString();
306321
const { sorts } = frontFilter;
@@ -522,6 +537,7 @@ export default createActions({
522537
DROP_MY_CHALLENGES: _.noop,
523538
DROP_ALL_CHALLENGES: _.noop,
524539
DROP_PAST_CHALLENGES: _.noop,
540+
DROP_RECOMMENDED_CHALLENGES: _.noop,
525541

526542
// GET_ALL_ACTIVE_CHALLENGES_INIT: getAllActiveChallengesInit,
527543
// GET_ALL_ACTIVE_CHALLENGES_DONE: getAllActiveChallengesDone,
@@ -535,6 +551,9 @@ export default createActions({
535551
GET_ALL_CHALLENGES_INIT: getAllChallengesInit,
536552
GET_ALL_CHALLENGES_DONE: getAllChallengesDone,
537553

554+
GET_RECOMMENDED_CHALLENGES_INIT: getRecommendedChallengesInit,
555+
GET_RECOMMENDED_CHALLENGES_DONE: getRecommendedChallengesDone,
556+
538557
GET_ACTIVE_CHALLENGES_INIT: getActiveChallengesInit,
539558
GET_ACTIVE_CHALLENGES_DONE: getActiveChallengesDone,
540559

src/shared/components/challenge-listing/Filters/FiltersPanel/index.jsx

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ export default function FiltersPanel({
6464
// isSavingFilter,
6565
expanded,
6666
setExpanded,
67+
setSort,
6768
}) {
6869
if (hidden && !expanded) {
6970
return (
@@ -249,6 +250,39 @@ export default function FiltersPanel({
249250
const past = isPastBucket(activeBucket);
250251
const disableClearFilterButtons = isFilterEmpty(filterState, past ? 'past' : '', activeBucket);
251252

253+
const availableTypes = activeBucket === 'openForRegistration'
254+
? validTypes : validTypes.filter(item => item.abbreviation !== 'REC');
255+
256+
const handleTypeChange = (option, e) => {
257+
let { types } = filterState;
258+
if (e.target.checked) {
259+
types = types.concat(option.value);
260+
} else {
261+
types = types.filter(type => type !== option.value);
262+
}
263+
264+
if (option.label === 'Recommended') {
265+
types = types.filter(type => type === 'REC');
266+
if (!e.target.checked) {
267+
setFilterState({ ..._.clone(filterState), types: ['TSK', 'CH', 'F2F'] });
268+
setSort('openForRegistration', 'startDate');
269+
} else {
270+
setSort('openForRegistration', 'updatedBy');
271+
setFilterState({ ..._.clone(filterState), types });
272+
}
273+
} else {
274+
types = types.filter(type => type !== 'REC');
275+
setFilterState({ ..._.clone(filterState), types });
276+
setSort('openForRegistration', 'startDate');
277+
}
278+
};
279+
280+
const recommendedCheckboxTip = (
281+
<div styleName="tctooltiptext">
282+
<p>Shows available challenges <br /> that match your skills</p>
283+
</div>
284+
);
285+
252286
return (
253287
<div styleName="FiltersPanel">
254288
<div styleName="header">
@@ -416,7 +450,7 @@ export default function FiltersPanel({
416450
</span>
417451
<div styleName="checkboxes">
418452
{
419-
validTypes
453+
availableTypes
420454
.map(mapTypes)
421455
.map(option => (
422456
<span styleName="checkbox" key={option.value}>
@@ -426,19 +460,26 @@ export default function FiltersPanel({
426460
name={option.label}
427461
id={option.label}
428462
checked={filterState.types.includes(option.value)}
429-
onChange={(e) => {
430-
let { types } = filterState;
431-
432-
if (e.target.checked) {
433-
types = types.concat(option.value);
434-
} else {
435-
types = types.filter(type => type !== option.value);
436-
}
437-
438-
setFilterState({ ..._.clone(filterState), types });
439-
}}
463+
onChange={e => handleTypeChange(option, e)}
440464
/>
441-
<label styleName="checkbox-label" htmlFor={option.label}>{option.label}</label>
465+
{
466+
option.label === 'Recommended'
467+
? (
468+
<label styleName="checkbox-label" htmlFor={option.label}>
469+
<Tooltip
470+
id="recommended-tip"
471+
content={recommendedCheckboxTip}
472+
className={style['tooltip-overlay']}
473+
trigger={['hover', 'focus']}
474+
>
475+
{option.label}
476+
</Tooltip>
477+
478+
</label>
479+
)
480+
481+
: <label styleName="checkbox-label" htmlFor={option.label}>{option.label}</label>
482+
}
442483
</span>
443484
))
444485
}
@@ -612,4 +653,5 @@ FiltersPanel.propTypes = {
612653
onClose: PT.func,
613654
expanded: PT.bool.isRequired,
614655
setExpanded: PT.func.isRequired,
656+
setSort: PT.func.isRequired,
615657
};

src/shared/components/challenge-listing/Filters/FiltersPanel/style.scss

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@
285285
display: inline-block;
286286
line-height: 30px;
287287
flex: 1 0 auto;
288-
min-width: calc(33% - 10px);
288+
min-width: calc(11% - 10px);
289289

290290
&:not(:last-child) {
291291
padding-right: 10px;
@@ -423,3 +423,9 @@
423423
}
424424
}
425425
}
426+
427+
.tctooltiptext {
428+
background: $tc-gray-90;
429+
border-radius: 6px;
430+
padding: 10px;
431+
}

src/shared/components/challenge-listing/Listing/Bucket/index.jsx

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ import PT from 'prop-types';
1010
import React, { useRef } from 'react';
1111
// import { config } from 'topcoder-react-utils';
1212
import Sort from 'utils/challenge-listing/sort';
13-
import { NO_LIVE_CHALLENGES_CONFIG, BUCKETS, BUCKET_DATA } from 'utils/challenge-listing/buckets';
13+
import {
14+
NO_LIVE_CHALLENGES_CONFIG, BUCKETS, BUCKET_DATA, isRecommendedChallengeType,
15+
} from 'utils/challenge-listing/buckets';
1416
import SortingSelectBar from 'components/SortingSelectBar';
1517
import Waypoint from 'react-waypoint';
1618
// import { challenge as challengeUtils } from 'topcoder-react-lib';
@@ -51,6 +53,17 @@ export default function Bucket({
5153
isLoggedIn,
5254
setSearchText,
5355
}) {
56+
const activeBucketData = isRecommendedChallengeType(bucket, filterState)
57+
? BUCKET_DATA[bucket].sorts : BUCKET_DATA[bucket].sorts.filter(item => item !== 'updatedBy');
58+
59+
let noLiveBucket = activeBucket;
60+
if (isRecommendedChallengeType(bucket, filterState)) {
61+
if (isLoggedIn) {
62+
noLiveBucket = BUCKETS.NO_RECOMMENDED_MATCH;
63+
} else {
64+
noLiveBucket = BUCKETS.NOT_LOGGED_IN;
65+
}
66+
}
5467
const refs = useRef([]);
5568
refs.current = [];
5669
const addToRefs = (el) => {
@@ -116,7 +129,7 @@ export default function Bucket({
116129
if (!loading && sortedChallenges.length === 0) {
117130
return (
118131
<div styleName="no-results">
119-
{ `${NO_LIVE_CHALLENGES_CONFIG[bucket]}` }
132+
{ `${NO_LIVE_CHALLENGES_CONFIG[noLiveBucket]}` }
120133
</div>
121134
);
122135
}
@@ -170,7 +183,7 @@ export default function Bucket({
170183
<SortingSelectBar
171184
onSelect={setSort}
172185
options={
173-
BUCKET_DATA[bucket].sorts.map(item => ({
186+
activeBucketData.map(item => ({
174187
label: Sort[item].name,
175188
value: item,
176189
}))

0 commit comments

Comments
 (0)