diff --git a/src/components/challenge-detail/Header/ChallengeTags.jsx b/src/components/challenge-detail/Header/ChallengeTags.jsx index 7ca45e9..f4f8ef2 100644 --- a/src/components/challenge-detail/Header/ChallengeTags.jsx +++ b/src/components/challenge-detail/Header/ChallengeTags.jsx @@ -26,6 +26,8 @@ import { COMPETITION_TRACKS } from "utils/tc"; import VerifiedTag from "components/challenge-listing/VerifiedTag"; import MatchScore from "components/challenge-listing/ChallengeCard/MatchScore"; import { calculateScore } from "../../../utils/challenge-listing/helper"; +import * as urlUtil from "utils/url"; +import * as constants from "constants"; import "./style.module.scss"; export default function ChallengeTags(props) { @@ -75,6 +77,19 @@ export default function ChallengeTags(props) { const tags = technPlatforms.filter((tag) => !matchSkills.includes(tag)); + const filterByChallengeType = urlUtil.buildQueryString({ + bucket: constants.FILTER_BUCKETS[1], + tracks: _.values(constants.FILTER_CHALLENGE_TRACK_ABBREVIATIONS), + page: 1, + }); + + const filterByTag = urlUtil.buildQueryString({ + bucket: constants.FILTER_BUCKETS[1], + tracks: _.values(constants.FILTER_CHALLENGE_TRACK_ABBREVIATIONS), + page: 1, + types: _.values(constants.FILTER_CHALLENGE_TYPE_ABBREVIATIONS), + }); + return (
{challengeType && ( @@ -84,7 +99,7 @@ export default function ChallengeTags(props) { setChallengeListingFilter({ types: [challengeType.name] }) ) } - to={`${challengesUrl}?types[]=${encodeURIComponent( + to={`${challengesUrl}${filterByChallengeType}&types[]=${encodeURIComponent( challengeType.abbreviation )}`} > @@ -112,7 +127,7 @@ export default function ChallengeTags(props) { onClick={() => setImmediate(() => setChallengeListingFilter({ tags: [tag] })) } - to={`${challengesUrl}?tags[]=${encodeURIComponent(tag)}`} + to={`${challengesUrl}${filterByTag}&tags[]=${encodeURIComponent(tag)}`} > {tag} diff --git a/src/constants/index.js b/src/constants/index.js index f679d1d..77faca2 100644 --- a/src/constants/index.js +++ b/src/constants/index.js @@ -29,14 +29,14 @@ export const FILTER_CHALLENGE_TRACKS = [ "Design", "Development", "Data Science", - "QA", + "Quality Assurance", ]; export const FILTER_CHALLENGE_TRACK_ABBREVIATIONS = { Design: "DES", Development: "DEV", "Data Science": "DS", - QA: "QA", + "Quality Assurance": "QA", }; export const CHALLENGE_SORT_BY = { diff --git a/src/containers/Challenges/Listing/ChallengeItem/index.jsx b/src/containers/Challenges/Listing/ChallengeItem/index.jsx index 82653ef..e9605b0 100644 --- a/src/containers/Challenges/Listing/ChallengeItem/index.jsx +++ b/src/containers/Challenges/Listing/ChallengeItem/index.jsx @@ -12,6 +12,8 @@ import * as utils from "../../../../utils"; import ProgressTooltip from "../tooltips/ProgressTooltip"; import PlacementsTooltip from "../tooltips/PlacementsTooltip"; import TagsMoreTooltip from "../tooltips/TagsMoreTooltip"; +import { CHALLENGES_URL } from 'constants'; +import { Link } from '@reach/router'; import "./styles.scss"; @@ -25,7 +27,7 @@ const ChallengeItem = ({ challenge, onClickTag, onClickTrack, isLoggedIn }) => { challenge.prizeSets ); - let submissionLink = `/earn/find/challenges/${challenge.id}`; + let submissionLink = `${CHALLENGES_URL}/${challenge.id}`; if (isLoggedIn && challenge.numOfSubmissions > 0) { submissionLink += "?tab=submissions"; } @@ -43,11 +45,11 @@ const ChallengeItem = ({ challenge, onClickTag, onClickTrack, isLoggedIn }) => {
- {challenge.name} - +
{ />
- - - + + - +
diff --git a/src/containers/Challenges/Listing/index.jsx b/src/containers/Challenges/Listing/index.jsx index d2cd3e4..e376d19 100644 --- a/src/containers/Challenges/Listing/index.jsx +++ b/src/containers/Challenges/Listing/index.jsx @@ -129,7 +129,7 @@ const Listing = ({ }} onClickTrack={(track) => { const filterChange = { - tracks: [track.replace("Quality Assurance", "QA")], + tracks: [track], page: 1, }; updateFilter(filterChange); diff --git a/src/containers/Filter/ChallengeFilter/index.jsx b/src/containers/Filter/ChallengeFilter/index.jsx index 2573dde..cc3e9ae 100644 --- a/src/containers/Filter/ChallengeFilter/index.jsx +++ b/src/containers/Filter/ChallengeFilter/index.jsx @@ -121,7 +121,7 @@ const ChallengeFilter = ({ updateFilter(filterChange); }} /> - {track} + {track.replace('Quality Assurance', 'QA')} ))}
diff --git a/src/containers/challenge-detail/index.jsx b/src/containers/challenge-detail/index.jsx index 5720f19..f3f3cfc 100644 --- a/src/containers/challenge-detail/index.jsx +++ b/src/containers/challenge-detail/index.jsx @@ -978,8 +978,7 @@ const mapDispatchToProps = (dispatch) => { } dispatch(updateFilter(change)); dispatch( - updateQuery({ ...stateProps.filter.challenge, ...change }), - change + updateQuery({ ...stateProps.filter.challenge, ...change }) ); }, setSpecsTabState: (state) => diff --git a/src/reducers/challenges.js b/src/reducers/challenges.js index 37fc947..31ae15a 100644 --- a/src/reducers/challenges.js +++ b/src/reducers/challenges.js @@ -17,14 +17,9 @@ function onGetChallengesInit(state) { return { ...state, loadingChallenges: true, loadingChallengesError: null }; } -function onGetChallengesDone(state, { payload }) { - const error = payload; - if (error.name === "AbortError") { - return { - ...state, - loadingChallenges: false, - loadingChallengesError: null, - }; +function onGetChallengesDone(state, { error, payload }) { + if (error) { + return onGetChallengesFailure(state, { payload }); } return { @@ -39,32 +34,31 @@ function onGetChallengesDone(state, { payload }) { }; } -// function onGetChallengesFailure(state, { payload }) { -// const error = payload; -// if (error.name === "AbortError") { -// return { -// ...state, -// loadingChallenges: false, -// loadingChallengesError: null, -// }; -// } +function onGetChallengesFailure(state, { payload }) { + const error = payload; + if (error.name === "AbortError") { + return { + ...state, + loadingChallenges: false, + loadingChallengesError: null, + }; + } -// return { -// ...state, -// loadingChallenges: false, -// loadingChallengesError: payload, -// challenges: [], -// total: 0, -// openForRegistrationCount: 0, -// initialized: true, -// }; -// } + return { + ...state, + loadingChallenges: false, + loadingChallengesError: payload, + challenges: [], + total: 0, + openForRegistrationCount: 0, + initialized: true, + }; +} export default handleActions( { GET_CHALLENGE_INIT: onGetChallengesInit, GET_CHALLENGES_DONE: onGetChallengesDone, - // GET_CHALLENGES_FAILURE: onGetChallengesFailure, }, defaultState ); diff --git a/src/utils/challenge.js b/src/utils/challenge.js index 5aca8a4..1775a04 100644 --- a/src/utils/challenge.js +++ b/src/utils/challenge.js @@ -6,34 +6,49 @@ import Joi from "joi"; import { initialChallengeFilter } from "../reducers/filter"; Joi.optionalId = () => Joi.string().uuid(); -Joi.page = () => Joi.number().integer().min(1); + +Joi.page = () => + Joi.alternatives() + .try( + Joi.number() + .min(1), + Joi.any().custom(() => 1) + ); + Joi.perPage = () => - Joi.number() - .integer() - .min(1) - .max(100) - .valid(...constants.PAGINATION_PER_PAGES); + Joi.alternatives() + .try( + Joi.number() + .integer() + .min(1) + .max(100) + .valid(...constants.PAGINATION_PER_PAGES), + Joi.any().custom(() => constants.PAGINATION_PER_PAGES[0]) + ); + Joi.bucket = () => Joi.string().custom((param) => constants.FILTER_BUCKETS.find( (bucket) => param && param.toLowerCase() === bucket.toLowerCase() - ) + ) || null ); + Joi.track = () => Joi.string().custom((param) => _.findKey( constants.FILTER_CHALLENGE_TRACK_ABBREVIATIONS, (trackAbbreviation) => param && param.toLowerCase() === trackAbbreviation.toLowerCase() - ) + ) || null ); + Joi.type = () => Joi.string().custom((param) => _.findKey( constants.FILTER_CHALLENGE_TYPE_ABBREVIATIONS, (typeAbbreviation) => param && param.toLowerCase() === typeAbbreviation.toLowerCase() - ) + ) || null ); export function getCurrencySymbol(prizeSets) { @@ -65,6 +80,7 @@ export function getCheckpointPrizes(prizeSets) { */ export function createChallengeFilter(params) { const schema = createChallengeFilter.schema; + const normalized = Joi.attempt( params, schema, diff --git a/src/utils/lifeCycle.js b/src/utils/lifeCycle.js index 3ccf7ff..0f64daf 100644 --- a/src/utils/lifeCycle.js +++ b/src/utils/lifeCycle.js @@ -1,6 +1,7 @@ import store from "../store"; import action from "../actions/initApp"; import * as utils from "../utils"; +import { CHALLENGES_URL } from '../constants'; export default function appInit() { let initialQuery; @@ -17,7 +18,7 @@ export default function appInit() { async function mount() { try { if (firstMounted) { - if (initialQuery && urlPath === "/earn/find/challenges") { + if (initialQuery && urlPath === CHALLENGES_URL) { const params = utils.url.parseUrlQuery(initialQuery); const filter = utils.challenge.createChallengeFilter(params); store.dispatch(action.initApp(filter));