{visibleTags.map((tag) => (
))}
diff --git a/src/containers/Challenges/Listing/ChallengeItem/Tags/styles.scss b/src/containers/Challenges/Listing/ChallengeItem/Tags/styles.scss
index 052530f..7664d85 100644
--- a/src/containers/Challenges/Listing/ChallengeItem/Tags/styles.scss
+++ b/src/containers/Challenges/Listing/ChallengeItem/Tags/styles.scss
@@ -1,9 +1,15 @@
@import "styles/variables";
.tags {
+ margin-top: -5px;
+ min-width: 1px;
+
> * {
- margin-right: 4px;
- margin-bottom: 4px;
+ margin-top: 5px;
+ }
+
+ > *:not(:last-child) {
+ margin-right: 5px;
}
}
diff --git a/src/containers/Challenges/Listing/ChallengeItem/index.jsx b/src/containers/Challenges/Listing/ChallengeItem/index.jsx
index 1fef4cd..bab2ad7 100644
--- a/src/containers/Challenges/Listing/ChallengeItem/index.jsx
+++ b/src/containers/Challenges/Listing/ChallengeItem/index.jsx
@@ -32,6 +32,10 @@ const ChallengeItem = ({ challenge, onClickTag, onClickTrack, isLoggedIn }) => {
submissionLink += "?tab=submissions";
}
+ const challengeName = utils.toBreakableWords(challenge.name, (w) =>
+ w.length > 20 ? `
${w}` : w
+ );
+
return (
@@ -46,7 +50,7 @@ const ChallengeItem = ({ challenge, onClickTag, onClickTrack, isLoggedIn }) => {
- {challenge.name}
+
* {
+ &:first-child {
+ margin-left: 0;
+ display: inline-block;
+ width: 64px;
+ }
+ }
+ }
+ }
+
+ .prize {
+ align-self: flex-start;
+ padding-top: 5px;
+ }
+ }
+
+ @include down($mfe-screen-xs) {
+ position: relative;
+ flex-wrap: wrap;
+ padding: 20px 0 20px 68px;
+
+ .track {
+ position: absolute;
+ left: 15px;
+ top: 20px;
+ }
+
+ .info {
+ width: 100%;
+
+ .name-container {
+ padding-right: 20px;
+
+ .name {
+ line-height: 20px;
+ }
+ }
+
+ .tags {
+ max-width: none;
+ min-width: 0;
+ }
+
+ .name-container,
+ .tags {
+ margin-bottom: 10px;
+ }
+
+ .nums {
+ display: none;
+ }
+ }
+ }
}
.track {
@@ -39,7 +110,7 @@
min-width: calc(50% - 84px);
flex: 1 1 auto;
- @media (min-width: $screen-xxl + 1px) {
+ @media (min-width: ($screen-xxl + 1px)) {
min-width: 294px;
max-width: 25%;
}
@@ -50,14 +121,11 @@
white-space: nowrap;
> * {
- margin: 0 20px;
&:first-child {
margin-left: 0;
- }
-
- &:last-child {
- margin-right: 0;
+ display: inline-block;
+ width: 84px;
}
}
}
diff --git a/src/containers/Challenges/Listing/index.jsx b/src/containers/Challenges/Listing/index.jsx
index bfc1318..8c25e12 100644
--- a/src/containers/Challenges/Listing/index.jsx
+++ b/src/containers/Challenges/Listing/index.jsx
@@ -14,6 +14,9 @@ import * as utils from "../../../utils";
import * as constants from "../../../constants";
import IconSearch from "../../../assets/icons/search.svg";
+import IconClear from "../../../assets/icons/close-gray.svg";
+import Button from "../../../components/Button";
+
import "./styles.scss";
const Listing = ({
@@ -47,6 +50,11 @@ const Listing = ({
updateFilter(filterChange);
};
+ const onShowSidebar = () => {
+ const sidebarEl = document.getElementById("sidebar-id");
+ sidebarEl.classList.add("show");
+ };
+
return (
@@ -70,6 +78,24 @@ const Listing = ({
}}
maxLength="100"
/>
+ {search.length ? (
+
+ {
+ onSearch.current(() => {
+ const filterChange = {
+ search: "",
+ page: 1,
+ };
+ updateFilter(filterChange);
+ });
+ }}
+ />
+
+ ) : (
+
+ )}
+
+
+
- {loadingChallenges ? (
- _.times(3, () =>
)
- ) : challenges.length ? (
-
- {challenges.map((challenge, index) => (
-
- {
- const filterChange = {
- tags: [tag],
- page: 1,
- };
- updateFilter(filterChange);
- }}
- onClickTrack={(track) => {
- const filterChange = {
- tracks: [track],
- page: 1,
- };
- updateFilter(filterChange);
- }}
- isLoggedIn={isLoggedIn}
- />
-
- ))}
-
-
{
- const filterChange = {
- page: utils.pagination.pageIndexToPage(event.pageIndex),
- perPage: event.pageSize,
- };
- updateFilter(filterChange);
- }}
- />
-
-
- ) : (
-
- )}
+ {loadingChallenges && _.times(3, () =>
)}
+ {!loadingChallenges &&
+ (challenges.length ? (
+
+ {challenges.map((challenge, index) => (
+
+ {
+ const filterChange = {
+ tags: [tag],
+ page: 1,
+ };
+ updateFilter(filterChange);
+ }}
+ onClickTrack={(track) => {
+ const filterChange = {
+ tracks: [track],
+ page: 1,
+ };
+ updateFilter(filterChange);
+ }}
+ isLoggedIn={isLoggedIn}
+ />
+
+ ))}
+
+ ) : (
+
+ ))}
+
+
+
{
+ const filterChange = {
+ page: utils.pagination.pageIndexToPage(event.pageIndex),
+ perPage: event.pageSize,
+ };
+ updateFilter(filterChange);
+ }}
+ />
+
+
);
};
diff --git a/src/containers/Challenges/Listing/styles.scss b/src/containers/Challenges/Listing/styles.scss
index 331471b..57f6fa8 100644
--- a/src/containers/Challenges/Listing/styles.scss
+++ b/src/containers/Challenges/Listing/styles.scss
@@ -11,7 +11,46 @@
.header-container {
display: flex;
- align-items: top;
+ align-items: flex-start;
+
+ @include down($mfe-screen-xs) {
+ flex-wrap: wrap;
+
+ .separator {
+ display: none;
+ }
+
+ .input-group {
+ width: 100%;
+ max-width: none;
+ flex: auto;
+ margin: 0 0 20px 0;
+ }
+
+ .sort-by {
+ max-width: 241px;
+ }
+
+ .sort-by,
+ .from-to {
+ flex: 1 1 auto;
+ margin: 0 22px 0 0;
+
+ @include down(375px - 1px) {
+ max-width: calc(100% - 92px);
+ }
+ }
+
+ .filter-button {
+ display: block;
+ margin: 0 0 0 auto;
+
+ button {
+ height: 40px;
+ border-radius: 20px;
+ }
+ }
+ }
}
.input-group {
@@ -19,13 +58,8 @@
display: inline-block;
margin-right: 16px;
margin-bottom: 17px;
- width: 38%;
- min-width: 380px;
-
- @include xs-to-md {
- width: 62%;
- min-width: 230px;
- }
+ flex: auto;
+ max-width: 380px;
.search-icon {
position: absolute;
@@ -39,6 +73,19 @@
height: 40px;
}
+ .clear-icon {
+ position: absolute;
+ bottom: 0;
+ right: 0;
+ z-index: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 46px;
+ height: 40px;
+ cursor: pointer;
+ }
+
input {
margin-top: 0 !important;
padding-left: 46px !important;
@@ -60,7 +107,8 @@
}
.from-to {
- display: inline-block;
+ width: 50%;
+ max-width: 241px;
}
.sort-by,
@@ -72,6 +120,14 @@
}
}
+.filter-button {
+ display: none;
+}
+
.pagination {
padding: 17px 0 15px;
+
+ @include down($mfe-screen-xs) {
+ padding: 20px;
+ }
}
diff --git a/src/containers/Challenges/index.jsx b/src/containers/Challenges/index.jsx
index 73833b7..3e9e9fe 100644
--- a/src/containers/Challenges/index.jsx
+++ b/src/containers/Challenges/index.jsx
@@ -12,7 +12,12 @@ import * as constants from "../../constants";
import { Banner } from "@topcoder/micro-frontends-earn-app";
import * as utils from "../../utils";
+import { useMediaQuery } from "react-responsive";
+import { useCssVariable } from "../../utils/hooks/useCssVariable";
+import IconArrow from "../../assets/icons/arrow.svg";
+
import "./styles.scss";
+import { useClickOutside } from "../../utils/hooks/useClickOutside";
const Challenges = ({
challenges,
@@ -74,20 +79,55 @@ const Challenges = ({
recommended &&
recommendedChallenges.length === 0;
+ const screenXs = useCssVariable("--mfe-screen-xs", (value) =>
+ parseInt(value)
+ );
+ const isScreenXs = useMediaQuery({ maxWidth: screenXs });
+
+ const [menuExpanded, setMenuExpanded] = useState(false);
+ const menuRef = useClickOutside(menuExpanded, (event) => {
+ setMenuExpanded(false);
+ });
+
+ const mobileMenu = (
+
+ );
+
return (
-
- CHALLENGES
- {/*
-
-
- */}
-
+
+
+
isScreenXs && setMenuExpanded(!menuExpanded)}
+ >
+ {isScreenXs && menuExpanded ? "EARN" : "CHALLENGES"}
+
+ {isScreenXs ? (
+
+
+
+ ) : (
+
+ {/*
+ */}
+
+ )}
+
+
+ {mobileMenu}
+
+
{initialized ? (
<>
{/*noRecommendedChallenges &&
*/}
diff --git a/src/containers/Challenges/styles.scss b/src/containers/Challenges/styles.scss
index 13c7fde..d3bca64 100644
--- a/src/containers/Challenges/styles.scss
+++ b/src/containers/Challenges/styles.scss
@@ -3,11 +3,51 @@
.page {
padding: $page-padding-y $page-padding-x 105px;
+
+ @include down($mfe-screen-xs) {
+ padding: 10px 0;
+ background-color: $tc-white;
+
+ :global(.banner) {
+ margin: 0 20px;
+ width: calc(100% - 40px);
+ }
+ }
}
.title {
@include barlow-condensed-medium;
margin-bottom: 22px;
+ font-size: 34px;
+ line-height: 1;
+
+ @include down($mfe-screen-xs) {
+ font-size: 25px;
+ line-height: 27px;
+ margin: 10px 0 0;
+ padding: 0 20px 10px 20px;
+ background-color: $tc-white;
+ position: relative;
+ z-index: 11;
+ cursor: pointer;
+
+ &.menu-title {
+ text-align: center;
+ }
+ }
+}
+
+.mobile-menu {
+ position: absolute;
+ width: 100%;
+ background-color: $tc-white;
+ border-top: 1px solid $gray3;
+ box-shadow: 0 10px 20px 0 rgba($tc-black, 0.25);
+ z-index: 10;
+
+ &.hidden {
+ display: none;
+ }
}
.button-icon {
@@ -36,3 +76,12 @@
margin: 0 2px;
}
}
+
+.arrow-down {
+ float: right;
+ vertical-align: middle;
+
+ &.up {
+ transform: rotate(180deg);
+ }
+}
diff --git a/src/containers/Filter/ChallengeFilter/styles.scss b/src/containers/Filter/ChallengeFilter/styles.scss
index fc29ced..539761c 100644
--- a/src/containers/Filter/ChallengeFilter/styles.scss
+++ b/src/containers/Filter/ChallengeFilter/styles.scss
@@ -33,10 +33,10 @@ $filter-padding-y: 3 * $base-unit;
.count-badge {
display: inline-block;
margin: -2px 0 0 $base-unit;
- padding: 2px 5px 0;
+ padding: 2px 5px;
font-weight: bold;
font-size: 11px;
- line-height: 14px;
+ line-height: 11px;
text-align: center;
color: white;
vertical-align: middle;
@@ -96,6 +96,10 @@ $filter-padding-y: 3 * $base-unit;
position: relative;
margin-top: -12px;
+ :global(.textInputContainer) {
+ width: 100%;
+ }
+
input {
padding-right: 36px !important;
}
diff --git a/src/containers/Submission/Submit/SubmitForm/index.jsx b/src/containers/Submission/Submit/SubmitForm/index.jsx
index 8d2798b..1504577 100644
--- a/src/containers/Submission/Submit/SubmitForm/index.jsx
+++ b/src/containers/Submission/Submit/SubmitForm/index.jsx
@@ -1,3 +1,4 @@
+/* eslint jsx-a11y/no-static-element-interactions:0 */
/**
* components.page.challenge-details.Submit
*
Component
@@ -50,6 +51,8 @@ const SubmitForm = ({
const propsRef = useRef();
propsRef.current = { resetForm };
+ const checkboxRef = useRef();
+
useEffect(() => {
return () => {
propsRef.current.resetForm();
@@ -93,6 +96,10 @@ const SubmitForm = ({
submit(getFormData());
};
+ const handleAgree = () => {
+ checkboxRef.current.checked = !checkboxRef.current.checked;
+ };
+
const id = "file-picker-submission";
const isLoadingCommunitiesList = !isCommunityListLoaded;
@@ -255,13 +262,14 @@ const SubmitForm = ({
Topcoder terms of use
and to the extent your uploaded file wins a topcoder
- Competition, you hereby assign, grant and transfer and agree to
- assign, grant and transfer to topcoder all right and title in and to
- the Winning Submission (as further described in the terms of use).
+ Competition, you hereby agree to assign, grant and transfer to
+ Topcoder all right and title in and to the Winning Submission (as
+ further described in the terms of use).
setAgreed(e.target.checked)}
@@ -269,7 +277,9 @@ const SubmitForm = ({
-
I UNDERSTAND AND AGREE
+
+ I UNDERSTAND AND AGREE
+
0}
hasThriveArticles={thriveArticles.length > 0}
- setChallengeListingFilter={setChallengeListingFilter}
unregisterFromChallenge={() =>
unregisterFromChallenge(auth, challengeId)
}
@@ -718,7 +716,6 @@ ChallengeDetailPageContainer.propTypes = {
resultsLoadedForChallengeId: PT.string.isRequired,
savingChallenge: PT.bool.isRequired,
selectedTab: PT.string.isRequired,
- setChallengeListingFilter: PT.func.isRequired,
setSpecsTabState: PT.func.isRequired,
specsTabState: PT.string.isRequired,
terms: PT.arrayOf(PT.shape()),
@@ -967,18 +964,6 @@ const mapDispatchToProps = (dispatch) => {
return challengeDetails;
});
},
- setChallengeListingFilter: (change, stateProps) => {
- const updateFilter = actions.filter.updateFilter;
- const updateQuery = actions.filter.updateChallengeQuery;
- change.page = 1;
- change.tracks = constants.FILTER_CHALLENGE_TRACKS;
- change.backet = constants.FILTER_BUCKETS[1];
- if (change.tags) {
- change.types = constants.FILTER_CHALLENGE_TYPES;
- }
- dispatch(updateFilter(change));
- dispatch(updateQuery({ ...stateProps.filter.challenge, ...change }));
- },
setSpecsTabState: (state) =>
dispatch(pageActions.page.challengeDetails.setSpecsTabState(state)),
unregisterFromChallenge: (auth, challengeId) => {
@@ -1041,18 +1026,9 @@ const mapDispatchToProps = (dispatch) => {
};
};
-const mergeProps = (stateProps, dispatchProps, ownProps) => ({
- ...ownProps,
- ...stateProps,
- ...dispatchProps,
- setChallengeListingFilter: (filter) =>
- dispatchProps.setChallengeListingFilter(filter, stateProps),
-});
-
const ChallengeDetailContainer = connect(
mapStateToProps,
- mapDispatchToProps,
- mergeProps
+ mapDispatchToProps
)(ChallengeDetailPageContainer);
export default ChallengeDetailContainer;
diff --git a/src/routers/challenge-list/index.jsx b/src/routers/challenge-list/index.jsx
index 6adcfb0..5fddb7f 100644
--- a/src/routers/challenge-list/index.jsx
+++ b/src/routers/challenge-list/index.jsx
@@ -11,6 +11,8 @@ import * as utils from "../../utils";
import store from "../../store";
import { initialChallengeFilter } from "../../reducers/filter";
import _ from "lodash";
+import { useMediaQuery } from "react-responsive";
+import { useCssVariable } from "../../utils/hooks/useCssVariable";
import "react-date-range/dist/theme/default.css";
import "react-date-range/dist/styles.css";
@@ -20,13 +22,6 @@ const App = () => {
const location = useLocation();
const previousControllerRef = useRef();
- useLayoutEffect(() => {
- showMenu(true);
- return () => {
- showMenu(false);
- };
- }, []);
-
useEffect(() => {
if (!location.search) {
const currentFilter = store.getState().filter.challenge;
@@ -72,18 +67,42 @@ const App = () => {
store.dispatch(actions.challenges.getChallengesDone(updatedFilter, signal));
}, [location]);
+ const onHideSidebar = () => {
+ const sidebarEl = document.getElementById("sidebar-id");
+ sidebarEl.classList.remove("show");
+ };
+
+ const screenXs = useCssVariable("--mfe-screen-xs", (value) =>
+ parseInt(value)
+ );
+ const isScreenXs = useMediaQuery({ maxWidth: screenXs });
+
+ useLayoutEffect(() => {
+ showMenu(true);
+ return () => {
+ showMenu(false);
+ };
+ }, [isScreenXs]);
+
return (
<>
-