diff --git a/.circleci/config.yml b/.circleci/config.yml index 0b075aa900..37fe8b4d60 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -24,7 +24,7 @@ install_dependency: &install_dependency apk upgrade apk add --no-cache jq py-pip sudo sudo pip install awscli --upgrade - + install_deploysuite: &install_deploysuite name: Installation of install_deploysuite. command: | @@ -35,10 +35,10 @@ install_deploysuite: &install_deploysuite restore_cache_settings_for_build: &restore_cache_settings_for_build key: docker-node-modules-v3-{{ checksum "package-lock.json" }} -save_cache_settings: &save_cache_settings - key: docker-node-modules-v3-{{ checksum "package-lock.json" }} +save_cache_settings: &save_cache_settings + key: docker-node-modules-v3-{{ checksum "package-lock.json" }} paths: - - node_modules + - node_modules build_docker_image: &build_docker_image name: Build of Docker image @@ -59,11 +59,11 @@ jobs: # Restoration of node_modules from cache. - restore_cache: *restore_cache_settings_for_build # Build of Docker image. - - run: + - run: name: "configuring environment" command: | ./awsconfiguration.sh DEV - ./buildenv.sh -e DEV -b dev_communityapp_buildvar,dev_communityapp_deployvar + ./buildenv.sh -e DEV -b dev_communityapp_buildvar,dev_communityapp_deployvar - run: *build_docker_image # Caching node modules. - save_cache: *save_cache_settings @@ -86,11 +86,11 @@ jobs: - run: *install_deploysuite # Restoration of node_modules from cache. - restore_cache: *restore_cache_settings_for_build - - run: + - run: name: "configuring environment" command: | ./awsconfiguration.sh DEV - ./buildenv.sh -e DEV -b test_communityapp_buildvar,test_communityapp_deployvar + ./buildenv.sh -e DEV -b test_communityapp_buildvar,test_communityapp_deployvar # Build of Docker image. - run: *build_docker_image # Caching node modules. @@ -114,11 +114,11 @@ jobs: - run: *install_deploysuite # Restoration of node_modules from cache. - restore_cache: *restore_cache_settings_for_build - - run: + - run: name: "configuring environment" command: | ./awsconfiguration.sh DEV - ./buildenv.sh -e DEV -b qa_communityapp_buildvar,qa_communityapp_deployvar + ./buildenv.sh -e DEV -b qa_communityapp_buildvar,qa_communityapp_deployvar # Build of Docker image. - run: *build_docker_image # Caching node modules. @@ -142,7 +142,7 @@ jobs: - run: *install_deploysuite # Restoration of node_modules from cache. - restore_cache: *restore_cache_settings_for_build - - run: + - run: name: "configuring environment" command: | ./awsconfiguration.sh PROD @@ -158,7 +158,7 @@ jobs: source awsenvconf source buildenvvar ./master_deploy.sh -d ECS -e PROD -t latest -s beta_communityapp_taskvar, -i communityapp - + # Build & Deploy against prod api backend "build-prod-staging": <<: *defaults @@ -170,7 +170,7 @@ jobs: - run: *install_deploysuite # Restoration of node_modules from cache. - restore_cache: *restore_cache_settings_for_build - - run: + - run: name: "configuring environment" command: | ./awsconfiguration.sh PROD @@ -191,7 +191,7 @@ jobs: --header "Circle-Token: ${CIRCLE_TOKEN}" \ --header 'content-type: application/json' \ --data '{"branch":"'"$CIRCLE_BRANCH"'","parameters":{"run_smoketesting":true , "run_performancetesting":false, "run_basedeployment": false}}' - + # Build & Deploy against production backend "build-prod": <<: *defaults @@ -203,7 +203,7 @@ jobs: - run: *install_deploysuite # Restoration of node_modules from cache. - restore_cache: *restore_cache_settings_for_build - - run: + - run: name: "configuring environment" command: | ./awsconfiguration.sh PROD @@ -211,7 +211,7 @@ jobs: # Build of Docker image. - run: *build_docker_image # Caching node modules. - - save_cache: *save_cache_settings + - save_cache: *save_cache_settings # Deployment. - deploy: name: Running MasterScript @@ -224,11 +224,11 @@ jobs: --header "Circle-Token: ${CIRCLE_TOKEN}" \ --header 'content-type: application/json' \ --data '{"branch":"'"$CIRCLE_BRANCH"'","parameters":{"run_smoketesting":true , "run_performancetesting":false, "run_basedeployment": false}}' - + # Automated Smoke Testing against Staging Smoke-Testing-On-Staging: <<: *defaults - steps: + steps: # Initialization. - checkout - setup_remote_docker @@ -236,7 +236,7 @@ jobs: - run: *install_deploysuite # Restoration of node_modules from cache. - restore_cache: *restore_cache_settings_for_build - - run: + - run: name: "configuring environment" command: | ./awsconfiguration.sh PROD @@ -250,11 +250,11 @@ jobs: ./automated-smoke-test/smoketest.sh automation-config-staging.json prod - store_artifacts: path: ./automated-smoke-test/test-results - + # Automated Smoke Testing against Production Smoke-Testing-On-Production: <<: *defaults - steps: + steps: # Initialization. - checkout - setup_remote_docker @@ -262,7 +262,7 @@ jobs: - run: *install_deploysuite # Restoration of node_modules from cache. - restore_cache: *restore_cache_settings_for_build - - run: + - run: name: "configuring environment" command: | ./awsconfiguration.sh PROD @@ -290,7 +290,7 @@ jobs: - run: name: Config Git command: git config --global url."https://git@".insteadOf git:// - - run: + - run: name: App npm install command: npm install no_output_timeout: 20m @@ -299,7 +299,7 @@ jobs: paths: - node_modules - run: npm test - + Performance-Testing: docker: # specify the version you desire here @@ -337,7 +337,7 @@ jobs: - store_artifacts: path: target/jmeter/reports - + workflows: version: 2 Build: @@ -349,17 +349,18 @@ workflows: filters: branches: only: - - free + - develop + - reskin # This is alternate dev env for parallel testing - "build-test": - context : org-global + context : org-global filters: branches: - only: + only: - circleci-fix # This is alternate dev env for parallel testing - "build-qa": - context : org-global + context : org-global filters: branches: only: @@ -373,20 +374,20 @@ workflows: - footer-update # This is stage env for production QA releases - "build-prod-staging": - context : org-global + context : org-global filters: &filters-staging branches: only: - develop - stat_marathon_match_link - # Production builds are exectuted + # Production builds are exectuted # when PR is merged to the master # Don't change anything in this configuration - # That might trigger wrong branch to be + # That might trigger wrong branch to be # deployed on the production # master branch. - "build-prod": - context : org-global + context : org-global filters: &filters-prod branches: only: diff --git a/__tests__/shared/components/ProfilePage/__snapshots__/index.jsx.snap b/__tests__/shared/components/ProfilePage/__snapshots__/index.jsx.snap index 3617e4c86f..212ffd27cc 100644 --- a/__tests__/shared/components/ProfilePage/__snapshots__/index.jsx.snap +++ b/__tests__/shared/components/ProfilePage/__snapshots__/index.jsx.snap @@ -30,6 +30,7 @@ exports[`renders a full Profile correctly 1`] = ` { )); expect(renderer.getRenderOutput()).toMatchSnapshot(); }); - -class Wrapper extends React.Component { - componentDidMount() {} - - render() { - return ; - } -} - -const instance = TU.renderIntoDocument(()); - -test('Render properly', () => { - const dropdown = TU.findAllInRenderedTree(instance, item => item && item.className && item.className.match('Select-control')); - TU.Simulate.touchEnd(dropdown[0]); - const options = TU.findAllInRenderedTree(instance, item => item && item.className && item.className.match('Select-option')); - expect(options).toHaveLength(1); - TU.Simulate.click(options[0]); -}); diff --git a/__tests__/shared/components/SubmissionManagement/__snapshots__/ScreeningDetails.jsx.snap b/__tests__/shared/components/SubmissionManagement/__snapshots__/ScreeningDetails.jsx.snap index e55cc05243..07413c50a2 100644 --- a/__tests__/shared/components/SubmissionManagement/__snapshots__/ScreeningDetails.jsx.snap +++ b/__tests__/shared/components/SubmissionManagement/__snapshots__/ScreeningDetails.jsx.snap @@ -15,21 +15,17 @@ exports[`Snapshot match 1`] = `

Your submission has been received, and will be evaluated during Review phase. + + + Need help? +

-
- - Help - -
-
+ /> `; @@ -48,6 +44,13 @@ exports[`Snapshot match 2`] = `

You have failed screening + + + Need help? +

Need more info on how to pass screening? Go to help to read Rules & Policies.

-
- - Help - -
`; @@ -86,6 +79,13 @@ exports[`Snapshot match 3`] = `

You have failed screening and the screener has given you the following warning. + + + Need help? +

Need more info on how to pass screening? Go to help to read Rules & Policies.

-
- - Help - -
`; @@ -140,21 +130,17 @@ exports[`Snapshot match 4`] = `

You have passed screening. + + + Need help? +

-
- - Help - -
-
+ /> `; @@ -173,6 +159,13 @@ exports[`Snapshot match 5`] = `

You have passed screening, but the screener has given you 1 warnings that you must fix in round 2. + + + Need help? +

Need more info on how to pass screening? Go to help to read Rules & Policies.

-
- - Help - -
`; @@ -227,6 +210,13 @@ exports[`Snapshot match 6`] = `

Your submission has been received, and will be screened after the end of the phase + + + Need help? +

-
- - Help - -
`; diff --git a/__tests__/shared/components/SubmissionManagement/__snapshots__/Submission.jsx.snap b/__tests__/shared/components/SubmissionManagement/__snapshots__/Submission.jsx.snap index 7a713fe290..253eaf8c47 100644 --- a/__tests__/shared/components/SubmissionManagement/__snapshots__/Submission.jsx.snap +++ b/__tests__/shared/components/SubmissionManagement/__snapshots__/Submission.jsx.snap @@ -7,14 +7,29 @@ exports[`Snapshot match 1`] = ` -
+ + ID + + + + + TYPE + - + + Submission Date + Invalid date -

{setStatusInfo().message} + + {' '}Need help? +

{warnings} {((hasStatusFailed) || (hasStatusPassed && hasWarnings)) - && ( -

- Need more info on how to pass screening? - Go to help to read Rules & Policies. -

- )} -
- - Help - -
+ && ( +

+ Need more info on how to pass screening? + Go to help to read Rules & Policies. +

+ )}
); diff --git a/src/shared/components/SubmissionManagement/ScreeningDetails/styles.scss b/src/shared/components/SubmissionManagement/ScreeningDetails/styles.scss index a606c484da..033db1579e 100644 --- a/src/shared/components/SubmissionManagement/ScreeningDetails/styles.scss +++ b/src/shared/components/SubmissionManagement/ScreeningDetails/styles.scss @@ -12,12 +12,11 @@ $red-color: $tc-red; } .screening-details { - background: $tc-gray-neutral-light; - font-weight: 400; - font-size: 15px; - color: $gray-color; + font-weight: 500; + font-size: 14px; + color: $tc-black; letter-spacing: 0; - line-height: $status-space-25; + line-height: 22px; .screening-details-head { display: flex; @@ -83,6 +82,7 @@ $red-color: $tc-red; } .help-link { - padding: 1px 6px; + color: $tc-dark-blue-110; + cursor: pointer; } } diff --git a/src/shared/components/SubmissionManagement/Submission/index.jsx b/src/shared/components/SubmissionManagement/Submission/index.jsx index 919c04fd62..def59a603b 100644 --- a/src/shared/components/SubmissionManagement/Submission/index.jsx +++ b/src/shared/components/SubmissionManagement/Submission/index.jsx @@ -14,11 +14,12 @@ import _ from 'lodash'; import moment from 'moment'; import React from 'react'; -import { COMPETITION_TRACKS, CHALLENGE_STATUS, safeForDownload } from 'utils/tc'; +// CHALLENGE_STATUS +import { COMPETITION_TRACKS, safeForDownload } from 'utils/tc'; import PT from 'prop-types'; -import DeleteIcon from '../Icons/IconTrashSimple.svg'; +// import DeleteIcon from '../Icons/IconTrashSimple.svg'; import DownloadIcon from '../Icons/IconSquareDownload.svg'; import ExpandIcon from '../Icons/IconMinimalDown.svg'; import ScreeningStatus from '../ScreeningStatus'; @@ -31,10 +32,10 @@ export default function Submission(props) { showScreeningDetails, track, onDownload, - onDelete, + // onDelete, onShowDetails, - status, - allowDelete, + // status, + // allowDelete, } = props; const formatDate = date => moment(+new Date(date)).format('MMM DD, YYYY hh:mm A'); const onDownloadSubmission = onDownload.bind(1, submissionObject.id); @@ -43,29 +44,33 @@ export default function Submission(props) { return ( + ID {submissionObject.id} -
{submissionObject.legacySubmissionId}
+ {/*
{submissionObject.legacySubmissionId}
*/} - + + TYPE {submissionObject.type} + Submission Date {formatDate(submissionObject.created)} { - track === COMPETITION_TRACKS.DES && ( - - {safeForDownloadCheck !== true ? safeForDownloadCheck : submissionObject.screening - && ( - - )} - - ) - } + track === COMPETITION_TRACKS.DES && ( + + Screening Status + {safeForDownloadCheck !== true ? safeForDownloadCheck : submissionObject.screening + && ( + + )} + + ) + }
{ /* - TODO: At the moment we just fetch downloads from the legacy - Topcoder Studio API, and we don't need any JS code to this. - It may change soon, as we move to the new TC API for - downloads. Then we'll use this commented out code or - remove it for good. - - */ } - {status !== CHALLENGE_STATUS.COMPLETED - && track !== COMPETITION_TRACKS.DES - && ( - - ) - } + TODO: At the moment we just fetch downloads from the legacy + Topcoder Studio API, and we don't need any JS code to this. + It may change soon, as we move to the new TC API for + downloads. Then we'll use this commented out code or + remove it for good. + + */ } + {/* {status !== CHALLENGE_STATUS.COMPLETED */} + {/* && track !== COMPETITION_TRACKS.DES */} + {/* && ( */} + {/* */} + {/* ) */} + {/* } */}
); diff --git a/src/shared/components/SubmissionManagement/SubmissionManagement/styles.scss b/src/shared/components/SubmissionManagement/SubmissionManagement/styles.scss index bb94798ea6..c0422a6b52 100644 --- a/src/shared/components/SubmissionManagement/SubmissionManagement/styles.scss +++ b/src/shared/components/SubmissionManagement/SubmissionManagement/styles.scss @@ -9,12 +9,50 @@ $gray-color: $tc-gray-40; $light-gray-color: $tc-gray-neutral-light; .btn-wrap { - text-align: center; + display: flex; + justify-content: flex-end; + margin-right: 32px; + margin-top: 34px; color: white; + + @include xs-to-md { + margin-right: 16px; + margin-top: 32px; + } } .add-sub-btn { - margin: 10px auto; + @include roboto-bold; + + font-weight: 700; + font-size: 16px; + line-height: 24px; + border-radius: 50px !important; + background: #137d60 !important; + color: #fff !important; + text-transform: uppercase; + + @include xs-to-md { + font-size: 14px; + line-height: 20px; + } +} + +.add-sub-btn-warning { + @include roboto-bold; + + font-weight: 700; + font-size: 16px; + line-height: 24px; + border-radius: 50px !important; + background: $tc-red-70 !important; + color: #fff !important; + text-transform: uppercase; + + @include xs-to-md { + font-size: 14px; + line-height: 20px; + } } .submission-management { @@ -22,7 +60,7 @@ $light-gray-color: $tc-gray-neutral-light; } .submission-management-content { - padding: $submang-space-20 $submang-space-140; + padding: 0 32px; @include md { padding: $submang-space-20 $submang-space-35; @@ -39,7 +77,7 @@ $light-gray-color: $tc-gray-neutral-light; font-size: 15px; color: $tc-gray-50; line-height: $submang-space-25; - margin-top: $submang-space-50; + margin-top: 36px; margin-bottom: $base-unit; @include xs-to-sm { @@ -49,9 +87,18 @@ $light-gray-color: $tc-gray-neutral-light; } .title { - font-size: 20px; - color: $tc-gray-80; - line-height: $submang-space-30; + @include barlow-bold; + + font-weight: 600; + font-size: 24px; + color: $tc-black; + line-height: 28px; + text-transform: uppercase; + + @include xs-to-md { + font-size: 20px; + line-height: 22px; + } } .round-ends { @@ -75,14 +122,65 @@ $light-gray-color: $tc-gray-neutral-light; } } + .subTitle { + display: flex; + margin-top: 12px; + + @include xs-to-md { + margin: 17px 16px 0 16px; + flex-direction: column; + } + + .round { + @include roboto-regular; + + font-weight: 400; + font-size: 16px; + line-height: 24px; + color: $tc-black; + + span { + @include roboto-bold; + + font-weight: 700; + } + + @include xs-to-md { + font-size: 14px; + line-height: 20px; + } + } + + .seperator { + width: 2px; + height: 24px; + left: 228px; + top: 0; + background: #d4d4d4; + border-radius: 1px; + margin: 0 16px; + + @include xs-to-md { + display: none; + } + } + } + .recommend-info { + @include roboto-regular; + + font-size: 16px; font-weight: 400; - color: $tc-gray-50; - line-height: $submang-space-25; + color: $tc-black; + line-height: 24px; margin-bottom: $submang-space-30; + margin-top: 40px; @include xs-to-sm { padding: 0 15px; + margin-top: 32px; + font-size: 14px; + line-height: 20px; } } } @@ -92,8 +190,8 @@ $light-gray-color: $tc-gray-neutral-light; justify-content: space-between; width: 100%; font-weight: 400; - padding: $submang-space-25 $submang-space-50; - background: $light-gray-color; + padding: $submang-space-25 32px 0 32px; + background: #fff; border-bottom: 1px solid $tc-gray-neutral-dark; @include md { @@ -102,36 +200,64 @@ $light-gray-color: $tc-gray-neutral-light; @include xs-to-sm { flex-direction: column; - padding: $submang-space-20 15px; + padding: 9px 16px; } .left-col { + display: flex; padding-right: 200px; + margin-top: 15px; + margin-bottom: 40px; @include xs-to-sm { padding-right: 0; + display: flex; + flex-direction: column; } .name { - font-size: 28px; + @include barlow-bold; + + font-size: 34px; color: $tc-black; - line-height: $submang-space-35; + line-height: 32px; + font-weight: 600; + margin-left: 16px; + margin-top: -6px; + + @include xs-to-sm { + font-size: 28px; + line-height: 32px; + margin-top: 0; + margin-left: 0; + } } .back-btn { - background: none; - color: $gray-color; - font-size: 20px; - line-height: $submang-space-25; - margin-top: 5px; - display: inline-block; - padding: 0; - border: none; - font-weight: 400; - text-transform: initial; + @include roboto-bold; + + font-weight: 700; + font-size: 16px; + line-height: 24px; + border: 0; + color: #137d60 !important; + width: 32px; + height: 24px; + position: relative; + + @include xs-to-md { + margin-left: 0; + margin-bottom: 8px; + } - &:focus { - outline: none; + svg { + border: 1.5px solid #137d60; + border-radius: 24px; + + @include xs-to-md { + margin-left: 0; + margin-bottom: 15px; + } } } } @@ -150,12 +276,6 @@ $light-gray-color: $tc-gray-neutral-light; } } - .round { - font-size: 15px; - color: $tc-gray-80; - line-height: $submang-space-25; - } - .time-left { font-size: 20px; color: $tc-gray-80; diff --git a/src/shared/components/SubmissionManagement/SubmissionsTable/styles.scss b/src/shared/components/SubmissionManagement/SubmissionsTable/styles.scss index 98f5946c1d..aa19df3378 100644 --- a/src/shared/components/SubmissionManagement/SubmissionsTable/styles.scss +++ b/src/shared/components/SubmissionManagement/SubmissionsTable/styles.scss @@ -8,33 +8,31 @@ $submission-space-25: $base-unit * 5; $submission-space-50: $base-unit * 10; .submissions-table { - border: 1px solid $tc-gray-10; + // border: 1px solid $tc-gray-10; overflow: hidden; - border-radius: 4px 4px 0 0; + // border-radius: 4px 4px 0 0; @include xs-to-sm { border: none; border-radius: 0; border-top: 1px solid $tc-gray-10; border-bottom: 1px solid $tc-gray-10; + margin: 0 16px; } table { width: 100%; - thead { - tr { - background: $tc-gray-neutral-light; - } - } - th { - font-size: 13px; - color: $tc-gray-50; - font-weight: 500; + @include barlow-bold; + + font-size: 11px; + color: #767676; + font-weight: 600; line-height: $status-space-20; text-align: left; - padding: $status-space-25 $status-space-20; + padding: 0 15px 11px 15px; + text-transform: uppercase; &.status, &.actions { @@ -70,11 +68,18 @@ $submission-space-50: $base-unit * 10; td { vertical-align: middle; - padding: $submission-space-20; + padding: 16px 16px 2px 16px; background: $tc-white; + font-size: 14px; + color: $tc-black; + font-weight: 500; border-top: 1px solid $tc-gray-10; line-height: 12px; + @include xs-to-md { + padding: 16px 16px 2px 8px; + } + &.no-submission { line-height: $submission-space-20; padding: $submission-space-50 $submission-space-20; @@ -82,19 +87,27 @@ $submission-space-50: $base-unit * 10; } &.dev-details { - background: $tc-gray-neutral-light; padding-right: 60px; + border-top: 0; + padding-top: 0; } } .id-col { font-weight: 700; + width: 32%; + } + + .type-col { + width: 21%; } .date-col { - color: $tc-gray-50; - font-weight: 400; - line-height: $submission-space-20; + width: 20%; + color: $tc-black; + font-weight: 500; + line-height: 22px; + font-size: 14px; } .status-col { @@ -128,6 +141,8 @@ $submission-space-50: $base-unit * 10; padding: 0; line-height: 0; display: inline-block; + margin-left: 15px; + margin-top: 3px; &:focus { outline: none; diff --git a/src/shared/components/SubmissionPage/FilestackFilePicker/index.jsx b/src/shared/components/SubmissionPage/FilestackFilePicker/index.jsx index 848d8fc69d..f2db4d3d9a 100644 --- a/src/shared/components/SubmissionPage/FilestackFilePicker/index.jsx +++ b/src/shared/components/SubmissionPage/FilestackFilePicker/index.jsx @@ -18,7 +18,7 @@ import { PrimaryButton } from 'topcoder-react-ui-kit'; import { config } from 'topcoder-react-utils'; import { errors } from 'topcoder-react-lib'; -import './styles.scss'; +import style from './styles.scss'; const { fireErrorMessage } = errors; @@ -146,7 +146,6 @@ class FilestackFilePicker extends React.Component { fileName, fileExtensions, title, - mandatory, error, dragged, setDragged, @@ -167,13 +166,6 @@ class FilestackFilePicker extends React.Component {

{title}

- { - mandatory && ( -

- *mandatory -

- ) - }
- Drag and drop your + Drag and drop your{' '} {fileExtensions.join(' or ')} {' '} file here. @@ -219,8 +211,8 @@ class FilestackFilePicker extends React.Component {
) } - - {isChallengeBelongToTopgearGroup ? 'Set URL' : 'Pick a File'} + + {isChallengeBelongToTopgearGroup ? 'Set URL' : 'SELECT A FILE'} {!isChallengeBelongToTopgearGroup && (
(
- - - ‹ - + +

- Back to challenge + {title}

-

- {title} -

); /** - * Prop Validation - */ + * Prop Validation + */ Header.propTypes = { challengeId: PT.string.isRequired, challengesUrl: PT.string.isRequired, diff --git a/src/shared/components/SubmissionPage/Header/styles.scss b/src/shared/components/SubmissionPage/Header/styles.scss index c51586c4a7..d5cdd46a4b 100644 --- a/src/shared/components/SubmissionPage/Header/styles.scss +++ b/src/shared/components/SubmissionPage/Header/styles.scss @@ -4,33 +4,37 @@ @include roboto-regular; display: flex; - padding: 30px 60px; - background-color: #fcfcfc; + padding: 30px 0; + background-color: #fff; width: 100%; justify-content: space-between; align-items: center; border-bottom: 1px solid #f0f0f0; @include xs-to-md { - padding: 30px 20px; + padding: 30px 0; } - a { - font-size: 18px; - color: $tc-gray-60; - font-weight: 300; + .header-link { display: flex; - align-items: center; - - span { - font-size: 54px; - display: block; - position: relative; - top: -3px; - margin-right: 6px; + + @include xs-to-md { + flex-direction: column; } } + p { + @include barlow-bold; + + font-weight: 600; + line-height: 32px; + font-size: 34px; + color: #2a2a2a; + display: flex; + margin-left: 16px; + margin-top: -8px; + } + h1 { font-weight: 300; font-size: 24px; @@ -53,10 +57,30 @@ text-align: right; } } +} - p { - @include xs-to-sm { - display: none; - } +.back-arrow { + width: 32px; + height: 24px; + border: 1.5px solid #137d60; + color: #137d60; + border-radius: 24px; + padding: 4px 8px; + margin-bottom: 10px; + position: relative; + + @include xs-to-md { + margin-left: 15px; + margin-bottom: 15px; + } +} + +.left-arrow { + border: 1.5px solid #137d60; + border-radius: 24px; + + @include xs-to-md { + margin-left: 15px; + margin-bottom: 15px; } } diff --git a/src/shared/components/SubmissionPage/Submit/index.jsx b/src/shared/components/SubmissionPage/Submit/index.jsx index 6965d1d751..41fa36fbf5 100644 --- a/src/shared/components/SubmissionPage/Submit/index.jsx +++ b/src/shared/components/SubmissionPage/Submit/index.jsx @@ -19,7 +19,7 @@ import { COMPETITION_TRACKS } from 'utils/tc'; import FilestackFilePicker from '../FilestackFilePicker'; import Uploading from '../Uploading'; -import './styles.scss'; +import style from './styles.scss'; /** * Submissions Page shown to develop challengers. @@ -171,6 +171,8 @@ class Submit extends React.Component { dragged: false, }); + const disabled = !agreed || !!fpState.error || !fpState.fileName; + return ( (!isSubmitting && !submitDone && !errorMsg) ? (
@@ -184,56 +186,60 @@ class Submit extends React.Component {

- { isChallengeBelongToTopgearGroup ? 'URL' : 'FILES'} + { isChallengeBelongToTopgearGroup ? 'URL' : 'SUBMISSION UPLOAD'}

-

+

Please follow the instructions on the Challenge Details page regarding what your submission should contain and how it should be organized.

-
-
+ {/* eslint-disable-next-line max-len */} + { track === COMPETITION_TRACKS.DEV || track === COMPETITION_TRACKS.DS || track === COMPETITION_TRACKS.QA ? ( +

+ Upload your entire submission as a single zip file. If you are having + trouble uploading your file, please send your submission to support@topcoder.com +

+ ) : null }
{ track === COMPETITION_TRACKS.DEV ? (
- {isChallengeBelongToTopgearGroup - ? (

Enter the URL to your submission.

) - : (

Upload your entire submission as a single zip file.

)} + {!!isChallengeBelongToTopgearGroup + && (

Enter the URL to your submission.

)}
) : null } { track === COMPETITION_TRACKS.DES ? ( -
+
  1. Place your submission files into a "Submission.zip" file.
  2. Place all of your source files into a "Source.zip" file.
  3. -
  4. Create a JPG preview file.
  5. -
  6. - Create a declaration.txt file. Document fonts, stock art - and icons used. -
  7. -
  8. - Zip the 4 files from the previous steps - into a single zip file and upload below. -
  9. +
  10. Create a .jpg preview file
  11. + {/* eslint-disable-next-line max-len */} +
  12. Create a “Declaration.txt” file that documents all fonts, stock art, and icons used
  13. + {/* eslint-disable-next-line max-len */} +
  14. Zip the 4 files from the previous steps into a single .zip file and upload.
-

For detailed information on packaging your submission, please visit the - ‌ +

+ For detailed information on packaging your submissions, please visit the +   - help center. + Help Center. +   + If you are having trouble uploading your file, please send your submission to support@topcoder.com

) : null }
+
+
{ isLoadingCommunitiesList ? () : ( )}
- { isChallengeBelongToTopgearGroup - ? ( -

- If you are having trouble submitting, please send - your submission to - ‌ - - support@topcoder.com - -

- ) - : ( -

- If you are having trouble uploading your file, please send - your submission to - ‌ - - support@topcoder.com - -

- )}
+

Submitting your files means you hereby agree to the @@ -308,14 +290,18 @@ class Submit extends React.Component {

- I UNDERSTAND AND AGREE + I understand and agree
+
+
+
- Submit + SUBMIT
diff --git a/src/shared/components/SubmissionPage/Submit/styles.scss b/src/shared/components/SubmissionPage/Submit/styles.scss index b37cca0d8d..0c06f5f2e7 100644 --- a/src/shared/components/SubmissionPage/Submit/styles.scss +++ b/src/shared/components/SubmissionPage/Submit/styles.scss @@ -8,7 +8,7 @@ flex-direction: column; background-color: white; width: 100%; - padding: 5px 60px; + padding: 5px 0; @include sm-to-md { padding: 0; @@ -32,11 +32,14 @@ .row { display: flex; - padding: 30px 0; - margin-bottom: 70px; + padding-top: 30px; + margin-bottom: 32px; + justify-content: space-between; + flex-direction: row; @include sm-to-md { margin: 0 20px; + flex-direction: column; } @include sm { @@ -51,8 +54,7 @@ .left { padding-right: 33px; - border-right: 6px solid #f6f6f6; - max-width: 310px; + width: 50%; @include md-to-lg { padding-right: 20px; @@ -61,48 +63,49 @@ @include sm { border-right: none; max-width: 100%; + width: 100%; + padding-right: 0; } - p, - a { - font-size: 13px; - color: $tc-gray-60; - font-style: italic; - max-width: 270px; - width: 270px; - line-height: 20px; - margin-bottom: 12px; - - @media (min-width: 800px) and (max-width: 1000px) { - max-width: 220px; - width: 220px; - } + p.note { + @include roboto-regular; - @media (min-width: 768px) and (max-width: 800px) { - max-width: 200px; - width: 200px; - } + background-color: #fff0ce; + border-radius: 4px; + padding: 16px; + font-size: 16px; + line-height: 24px; + color: #2a2a2a; + } - @include sm { - max-width: 100%; - width: 100%; - } + .additional-note { + @include roboto-regular; - @include sm-to-md { - margin-bottom: 25px; - } + margin-top: 8px; + font-size: 16px; + line-height: 24px; + color: #2a2a2a; + } + + a { + font-size: 16px; + color: $tc-dark-blue; + cursor: pointer; } h2 { - font-size: 15px; - line-height: 25px; - margin-bottom: 4px; + @include barlow-bold; + + font-size: 22px; + line-height: 26px; + margin-bottom: 24px; + color: #2a2a2a; } } .right { - width: 100%; margin-left: 60px; + width: 50%; @media (min-width: 768px) and (max-width: 1280px) { margin-left: 30px; @@ -110,6 +113,7 @@ @include sm { margin-left: 0; + width: 100%; } & > p { @@ -127,6 +131,7 @@ .file-picker-container { display: flex; + height: 100%; margin-bottom: 40px; @include xs-to-md { @@ -139,24 +144,20 @@ } .agree { - background-color: #fcfcfc; + background-color: #f4f4f4; border-top: 1px solid #f0f0f0; border-bottom: 1px solid #f0f0f0; margin-bottom: 30px; - padding: 30px 60px; + margin-top: 24px; + padding: 16px 16px 22px 16px; flex-direction: column; align-items: center; - @include xs-to-lg { - margin: 0; - } - - @include xs-to-md { - padding: 30px; - } - p { - font-size: 13px; + @include roboto-bold; + + font-weight: 500; + font-size: 16px; color: #37373c; line-height: 24px; margin-bottom: 50px; @@ -178,13 +179,12 @@ .tc-checkbox { height: 15px; - width: 210px; + width: 100%; margin: 0; padding: 0; vertical-align: bottom; position: relative; display: inline-block; - margin-bottom: 30px; input[type=checkbox] { visibility: visible; @@ -218,25 +218,27 @@ background: transparent; top: 3px; left: 2px; - border: 3px solid $tc-dark-blue; + border: 3px solid #137d60; border-top: none; border-right: none; transform: rotate(-45deg); transition: all 0.15s ease-in-out; } - &:hover::after { - opacity: 0.3; + @media (min-width: 768px) { + &:hover::after { + opacity: 0.3; + } } } input[type=checkbox]:checked ~ label { - background: $tc-dark-blue; - border-color: $tc-dark-blue; + background: #137d60; + border-color: #137d60; } input[type=checkbox]:focus ~ label { - outline: 2px auto $tc-dark-blue; + outline: 2px auto #137d60; } input[type=checkbox]:checked + label::after { @@ -246,3 +248,40 @@ } } } + +.hr { + opacity: 0.5; + + @include xs-to-md { + margin-top: 24px; + margin-bottom: 24px; + } +} + +.submitArea { + width: 100%; + display: flex; + justify-content: flex-end; +} + +.button { + @include roboto-bold; + + font-weight: 700; + font-size: 16px; + line-height: 24px; + border-radius: 50px !important; + background: #137d60 !important; + color: #fff !important; +} + +.buttonDisabled { + @include roboto-bold; + + font-weight: 700; + font-size: 16px; + line-height: 24px; + border-radius: 50px !important; + color: #767676 !important; + background: #f4f4f4 !important; +} diff --git a/src/shared/components/SubmissionPage/Uploading/index.jsx b/src/shared/components/SubmissionPage/Uploading/index.jsx index 7f22beff1c..4c6cff567a 100644 --- a/src/shared/components/SubmissionPage/Uploading/index.jsx +++ b/src/shared/components/SubmissionPage/Uploading/index.jsx @@ -8,13 +8,12 @@ */ import React from 'react'; import PT from 'prop-types'; -import { Link } from 'react-router-dom'; -import RobotHappy from 'assets/images/robot-happy.svg'; -import RobotSad from 'assets/images/robot-embarassed.svg'; +import UploadSuccess from 'assets/images/upload-success.svg'; +import UploadLoading from 'assets/images/upload-loading.svg'; +import UploadFail from 'assets/images/upload-fail.svg'; import { PrimaryButton, Button } from 'topcoder-react-ui-kit'; -import './styles.scss'; - import { COMPETITION_TRACKS } from 'utils/tc'; +import style from './styles.scss'; const Uploading = ({ challengeId, @@ -32,171 +31,178 @@ const Uploading = ({
{ - isSubmitting - && ( -

- UPLOADING SUBMISSION FOR -

- ) - } - { - submitDone - && ( -

- SUBMISSION COMPLETED FOR -

- ) - } - { - error - && ( -

- ERROR SUBMITTING FOR -

- ) - } - { - isSubmitting - && ( -

- “ - {challengeName } - ” -

- ) - } - { - (submitDone || error) - && ( - - {challengeName} - - ) - } - { - (isSubmitting || submitDone) - && - } - { - error - && - } - { - isSubmitting - && ( -

- Hey, your work is AWESOME! Please don't close this window while I'm - working, you'll lose all files! -

- ) - } - { - isSubmitting && !submitDone - && ( -
-
-
- ) - } - { - isSubmitting && !submitDone - && ( -

- Uploaded: - {(100 * uploadProgress).toFixed()} - % -

- ) - } - { - error - && ( -

- Oh, that’s embarrassing! The file couldn’t be - uploaded, I’m so sorry. -

- ) - } - { - error - && ( -
- {error} -
- ) - } - { - error - && ( -
- - retry()} - > - Try Again - -
- ) - } - { - submitDone && !error - && ( -

- Thanks for participating! We’ve received your submission and will - send you an email shortly to confirm and explain what happens next. -

- ) - } - { - submitDone && !error - && ( -
- { track === COMPETITION_TRACKS.DES ? ( - - - back()} - > - View My Submissions - - - ) : ( - - - back()} - > - Back to Challenge - - - )} -
- ) - } + isSubmitting + && ( +

+ UPLOADING SUBMISSION FOR +

+ ) + } + { + submitDone + && ( +

+ UPLOADING COMPLETED FOR +

+ ) + } + { + error + && ( +

+ ERROR SUBMITTING FOR +

+ ) + } + { + isSubmitting + && ( +

+ “ + {challengeName } + ” +

+ ) + } + { + (submitDone || error) + && ( +

+ {challengeName} +

+ ) + } + { + (isSubmitting && !submitDone) &&
+ } + { + (!isSubmitting && submitDone) && + } + { + error + && + } + { + isSubmitting + && ( +

+ Hey, your work is AWESOME! Please don't close this window while uploading, + Your progress will be lost. +

+ ) + } + { + isSubmitting && !submitDone + && ( +
+
+
+ ) + } + { + isSubmitting && !submitDone + && ( +

+ Uploading: + {(100 * uploadProgress).toFixed()} + % +

+ ) + } + { + error + && ( +

+ Oh, that’s embarrassing! The file couldn’t be + uploaded. +

+ ) + } + { + error + && ( +
+ {error} +
+ ) + } + { + error + && ( +
+ + retry()} + theme={{ button: style.button }} + > + Try Again + +
+ ) + } + { + submitDone && !error + && ( +

+ Thanks for participating! We’ve received your submission and will + send you an email shortly to confirm and explain what happens next. +

+ ) + } + { + submitDone && !error + && ( +
+ { track === COMPETITION_TRACKS.DES ? ( + + + back()} + theme={{ button: style.button }} + > + My Submissions + + + ) : ( + + + back()} + theme={{ button: style.button }} + > + MY SUBMISSIONS + + + )} +
+ ) + }
); /** - * Prop Validation - */ + * Prop Validation + */ Uploading.propTypes = { challengeId: PT.string.isRequired, challengeName: PT.string.isRequired, diff --git a/src/shared/components/SubmissionPage/Uploading/styles.scss b/src/shared/components/SubmissionPage/Uploading/styles.scss index d39f367a05..da5f354fdf 100644 --- a/src/shared/components/SubmissionPage/Uploading/styles.scss +++ b/src/shared/components/SubmissionPage/Uploading/styles.scss @@ -14,13 +14,6 @@ padding: 30px; } -.link, -.link:visited { - font-size: 20px; - line-height: 30px; - color: #1a85ff; -} - .uploading { display: flex; flex-direction: column; @@ -28,62 +21,136 @@ width: 100%; .error-msg { + @include roboto-bold; + + font-weight: 500; width: 500px; - margin-bottom: 45px; - padding: 5px 13px; - background: #fff4f4; - border: 1px solid #ffd4d1; - color: #f22f24; - font-size: 13px; - border-radius: 2px; - font-style: italic; + margin-bottom: 24px; + color: #ef476f; + line-height: 24px; + font-size: 16px; text-align: center; + + @include xs-to-sm { + width: 100%; + } } .progress-container { - width: 650px; + width: 90%; height: 10px; - background-color: $tc-gray-10; - border-radius: 12px; + background-color: #e9e9e9; + border-radius: 8px; .progress-bar { width: 0%; - height: 10px; - background-color: $tc-dark-blue; - border-radius: 12px; + height: 16px; + background-color: #9d41c9; + border-radius: 8px; } } h3 { - font-size: 20px; - line-height: 30px; - color: #3d3d3d; + @include barlow-bold; + + font-size: 24px; + line-height: 28px; + font-weight: 600; + color: $tc-black; } svg { - margin-top: 50px; + margin-top: 84px; + + @include xs-to-md { + margin-top: 40px; + } + } + + div.animate { + svg { + animation-name: spin; + animation-duration: 2000ms; + animation-iteration-count: infinite; + animation-timing-function: linear; + } + } + + h4.link { + @include roboto-regular; + + font-weight: 400; + text-align: center; + font-size: 24px; + line-height: 32px; + color: $tc-black; + margin-top: 24px; } p { - font-size: 15px; - color: #a3a3ad; - width: 80%; + @include roboto-bold; + + font-size: 16px; + font-weight: 700; + line-height: 24px; + color: $tc-black; text-align: center; - line-height: 18px; margin-bottom: 30px; - margin-top: 30px; + margin-top: 80px; + + @include xs-to-md { + margin-top: 40px; + } } .submitting { - margin-top: 20px; - font-size: 13px; + @include roboto-regular; + + font-weight: 400; + text-align: center; + margin-top: 8px; + font-size: 14px; + line-height: 22px; color: $tc-black; } .button-container { align-items: center; - flex-wrap: wrap; + flex-wrap: nowrap; display: flex; justify-content: center; } } + +.button { + @include roboto-bold; + + font-weight: 700; + font-size: 16px; + line-height: 24px; + border-radius: 50px !important; + background: #137d60 !important; + color: #fff !important; +} + +.buttonOutlined { + @include roboto-bold; + + font-weight: 700; + font-size: 16px; + line-height: 24px; + border-radius: 50px !important; + background: #fff !important; + color: #137d60 !important; + border: 2px solid #137d60; +} + +@keyframes spin { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } +} diff --git a/src/shared/components/Switch/style.scss b/src/shared/components/Switch/style.scss index 59bebc9a6b..ef1e431faf 100644 --- a/src/shared/components/Switch/style.scss +++ b/src/shared/components/Switch/style.scss @@ -19,7 +19,7 @@ } .enabled { - background: $tc-dark-blue; + background: $listing-checkbox-green; .handle { right: 0; diff --git a/src/shared/components/SwitchWithLabel/index.jsx b/src/shared/components/SwitchWithLabel/index.jsx index 43c3b0fba0..edcc343934 100644 --- a/src/shared/components/SwitchWithLabel/index.jsx +++ b/src/shared/components/SwitchWithLabel/index.jsx @@ -35,7 +35,7 @@ function SwitchWithLabel({ switch: theme.switch, }} /> - {labelAfter} + {labelAfter}
); } diff --git a/src/shared/components/SwitchWithLabel/style.scss b/src/shared/components/SwitchWithLabel/style.scss index ad87cc8e11..0627c2c18a 100644 --- a/src/shared/components/SwitchWithLabel/style.scss +++ b/src/shared/components/SwitchWithLabel/style.scss @@ -1,7 +1,7 @@ @import '~styles/mixins'; .switch { - margin: 0 5px; + margin-right: 5px; position: relative; top: 3px; } @@ -9,6 +9,11 @@ .wrapper { cursor: pointer; display: inline-block; - font-size: 12px; - font-weight: normal; + font-size: 14px; + color: $tc-black; + line-height: 22px; + + @include roboto-regular; + + font-weight: 400; } diff --git a/src/shared/components/Tooltip/style.scss b/src/shared/components/Tooltip/style.scss index 9e65bce94a..26c4735ae7 100644 --- a/src/shared/components/Tooltip/style.scss +++ b/src/shared/components/Tooltip/style.scss @@ -8,7 +8,7 @@ } .rc-tooltip-inner { - border-radius: 3px; + border-radius: 8px; background: $tc-gray-80; padding: 0; } @@ -17,6 +17,7 @@ .rc-tooltip-placement-topLeft .rc-tooltip-arrow, .rc-tooltip-placement-topRight .rc-tooltip-arrow { border-top-color: $tc-gray-80; + background: url(assets/images/tooltip-arrow.svg); } .rc-tooltip-placement-right .rc-tooltip-arrow, diff --git a/src/shared/components/TrackIcon/style.scss b/src/shared/components/TrackIcon/style.scss index 96c861f9db..97e722a8c2 100644 --- a/src/shared/components/TrackIcon/style.scss +++ b/src/shared/components/TrackIcon/style.scss @@ -5,6 +5,9 @@ $track-space-10: $base-unit * 2; $track-space-15: $base-unit * 3; $track-space-20: $base-unit * 4; $track-radius-4: $corner-radius * 2; +$track-code-green: #35ac35; +$track-code-blue: #2984bd; +$track-code-turquose: #0ab88a; .trackIcon { display: flex; @@ -24,24 +27,26 @@ $track-radius-4: $corner-radius * 2; line-height: $track-space-15; color: $tc-white; padding: $track-code-pad - 1 0 $track-code-pad; - border-radius: $corner-radius; + border-radius: 4px; cursor: pointer; width: 100%; height: 100%; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; &.design, &.generic { - background: $tc-light-blue-110; + background: $track-code-blue; } &.develop, &.development { - background: $tc-green-110; + background: $track-code-green; } &.qa, &.quality-assurance { - background: $tc-purple-120; + background: $track-code-turquose; } &.data_science, @@ -55,12 +60,14 @@ $track-radius-4: $corner-radius * 2; @include roboto-regular; text-align: center; - font-size: 10px; + font-size: 9px; font-weight: 700; border-radius: $corner-radius + 1px; - line-height: $tco-line-hieght; + line-height: 8px; padding: $base-unit - 1 0; - margin-top: $base-unit - 4; + margin-top: 0; + border-top-left-radius: 0; + border-top-right-radius: 0; &.design, &.generic { diff --git a/src/shared/components/challenge-detail/Button/index.jsx b/src/shared/components/challenge-detail/Button/index.jsx new file mode 100644 index 0000000000..c7bd4c7891 --- /dev/null +++ b/src/shared/components/challenge-detail/Button/index.jsx @@ -0,0 +1,64 @@ +import React from 'react'; +import PT from 'prop-types'; + +import './styles.scss'; + +/** + * Displays a button. + * + * @param {Object} props component properties + * @returns {JSX.Element} + */ +const Button = ({ + children, + className, + onClick, + isInverted, + isPrimary, + isSelected, + isText, + shade, + size, + style, + disabled, + value, +}) => ( + +); + +Button.defaultProps = { + isInverted: false, + isPrimary: false, + disabled: false, +}; + +Button.propTypes = { + children: PT.node.isRequired, + className: PT.string.isRequired, + onClick: PT.func.isRequired, + isInverted: PT.bool, + isPrimary: PT.bool, + isSelected: PT.bool.isRequired, + isText: PT.bool.isRequired, + shade: PT.oneOf(['dark']).isRequired, + size: PT.string.isRequired, + style: PT.oneOf(['circle']).isRequired, + value: PT.any.isRequired, + disabled: PT.bool, +}; diff --git a/src/shared/components/challenge-detail/Button/styles.scss b/src/shared/components/challenge-detail/Button/styles.scss new file mode 100644 index 0000000000..5310273f4d --- /dev/null +++ b/src/shared/components/challenge-detail/Button/styles.scss @@ -0,0 +1,91 @@ +@import '~styles/mixins'; + +.button { + @include roboto-bold; + + padding: 8px 13px; + font-size: 12px; + color: #137d60; + line-height: 1; + letter-spacing: 0.8px; + white-space: nowrap; + appearance: none; + background: $tc-white; + border: 1px solid #137d60; + border-radius: 15px; + + &.is-selected { + color: $tc-gray-90; + border-color: $tc-gray-90; + } + + &.button-circle { + display: flex; + justify-content: center; + align-items: center; + padding: 0; + width: 30px; + height: 30px; + } + + &.button-primary { + &.button-inverted { + border: none; + padding: 9px 14px; + } + } +} + +.button-primary { + color: $tc-white; + background-color: #137d60; + + &.button-inverted { + color: #137d60; + background-color: $tc-white; + } +} + +.button-text { + padding: 0; + letter-spacing: 1px; + color: inherit; + border: none; + background: none; +} + +.button-lg { + padding: 12px 20px; + font-size: 12px; + border-radius: 20px; + + &.button-circle { + padding: 0; + width: 40px; + height: 40px; + } + + &.button-primary { + &.button-inverted { + padding: 13px 21px; + } + } +} + +.button-sm { + border-radius: 10px; + padding: 4px 13px; + font-size: 10px; + + &.button-circle { + padding: 0; + width: 20px; + height: 20px; + } + + &.button-primary { + &.button-inverted { + padding: 5px 14px; + } + } +} diff --git a/src/shared/components/challenge-detail/Checkpoints/index.jsx b/src/shared/components/challenge-detail/Checkpoints/index.jsx index a6e1282d5a..71386b2263 100644 --- a/src/shared/components/challenge-detail/Checkpoints/index.jsx +++ b/src/shared/components/challenge-detail/Checkpoints/index.jsx @@ -2,7 +2,10 @@ import React from 'react'; import PT from 'prop-types'; -import style from './styles.scss'; +import ArrowDown from 'assets/images/icon-arrow-down-black.svg'; +import ArrowUp from 'assets/images/icon-arrow-up-black.svg'; + +import './styles.scss'; function Checkpoints(props) { const { @@ -16,7 +19,7 @@ function Checkpoints(props) { return (
-
+ {/*
{ checkpointResults && checkpointResults.map((item, index) => (
+
*/}

Checkpoint Winners & General Feedback

+
Check forums for general feedback

{ - item.expanded ? '-' : '+' + item.expanded ? : } diff --git a/src/shared/components/challenge-detail/Checkpoints/styles.scss b/src/shared/components/challenge-detail/Checkpoints/styles.scss index 3446131ca6..55fc6fa946 100644 --- a/src/shared/components/challenge-detail/Checkpoints/styles.scss +++ b/src/shared/components/challenge-detail/Checkpoints/styles.scss @@ -3,7 +3,7 @@ $tc-gray-border: #aaaab5; .challenge-detail-checkpoints { display: flex; - justify-content: center; + justify-content: flex-start; .challenge-checkpoint-list { margin: 50px 20px 50px 10px; @@ -22,7 +22,7 @@ $tc-gray-border: #aaaab5; border-radius: 2px; color: $tc-dark-blue; padding: 10px 0; - margin-bottom: 10px; + margin-bottom: 8px; width: 190px; max-width: 190px; line-height: 30px; @@ -33,15 +33,40 @@ $tc-gray-border: #aaaab5; .challenge-checkpoint-detail { flex: 1; - margin: 50px 10px 50px 20px; - max-width: 740px; + margin: 34px 19px 36px 29px; + + @include xs-to-sm { + margin: 24px 16px; + } & > h2 { - @include tc-label-xl; + @include barlow-bold; + font-weight: 600; color: $tc-black; - line-height: 30px; + font-size: 24px; + line-height: 28px; + text-transform: uppercase; margin-bottom: 10px; + + @include xs-to-sm { + font-size: 20px; + line-height: 22px; + } + } + + & > h5 { + @include roboto-regular; + + font-size: 16px; + line-height: 24px; + font-weight: 400; + margin-top: 16px; + + @include xs-to-sm { + font-size: 14px; + line-height: 20px; + } } & > p { @@ -59,53 +84,68 @@ $tc-gray-border: #aaaab5; justify-content: center; .challenge-checkpoint-submission { - @include tc-label-xl; + @include barlow-bold; flex: 1; - background: $tc-gray-neutral-light; - border: 1px solid $tc-gray-10; - border-radius: 2px; - color: $tc-dark-blue; - line-height: 30px; + background: #f4f4f4; + padding: 8px 8px 8px 16px; + border: 0; + color: $tc-black; + font-size: 18px; + line-height: 22px; text-align: left; - padding: 10px 0 10px 17px; display: flex; + font-weight: 600; + text-transform: uppercase; + border-radius: 4px; overflow: hidden; justify-content: space-between; cursor: pointer; - &:hover, - &:focus, - &:active { - outline: Initial; - border: 1px solid $tc-gray-10; - } - - &:hover { - background: $tc-gray-neutral-dark; + @include xs-to-sm { + font-size: 16px; + line-height: 18px; } .challenge-checkpoint-expander { padding-right: 23px; - } - .feedback-text { @include xs-to-sm { - display: none; + padding-right: 16px; + } + + svg { + width: 12px; + height: 12px; + padding-top: 2px; + padding-bottom: 2px; } } + + .feedback-text { + @include xs-to-sm; + } } .challenge-checkpoint-feedback { - @include tc-body-md; + @include roboto-regular; flex: 1; white-space: pre-wrap; - color: $tc-gray-90; - padding: 15px 15px 25px; + color: $tc-black; + font-size: 16px; + font-weight: 400; + line-height: 24px; + padding: 16px; + background-color: #f4f4f4; + + @include xs-to-sm { + font-size: 14px; + line-height: 20px; + } span { - color: $tc-gray-40; + color: $tc-black; } } } diff --git a/src/shared/components/challenge-detail/Header/ChallengeTags.jsx b/src/shared/components/challenge-detail/Header/ChallengeTags.jsx index 082bdfc917..d0c45b0615 100644 --- a/src/shared/components/challenge-detail/Header/ChallengeTags.jsx +++ b/src/shared/components/challenge-detail/Header/ChallengeTags.jsx @@ -77,15 +77,19 @@ export default function ChallengeTags(props) { { challengeType && ( - ( - setImmediate(() => setChallengeListingFilter({ types: [challengeType.abbreviation] })) - ) - } - to={`${challengesUrl}?types[]=${encodeURIComponent(challengeType.abbreviation)}`} - > - {challengeType.name} - +

+ ( + setImmediate(() => setChallengeListingFilter( + { types: [challengeType.abbreviation] }, + )) + ) + } + to={`${challengesUrl}?types[]=${encodeURIComponent(challengeType.abbreviation)}`} + > + {challengeType.name} + +
) } { @@ -124,15 +128,17 @@ export default function ChallengeTags(props) { tags.map(tag => ( tag && ( - setImmediate(() => setChallengeListingFilter({ search: tag })) - } - to={`${challengesUrl}?search=${ - encodeURIComponent(tag)}`} - > - {tag} - + + setImmediate(() => setChallengeListingFilter({ search: tag })) + } + to={`${challengesUrl}?search=${ + encodeURIComponent(tag)}`} + > + {tag} + + ) )) } diff --git a/src/shared/components/challenge-detail/Header/DeadlinesPanel/Card/index.jsx b/src/shared/components/challenge-detail/Header/DeadlinesPanel/Card/index.jsx index 154e95a46b..d58cfb4a75 100644 --- a/src/shared/components/challenge-detail/Header/DeadlinesPanel/Card/index.jsx +++ b/src/shared/components/challenge-detail/Header/DeadlinesPanel/Card/index.jsx @@ -5,12 +5,16 @@ import moment from 'moment'; import PT from 'prop-types'; import React from 'react'; +import CalendarIcon from 'assets/images/icon-calendar-2.svg'; +import CalendarIconActive from 'assets/images/icon-calendar-2-active.svg'; +import TimeIcon from 'assets/images/icon-time.svg'; +import TimeIconActive from 'assets/images/icon-time-active.svg'; import './style.scss'; /* Date/time format to use in the card. */ -const FORMAT = 'MMM DD, HH:mm'; -const FORMAT_YEAR = 'MMM DD YYYY, HH:mm'; +const FORMAT_YEAR = 'MMM DD, YYYY'; +const TIME = 'HH:mm'; export default function Card({ past, time, title }) { const time2 = moment(time); @@ -20,9 +24,20 @@ export default function Card({ past, time, title }) {

{title}

-

- {time2.format(time2.year() !== moment().year() ? FORMAT_YEAR : FORMAT)} -

+
+

+ { past2 ? : } + + {time2.format(FORMAT_YEAR)} + +

+

+ { past2 ? : } + + {time2.format(TIME)} + +

+
); } diff --git a/src/shared/components/challenge-detail/Header/DeadlinesPanel/Card/style.scss b/src/shared/components/challenge-detail/Header/DeadlinesPanel/Card/style.scss index ea1acb8c97..d2ed40c6c5 100644 --- a/src/shared/components/challenge-detail/Header/DeadlinesPanel/Card/style.scss +++ b/src/shared/components/challenge-detail/Header/DeadlinesPanel/Card/style.scss @@ -1,15 +1,34 @@ @import "~styles/mixins"; +.open { + color: $tc-white; +} + +.past { + color: #aaa; +} + .open, .past { @include roboto-regular; margin-bottom: 10px; padding: 0 20px; - border-right: 1px solid $tc-gray-10; + border-left: 1px solid $tc-gray-40; + + @include xs-to-md { + border-left: none; + border-bottom: 1px solid $tc-gray-40; + padding-top: 16px; + padding-bottom: 16px; - &:last-child { - border-right: none; + &:last-child { + border-bottom: none; + } + } + + &:first-child { + border-left: none; } } @@ -17,15 +36,47 @@ font-size: 20px; letter-spacing: -0.5px; line-height: 25px; + font-weight: 500; + margin-top: 7px; + + span { + margin-left: 8px; + } +} + +.time { + font-size: 20px; + letter-spacing: -0.5px; + line-height: 25px; + font-weight: 500; + margin-top: 4px; + + span { + margin-left: 8px; + } } -.open .date { color: $tc-white; } -.past .date { color: $tc-green; } +.open .date { + color: $tc-white; + + svg { + path: { + fill: $tc-white; + } + } +} +.past .date { color: #aaa; } .title { - font-size: 13px; - color: $tc-gray-40; + font-size: 12px; + font-weight: 700; letter-spacing: 0; + color: #fff; line-height: 15px; margin-bottom: 5px; + text-transform: uppercase; +} + +.past .title { + color: $tc-gray-40; } diff --git a/src/shared/components/challenge-detail/Header/DeadlinesPanel/style.scss b/src/shared/components/challenge-detail/Header/DeadlinesPanel/style.scss index 43adf5858b..a277dce7e6 100644 --- a/src/shared/components/challenge-detail/Header/DeadlinesPanel/style.scss +++ b/src/shared/components/challenge-detail/Header/DeadlinesPanel/style.scss @@ -1,11 +1,19 @@ @import "~styles/mixins"; .panel { - background-color: $tc-gray-80; + background-color: #555; display: flex; flex-wrap: wrap; - padding: 30px 0 15px; + justify-content: space-between; + padding: 30px 150px 15px 0; position: relative; + + @include xs-to-md { + flex-direction: column; + padding-top: 0; + padding-right: 16px; + padding-left: 16px; + } } .timezone { diff --git a/src/shared/components/challenge-detail/Header/Prizes.jsx b/src/shared/components/challenge-detail/Header/Prizes.jsx index d988f46069..68db58e384 100644 --- a/src/shared/components/challenge-detail/Header/Prizes.jsx +++ b/src/shared/components/challenge-detail/Header/Prizes.jsx @@ -38,17 +38,17 @@ export default function Prizes({ pointPrizes, prizes }) { {getOrdinal(rank)}

-
+
); }) diff --git a/src/shared/components/challenge-detail/Header/TabSelector/index.jsx b/src/shared/components/challenge-detail/Header/TabSelector/index.jsx index 126c5de184..4b23fda667 100644 --- a/src/shared/components/challenge-detail/Header/TabSelector/index.jsx +++ b/src/shared/components/challenge-detail/Header/TabSelector/index.jsx @@ -1,14 +1,20 @@ /* eslint jsx-a11y/no-static-element-interactions:0 */ +/* eslint-disable jsx-a11y/click-events-have-key-events */ /* Stateless tab control to switch between various views available in challenge detail page. */ import _ from 'lodash'; -import React from 'react'; +import React, { useState } from 'react'; import PT from 'prop-types'; +import cn from 'classnames'; import { TABS as DETAIL_TABS } from 'actions/page/challenge-details'; import { config } from 'topcoder-react-utils'; +import { useMediaQuery } from 'react-responsive'; +import ArrowIcon from 'assets/images/ico-arrow-down.svg'; +import CloseIcon from 'assets/images/icon-close-green.svg'; +import SortIcon from 'assets/images/icon-sort-mobile.svg'; import style from './style.scss'; @@ -32,15 +38,95 @@ export default function ChallengeViewSelector(props) { trackLower, hasRegistered, mySubmissions, + onSort, } = props; + const { type, tags } = challenge; + + const [currentSelected, setCurrentSelected] = useState('Details'); + const [isTabClosed, setIsTabClosed] = useState(true); + const [expanded, setExpanded] = useState(false); + const [selectedSortOption, setSelectedSortOption] = useState(); + const isF2F = type === 'First2Finish'; + const isBugHunt = _.includes(tags, 'Bug Hunt'); + const isDesign = trackLower === 'design'; + + let SubmissionSortOptions = [ + { field: 'Rating', sort: 'desc', name: 'Rating: High to Low' }, + { field: 'Rating', sort: 'asc', name: 'Rating: Low to High' }, + { field: 'Username', sort: 'asc', name: 'Username' }, + { field: 'Submission Date', sort: 'desc', name: 'Submission Date: New to Old' }, + { field: 'Submission Date', sort: 'asc', name: 'Submission Date: Old to New' }, + { field: 'Initial Score', sort: 'desc', name: 'Initial Score: High to Low' }, + { field: 'Initial Score', sort: 'asc', name: 'Initial Score: Low to High' }, + { field: 'Final Score', sort: 'desc', name: 'Final Score: High to Low' }, + { field: 'Final Score', sort: 'asc', name: 'Final Score: Low to High' }, + ]; + + let RegistrationSortOptions = [ + { field: 'Rating', sort: 'desc', name: 'Rating: High to Low' }, + { field: 'Rating', sort: 'asc', name: 'Rating: Low to High' }, + { field: 'Username', sort: 'asc', name: 'Username' }, + { field: 'Registration Date', sort: 'desc', name: 'Registration Date: New to Old' }, + { field: 'Registration Date', sort: 'asc', name: 'Registration Date: Old to New' }, + { field: 'Submitted Date', sort: 'desc', name: 'Submitted Date: New to Old' }, + { field: 'Submitted Date', sort: 'asc', name: 'Submitted Date: Old to New' }, + ]; + + const MarathonSortOptions = [ + { field: 'Final Rank', sort: 'desc', name: 'Final Rank: High to Low' }, + { field: 'Final Rank', sort: 'asc', name: 'Final Rank: Low to High' }, + { field: 'Provisional Rank', sort: 'desc', name: 'Provisional Rank: High to Low' }, + { field: 'Provisional Rank', sort: 'asc', name: 'Provisional Rank: Low to High' }, + { field: 'Rating', sort: 'desc', name: 'Rating: High to Low' }, + { field: 'Rating', sort: 'asc', name: 'Rating: Low to High' }, + { field: 'Username', sort: 'asc', name: 'Username' }, + { field: 'Final Score', sort: 'desc', name: 'Final Score: High to Low' }, + { field: 'Final Score', sort: 'asc', name: 'Final Score: Low to High' }, + { field: 'Provisional Score', sort: 'desc', name: 'Provisional Score: High to Low' }, + { field: 'Provisional Score', sort: 'asc', name: 'Provisional Score: Low to High' }, + { field: 'Submission Date', sort: 'desc', name: 'Submission Date: New to Old' }, + { field: 'Submission Date', sort: 'asc', name: 'Submission Date: Old to New' }, + ]; + + const MySubmissionsSortOptions = [ + { field: 'Submission ID', sort: 'desc', name: 'Submission ID: High to Low' }, + { field: 'Submission ID', sort: 'asc', name: 'Submission ID: Low to High' }, + { field: 'Status', sort: 'desc', name: 'Status: High to Low' }, + { field: 'Status', sort: 'asc', name: 'Status: Low to High' }, + { field: 'Final', sort: 'desc', name: 'Final Score: High to Low' }, + { field: 'Final', sort: 'asc', name: 'Final Score: Low to High' }, + { field: 'Provision', sort: 'desc', name: 'Provisional Score: High to Low' }, + { field: 'Provision', sort: 'asc', name: 'Provisional Score: Low to High' }, + { field: 'Time', sort: 'desc', name: 'Time: New to Old' }, + { field: 'Time', sort: 'asc', name: 'Time: Old to New' }, + ]; + + if (isF2F || isBugHunt) { + SubmissionSortOptions = SubmissionSortOptions.slice(2); + } + + if (isMM) { + SubmissionSortOptions = MarathonSortOptions; + } + + if (isDesign) { + RegistrationSortOptions = RegistrationSortOptions.slice(2); + } + + let sortOptions = currentSelected === DETAIL_TABS.SUBMISSIONS + ? SubmissionSortOptions : RegistrationSortOptions; + + if (currentSelected === DETAIL_TABS.MY_SUBMISSIONS) { + sortOptions = MySubmissionsSortOptions; + } + const numOfSub = numOfSubmissions + (numOfCheckpointSubmissions || 0); const forumId = _.get(challenge, 'legacy.forumId') || 0; const discuss = _.get(challenge, 'discussions', []).filter(d => ( d.type === 'challenge' && !_.isEmpty(d.url) )); const roles = _.get(challenge, 'userDetails.roles') || []; - const isDesign = trackLower === 'design'; const forumEndpoint = isDesign ? `/?module=ThreadList&forumID=${forumId}` @@ -49,6 +135,8 @@ export default function ChallengeViewSelector(props) { const handleSelectorClicked = (e, selector) => { /* eslint-env browser */ e.preventDefault(); + setCurrentSelected(selector); + setIsTabClosed(true); onSelectorClicked(selector); }; @@ -73,167 +161,271 @@ export default function ChallengeViewSelector(props) { } }; - return ( -
-
-
-
+ const desktop = useMediaQuery({ minWidth: 1024 }); + + const tabDetail = ( + + { handleSelectorClicked(e, DETAIL_TABS.DETAILS); }} + onKeyPress={(e) => { handleSelectorClicked(e, DETAIL_TABS.DETAILS); }} + styleName={getSelectorStyle(selectedView, DETAIL_TABS.DETAILS)} + > + DETAILS + + { + numOfRegistrants ? ( + { + handleSelectorClicked(e, DETAIL_TABS.REGISTRANTS); + }} + onKeyPress={(e) => { + handleSelectorClicked(e, DETAIL_TABS.REGISTRANTS); + }} + styleName={getSelectorStyle(selectedView, DETAIL_TABS.REGISTRANTS)} + > + REGISTRANTS + {numOfRegistrants} + + ) : null + } + { + isDesign && checkpointCount > 0 + && ( { handleSelectorClicked(e, DETAIL_TABS.DETAILS); }} - onKeyPress={(e) => { handleSelectorClicked(e, DETAIL_TABS.DETAILS); }} - styleName={getSelectorStyle(selectedView, DETAIL_TABS.DETAILS)} + aria-selected={selectedView === DETAIL_TABS.CHECKPOINTS} + onClick={(e) => { handleSelectorClicked(e, DETAIL_TABS.CHECKPOINTS); }} + onKeyPress={(e) => { handleSelectorClicked(e, DETAIL_TABS.CHECKPOINTS); }} + styleName={getSelectorStyle(selectedView, DETAIL_TABS.CHECKPOINTS)} > - DETAILS + CHECKPOINTS + {checkpointCount} - { - numOfRegistrants ? ( - { - handleSelectorClicked(e, DETAIL_TABS.REGISTRANTS); - }} - onKeyPress={(e) => { - handleSelectorClicked(e, DETAIL_TABS.REGISTRANTS); - }} - styleName={getSelectorStyle(selectedView, DETAIL_TABS.REGISTRANTS)} - > - REGISTRANTS ( - {numOfRegistrants} - ) - - ) : null - } - { - isDesign && checkpointCount > 0 - && ( + ) + } + { + (numOfSub && isLoggedIn) ? ( { handleSelectorClicked(e, DETAIL_TABS.CHECKPOINTS); }} - onKeyPress={(e) => { handleSelectorClicked(e, DETAIL_TABS.CHECKPOINTS); }} - styleName={getSelectorStyle(selectedView, DETAIL_TABS.CHECKPOINTS)} + aria-selected={selectedView === DETAIL_TABS.SUBMISSIONS} + onClick={(e) => { handleSelectorClicked(e, DETAIL_TABS.SUBMISSIONS); }} + onKeyPress={(e) => { handleSelectorClicked(e, DETAIL_TABS.SUBMISSIONS); }} + styleName={getSelectorStyle(selectedView, DETAIL_TABS.SUBMISSIONS)} > - CHECKPOINTS ( - {checkpointCount} - ) + SUBMISSIONS + {numOfSub} - ) - } - { - (numOfSub && isLoggedIn) ? ( - { handleSelectorClicked(e, DETAIL_TABS.SUBMISSIONS); }} - onKeyPress={(e) => { handleSelectorClicked(e, DETAIL_TABS.SUBMISSIONS); }} - styleName={getSelectorStyle(selectedView, DETAIL_TABS.SUBMISSIONS)} - > - SUBMISSIONS ( - {numOfSub} - ) - - ) : null - } - { - (hasRegistered && isMM && mySubmissions) ? ( - { handleSelectorClicked(e, DETAIL_TABS.MY_SUBMISSIONS); }} - onKeyPress={(e) => { handleSelectorClicked(e, DETAIL_TABS.MY_SUBMISSIONS); }} - styleName={getSelectorStyle(selectedView, DETAIL_TABS.MY_SUBMISSIONS)} - > - MY SUBMISSIONS ( - {mySubmissions.length} - ) - - ) : null - } - { - (hasRegistered && mySubmissions.length > 0) && ( - - SUBMISSION REVIEW - - ) - } - { - numWinners ? ( - { handleSelectorClicked(e, DETAIL_TABS.WINNERS); }} - onKeyPress={(e) => { handleSelectorClicked(e, DETAIL_TABS.WINNERS); }} - styleName={getSelectorStyle(selectedView, DETAIL_TABS.WINNERS)} - > - WINNERS ( - { numWinners } - ) - - ) : null - } - { (() => { - if (hasRegistered || Boolean(roles.length)) { - if (!_.isEmpty(discuss)) { - return ( - discuss.map(d => ( - - CHALLENGE DISCUSSION - - )) - ); - } - if (forumId > 0) { - return ( + ) : null + } + { + (hasRegistered && isMM && mySubmissions) ? ( + { handleSelectorClicked(e, DETAIL_TABS.MY_SUBMISSIONS); }} + onKeyPress={(e) => { handleSelectorClicked(e, DETAIL_TABS.MY_SUBMISSIONS); }} + styleName={getSelectorStyle(selectedView, DETAIL_TABS.MY_SUBMISSIONS)} + > + MY SUBMISSIONS + {mySubmissions.length} + + ) : null + } + { + (hasRegistered && mySubmissions.length > 0) && ( + + SUBMISSION REVIEW + + ) + } + { + numWinners ? ( + { handleSelectorClicked(e, DETAIL_TABS.WINNERS); }} + onKeyPress={(e) => { handleSelectorClicked(e, DETAIL_TABS.WINNERS); }} + styleName={getSelectorStyle(selectedView, DETAIL_TABS.WINNERS)} + > + WINNERS + {numWinners} + + ) : null + } + { (() => { + if (hasRegistered || Boolean(roles.length)) { + if (!_.isEmpty(discuss)) { + return ( + discuss.map(d => ( - CHALLENGE FORUM + CHALLENGE DISCUSSION - ); - } + )) + ); + } + if (forumId > 0) { + return ( + + CHALLENGE FORUM + + ); } - return ''; - })()} - { - isMM && ( - { handleSelectorClicked(e, DETAIL_TABS.MM_DASHBOARD); }} - onKeyPress={(e) => { handleSelectorClicked(e, DETAIL_TABS.MM_DASHBOARD); }} - styleName={getSelectorStyle(selectedView, DETAIL_TABS.MM_DASHBOARD)} - > - DASHBOARD - + } + return ''; + })()} + { + isMM && ( + { handleSelectorClicked(e, DETAIL_TABS.MM_DASHBOARD); }} + onKeyPress={(e) => { handleSelectorClicked(e, DETAIL_TABS.MM_DASHBOARD); }} + styleName={getSelectorStyle(selectedView, DETAIL_TABS.MM_DASHBOARD)} + > + DASHBOARD + + ) + } + + ); + + const isSubmissionTabSelected = (isDesign && !(challenge.submissionViewable === 'true')) ? currentSelected === DETAIL_TABS.REGISTRANTS + : currentSelected === DETAIL_TABS.SUBMISSIONS + || currentSelected === DETAIL_TABS.REGISTRANTS + || currentSelected === DETAIL_TABS.MY_SUBMISSIONS; + + return ( +
+ { + !desktop && ( +
+
+
setIsTabClosed(!isTabClosed)} + > +
+

{currentSelected}

+ { + currentSelected === DETAIL_TABS.REGISTRANTS && numOfRegistrants && ( + {numOfRegistrants} + ) + } + { + currentSelected === DETAIL_TABS.SUBMISSIONS && numOfSub && isLoggedIn && ( + {numOfSub} + ) + } + { + currentSelected === DETAIL_TABS.MY_SUBMISSIONS && hasRegistered + && isMM && mySubmissions && ( + {mySubmissions.length} + ) + } + { + currentSelected === DETAIL_TABS.WINNERS && numWinners + && ( + {numWinners} + ) + } +
+
setIsTabClosed(!isTabClosed)} + > + +
+
+ { + !isTabClosed && ( +
+ {tabDetail} +
) } -
+
+ { + isSubmissionTabSelected && ( +
setExpanded(!expanded)} + > + +
+ ) + } + { + expanded && ( +
+
+

SORT

+
setExpanded(false)} tabIndex={0}> + +
+
+
+ { + sortOptions.map((option, index) => ( +
{ + setSelectedSortOption(option.name); + onSort(currentSelected, option); + setExpanded(false); + }} + > + {option.name} +
+ )) + } +
+
+ ) + } +
+ ) + } + { + desktop && ( +
+ {tabDetail} +
+ ) + }
); } @@ -261,6 +453,8 @@ ChallengeViewSelector.propTypes = { }), type: PT.string, track: PT.string, + tags: PT.arrayOf(PT.shape()), + submissionViewable: PT.string, }), isMM: PT.bool, checkpointCount: PT.number, @@ -273,4 +467,5 @@ ChallengeViewSelector.propTypes = { trackLower: PT.string.isRequired, hasRegistered: PT.bool.isRequired, mySubmissions: PT.arrayOf(PT.shape()).isRequired, + onSort: PT.func.isRequired, }; diff --git a/src/shared/components/challenge-detail/Header/TabSelector/style.scss b/src/shared/components/challenge-detail/Header/TabSelector/style.scss index fca6b1c885..f684f57548 100644 --- a/src/shared/components/challenge-detail/Header/TabSelector/style.scss +++ b/src/shared/components/challenge-detail/Header/TabSelector/style.scss @@ -1,10 +1,142 @@ @import "~styles/mixins"; +.mobile-wrapper { + @include xs-to-sm { + display: flex; + } +} + +.mobile-sort-icon { + display: none; + + @include xs-to-sm { + display: inline-block; + margin-left: 8px; + } +} + +.challenge-view-selector-mobile { + .mobile-tab-container { + background-color: #eaf6fd; + height: 40px; + margin-top: 32px; + display: flex; + justify-content: space-between; + border-radius: 4px 4px 0 0; + border-bottom: 1px solid #d4d4d4; + + .title { + @include barlow-bold; + + display: flex; + justify-content: center; + align-self: center; + height: 100%; + font-weight: 700; + color: $tco-black; + font-size: 14px; + line-height: 20px; + text-transform: uppercase; + padding-left: 16px; + padding-top: 10px; + } + + .icon { + width: 16px; + height: 9px; + margin-right: 15px; + display: flex; + flex-direction: column; + justify-content: center; + align-self: center; + cursor: pointer; + transform: scale(1.5); + } + + .down { + transform: scale(1.5) rotate(180deg); + margin-right: 20px !important; + } + + @include xs-to-md { + width: 100%; + margin: 0; + } + } + + .challenge-selected-view { + font-weight: 700 !important; + background-color: #bae1f9 !important; + } + + .mobile-tab-left-content { + display: flex; + align-items: center; + } + + .mobile-tab-num { + @include roboto-regular; + + font-weight: 500; + font-size: 14px; + line-height: 16px; + background: #2c95d7; + border-radius: 50px; + padding: 0 8px; + text-align: center; + color: $tc-white; + margin-left: 4px; + margin-top: 1px; + } + + @include xs-to-md { + width: 100%; + } +} + +.mobile-tab-expanded { + margin: 0 16px; + background-color: #eaf6fd; + flex-direction: column; + display: flex; + + a { + width: 100%; + height: 40px; + margin: 0; + + @include barlow-bold; + + font-weight: 600; + color: #555; + font-size: 14px; + line-height: 20px; + text-transform: uppercase; + padding-left: 16px; + padding-top: 10px; + } + + .active { + background-color: #bae1f9; + + p { + color: $tco-black; + font-weight: 700; + } + } + + @include xs-to-sm { + margin: 0; + } +} + .challenge-view-selector { display: flex; flex-wrap: wrap; - justify-content: center; position: relative; + padding-bottom: 10px; + border-bottom: silver solid 1px; + gap: 16px; @include xs-to-sm { flex-wrap: nowrap; @@ -13,30 +145,61 @@ } .challenge-selector-common { - font-family: roboto, sans-serif; - font-size: 13px; - line-height: 30px; - margin: 10px 20px 0; + @include barlow-bold; + + font-weight: 700; + line-height: 20px; + font-size: 14px; + margin: 10px 10px 0; cursor: pointer; white-space: nowrap; + position: relative; } .challenge-selected-view { - font-weight: 700; - color: $tc-dark-blue; - border-bottom: 3px solid $tc-dark-blue; + font-weight: 700 !important; + color: #2a2a2a; + + &::after { + content: ""; + background-image: url(assets/images/nav-active-item.svg); + height: 10px; + width: 40px; + justify-content: center; + z-index: 100; + display: block; + position: absolute; + top: 30px; + left: 20%; + } } .challenge-unselected-view { - font-weight: 400; - color: $tc-gray-70; - border-bottom: 3px hidden $tc-white; + font-weight: 600; + color: #555; + position: relative; } } +.num { + background: #2c95d7; + border-radius: 50px; + padding: 0 8px; + text-align: center; + color: $tc-white; + margin-left: 4px; +} + .container { - margin-top: 4 * $base-unit; + margin-top: 28px; + margin-left: 2px; + margin-right: 14px; position: relative; + background-color: #eaf6fd; + + @include xs-to-md { + background-color: transparent; + } } .mask { @@ -48,11 +211,76 @@ .mask.left { display: none; - background: linear-gradient(-90deg, rgba(250, 250, 251, 0) 3%, #fafafb 49%, #fafafb 98%); + background: transparent; left: 0; + + @include xs-to-sm { + background: transparent; + } } .mask.right { - background: linear-gradient(90deg, rgba(250, 250, 251, 0) 3%, #fafafb 49%, #fafafb 98%); + background: transparent; right: 0; + + @include xs-to-sm { + background: transparent; + } +} + +.sort-overlay { + position: absolute; + width: 100%; + height: 100%; + z-index: 10000; + background-color: #fff; + top: 0; + + .sort-header { + background-color: #f4f4f4; + display: flex; + justify-content: space-between; + padding: 10px 16px; + + p { + @include barlow-bold; + + font-weight: 600; + font-size: 14px; + line-height: 20px; + color: $tc-black; + } + } + + .sort-body { + background-color: #fff; + margin-left: -2px; + filter: drop-shadow(0 12px 20px rgba(0, 0, 0, 0.1)); + -webkit-filter: drop-shadow(0 12px 20px rgba(0, 0, 0, 0.1)); + border-radius: 4px; + + .sort-item { + @include roboto-regular; + + padding: 7.5px 0 0; + height: 40px; + color: #555; + font-size: 14px; + line-height: 20px; + border-bottom: 1px solid #d4d4d4; + + span { + margin: 0 12px; + } + + &:last-child { + border-bottom: 0; + } + + & .bold { + font-weight: 700 !important; + color: #000 !important; + } + } + } } diff --git a/src/shared/components/challenge-detail/Header/index.jsx b/src/shared/components/challenge-detail/Header/index.jsx index 39c0a3da57..0d11a811ee 100644 --- a/src/shared/components/challenge-detail/Header/index.jsx +++ b/src/shared/components/challenge-detail/Header/index.jsx @@ -12,7 +12,7 @@ import { isMM } from 'utils/challenge'; import PT from 'prop-types'; import React from 'react'; -import { DangerButton, PrimaryButton } from 'topcoder-react-ui-kit'; +import { PrimaryButton } from 'topcoder-react-ui-kit'; import { Link } from 'topcoder-react-utils'; import { COMPETITION_TRACKS } from 'utils/tc'; import { phaseEndDate } from 'utils/challenge-listing/helper'; @@ -58,6 +58,7 @@ export default function ChallengeHeader(props) { submissionEnded, mySubmissions, openForRegistrationChallenges, + onSort, } = props; const { @@ -120,10 +121,10 @@ export default function ChallengeHeader(props) { } /* userDetails.hasUserSubmittedForReview does not reset to false - * if the user has deleted all of their submissions, so we have to - * iterate through all their submissions and ensure that all of them - * are Deleted - */ + * if the user has deleted all of their submissions, so we have to + * iterate through all their submissions and ensure that all of them + * are Deleted + */ const hasSubmissions = !_.isEmpty(mySubmissions); const openPhases = sortedAllPhases.filter(p => p.isOpen); @@ -159,7 +160,7 @@ export default function ChallengeHeader(props) { return false; } if (phaseLowerCase.includes('registration') || phaseLowerCase.includes('checkpoint') - || phaseLowerCase.includes('submission') || phaseLowerCase.includes('review')) { + || phaseLowerCase.includes('submission') || phaseLowerCase.includes('review')) { return true; } return false; @@ -180,7 +181,7 @@ export default function ChallengeHeader(props) { const phases2 = allPhases.filter(p => p.name === 'Iterative Review' && !p.isOpen); const endPhaseDate = Math.max(...phases2.map(d => phaseEndDate(d))); relevantPhases = _.filter(relevantPhases, p => (p.name.toLowerCase().includes('registration') - || phaseEndDate(p).getTime() < endPhaseDate)); + || phaseEndDate(p).getTime() < endPhaseDate)); relevantPhases.push({ id: -1, name: 'Winners', @@ -219,7 +220,7 @@ export default function ChallengeHeader(props) { {nextDeadline || '-'} - } + }
); break; @@ -251,11 +252,16 @@ export default function ChallengeHeader(props) { _.some(allPhases, { phaseType: 'Final Fix', phaseStatus: 'Open' }); } + const disabled = !hasRegistered || unregistering || submissionEnded || isLegacyMM; + const registerButtonDisabled = registering || registrationEnded || isLegacyMM; + const unregisterButtonDisabled = unregistering + || registrationEnded || hasSubmissions || isLegacyMM; + return (
- +
@@ -275,38 +281,38 @@ export default function ChallengeHeader(props) { openForRegistrationChallenges={openForRegistrationChallenges} /> {(hasRecommendedChallenges || hasThriveArticles) && ( -
- {hasRecommendedChallenges && ( -
{ - document.getElementById('recommendedActiveChallenges').scrollIntoView(); - }} - > - Recommended Challenges -
- )} - - {hasRecommendedChallenges && hasThriveArticles && ( -
- )} - - {hasThriveArticles && ( -
{ - document.getElementById('recommendedThriveArticles').scrollIntoView(); - }} - >Recommended THRIVE Articles -
- )} +
+ {hasRecommendedChallenges && ( +
{ + document.getElementById('recommendedActiveChallenges').scrollIntoView(); + }} + > + Recommended Challenges +
+ )} + + {hasRecommendedChallenges && hasThriveArticles && ( +
+ )} + + {hasThriveArticles && ( +
{ + document.getElementById('recommendedThriveArticles').scrollIntoView(); + }} + >Recommended THRIVE Articles
+ )} +
)}
@@ -318,114 +324,118 @@ export default function ChallengeHeader(props) { { - bonusType ? ( -
- { - bonusType === 'Bonus' - ? ( -

- - BONUS: - {' '} - {numberOfCheckpointsPrizes} - - ‌ - CHECKPOINTS AWARDED WORTH - ‌ - - $ - {topCheckPointPrize} - - ‌ - EACH -

- ) - : ( -

- - RELIABILITY BONUS: $ - {reliabilityBonus.toFixed()} - -

- ) - } -
- ) : null - } + bonusType ? ( +
+ { + bonusType === 'Bonus' + ? ( +

+ + BONUS: + {' '} + {numberOfCheckpointsPrizes} + + ‌ + CHECKPOINTS AWARDED WORTH + ‌ + + $ + {topCheckPointPrize} + + ‌ + EACH +

+ ) + : ( +

+ + RELIABILITY BONUS: $ + {reliabilityBonus.toFixed()} + +

+ ) + } +
+ ) : null + } { - drPoints ? ( -
-

- - POINTS: - {drPoints} - -

-
- ) : null - } + drPoints ? ( +
+

+ + POINTS: + {drPoints} + +

+
+ ) : null + }
{hasRegistered ? ( - Unregister - + ) : ( Register )} Submit { - track === COMPETITION_TRACKS.DES && hasRegistered && !unregistering - && hasSubmissions && ( - - View Submissions - - ) - } + track === COMPETITION_TRACKS.DES && hasRegistered && !unregistering + && hasSubmissions && ( + + View Submissions + + ) + }
-
+
{nextDeadlineMsg} { - (status || '').toLowerCase() === 'active' - && ( -
- - {timeLeft} - - {' '} - until current deadline ends -
- ) - } + (status || '').toLowerCase() === 'active' + && ( +
+ Current Deadline Ends:{' '} + + {timeLeft} + +
+ ) + }
- Hide Deadlines ) : ( - Show Deadlines ) - } + }
{ - showDeadlineDetail - && - } + showDeadlineDetail + && + }
@@ -534,4 +543,5 @@ ChallengeHeader.propTypes = { isMenuOpened: PT.bool, mySubmissions: PT.arrayOf(PT.shape()).isRequired, openForRegistrationChallenges: PT.shape().isRequired, + onSort: PT.func.isRequired, }; diff --git a/src/shared/components/challenge-detail/Header/style.scss b/src/shared/components/challenge-detail/Header/style.scss index 2e4d9c7064..0832d4bb8c 100644 --- a/src/shared/components/challenge-detail/Header/style.scss +++ b/src/shared/components/challenge-detail/Header/style.scss @@ -4,21 +4,102 @@ margin: $base-unit 0; min-width: 0; width: 100%; + border-radius: 50px !important; + height: 48px; + padding: 0 25px !important; +} + +.submitButton { + margin: $base-unit 0; + min-width: 0; + width: 100%; + border-radius: 50px !important; + height: 48px; + padding: 0 25px !important; + background: #137d60 !important; + color: #fff !important; + + @include xs-to-sm { + width: fit-content; + } +} + +.submitButtonDisabled { + margin: $base-unit 0; + min-width: 0; + width: 100%; + border-radius: 50px !important; + height: 48px; + padding: 0 25px !important; + color: #767676 !important; + background: #f4f4f4 !important; + + @include xs-to-sm { + width: fit-content; + } +} + +.unregisterButton { + margin: $base-unit 0; + min-width: 0; + width: 100%; + border-radius: 50px !important; + height: 48px; + padding: 0 25px !important; + color: #137d60 !important; + border-color: #137d60 !important; + background: #fff !important; + + @include xs-to-sm { + width: fit-content; + } +} + +.registerBtn { + margin: $base-unit 0; + min-width: 0; + width: 100%; + border-radius: 50px !important; + height: 48px; + padding: 0 25px !important; + background-color: #137d60 !important; + + @include xs-to-sm { + width: fit-content; + } } .challenge-ops-container { - margin: 0 4 * $base-unit; - padding: 3 * $base-unit 0; - max-width: 245px; + display: flex; + margin-top: 32px; + margin-right: 18px; + text-transform: uppercase; + + button { + text-transform: uppercase; + } @include xs-to-sm { margin: auto; + flex-wrap: wrap; + justify-content: center; + + div, + a { + width: fit-content !important; + } } } .challenge-ops-wrapper { + display: flex; + flex-direction: column; + justify-content: center; + @include xs-to-sm { width: 100%; + margin-top: 24px; + margin-bottom: 34px; } } @@ -76,16 +157,30 @@ } } +.type-tag { + display: inline-block; +} + +.qa { + :global { + a { + background-color: #0ab88a !important; + + &:hover { + background-color: darken(#0ab88a, 10%) !important; + } + } + } +} + .challenge-outer-container { - background: $tc-gray-neutral-light; + background: $tc-white; border-radius: (3 * $corner-radius) (3 * $corner-radius) 0 0; @include xs-to-md { padding: 4px 4px 0 0; } - border-bottom: $tc-gray-20 solid 1px; - .important-detail { @include xs-to-md { padding: 15px 15px 0; @@ -96,17 +191,20 @@ } @include lg-to-xl { - padding: 20px 19px 0 30px; + padding: 20px 19px 0 27px; } .challenge-header { - @include tc-heading-lg; + @include barlow-bold; - color: $tc-black; + font-weight: 600; + font-size: 34px; + color: $tco-black; line-height: 40px; letter-spacing: -0.78px; - font-weight: 500; margin-bottom: 5px; + margin-left: 16px; + margin-top: 14px; @include xs-to-md { font-size: 20px; @@ -127,6 +225,18 @@ .tag-container { display: flex; align-items: center; + margin-left: 15px; + padding-top: 4px; + + @include xs-to-md { + width: 100%; + flex-wrap: wrap; + margin-top: 18px; + } + + span a:hover { + background-color: #d4d4d4 !important; + } } .recommend-container { @@ -134,20 +244,32 @@ align-items: center; margin-left: -5px; margin-bottom: 2px; + + @include xs-to-md { + margin-left: -16px; + margin-top: 8px; + } } .recommend-tag { - @include roboto-regular; + @include roboto-bold; margin-left: 17px; + font-weight: 700; font-size: 14px; + line-height: 14px; height: 20px; display: flex; align-items: center; + text-transform: uppercase; &.link { + @include roboto-bold; + cursor: pointer; - color: $tc-dark-blue-110; + color: #137d60; + text-transform: uppercase; + font-weight: 700; } &.separator { @@ -171,90 +293,139 @@ .prizes-ops-container { background-color: $tc-white; - border: 1px solid $tc-gray-20; - border-radius: 6px 6px 0 0; - margin-top: 20px; + border: 2px solid $tc-gray-20; + border-top-right-radius: 6px; + border-top-left-radius: 6px; + margin-top: 16px; + margin-left: 5px; + margin-right: 14px; + padding-bottom: 48px; display: flex; flex-wrap: wrap; align-items: stretch; @include xs-to-sm { - flex-direction: column; + flex-direction: row; + height: auto; + padding-bottom: 0; } .prizes-outer-container { flex: 4; .prizes-title { - @include roboto-bold; + @include barlow-bold; - margin-left: 20px; + font-size: 18px; + line-height: 22px; + color: $tco-black; + text-transform: uppercase; + margin-left: 22px; @include xs-to-md { + font-size: 16px; + font-weight: 600; margin-left: 10px; + text-align: center; } - margin-top: 20px; - font-size: 10px; - color: $tc-gray-50; - line-height: 10px; - letter-spacing: 1.33px; + margin-top: 14px; } .prizes-container { display: flex; align-content: center; - justify-content: center; flex-wrap: wrap; + margin-left: 24px; + margin-top: 36px; + width: 85%; + + @include xs-to-md { + width: 100%; + justify-content: center; + } .prize-fill { - min-width: 75px; - margin: 15px 15px 0 0; + margin: 15px 48px 0 0; + display: flex; + flex: 0 1 calc(15% - 8px); + + @include xs-to-md { + min-width: 100px; + margin-right: 32px; + } .prize-card { - display: inline-block; - border-bottom: $tc-dark-blue-30 solid 3px; - text-align: right; + display: flex; + border-bottom: 0; + border-radius: 20px; + width: 40px; + height: 40px; + margin-right: 8px; + background-color: #e0faf3; + justify-content: center; + flex-direction: column; + text-align: center; + + @include xs-to-md { + width: 32px; + height: 32px; + } .prize-rank { @include roboto-regular; - font-size: 13px; - color: $tc-gray-50; + font-size: 16px; + font-weight: 500; + color: $tco-black; letter-spacing: 0; - line-height: 15px; + line-height: 20px; margin-bottom: 5px; .rank-ordinal { - color: $tc-gray-50; + color: $tco-black; + } + + @include xs-to-md { + font-size: 12px; + margin-top: 3px; } } + } - .prize-money { - @include roboto-medium; + .prize-money { + @include roboto-medium; - font-size: 20px; - color: $tc-gray-80; - letter-spacing: -0.5px; - line-height: 30px; - margin-bottom: 5px; + font-size: 24px; + font-weight: 500; + color: #2a2a2a; + letter-spacing: -0.5px; + line-height: 32px; + margin-bottom: 5px; - .prize-currency { - color: $tc-gray-80; - } + .prize-currency { + color: #2a2a2a; + } + + @include xs-to-md { + font-size: 14px; + line-height: 30px; } } .prize-card[id='rank1'] { - border-bottom: $tc-gold solid 3px; + border-bottom: 0; + background-color: #ffd84d; } .prize-card[id='rank2'] { - border-bottom: $tc-silver solid 3px; + border-bottom: 0; + background-color: #d1d0cf; } .prize-card[id='rank3'] { - border-bottom: $tc-bronze solid 3px; + border-bottom: 0; + background-color: #d98f64; } } } @@ -262,10 +433,10 @@ .bonus-div { @include roboto-regular; - text-align: center; + text-align: left; color: $tc-black; line-height: 25px; - margin: 25px 15px 0; + margin: 25px 25px 0; padding-bottom: 20px; .bonus-text { @@ -285,28 +456,48 @@ border-radius: 0 0 6px 6px; border: 0 hidden $tc-white; overflow: hidden; + margin: 0 14px 0 4px; + min-height: 96px; .deadlines-overview { - background-color: $tc-gray-70; + background-color: #555; display: flex; flex-wrap: wrap; justify-content: space-between; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + + &.opened { + border-radius: 0 !important; + } + + @include xs-to-md { + flex-wrap: nowrap; + } .deadlines-overview-text { @include roboto-regular; display: flex; justify-content: flex-start; - color: $tc-gray-30; + color: $tc-white; line-height: 20px; - padding: 15px 20px; + padding: 23px 26px; font-size: 15px; + @include xs-to-md { + flex-direction: column; + } + .next-deadline { word-wrap: normal; border-right: $tc-gray-50 solid 1px; padding-right: 10px; display: inline; + + @include xs-to-md { + border-right: none; + } } .completed { @@ -316,6 +507,11 @@ .current-phase { overflow-wrap: normal; padding-left: 10px; + + @include xs-to-md { + padding-left: 0; + margin-top: 4px; + } } .deadline-highlighted { @@ -332,6 +528,8 @@ letter-spacing: 0; line-height: 20px; padding: 15px 20px; + margin-top: 10px; + margin-right: 8px; cursor: pointer; .collapse-text { @@ -346,7 +544,12 @@ } .left-arrow { - margin: 25px; + fill: #137d60; + position: absolute; + left: 35%; + right: 35%; + top: 35%; + bottom: 25%; } .title-wrapper { @@ -355,6 +558,27 @@ left: -25px; position: relative; top: -5px; + margin: 0 32px; + + @include xs-to-md { + flex-direction: column; + align-items: flex-start; + margin-left: 15px; + } +} + +.back-arrow { + width: 32px; + height: 24px; + border: 1.5px solid #137d60; + border-radius: 24px; + padding: 4px 8px; + margin-bottom: 10px; + position: relative; + + @include xs-to-md { + margin-left: 15px; + } } .matchScoreWrap { diff --git a/src/shared/components/challenge-detail/MMDashboard/Graph/index.jsx b/src/shared/components/challenge-detail/MMDashboard/Graph/index.jsx index 5698d730db..2139ef782a 100644 --- a/src/shared/components/challenge-detail/MMDashboard/Graph/index.jsx +++ b/src/shared/components/challenge-detail/MMDashboard/Graph/index.jsx @@ -27,6 +27,7 @@ export default function Graph({ statisticsData, baseline, awardLine }) { const options = { chart: { type: 'scatter', + backgroundColor: '#fff', }, title: { text: '', @@ -44,6 +45,7 @@ export default function Graph({ statisticsData, baseline, awardLine }) { })), pointStart: moment(_.min(dates)).valueOf(), pointInterval: 24 * 3600 * 1000, + backgroundColor: 'rgb(51,51,51)', }, ], legend: { @@ -72,6 +74,7 @@ export default function Graph({ statisticsData, baseline, awardLine }) { title: { enabled: false, }, + backgroundColor: '#fff', plotLines: [ ...(awardLine > 0 ? [ { @@ -94,7 +97,7 @@ export default function Graph({ statisticsData, baseline, awardLine }) { }, ] : []), { - color: 'rgba(51, 51, 51, 1)', + color: '#fff', value: 0, width: 3, }, @@ -104,7 +107,7 @@ export default function Graph({ statisticsData, baseline, awardLine }) { tooltip: { formatter() { const str = ` -
+

${this.point.customData.handle}


diff --git a/src/shared/components/challenge-detail/MMDashboard/Graph/styles.scss b/src/shared/components/challenge-detail/MMDashboard/Graph/styles.scss index e8c255aba3..8e0652361b 100644 --- a/src/shared/components/challenge-detail/MMDashboard/Graph/styles.scss +++ b/src/shared/components/challenge-detail/MMDashboard/Graph/styles.scss @@ -2,4 +2,22 @@ .graph-container { margin: 20px; + padding-right: 10px; + padding-bottom: 48px; + + :global { + svg { + margin-top: 15px; + margin-left: 9px; + + @include xs-to-md { + margin-left: 0; + } + } + } + + @include xs-to-md { + margin: 0 16px; + padding-right: 16px; + } } diff --git a/src/shared/components/challenge-detail/MySubmissions/SubmissionsList/index.jsx b/src/shared/components/challenge-detail/MySubmissions/SubmissionsList/index.jsx index e51f41bf8e..93e5f862f5 100644 --- a/src/shared/components/challenge-detail/MySubmissions/SubmissionsList/index.jsx +++ b/src/shared/components/challenge-detail/MySubmissions/SubmissionsList/index.jsx @@ -6,16 +6,17 @@ import React from 'react'; import cn from 'classnames'; import _ from 'lodash'; import moment from 'moment'; -import { PrimaryButton } from 'topcoder-react-ui-kit'; +import { PrimaryButton, Modal } from 'topcoder-react-ui-kit'; import PT from 'prop-types'; import { services } from 'topcoder-react-lib'; import sortList from 'utils/challenge-detail/sort'; -import IconComplete from '../../icons/completed.svg'; -import IconQueued from '../../icons/queued.svg'; +import IconClose from 'assets/images/icon-close-green.svg'; +import DateSortIcon from 'assets/images/icon-date-sort.svg'; +import SortIcon from 'assets/images/icon-sort.svg'; import IconFail from '../../icons/failed.svg'; import DownloadIcon from '../../../SubmissionManagement/Icons/IconSquareDownload.svg'; -import ArrowDown from '../../../../../assets/images/arrow-down.svg'; +// import SearchIcon from '../../../SubmissionManagement/Icons/IconSearch.svg'; import style from './styles.scss'; @@ -27,10 +28,18 @@ class SubmissionsListView extends React.Component { super(props); this.state = { sortedSubmissions: [], + submissionIdClicked: false, + statusClicked: false, + finalClicked: false, + provisionClicked: false, + timeClicked: false, + openModal: false, + selectedSubmission: {}, }; this.sortSubmissions = this.sortSubmissions.bind(this); this.getSubmissionsSortParam = this.getSubmissionsSortParam.bind(this); this.updateSortedSubmissions = this.updateSortedSubmissions.bind(this); + this.toggleModal = this.toggleModal.bind(this); } componentDidMount() { @@ -131,6 +140,11 @@ class SubmissionsListView extends React.Component { }); } + toggleModal(selectedSubmission) { + const { openModal } = this.state; + this.setState({ openModal: !openModal, selectedSubmission }); + } + render() { const { selectSubmission, @@ -152,23 +166,26 @@ class SubmissionsListView extends React.Component { } = challenge; const { sortedSubmissions, + submissionIdClicked, + statusClicked, + finalClicked, + provisionClicked, + timeClicked, + selectedSubmission, + openModal, } = this.state; + + const sortOptionClicked = { + submissionIdClicked: false, + statusClicked: false, + finalClicked: false, + provisionClicked: false, + timeClicked: false, + }; + return (
-
-

- My Submissions -

-
-
-
- Submission -
-
- Score -
-
Submission ID @@ -198,7 +216,7 @@ class SubmissionsListView extends React.Component { 'col-arrow-is-sorting': field === 'Submission ID', }, )} - > + >{ submissionIdClicked ? : }
@@ -218,6 +236,7 @@ class SubmissionsListView extends React.Component { field: 'Status', sort: (field === 'Status') ? revertSort : 'desc', }); + this.setState({ ...sortOptionClicked, statusClicked: true }); }} > Status @@ -229,7 +248,7 @@ class SubmissionsListView extends React.Component { 'col-arrow-is-sorting': field === 'Status', }, )} - > + >{ statusClicked ? : }
@@ -251,9 +270,10 @@ class SubmissionsListView extends React.Component { field: 'Final', sort: (field === 'Final') ? revertSort : 'desc', }); + this.setState({ ...sortOptionClicked, finalClicked: true }); }} > - Final + Final Score
+ >{ finalClicked ? : }
@@ -282,9 +302,10 @@ class SubmissionsListView extends React.Component { field: 'Provision', sort: (field === 'Provision') ? revertSort : 'desc', }); + this.setState({ ...sortOptionClicked, provisionClicked: true }); }} > - Provision + Provision Score
+ >{ provisionClicked ? : }
@@ -313,6 +334,7 @@ class SubmissionsListView extends React.Component { field: 'Time', sort: (field === 'Time') ? revertSort : 'desc', }); + this.setState({ ...sortOptionClicked, timeClicked: true }); }} > Time @@ -324,11 +346,13 @@ class SubmissionsListView extends React.Component { 'col-arrow-is-sorting': field === 'Time', }, )} - > + >{ timeClicked ? : }
-
+
+ ACTIONS +
{ @@ -339,14 +363,14 @@ class SubmissionsListView extends React.Component { finalScore = finalScore.toFixed(2); } } else { - finalScore = '-'; + finalScore = 'N/A'; } if (_.isNumber(provisionalScore)) { if (provisionalScore > 0) { provisionalScore = provisionalScore.toFixed(2); } } else { - provisionalScore = '-'; + provisionalScore = 'N/A'; } return (
@@ -362,56 +386,46 @@ class SubmissionsListView extends React.Component { type="button" styleName={cn( 'submission-table-column column-1-1', - { - 'is-highlight': field === 'Submission ID', - }, )} > +
Submission Id
{mySubmission.id}
+
Status
{mySubmission.provisionalScoringIsCompleted ? ( - - ) : ()} + Accepted + ) : In Queue}
+
Final Score
{(finalScore < 0) ? () : ({finalScore})}
+
Provisional Score
{(provisionalScore < 0) ? () : ({provisionalScore})}
- {moment(mySubmission.submissionTime).format('DD MMM YYYY')} {moment(mySubmission.submissionTime).format('HH:mm:ss')} +
Time
+ {moment(mySubmission.submissionTime).format('MMM DD, YYYY')} {moment(mySubmission.submissionTime).format('HH:mm')}
+ + {/* */}
@@ -447,6 +465,41 @@ class SubmissionsListView extends React.Component { > Add Submission + { + openModal && ( + +
+
+

Submission Details

+
this.toggleHistory({})}> + +
+
+
+
+ Submission: {selectedSubmission.submissionId} +
+
+
+ Review Type +
+
+ Reviewer +
+
+ Score +
+
+ Status +
+
+
this.toggleHistory({})} role="presentation"> + CLOSE +
+
+
+ ) + }
); } diff --git a/src/shared/components/challenge-detail/MySubmissions/SubmissionsList/styles.scss b/src/shared/components/challenge-detail/MySubmissions/SubmissionsList/styles.scss index 7c9af61010..e9055398cc 100644 --- a/src/shared/components/challenge-detail/MySubmissions/SubmissionsList/styles.scss +++ b/src/shared/components/challenge-detail/MySubmissions/SubmissionsList/styles.scss @@ -18,9 +18,39 @@ color: inherit; padding: 0; background: transparent; + text-transform: uppercase; } } +.actions-col { + @include barlow-bold; + + font-size: 11px; + line-height: 14px; + font-weight: 600; + color: #767676; +} + +.accepted { + color: #0ab88a; + + @include roboto-medium; + + font-weight: 500; + font-size: 14px; + line-height: 22px; +} + +.queue { + color: #f46500; + + @include roboto-medium; + + font-weight: 500; + font-size: 14px; + line-height: 22px; +} + .h2 { @include roboto-bold; @@ -40,6 +70,23 @@ width: 181px; margin-top: 25px !important; align-self: center; + background-color: #137d60 !important; + border-radius: 50px !important; + padding: 12px 24px; + text-transform: uppercase; + + @include roboto-bold; + + font-weight: 700; + font-size: 16px; + line-height: 24px; + color: #fff !important; + border: 0; + + &:hover { + background-color: lighten(#137d60, 5%) !important; + background-image: none !important; + } } .submission-table { @@ -49,46 +96,109 @@ flex-direction: column; font-size: 13px; line-height: 20px; - margin-top: 30px; + margin: 16px 40px 0 40px; + + @include xs-to-sm { + margin: 16px 0 0 0; + } } button.column-1-1, .column-1-1 { - width: 50%; - color: $tc-dark-blue; + width: 35%; + + @include xs-to-sm { + width: 100%; + align-items: flex-start; + } } .submission-table-header { - background: #fafafb; + height: 40px !important; + + span { + @include barlow-bold; + + font-size: 11px; + line-height: 14px; + font-weight: 600; + color: #767676; + } .column-1-1 { color: #888894; } + + @include xs-to-sm { + display: none !important; + } } .submission-table-column { + @include roboto-medium; + + font-weight: 500; + font-size: 14px; + color: #2a2a2a; + line-height: 22px; display: flex; - justify-content: center; + justify-content: flex-start; align-items: center; height: 40px; + + @include xs-to-sm { + display: flex; + flex-direction: column; + justify-content: flex-start; + height: auto; + } } .submission-table-row { display: flex; - border: 1px solid #ededf2; border-bottom: none; + height: 54px; + margin-top: 5px; + border-top: 1px solid #ededf2; + position: relative; + + &:first-child { + border-top: 0; + } &:last-child { border-bottom: 1px solid #ededf2; } + + @include xs-to-md { + display: flex; + flex-direction: column; + border-top: 1px solid #ededf2; + margin: 0 32px 0 16px; + height: auto; + } } .column-1 { - width: 30%; + width: 22%; + display: flex; + justify-content: space-between; + + @include xs-to-sm { + width: 100%; + align-items: flex-start; + } } .column-2 { - width: 70%; + width: 78%; + display: flex; + justify-content: space-between; + + @include xs-to-sm { + width: 100%; + align-items: flex-start; + } } .score-title { @@ -96,54 +206,103 @@ button.column-1-1, span { margin-left: 28%; + align-items: flex-start; } } .column-1-2 { - width: 50%; + &.status-row { + margin-right: -16px; + } + + @include xs-to-sm { + width: 100%; + align-items: flex-start; + } } .column-2-1 { - width: 25%; + width: 28%; justify-content: flex-end; padding-right: 20px; + + &.final-score-row { + margin-left: -40px; + + @include xs-to-sm { + margin-left: 0; + } + } + + @include xs-to-sm { + width: 100%; + align-items: flex-start; + margin-left: 0; + } } .column-2-2 { - width: 25%; + width: 18%; justify-content: flex-end; padding-right: 20px; + + &.provisional-score-row { + margin-left: -23px; + + @include xs-to-sm { + margin-left: 0; + } + } + + @include xs-to-sm { + width: 100%; + align-items: flex-start; + } } .column-2-3 { - width: 30%; + width: 18%; justify-content: flex-start; padding-left: 40px; + + &.time-row { + margin-left: 65px; + + @include xs-to-sm { + margin-left: 0; + margin-bottom: 16px; + } + } + + @include xs-to-sm { + width: 100%; + align-items: flex-start; + padding-left: 0; + } } .column-2-4 { - width: 20%; + width: 8%; + + @include xs-to-sm { + width: auto; + align-items: flex-start; + margin-top: 16px; + position: absolute; + flex-direction: row; + right: 0; + top: 0; + } } -.icon-download { - :global { - path { - fill: $tc-dark-blue; - } - } +.icon-search { + margin-left: 17px; } .col-arrow { display: flex; padding-left: 5px; margin-right: -19px; - - :global { - svg { - margin-bottom: 1px; - height: 8px; - } - } } .col-arrow-is-sorting { @@ -154,17 +313,6 @@ button.column-1-1, } } -.col-arrow-sort-asc { - :global { - svg { - -moz-transform: scale(1, -1); - -o-transform: scale(1, -1); - -webkit-transform: scale(1, -1); - transform: scale(1, -1); - } - } -} - .header-sort { display: flex; justify-content: center; @@ -183,5 +331,129 @@ button.column-1-1, button.is-highlight, .is-highlight { - background: rgba(26, 133, 255, 0.05); + display: inherit; +} + +.mobile-header { + display: none; + + @include xs-to-sm { + display: block; + margin-top: 16px; + font-size: 11px; + line-height: 14px; + + @include barlow-bold; + + font-weight: 600; + color: #767676; + text-align: left; + } +} + +.col-arrow-sort-asc { + -moz-transform: scale(1, -1); + -o-transform: scale(1, -1); + -webkit-transform: scale(1, -1); + transform: scale(1, -1); +} + +.mySubModal { + padding-bottom: 10px; + border-radius: 8px; + margin: 25px 32px 32px; +} + +.header { + display: flex; + justify-content: space-between; + + .title { + @include barlow-medium; + + font-weight: 600; + color: #2a2a2a; + font-size: 18px; + line-height: 22px; + text-transform: uppercase; + } + + .icon { + cursor: pointer; + margin-top: 5px; + } +} + +.submission-text { + @include roboto-regular; + + font-size: 16px; + color: #2a2a2a; + line-height: 24px; + margin-top: 24px; + + span { + font-weight: 700; + } +} + +.detail-row { + display: flex; + margin-top: 24px; + + .col { + @include barlow-medium; + + font-weight: 600; + font-size: 11px; + line-height: 14px; + color: #767676; + } + + .col-1 { + flex: 40; + } + + .col-2 { + flex: 40; + } + + .col-3 { + flex: 40; + } + + .col-4 { + flex: 40; + } +} + +hr { + opacity: 0.5; +} + +.close-btn { + cursor: pointer; + display: flex; + justify-content: flex-end; + margin-top: 24px; + margin-bottom: 32px; + background-color: #137d60; + padding: 8px 24px; + border-radius: 24px; + float: right; + + span { + @include roboto-bold; + + font-weight: 700; + font-size: 14px; + line-height: 24px; + color: #fff; + } + + @include xs-to-sm { + border-top: 1px solid #e9e9e9; + position: sticky; + margin-bottom: 16px; + } } diff --git a/src/shared/components/challenge-detail/MySubmissions/index.jsx b/src/shared/components/challenge-detail/MySubmissions/index.jsx index 824b29d0d6..a3232f8c56 100644 --- a/src/shared/components/challenge-detail/MySubmissions/index.jsx +++ b/src/shared/components/challenge-detail/MySubmissions/index.jsx @@ -64,7 +64,7 @@ class MySubmissionsView extends React.Component { const { selectedSubmission, submissionsSortDetail } = this.state; if (!_.isEmpty(loadingMMSubmissionsForChallengeId)) { - return ; + return
; } return ( diff --git a/src/shared/components/challenge-detail/MySubmissions/styles.scss b/src/shared/components/challenge-detail/MySubmissions/styles.scss index 79474dde9a..e3d3cfb71c 100644 --- a/src/shared/components/challenge-detail/MySubmissions/styles.scss +++ b/src/shared/components/challenge-detail/MySubmissions/styles.scss @@ -11,7 +11,9 @@ .content { display: flex; flex-direction: column; - margin: 50px 20px; - max-width: 960px; width: 100%; } + +.loading { + margin-top: 30px; +} diff --git a/src/shared/components/challenge-detail/RecommendedActiveChallenges/ChallengesCard/style.scss b/src/shared/components/challenge-detail/RecommendedActiveChallenges/ChallengesCard/style.scss index 52eaa9fe0d..23ae559f84 100644 --- a/src/shared/components/challenge-detail/RecommendedActiveChallenges/ChallengesCard/style.scss +++ b/src/shared/components/challenge-detail/RecommendedActiveChallenges/ChallengesCard/style.scss @@ -68,6 +68,8 @@ font-size: 13px; line-height: 15px; margin-right: 24px; + white-space: nowrap; + margin-top: 5px; @include xs { margin-left: -20px; diff --git a/src/shared/components/challenge-detail/Registrants/index.jsx b/src/shared/components/challenge-detail/Registrants/index.jsx index 5722c029a8..6863186f22 100644 --- a/src/shared/components/challenge-detail/Registrants/index.jsx +++ b/src/shared/components/challenge-detail/Registrants/index.jsx @@ -11,8 +11,9 @@ import cn from 'classnames'; import { getRatingLevel } from 'utils/tc'; import sortList from 'utils/challenge-detail/sort'; +import DateSortIcon from 'assets/images/icon-date-sort.svg'; +import SortIcon from 'assets/images/icon-sort.svg'; import CheckMark from '../icons/check-mark.svg'; -import ArrowDown from '../../../../assets/images/arrow-down.svg'; import './style.scss'; function formatDate(date) { @@ -23,7 +24,7 @@ function formatDate(date) { function getDate(arr, handle) { const results = arr.filter(a => _.toString(a.createdBy || a.memberHandle) === _.toString(handle)) .sort((a, b) => new Date(b.submissionTime || b.submissionDate).getTime() - - new Date(a.submissionTime || a.submissionDate).getTime()); + - new Date(a.submissionTime || a.submissionDate).getTime()); return results[0] ? (results[0].submissionTime || results[0].submissionDate) : ''; } @@ -34,7 +35,7 @@ function passedCheckpoint(checkpoints, handle, results) { function getPlace(results, handle, places) { const found = _.find(results, w => _.toString(w.memberHandle) === _.toString(handle) - && w.placement <= places && w.submissionStatus !== 'Failed Review'); + && w.placement <= places && w.submissionStatus !== 'Failed Review'); if (found) { return found.placement; @@ -48,6 +49,11 @@ export default class Registrants extends React.Component { this.state = { sortedRegistrants: [], + ratingClicked: false, + usernameClicked: false, + registrationDateClicked: false, + round1SubmissionClicked: false, + submissionDateClicked: false, }; this.getCheckPoint = this.getCheckPoint.bind(this); @@ -66,15 +72,15 @@ export default class Registrants extends React.Component { const { registrants, registrantsSort } = this.props; if ( !_.isEqual(prevProps.registrants, registrants) - || !_.isEqual(prevProps.registrantsSort, registrantsSort) + || !_.isEqual(prevProps.registrantsSort, registrantsSort) ) { this.updateSortedRegistrants(); } } /** - * Get checkpoint date of registrant - */ + * Get checkpoint date of registrant + */ getCheckPointDate() { const { challenge, @@ -85,9 +91,9 @@ export default class Registrants extends React.Component { } /** - * Get checkpoint of registrant - * @param {Object} registrant registrant info - */ + * Get checkpoint of registrant + * @param {Object} registrant registrant info + */ getCheckPoint(registrant) { const { challenge, @@ -96,13 +102,13 @@ export default class Registrants extends React.Component { const checkpointDate = this.getCheckPointDate(); const twoRounds = challenge.round1Introduction - && challenge.round2Introduction; + && challenge.round2Introduction; let checkpoint; if (twoRounds) { checkpoint = getDate(checkpoints, registrant.memberHandle); if (!checkpoint - && moment(registrant.submissionDate).isBefore(checkpointDate)) { + && moment(registrant.submissionDate).isBefore(checkpointDate)) { checkpoint = registrant.submissionDate; } } @@ -111,9 +117,9 @@ export default class Registrants extends React.Component { } /** - * Get final of registrant - * @param {Object} registrant get checkpoint of registrant - */ + * Get final of registrant + * @param {Object} registrant get checkpoint of registrant + */ getFinal(registrant) { let final; if (moment(registrant.submissionDate).isAfter(this.getCheckPointDate())) { @@ -123,9 +129,9 @@ export default class Registrants extends React.Component { } /** - * Check if it have flag for first try - * @param {Object} registrant registrant info - */ + * Check if it have flag for first try + * @param {Object} registrant registrant info + */ getFlagFirstTry(registrant) { const { notFoundCountryFlagUrl } = this.props; if (!registrant.countryInfo || notFoundCountryFlagUrl[registrant.countryInfo.countryCode]) { @@ -136,8 +142,8 @@ export default class Registrants extends React.Component { } /** - * Get registrans sort parameter - */ + * Get registrans sort parameter + */ getRegistrantsSortParam() { const { registrantsSort, @@ -157,8 +163,8 @@ export default class Registrants extends React.Component { } /** - * Update sorted registrant array - */ + * Update sorted registrant array + */ updateSortedRegistrants() { const { registrants } = this.props; const sortedRegistrants = _.cloneDeep(registrants); @@ -167,9 +173,9 @@ export default class Registrants extends React.Component { } /** - * Sort array of registrant - * @param {Array} registrants array of registrant - */ + * Sort array of registrant + * @param {Array} registrants array of registrant + */ sortRegistrants(registrants) { const { field, sort } = this.getRegistrantsSortParam(); return sortList(registrants, field, sort, (a, b) => { @@ -244,7 +250,23 @@ export default class Registrants extends React.Component { track, } = challenge; - const { sortedRegistrants } = this.state; + const { + sortedRegistrants, + ratingClicked, + usernameClicked, + registrationDateClicked, + submissionDateClicked, + round1SubmissionClicked, + } = this.state; + + const sortOptionClicked = { + ratingClicked: false, + usernameClicked: false, + registrationDateClicked: false, + submissionDateClicked: false, + round1SubmissionClicked: false, + }; + const { field, sort } = this.getRegistrantsSortParam(); const revertSort = (sort === 'desc') ? 'asc' : 'desc'; const isDesign = track.toLowerCase() === 'design'; @@ -255,44 +277,46 @@ export default class Registrants extends React.Component { const checkpoints = challenge.checkpoints || []; const twoRounds = challenge.round1Introduction - && challenge.round2Introduction; + && challenge.round2Introduction; const places = prizes.length; return (
{ - !isDesign && ( - - ) - } + !isDesign && ( + + ) + }
{twoRounds && ( @@ -339,6 +364,7 @@ export default class Registrants extends React.Component { field: 'Round 1 Submitted Date', sort: (field === 'Round 1 Submitted Date') ? revertSort : 'desc', }); + this.setState({ ...sortOptionClicked, round1SubmissionClicked: true }); }} type="button" > @@ -351,7 +377,7 @@ export default class Registrants extends React.Component { 'col-arrow-is-sorting': field === 'Round 1 Submitted Date', }, )} - > + >{ round1SubmissionClicked ? : }
)} @@ -361,6 +387,7 @@ export default class Registrants extends React.Component { field: 'Submitted Date', sort: (field === 'Submitted Date') ? revertSort : 'desc', }); + this.setState({ ...sortOptionClicked, submissionDateClicked: true }); }} type="button" styleName="col-6 table-header" @@ -374,95 +401,98 @@ export default class Registrants extends React.Component { 'col-arrow-is-sorting': field === 'Submitted Date', }, )} - > + >{ submissionDateClicked ? : }
{ - sortedRegistrants.map((r) => { - const placement = getPlace(results, r.memberHandle, places); - let checkpoint = this.getCheckPoint(r); - if (checkpoint) { - checkpoint = formatDate(checkpoint); - } - const final = this.getFinal(r); - - return ( -
- { - !isDesign && ( -
-
- Rating -
-
- - { (!_.isNil(r.rating) && r.rating !== 0) ? r.rating : '-'} - -
-
- ) - } - -
-
- Registration Date -
- {formatDate(r.created)} -
- { - twoRounds - && ( -
-
- Round 1 Submitted Date -
-
- - {checkpoint} - - { - passedCheckpoint(checkpoints, r.memberHandle, checkpointResults) - && - } -
-
- ) - } -
-
- {twoRounds ? 'Round 2 ' : ''} - Submitted Date -
-
- - {formatDate(final)} - - {placement > 0 && ( - - {placement} - - )} -
-
-
- ); - }) - } + sortedRegistrants.map((r) => { + const placement = getPlace(results, r.memberHandle, places); + let checkpoint = this.getCheckPoint(r); + if (checkpoint) { + checkpoint = formatDate(checkpoint); + } + const final = this.getFinal(r); + + return ( +
+ { + !isDesign && ( +
+
+ Rating +
+
+ + { (!_.isNil(r.rating) && r.rating !== 0) ? r.rating : '-'} + +
+
+ ) + } +
+
+ USERNAME +
+ + + {r.memberHandle} + + +
+
+
+ Registration Date +
+ {formatDate(r.created)} +
+ { + twoRounds + && ( +
+
+ Round 1 Submitted Date +
+
+ + {checkpoint} + + { + passedCheckpoint(checkpoints, r.memberHandle, checkpointResults) + && + } +
+
+ ) + } +
+
+ {twoRounds ? 'Round 2 ' : ''} + Submitted Date +
+
+ + {formatDate(final)} + + {placement > 0 && ( + + {placement} + + )} +
+
+
+ ); + }) + }
); diff --git a/src/shared/components/challenge-detail/Registrants/style.scss b/src/shared/components/challenge-detail/Registrants/style.scss index b2e79d259a..2102216b39 100644 --- a/src/shared/components/challenge-detail/Registrants/style.scss +++ b/src/shared/components/challenge-detail/Registrants/style.scss @@ -3,24 +3,25 @@ .container { @include roboto-regular; - padding-top: 66px; - padding-bottom: 197px; - max-width: 966px; - margin: 0 auto; + padding-top: 30px; + padding-bottom: 50px; + margin: 0 41px; @include xs-to-sm { - padding: 0 30px 30px; + padding: 0; + margin: 0 16px; } } .head { font-weight: 500; - font-size: 13px; - line-height: 15px; - padding-bottom: 14px; - color: $tc-gray-50; + color: #767676; + font-size: 11px; + line-height: 14px; display: flex; - border-bottom: 1px solid $tc-gray-10; + text-transform: uppercase; + padding-top: 14px; + padding-bottom: 17px; @include xs-to-sm { display: none; @@ -32,37 +33,66 @@ display: flex; flex-direction: column; align-items: center; + margin-right: 18px; } } .row { + @include roboto-medium; + display: flex; - line-height: 50px; - color: $tc-gray-70; - font-size: 15px; - border-bottom: 1px solid $tc-gray-10; + line-height: 22px; + color: $tc-black; + font-size: 14px; + font-weight: 500; + padding-top: 16px; + padding-bottom: 15px; + border-top: 1px solid $tc-gray-10; + + &:last-child { + border-bottom: 1px solid $tc-gray-10; + } + + &:first-child { + @include xs-to-sm { + margin-top: 24px; + } + } @include xs-to-sm { flex-direction: column; - padding-top: 15px; - padding-bottom: 15px; + padding-top: 16px; + padding-left: 4px; width: 100%; + margin-top: 0; + padding-bottom: 12px !important; } } .sm-only { display: none; + .cell { + padding-top: 5px; + } + @include xs-to-sm { display: block; } } .title { - color: $tc-gray-50; - font-size: 13px; - line-height: 15px; - font-weight: 500; + @include barlow-bold; + + color: $tc-black; + font-size: 11px; + line-height: 14px; + font-weight: 600; + text-transform: uppercase; + + @include xs-to-sm { + padding-top: 2px; + } } .col-1, @@ -77,7 +107,6 @@ outline: none; font: inherit; color: inherit; - padding: 10; @include xs-to-sm { padding-left: 0; @@ -140,7 +169,8 @@ } .col-2 { - width: 150px; + width: 25%; + padding-left: 5px; @include xs-to-sm { padding-left: 0; @@ -151,12 +181,14 @@ } .col-3 { - width: 298px; + width: 26%; + padding-left: 10px !important; @include xs-to-sm { font-size: 15px; line-height: 25px; margin-bottom: 10px; + padding-left: 0 !important; width: auto; } @@ -170,11 +202,13 @@ } .col-4 { - width: 317px; + width: 24%; + padding-left: 10px; @include xs-to-sm { margin-bottom: 15px; line-height: 20px; + padding-left: 0; width: auto; } } @@ -182,10 +216,12 @@ .col-5 { display: flex; align-items: center; + padding-left: 10px; @include xs-to-sm { margin-bottom: 15px; line-height: 20px; + padding-left: 0; flex-direction: column; align-items: flex-start; width: auto; @@ -196,11 +232,13 @@ display: flex; align-items: center; width: 351px; + padding-left: 10px; @include xs-to-sm { line-height: 20px; flex-direction: column; align-items: flex-start; + padding-left: 0; width: auto; } } @@ -208,13 +246,16 @@ .table-header { cursor: pointer; background: transparent; + text-transform: uppercase; + &:focus, &:hover { - color: $tc-dark-blue; + color: $tc-black; + font-weight: 700; :global { - g { - fill: $tc-dark-blue; + path { + fill: $tc-black; } } } diff --git a/src/shared/components/challenge-detail/Specification/SideBar/ShareSocial.jsx b/src/shared/components/challenge-detail/Specification/SideBar/ShareSocial.jsx index 9dde5a54bd..a48b1fdcfa 100644 --- a/src/shared/components/challenge-detail/Specification/SideBar/ShareSocial.jsx +++ b/src/shared/components/challenge-detail/Specification/SideBar/ShareSocial.jsx @@ -6,7 +6,6 @@ import React from 'react'; import TwitterIcon from '../../../../../assets/images/social/icon_twitter.svg'; import FacebookIcon from '../../../../../assets/images/social/icon_facebook.svg'; -import PrintIcon from '../../../../../assets/images/social/icon_print.svg'; import EmailIcon from '../../../../../assets/images/social/icon_email.svg'; import MoreIcon from '../../../../../assets/images/social/icon_plus.svg'; @@ -32,14 +31,14 @@ export default class ShareSocial extends React.Component { render() { return (
{ this.shareDiv = htmlDiv; }} styleName="tc-share-social"> -
+
- + - - - { !isDesign && !isMM && ( -
-

- REVIEW STYLE: -

-

- Final Review: -

- - {reviewTypeTitle} - -
- ? -
-
-
-

- Approval: -

- - User Sign-Off - -
- ? -
-
-
-
- ) - } - { - !isMM && ( -
-

- CHALLENGE LINKS: -

- { - isDevelop && environment && environment.length > 0 - && ( -

- - Environment - -

- ) - } - { - isDevelop && codeRepo && codeRepo.length > 0 - && ( -

- - Code Repository - -

- ) - } - { - screeningScorecardId > 0 - && ( -

- - Screening Scorecard - -

- ) - } - { - reviewScorecardId > 0 && !isDesign - && ( +
+

+ REVIEW STYLE: +

+

+ Final Review: +

- - Review Scorecard - - -
- ? + {reviewTypeTitle} + +
+
- ) - } - { - !isDesign && ( +

+ Approval: +

- - Useable Code Rules - - -
- ? +
+
- ) - } -
+
) } - { isMM && ( + { + !isMM && ( +
+

+ CHALLENGE LINKS: +

+ { + isDevelop && environment && environment.length > 0 + && ( +

+ + Environment + +

+ ) + } + { + isDevelop && codeRepo && codeRepo.length > 0 + && ( +

+ + Code Repository + +

+ ) + } + { + screeningScorecardId > 0 + && ( +

+ + Screening Scorecard + +

+ ) + } + { + reviewScorecardId > 0 && !isDesign + && ( + + + Review Scorecard + + +
+ +
+
+
+ ) + } + { + !isDesign && ( + + + Useable Code Rules + + +
+ +
+
+
+ ) + } +
+ ) + } + {isMM && (

CHALLENGE LINKS: @@ -272,155 +288,159 @@ export default function SideBar({ { isDesign && ( -
-

- SUBMISSION FORMAT: -

-

- Your Design Files: -

-
    -
  1. - Look for instructions in this challenge regarding what files to provide. -
  2. -
  3. - Place your submission files into a "Submission.zip" file. -
  4. -
  5. - Place all of your source files into a "Source.zip" file. -
  6. -
  7. - Declare your fonts, stock photos, and icons in a "Declaration.txt" file. -
  8. -
  9. - Create a JPG preview file. -
  10. -
  11. - Place the 4 files you just created into a single zip file. - This will be what you upload. -
  12. -
-

- Trouble formatting your submission or want to learn more? - ‌ - - Read the FAQ. - -

-

- Fonts, Stock Photos, and Icons: -

-

- All fonts, stock photos, and icons within your design must be declared - when you submit. DO NOT include any 3rd party files in your - submission or source files. Read about the - {' '} - - policy. - -

-

- Screening: -

-

- All submissions are screened for eligibility before the challenge - holder picks winners. Don - " - t let your hard work go to waste. Learn more about how to -   - - pass screening. - -

- {(forumLink || !_.isEmpty(discuss)) && ( +
+

+ SUBMISSION FORMAT: +

+

+ Your Design Files: +

+
    +
  1. + Look for instructions in this challenge regarding what files to provide. +
  2. +
  3. + Place your submission files into a "Submission.zip" file. +
  4. +
  5. + Place all of your source files into a "Source.zip" file. +
  6. +
  7. + Declare your fonts, stock photos, and icons in a "Declaration.txt" file. +
  8. +
  9. + Create a JPG preview file. +
  10. +
  11. + Place the 4 files you just created into a single zip file. + This will be what you upload. +
  12. +

- Questions? + Trouble formatting your submission or want to learn more? ‌ - {_.isEmpty(discuss) && ( - - Ask in the Challenge Discussion Forums. - - )} + + Read the FAQ. +

- )} - {!_.isEmpty(discuss) && ( -
    - { discuss.map(d => ( -
  • +

    + Fonts, Stock Photos, and Icons: +

    +

    + All fonts, stock photos, and icons within your design must be declared + when you submit. DO NOT include any 3rd party files in your + submission or source files. Read about the + {' '} + + policy. + +

    +

    + Screening: +

    +

    + All submissions are screened for eligibility before the challenge + holder picks winners. Don't let your hard work go to waste. + Learn more about how to +   + + pass screening. + +

    +

    + CHALLENGE LINKS: +

    + {(forumLink || !_.isEmpty(discuss)) && ( +

    + Questions? + ‌ + {_.isEmpty(discuss) && ( - CHALLENGE DISCUSSION + Ask in the Challenge Discussion Forums. -

  • - ))} -
- )} -

- SOURCE FILES: -

- { - fileTypes - && ( -
    - { - fileTypes.value && fileTypes.value.length > 0 - ? JSON.parse(fileTypes.value).map(fileT => ( -
  • - {fileT} -
  • - )) - : undefined - } -
- ) - } -

- You must include all source files with your submission. -

-

- SUBMISSION LIMIT: -

-

+ )} +

+ )} + {!_.isEmpty(discuss) && discuss.map(d => ( +

+ + CHALLENGE DISCUSSION + +

+ )) + } +

+ SOURCE FILES: +

{ - submissionLimit - ? submissionLimitDisplay : ( - - {submissionLimitDisplay} - - ) + fileTypes + && ( +
    + { + fileTypes.value && fileTypes.value.length > 0 + ? JSON.parse(fileTypes.value) + .map(fileT => ( +
  • + {fileT} +
  • + )) + : undefined + } +
+ ) } -

-
+

+ You must include all source files with your submission. +

+

+ SUBMISSION LIMIT: +

+

+ { + submissionLimit + ? submissionLimitDisplay : ( + + {submissionLimitDisplay} + + ) + } +

+
) } { terms.length > 0 && ( -
-

- CHALLENGE TERMS: -

-
- { - terms.map(t => ( -
- - {t.title} - -
- )) - } +
+

+ CHALLENGE TERMS: +

+
+ { + terms.map(t => ( +
+ + {t.title} + +
+ )) + } +
-
) }
@@ -434,11 +454,16 @@ export default function SideBar({ target="_blank" rel="noreferrer" > - Topcoder Extension
for VSCode + Topcoder Extension for VSCode - -
- ? + +
+
@@ -449,11 +474,11 @@ export default function SideBar({ target="_blank" rel="noreferrer" > - Topcoder Templates
repository + Topcoder Templates repository
- { shareable && ( + {shareable && (

SHARE: @@ -461,7 +486,7 @@ export default function SideBar({

)} - { legacyId && ( + {legacyId && (

ID: {legacyId}

diff --git a/src/shared/components/challenge-detail/Specification/SideBar/social_media.scss b/src/shared/components/challenge-detail/Specification/SideBar/social_media.scss index 5b463bf264..3b5c60b3bc 100644 --- a/src/shared/components/challenge-detail/Specification/SideBar/social_media.scss +++ b/src/shared/components/challenge-detail/Specification/SideBar/social_media.scss @@ -5,10 +5,3 @@ $tc-fb-blue: #325fba; margin-top: 10px; white-space: nowrap; } - -.facebook-icon { - @include roboto-bold; - - width: 35px; - height: 35px; -} diff --git a/src/shared/components/challenge-detail/Specification/SideBar/styles.scss b/src/shared/components/challenge-detail/Specification/SideBar/styles.scss index 131f15fb3e..c245d60655 100644 --- a/src/shared/components/challenge-detail/Specification/SideBar/styles.scss +++ b/src/shared/components/challenge-detail/Specification/SideBar/styles.scss @@ -5,10 +5,13 @@ } .challenge-spec-sidebar { - background: $tc-dark-blue-10; - width: 245px; - margin: (11 * $base-unit) 0; - padding: 4 * $base-unit; + @include roboto-regular; + + background: #f4f4f4; + width: 325px; + padding: 23px; + margin-right: 30px; + margin-top: 34px; @include md { margin: (8 * $base-unit) 0; @@ -35,22 +38,14 @@ } .tctooltip { - background: $tc-green-110; - font-style: roboto; - font-weight: 700; - font-size: 13px; - line-height: 20px; - color: $tc-white; - padding: 0 6px; - border-radius: 10px; - margin: 0 5px; - cursor: pointer; + margin-left: 5px; + margin-top: 3px; } .tctooltiptext { background: $tc-gray-90; - border-radius: 6px; - padding: 5px; + border-radius: 8px !important; + padding: 10px; h4 { @include roboto-bold; @@ -78,7 +73,7 @@ } .tooltiptextapproval { - margin: 0 0 0 -80px; + border-radius: 8px; } .challenge-sidebar-inner { @@ -98,16 +93,21 @@ h2 { @include roboto-bold; - font-size: 13px; + font-size: 18px; color: $tc-gray-90; line-height: 20px; padding-bottom: 2px; } + a { + color: #0d61bf; + font-weight: 500; + } + h3 { @include roboto-bold; - font-size: 13px; + font-size: 16px; color: $tc-gray-90; line-height: 20px; margin-top: 4 * $base-unit; @@ -155,7 +155,8 @@ font-weight: 700; text-align: right; content: counter(item) "."; - padding: 0 10px 0 0; + padding: 0 8px 0 0; + width: 20px; } } diff --git a/src/shared/components/challenge-detail/Specification/styles.scss b/src/shared/components/challenge-detail/Specification/styles.scss index 4802a573f1..bd21a44f4a 100644 --- a/src/shared/components/challenge-detail/Specification/styles.scss +++ b/src/shared/components/challenge-detail/Specification/styles.scss @@ -244,7 +244,7 @@ $tc-link-visited: #0c4e98; h1 { @include roboto-bold; - font-size: 28px; + font-size: 32px; color: #151516; letter-spacing: -0.78px; line-height: 40px; @@ -254,16 +254,16 @@ $tc-link-visited: #0c4e98; h2 { @include roboto-bold; - font-size: 20px; + font-size: 24px; color: $tc-black; - line-height: 30px; + line-height: 28px; margin: (6 * $base-unit) 0 (2 * $base-unit); } h3 { @include roboto-bold; - font-size: 15px; + font-size: 18px; color: $tc-black; line-height: 25px; margin: (5 * $base-unit) 0 0; @@ -422,8 +422,7 @@ $tc-link-visited: #0c4e98; @include roboto-regular; width: 100%; - padding: 0 20px; - max-width: 720px; + padding: 0 34px; align-self: center; font-size: 15px; color: $tc-gray-90; diff --git a/src/shared/components/challenge-detail/Submissions/SubmissionRow/SubmissionHistoryRow/index.jsx b/src/shared/components/challenge-detail/Submissions/SubmissionRow/SubmissionHistoryRow/index.jsx index d58147effb..b132c539ea 100644 --- a/src/shared/components/challenge-detail/Submissions/SubmissionRow/SubmissionHistoryRow/index.jsx +++ b/src/shared/components/challenge-detail/Submissions/SubmissionRow/SubmissionHistoryRow/index.jsx @@ -21,10 +21,7 @@ export default function SubmissionHistoryRow({ provisionalScore, submissionTime, isReviewPhaseComplete, - onShowPopup, - submissionId, status, - member, }) { const getInitialReviewResult = () => { if (provisionalScore && provisionalScore < 0) return ; @@ -38,50 +35,41 @@ export default function SubmissionHistoryRow({ case 'failed': return ; default: - return provisionalScore; + return provisionalScore === '-' ? 'N/A' : provisionalScore; } }; const getFinalScore = () => { if (isMM && finalScore && finalScore > -1 && isReviewPhaseComplete) { return finalScore; } - return '-'; + return 'N/A'; }; return (
- { isMM ?
: null } -
- {submission} +
+
SUBMISSION
+ {submission}
-
-
+
+
FINAL SCORE
+
{getFinalScore()}
-
+
+
+
PROVISIONAL SCORE
+
{getInitialReviewResult()}
-
-
+
+
TIME
+
{moment(submissionTime).format('DD MMM YYYY')} {moment(submissionTime).format('HH:mm:ss')}
- { - isMM && ( -
-
onShowPopup(true, submissionId, member)} - > - View Details -
-
- ) - }
); @@ -94,7 +82,6 @@ SubmissionHistoryRow.defaultProps = { }; SubmissionHistoryRow.propTypes = { - member: PT.string.isRequired, isMM: PT.bool.isRequired, submission: PT.number.isRequired, finalScore: PT.oneOfType([ @@ -108,6 +95,4 @@ SubmissionHistoryRow.propTypes = { ]), submissionTime: PT.string.isRequired, isReviewPhaseComplete: PT.bool, - submissionId: PT.string.isRequired, - onShowPopup: PT.func.isRequired, }; diff --git a/src/shared/components/challenge-detail/Submissions/SubmissionRow/SubmissionHistoryRow/style.scss b/src/shared/components/challenge-detail/Submissions/SubmissionRow/SubmissionHistoryRow/style.scss index 93e9f3a5c2..afe69cc0bb 100644 --- a/src/shared/components/challenge-detail/Submissions/SubmissionRow/SubmissionHistoryRow/style.scss +++ b/src/shared/components/challenge-detail/Submissions/SubmissionRow/SubmissionHistoryRow/style.scss @@ -1,8 +1,11 @@ @import "~styles/mixins"; .container { + border-bottom: 1px solid #e9e9e9; + @include xs-to-sm { padding-top: 10px; + padding-bottom: 16px; } .row { @@ -10,17 +13,31 @@ color: $tc-gray-70; display: flex; border-bottom: 1px solid $tc-gray-10; + padding: 16px 0; &.no-border { border: none; } + + @include xs-to-sm { + padding: 0; + display: flex; + flex-direction: column; + } } .col { text-align: center; + @include roboto-medium; + + font-weight: 500; + font-size: 14px; + line-height: 22px; + padding: 0; + &.child { - height: 40px; + height: 57px; @include xs-to-sm { height: auto; @@ -28,104 +45,80 @@ } &.col-1 { - flex: 22; - display: flex; + flex: 30; - @include xs-to-sm { - display: none; - } + @include roboto-medium; - .col { - flex: 1; - } + color: #2a2a2a; + font-weight: 500; + font-size: 14px; + line-height: 22px; + text-align: left; - .col-left { - color: black; + @include xs-to-sm { + flex: 10; } } &.col-2 { - flex: 40; + flex: 30; + + @include roboto-medium; + + color: #2a2a2a; + font-weight: 500; + font-size: 14px; + line-height: 22px; text-align: left; - color: $tc-gray-50; @include xs-to-sm { - flex: 10; - padding-left: 10px; - } - - a { - color: black; + display: block; } } &.col-3 { - flex: 35; - display: flex; - color: $tc-gray-50; + flex: 30; - @include xs-to-sm { - display: block; - } - - .col { - flex: 1; - - @include xs-to-sm { - width: 50%; - text-align: left; - display: inline-block; - - &:first-child { - text-align: center; - font-weight: 500; - color: $tc-black; - } - - &:nth-child(2) { - &::before { - display: inline-block; - content: '/'; - margin: 0 4px; - } - } - } - } + @include roboto-medium; - .col-left { - color: black; - } + color: #2a2a2a; + font-weight: 500; + font-size: 14px; + line-height: 22px; + text-align: left; } &.col-4 { - flex: 35; - color: $tc-gray-50; - - &.history-time { - display: flex; + flex: 10; - @include xs-to-sm { - flex-direction: column; - padding-left: 0; - padding-right: 0; - } + @include roboto-medium; - .col { - flex: 1; - } - } + color: #2a2a2a; + font-weight: 500; + font-size: 14px; + line-height: 22px; + text-align: left; &.mm { - flex: 25; + flex: 30; } } + } +} - &.col-5 { - flex: 10; - color: #0a71e6; - cursor: pointer; - min-width: 83px; - outline: none; - } +.mobile-header { + display: none; + + @include xs-to-sm { + display: block; + margin-top: 16px; + font-size: 11px; + line-height: 14px; + + @include barlow-bold; + + font-weight: 600; + color: #767676; + text-align: left; } } diff --git a/src/shared/components/challenge-detail/Submissions/SubmissionRow/index.jsx b/src/shared/components/challenge-detail/Submissions/SubmissionRow/index.jsx index 81a3081e20..3aa50bfb4f 100644 --- a/src/shared/components/challenge-detail/Submissions/SubmissionRow/index.jsx +++ b/src/shared/components/challenge-detail/Submissions/SubmissionRow/index.jsx @@ -7,22 +7,23 @@ import React from 'react'; import PT from 'prop-types'; import _ from 'lodash'; import { getRatingLevel } from 'utils/tc'; +import { Modal } from 'topcoder-react-ui-kit'; +import IconClose from 'assets/images/icon-close-green.svg'; import moment from 'moment'; -import ArrowNext from '../../../../../assets/images/arrow-next.svg'; import Failed from '../../icons/failed.svg'; import InReview from '../../icons/in-review.svg'; import Queued from '../../icons/queued.svg'; import SubmissionHistoryRow from './SubmissionHistoryRow'; -import './style.scss'; +import style from './style.scss'; export default function SubmissionRow({ isMM, openHistory, member, submissions, score, toggleHistory, isReviewPhaseComplete, finalRank, provisionalRank, onShowPopup, rating, }) { const { - submissionTime, provisionalScore, status, + submissionTime, provisionalScore, status, submissionId, } = submissions[0]; let { finalScore } = submissions[0]; finalScore = (!finalScore && finalScore < 0) || !isReviewPhaseComplete ? '-' : finalScore; @@ -54,30 +55,38 @@ export default function SubmissionRow({ if (s && s < 0) return 0; return s; } - return '-'; + return 'N/A'; }; return ( -
+
{ isMM ? ( -
-
+ +
+
FINAL RANK
{ - isReviewPhaseComplete ? finalRank || '-' : '-' - } + isReviewPhaseComplete ? finalRank || 'N/A' : 'N/A' + }
-
- { provisionalRank || '-' } +
PROVISIONAL RANK
+
+
+ { provisionalRank || 'N/A' } +
-
+
) : null } -
+
+
RATING
{rating || '-'} +
+
+
USERNAME
-
-
+
+
FINAL SCORE
+
{getFinalReviewResult()}
-
- {getInitialReviewResult()} +
+
+
PROVISIONAL SCORE
+
+ {getInitialReviewResult() ? getInitialReviewResult() : 'N/A'}
-
+
+
+
SUBMISSION DATE
+
{moment(submissionTime).format('DD MMM YYYY')} {moment(submissionTime).format('HH:mm:ss')}
-
- {openHistory - && ( -
-
-
- { isMM ?
: null } -
- Submission + { openHistory && ( + +
+
+

Submission History

+
+
-
-
-
- Final +
+
+
+ Submission: {submissionId} +
+
+
+ { isMM ?
: null } +
+ Submission
-
- Provisional +
+
+
+ Final Score +
+
+
+ Provisional Score +
+
+
+ Time +
+ { + isMM && ( +
 
+ ) + }
-
- Time -
- { - isMM && ( -
 
- ) - } +
+ { + submissions.map((submissionHistory, index) => ( + + )) + } +
+ CLOSE
- { - submissions.map((submissionHistory, index) => ( - - )) - } -
+ ) - } + }
); } diff --git a/src/shared/components/challenge-detail/Submissions/SubmissionRow/style.scss b/src/shared/components/challenge-detail/Submissions/SubmissionRow/style.scss index 4f6023b3f1..0003cf2e88 100644 --- a/src/shared/components/challenge-detail/Submissions/SubmissionRow/style.scss +++ b/src/shared/components/challenge-detail/Submissions/SubmissionRow/style.scss @@ -1,6 +1,56 @@ @import "~styles/mixins"; -.container { +.history { + padding-bottom: 10px; + border-radius: 8px; + margin: 25px 32px 32px; +} + +.history-head { + display: flex; + margin-top: 24px; + width: 100%; + padding-bottom: 16px; + border-bottom: 1px solid #e9e9e9; + + .col { + text-transform: uppercase; + + @include roboto-medium; + + color: #2a2a2a; + font-weight: 500; + font-size: 14px; + line-height: 22px; + text-align: left; + + &.col-1 { + flex: 0; + } + + &.col-2 { + flex: 30; + } + + &.col-3 { + flex: 30; + } + + &.col-4 { + flex: 30; + } + + &.col-5 { + flex: 30; + } + } + + @include xs-to-sm { + display: none; + } +} + +.wrapper { a { cursor: pointer; } .row { @@ -10,7 +60,12 @@ border-bottom: 1px solid $tc-gray-10; @include xs-to-sm { - align-items: center; + flex-direction: column; + border-top: 1px solid #e9e9e9; + border-bottom: 0; + margin-left: 16px; + margin-top: 25px; + margin-right: 34px; } &.no-border { @@ -19,10 +74,6 @@ } .history { - color: $tc-gray-70; - background: #faf9fa; - padding-bottom: 10px; - .history-head { font-weight: 500; font-size: 13px; @@ -45,11 +96,30 @@ .col-4 { flex: 35; } + + @include xs-to-sm { + display: none; + } + } + } + + div.col { + padding: 16px 0; + + @include xs-to-sm { + padding-top: 0; + padding-bottom: 0; } } .col { - text-align: center; + @include roboto-medium; + + color: #2a2a2a; + font-weight: 500; + font-size: 14px; + line-height: 22px; + text-align: left; &.col-1 { flex: 20; @@ -59,51 +129,22 @@ flex: 15; display: block; } - - .col { - flex: 1; - - @include xs-to-sm { - text-align: left; - display: inline-block; - - &:nth-child(2) { - &::before { - display: inline-block; - content: '/'; - margin: 0 4px; - } - } - } - } - - .col-left { - color: black; - } } &.col-2 { - flex: 35; + flex: 20; text-align: left; - padding-left: 10px; color: $tc-gray-50; + padding-left: 10px; display: flex; @include xs-to-sm { - flex: 33; - } - - a { - color: black; - } - - .col { - flex: 1; + padding-left: 0; } } &.col-3 { - flex: 45; + flex: 20; display: flex; color: $tc-gray-50; @@ -113,30 +154,9 @@ text-align: left; } - .col { - flex: 1; - - @include xs-to-sm { - text-align: left; - display: inline-block; - - &:nth-child(2) { - &::before { - display: inline-block; - content: '/'; - margin: 0 4px; - } - } - - &.time { - width: 100%; - display: block; - } - } - } - - .col-left { - color: black; + &.time { + width: 100%; + display: block; } } @@ -147,39 +167,27 @@ @include xs-to-sm { flex: 10; } + } - a span { - display: flex; - align-items: center; - height: 100%; - float: right; - - &.text { - @include xs-to-sm { - display: none; - } - } - - .icon { - width: 15px; - height: 15px; - margin: 0 15px 0 10px; - - &.down { - transform: rotate(90deg); - -moz-transform: rotate(90deg); - -webkit-transform: rotate(90deg); - } - } - } + &.col-5 { + flex: 20; + } - &.mm { - flex: 25; - } + &.col-6 { + flex: 20; } - &.col-5 { - flex: 10; + &.col-7 { + flex: 20; + } + + &.col-8 { + flex: 13; + } + + .text { + cursor: pointer; + color: #0d61bf; } } @@ -213,3 +221,98 @@ .level-5 { color: $member-red !important; } + +.header { + display: flex; + justify-content: space-between; + margin-bottom: 25px; + + .title { + @include barlow-medium; + + font-weight: 600; + color: #2a2a2a; + font-size: 18px; + line-height: 22px; + text-transform: uppercase; + } + + .icon { + cursor: pointer; + margin-top: 5px; + } +} + +hr { + opacity: 0.5; +} + +.submission-text { + @include roboto-regular; + + font-size: 16px; + color: #2a2a2a; + line-height: 24px; + margin-top: 24px; + + span { + font-weight: 700; + } +} + +.container { + width: 750px !important; + border-radius: 8px; + + @include xs-to-sm { + margin: 9px 16px 16px 9px; + max-width: 100% !important; + top: 43%; + padding: 0 !important; + overflow-y: scroll; + } +} + +.close-btn { + cursor: pointer; + display: flex; + justify-content: flex-end; + margin-top: 24px; + margin-bottom: 32px; + background-color: #137d60; + padding: 8px 24px; + border-radius: 24px; + float: right; + + span { + @include roboto-bold; + + font-weight: 700; + font-size: 14px; + line-height: 24px; + color: #fff; + } + + @include xs-to-sm { + border-top: 1px solid #e9e9e9; + position: sticky; + margin-bottom: 16px; + } +} + +.mobile-header { + display: none; + + @include xs-to-sm { + display: block; + margin-top: 16px; + font-size: 11px; + line-height: 14px; + + @include barlow-bold; + + font-weight: 600; + color: #767676; + text-align: left; + } +} diff --git a/src/shared/components/challenge-detail/Submissions/index.jsx b/src/shared/components/challenge-detail/Submissions/index.jsx index b15855038d..7fbb08d4e6 100644 --- a/src/shared/components/challenge-detail/Submissions/index.jsx +++ b/src/shared/components/challenge-detail/Submissions/index.jsx @@ -13,7 +13,9 @@ import { config } from 'topcoder-react-utils'; import { submission as submissionUtils } from 'topcoder-react-lib'; import { isTokenExpired } from '@topcoder-platform/tc-auth-lib'; import cn from 'classnames'; -import { PrimaryButton } from 'topcoder-react-ui-kit'; +import { Button } from 'topcoder-react-ui-kit'; +import DateSortIcon from 'assets/images/icon-date-sort.svg'; +import SortIcon from 'assets/images/icon-sort.svg'; import sortList from 'utils/challenge-detail/sort'; import challengeDetailsActions from 'actions/page/challenge-details'; @@ -22,7 +24,6 @@ import { goToLogin, getRatingLevel } from 'utils/tc'; import Lock from '../icons/lock.svg'; import SubmissionRow from './SubmissionRow'; import SubmissionInformationModal from './SubmissionInformationModal'; -import ArrowDown from '../../../../assets/images/arrow-down.svg'; import style from './style.scss'; const { getProvisionalScore, getFinalScore } = submissionUtils; @@ -34,6 +35,14 @@ class SubmissionsComponent extends React.Component { isShowInformation: false, memberOfModal: '', sortedSubmissions: [], + ratingClicked: false, + usernameClicked: false, + dateClicked: false, + initialScoreClicked: false, + finalScoreClicked: false, + finalRankClicked: false, + provisionalRankClicked: false, + provisionalScoreClicked: false, }; this.onHandleInformationPopup = this.onHandleInformationPopup.bind(this); this.getSubmissionsSortParam = this.getSubmissionsSortParam.bind(this); @@ -66,8 +75,8 @@ class SubmissionsComponent extends React.Component { const { submissions, mmSubmissions, submissionsSort } = this.props; if ( (!isMM && !_.isEqual(prevProps.submissions, submissions)) - || (isMM && !_.isEqual(prevProps.mmSubmissions, mmSubmissions)) - || !_.isEqual(prevProps.submissionsSort, submissionsSort) + || (isMM && !_.isEqual(prevProps.mmSubmissions, mmSubmissions)) + || !_.isEqual(prevProps.submissionsSort, submissionsSort) ) { this.updateSortedSubmissions(); } @@ -86,9 +95,9 @@ class SubmissionsComponent extends React.Component { } /** - * Check if it have flag for first try - * @param {Object} registrant registrant info - */ + * Check if it have flag for first try + * @param {Object} registrant registrant info + */ getFlagFirstTry(registrant) { const { notFoundCountryFlagUrl } = this.props; if (!registrant.countryInfo || notFoundCountryFlagUrl[registrant.countryInfo.countryCode]) { @@ -99,8 +108,8 @@ class SubmissionsComponent extends React.Component { } /** - * Get submission sort parameter - */ + * Get submission sort parameter + */ getSubmissionsSortParam(isMM, isReviewPhaseComplete) { const { submissionsSort, @@ -128,8 +137,8 @@ class SubmissionsComponent extends React.Component { } /** - * Update sorted submission array - */ + * Update sorted submission array + */ updateSortedSubmissions() { const { challenge } = this.props; const isMM = checkIsMM(challenge); @@ -140,16 +149,16 @@ class SubmissionsComponent extends React.Component { } /** - * Sort array of submission - * @param {Array} submissions array of submission - */ + * Sort array of submission + * @param {Array} submissions array of submission + */ sortSubmissions(submissions) { const { challenge } = this.props; const isMM = checkIsMM(challenge); const isReviewPhaseComplete = this.checkIsReviewPhaseComplete(); const { field, sort } = this.getSubmissionsSortParam(isMM, isReviewPhaseComplete); let isHaveFinalScore = false; - if (field === 'Initial / Final Score') { + if (field === 'Initial Score' || 'Final Score') { isHaveFinalScore = _.some(submissions, s => !_.isNil( s.reviewSummation && s.reviewSummation[0].aggregateScore, )); @@ -190,7 +199,7 @@ class SubmissionsComponent extends React.Component { valueB = new Date(b.created); break; } - case 'Initial / Final Score': { + case 'Initial Score': { if (isHaveFinalScore) { valueA = getFinalScore(a); valueB = getFinalScore(b); @@ -239,8 +248,8 @@ class SubmissionsComponent extends React.Component { } /** - * Check if review phase complete - */ + * Check if review phase complete + */ checkIsReviewPhaseComplete() { const { challenge, @@ -290,7 +299,30 @@ class SubmissionsComponent extends React.Component { const { field, sort } = this.getSubmissionsSortParam(isMM, isReviewPhaseComplete); const revertSort = (sort === 'desc') ? 'asc' : 'desc'; - const { isShowInformation, memberOfModal, sortedSubmissions } = this.state; + const { + isShowInformation, + memberOfModal, + sortedSubmissions, + ratingClicked, + usernameClicked, + dateClicked, + initialScoreClicked, + finalScoreClicked, + finalRankClicked, + provisionalRankClicked, + provisionalScoreClicked, + } = this.state; + + const sortOptionClicked = { + ratingClicked: false, + usernameClicked: false, + dateClicked: false, + initialScoreClicked: false, + finalScoreClicked: false, + finalRankClicked: false, + provisionalRankClicked: false, + provisionalScoreClicked: false, + }; const modalSubmissionBasicInfo = () => _.find(mmSubmissions, item => item.member === memberOfModal); @@ -361,235 +393,82 @@ class SubmissionsComponent extends React.Component {
{ - sortedSubmissions.map(renderSubmission) - } + sortedSubmissions.map(renderSubmission) + }
{ - checkpoints.length > 0 - && ( -
- ROUND 1 (CHECKPOINT) SUBMISSIONS -
- ) - } + checkpoints.length > 0 + && ( +
+ ROUND 1 (CHECKPOINT) SUBMISSIONS +
+ ) + } { - checkpoints.length > 0 - && ( -
- { - checkpoints.map(renderSubmission) - } -
- ) - } + checkpoints.length > 0 + && ( +
+ { + checkpoints.map(renderSubmission) + } +
+ ) + }
) : (
-
+
Private Challenge
-
+
Submissions are not viewable for this challenge
-
+ There are many reason why the submissions may not be viewable, such as the allowance of stock art, or a client's desire to keep the work private. -
+
); } if (!_.isEmpty(loadingMMSubmissionsForChallengeId)) { - return ; + return
; } return ( -
- { - isMM ? ( -
-
- Rank -
-
- User -
-
- Score -
-
-
- ) : ( -
- { - !isF2F && !isBugHunt && ( - - ) - } - - - -
- ) - } +
{ - isMM && ( -
-
- - -
-
- + !isMM && ( +
+ { + !isF2F && !isBugHunt && ( + + ) + } -
-
-
-
- ) - } - { - isMM && ( - sortedSubmissions.map((submission, index) => ( - { toggleSubmissionHistory(index); }} - openHistory={(submissionHistoryOpen[index.toString()] || false)} - isLoadingSubmissionInformation={isLoadingSubmissionInformation} - submissionInformation={submissionInformation} - onShowPopup={this.onHandleInformationPopup} - getFlagFirstTry={this.getFlagFirstTry} - onGetFlagImageFail={onGetFlagImageFail} - /> - )) - ) - } + ) + } { - !isMM && ( - sortedSubmissions.map(s => ( -
- { - !isF2F && !isBugHunt && ( -
- { (s.registrant && !_.isNil(s.registrant.rating)) ? s.registrant.rating : '-'} + isMM && ( +
+
+ +
+
+
-
- {moment(s.created).format('MMM DD, YYYY HH:mm')} +
+
-
- { - (!_.isEmpty(s.review) && !_.isEmpty(s.review[0]) && s.review[0].score) - ? s.review[0].score.toFixed(2) - : 'N/A' - } - ‌ - ‌/ - ‌ +
+ +
+
+ +
+
+ +
+
+ ACTIONS +
+
+ ) + } + { + isMM && ( + sortedSubmissions.map((submission, index) => ( + { toggleSubmissionHistory(index); }} + openHistory={(submissionHistoryOpen[index.toString()] || false)} + isLoadingSubmissionInformation={isLoadingSubmissionInformation} + submissionInformation={submissionInformation} + onShowPopup={this.onHandleInformationPopup} + getFlagFirstTry={this.getFlagFirstTry} + onGetFlagImageFail={onGetFlagImageFail} + submissionDetail={submission} + /> + )) + ) + } + { + !isMM && ( + sortedSubmissions.map(s => ( +
{ - (s.reviewSummation && s.reviewSummation[0].aggregateScore) - ? s.reviewSummation[0].aggregateScore.toFixed(2) - : 'N/A' + !isF2F && !isBugHunt && ( + +
RATING
+
+ { (s.registrant && !_.isNil(s.registrant.rating)) ? s.registrant.rating : '-'} +
+
+ ) } + +
+
SUBMISSION DATE
+

+ {moment(s.created).format('MMM DD, YYYY HH:mm')} +

+
+
+
INITIAL SCORE
+

+ { + (!_.isEmpty(s.review) && !_.isEmpty(s.review[0]) && s.review[0].score) + ? s.review[0].score.toFixed(2) + : 'N/A' + } +

+
+
+
FINAL SCORE
+

+ { + (s.reviewSummation && s.reviewSummation[0].aggregateScore) + ? s.reviewSummation[0].aggregateScore.toFixed(2) + : 'N/A' + } +

+
-
- )) - ) + )) + ) + } + { + isMM &&
} {isMM && ( - - Add Submission - + )} { - isMM && isShowInformation && ( - - ) - } + isMM && isShowInformation && ( + + ) + }
); } @@ -843,7 +922,7 @@ function mapStateToProps(state) { submissionHistoryOpen: state.page.challengeDetails.submissionHistoryOpen, submissionTestcaseOpen: state.page.challengeDetails.submissionTestcaseOpen, isLoadingSubmissionInformation: - Boolean(state.challenge.loadingSubmissionInformationForSubmissionId), + Boolean(state.challenge.loadingSubmissionInformationForSubmissionId), submissionInformation: state.challenge.submissionInformation, }; } diff --git a/src/shared/components/challenge-detail/Submissions/style.scss b/src/shared/components/challenge-detail/Submissions/style.scss index 85a3c7b5e8..e186e80f70 100644 --- a/src/shared/components/challenge-detail/Submissions/style.scss +++ b/src/shared/components/challenge-detail/Submissions/style.scss @@ -3,7 +3,6 @@ .container { @include roboto-regular; - max-width: 1060px; margin-left: auto; margin-right: auto; @@ -120,13 +119,17 @@ } .head { + @include barlow-bold; + + font-weight: 600; font-weight: 500; - font-size: 15px; - line-height: 15px; + font-size: 11px; + line-height: 14px; padding-bottom: 14px; - padding-top: 14px; - color: $tc-gray-50; - background: #e8e8e8; + padding-bottom: 17px; + color: #767676; + background: #fff; + text-transform: uppercase; display: flex; border-radius: 5px 5px 0 0; @@ -148,10 +151,9 @@ font-weight: 500; font-size: 13px; line-height: 15px; - padding-bottom: 7px; + padding-bottom: 17px; padding-top: 7px; color: $tc-gray-50; - background: #faf9fa; display: flex; border-bottom: 1px solid $tc-gray-10; @@ -165,16 +167,56 @@ } .lock { - fill: $tc-light-blue; - height: 136px; - margin-bottom: 30px; - width: 110px; + height: 53px; + width: 48px; + margin-bottom: 24px; + margin-top: 24px; + } + + .lock-title { + @include barlow-bold; + + font-weight: 600; + font-size: 24px; + line-height: 28px; + text-align: center; + color: $tco-black; + text-transform: uppercase; + } + + .lock-subtitle { + @include roboto-medium; + + font-weight: 500; + font-size: 14px; + line-height: 16px; + letter-spacing: 0.5px; + text-align: center; + color: $tco-black; + margin-top: 14px; + text-transform: capitalize; + } + + .lock-desc { + @include roboto-regular; + + font-weight: 400; + font-size: 16px; + line-height: 24px; + text-align: center; + color: $tco-black; + margin-top: 60px; + width: 540px; + + @include xs-to-sm { + width: auto; + } } } .container.dev { - margin: 30px 80px; - padding-bottom: 30px; + margin: 0 46px; + padding-bottom: 0; line-height: 50px; text-align: center; @@ -184,62 +226,81 @@ } .col { - text-align: center; + text-align: left; &.col-1 { - flex: 22; + flex: 20; display: flex; - - .col { - flex: 1; - } } &.col-2 { - flex: 35; + flex: 20; display: flex; color: $tc-gray-50; padding-left: 10px; - - a { - color: black; - } - - .col { - flex: 1; - } } &.col-3 { - flex: 45; + flex: 20; display: flex; color: $tc-gray-50; - - .col { - flex: 1; - } } &.col-4 { flex: 20; color: $tc-gray-50; } + + &.col-5 { + flex: 19; + color: $tc-gray-50; + } + + &.col-6 { + flex: 20; + color: $tc-gray-50; + } + + &.col-7 { + flex: 20; + color: $tc-gray-50; + } + + &.col-8 { + flex: 13; + color: $tc-gray-50; + } } .handle { color: $tc-dark-blue; } + &.mm { + margin: 28px 32px 0 32px; + + @include xs-to-sm { + margin: 0; + } + } + &.non-mm { .head { + @include barlow-bold; + + font-weight: 600; font-weight: 500; - font-size: 13px; - line-height: 15px; - padding-bottom: 14px; - color: $tc-gray-50; - display: flex; - border-bottom: 1px solid $tc-gray-10; - background: transparent; + font-size: 11px; + line-height: 14px; + padding-bottom: 17px; + padding-top: 14px; + color: #767676; + background: #fff; + border-bottom: 1px solid #e9e9e9; + + * { + text-transform: uppercase; + } @include xs-to-sm { display: none; @@ -247,10 +308,39 @@ } .row { - color: $tc-gray-70; + @include roboto-medium; + + color: $tc-black; + font-weight: 500; display: flex; - border-bottom: 1px solid $tc-gray-10; - font-size: 15px; + border-bottom: 1px solid #e9e9e9; + font-size: 14px; + line-height: 22px; + padding-top: 16px; + padding-bottom: 15px; + + @include xs-to-sm { + flex-direction: column; + margin: 0 16px; + border-top: 1px solid #e9e9e9; + } + } + + .mobile-header { + display: none; + + @include xs-to-sm { + display: block; + margin-top: 16px; + font-size: 11px; + line-height: 14px; + + @include barlow-bold; + + font-weight: 600; + color: #767676; + text-align: left; + } } .col-1 { @@ -267,21 +357,73 @@ } .col-2 { - width: 10%; + width: 15%; justify-content: flex-start; display: flex; } .col-3 { - width: 26.6%; + width: 18.6%; + + a { + padding-left: 20px; + + @include xs-to-sm { + padding-left: 0; + } + } + + @include xs-to-sm { + text-align: left; + } } .col-4 { - width: 26.6%; + width: 20.6%; + + p { + padding-left: 20px; + + @include xs-to-sm { + padding-left: 0; + } + } + + @include xs-to-sm { + text-align: left; + } } .col-5 { - width: 26.6%; + width: 19.6%; + + p { + padding-right: 60px; + + @include xs-to-sm { + padding-right: 0; + } + } + + @include xs-to-sm { + text-align: left; + } + } + + .col-6 { + width: 21.6%; + + p { + padding-right: 55px; + + @include xs-to-sm { + padding-right: 0; + } + } + + @include xs-to-sm { + text-align: left; + } } .handle { @@ -327,6 +469,8 @@ } .header-sort { + @include barlow-bold; + display: flex; justify-content: center; align-items: center; @@ -337,15 +481,13 @@ color: inherit; padding: 0; background: transparent; + font-size: 11px; + line-height: 14px; + &:focus, &:hover { - color: $tc-dark-blue; - - :global { - g { - fill: $tc-dark-blue; - } - } + color: $tc-black; + font-weight: 700; } } @@ -354,6 +496,23 @@ width: 181px; margin-top: 25px !important; align-self: center; + background-color: #137d60 !important; + border-radius: 50px !important; + padding: 12px 24px; + text-transform: uppercase; + + @include roboto-bold; + + font-weight: 700; + font-size: 16px; + line-height: 24px; + color: #fff !important; + border: 0; + + &:hover { + background-color: lighten(#137d60, 5%) !important; + background-image: none !important; + } } .level-1 { @@ -375,3 +534,18 @@ .level-5 { color: $member-red !important; } + +.loading { + margin-top: 30px; +} + +.bottom-line { + display: none; + + @include xs-to-sm { + display: block; + width: 100%; + border-top: 1px solid #e9e9e9 !important; + margin: 16px 16px 0 16px; + } +} diff --git a/src/shared/components/challenge-detail/ThriveArticles/index.jsx b/src/shared/components/challenge-detail/ThriveArticles/index.jsx index 97684c34b4..000cea3f22 100644 --- a/src/shared/components/challenge-detail/ThriveArticles/index.jsx +++ b/src/shared/components/challenge-detail/ThriveArticles/index.jsx @@ -2,10 +2,11 @@ import React from 'react'; import PT from 'prop-types'; import { map } from 'lodash'; import { config } from 'topcoder-react-utils'; +import { Button } from 'topcoder-react-ui-kit'; import moment from 'moment'; import CalendarIcon from '../../../../assets/images/calendar.svg'; -import './style.scss'; +import style from './style.scss'; export default function ThriveArticles({ articles }) { const formatTitle = (title) => { @@ -39,13 +40,21 @@ export default function ThriveArticles({ articles }) { )); return (
+
Recommended THRIVE Articles
- +
{items} diff --git a/src/shared/components/challenge-detail/ThriveArticles/style.scss b/src/shared/components/challenge-detail/ThriveArticles/style.scss index c1f23de066..46d7bbea94 100644 --- a/src/shared/components/challenge-detail/ThriveArticles/style.scss +++ b/src/shared/components/challenge-detail/ThriveArticles/style.scss @@ -1,30 +1,68 @@ @import "~styles/mixins"; +.hr { + background-color: #d4d4d4; + border-radius: 0; + height: 2px; + margin: 48px 0; + + @include xs-to-sm { + margin: 24px 0; + } +} + +.button { + @include roboto-bold; + + align-self: center !important; + position: relative !important; + white-space: nowrap !important; + border-color: #137d60 !important; + color: #137d60 !important; + margin: 0 !important; + border-radius: 24px !important; + border-width: 2px !important; + font-size: 13px !important; + font-weight: 700 !important; + line-height: 24px; + letter-spacing: 0.2px; + min-height: 32px !important; + padding: 3px 17px !important; + + @include xs-to-sm { + align-self: flex-start !important; + } +} + .container { @include roboto-regular; - max-width: 1240px; width: 100%; display: flex; background-color: $tc-white; flex-direction: column; border-radius: (3 * $corner-radius); - padding: 22px 11px 28px; - margin: 50px auto 0; + padding: 0 32px 48px 32px; + + @include xs-to-sm { + padding: 0 16px 24px 16px; + } } .header-container { display: flex; - align-items: center; + align-items: flex-start; justify-content: space-between; } .header { - @include roboto-bold; + @include barlow-bold; - margin-left: 13px; - font-size: 20px; + font-size: 24px; + line-height: 28px; color: $tc-black; + text-transform: uppercase; + width: 55%; } .right-url { @@ -36,18 +74,25 @@ .articles { display: flex; flex-wrap: wrap; + justify-content: flex-start; + flex-direction: row; } .article { display: flex; - width: 380px; + flex: 1; position: relative; overflow: hidden; - margin: 20px 13px 0; + margin-top: 20px; + margin-right: 20px; border-radius: (5 * $corner-radius); background-color: #f4f4f4; } +.article:nth-child(3n) { + margin-right: 0; +} + .article-left { display: flex; flex: 1; @@ -56,13 +101,14 @@ } .article-read-time { - @include roboto-regular; + @include roboto-bold; - margin-top: 13px; + margin-top: 16px; font-size: 12px; - font-weight: 500; - letter-spacing: -0.33px; - color: $tc-gray-70; + line-height: 16px; + font-weight: 700; + color: #555; + text-transform: uppercase; } .article-title { @@ -70,8 +116,8 @@ margin-top: 1px; font-size: 20px; - line-height: 1.1; - color: $tc-gray-70; + line-height: 26px; + color: #2a2a2a; } .article-create-time { @@ -80,10 +126,10 @@ display: flex; align-items: center; margin-top: 11px; - font-size: 12px; + font-size: 14px; font-weight: 500; letter-spacing: -0.33px; - color: $tc-gray-70; + color: #2a2a2a; svg { margin-right: 5px; @@ -112,6 +158,10 @@ } @include xs-to-md { + .articles { + flex-direction: column; + } + .article { width: 100%; } diff --git a/src/shared/components/challenge-detail/Winners/Winner/index.jsx b/src/shared/components/challenge-detail/Winners/Winner/index.jsx index bd545f7808..f5f7b999ea 100644 --- a/src/shared/components/challenge-detail/Winners/Winner/index.jsx +++ b/src/shared/components/challenge-detail/Winners/Winner/index.jsx @@ -3,8 +3,7 @@ import PT from 'prop-types'; import React, { useEffect, useState } from 'react'; import _ from 'lodash'; import { config } from 'topcoder-react-utils'; - -import Lock from '../../icons/lock.svg'; +import { formatOrdinals, numberWithCommas } from 'utils/challenge-detail/helper'; import style from './style.scss'; @@ -14,7 +13,6 @@ function getId(submissions, placement) { export default function Winner({ isDesign, - last, prizes, submissions, viewable, @@ -27,9 +25,6 @@ export default function Winner({ const submissionId = viewable && getId(submissions, winner.placement); - let placeStyle = winner.placement < 4 ? `place-${winner.placement}` : ''; - if (last) placeStyle += ' last'; - let avatarUrl = winner.photoURL; if (avatarUrl) { avatarUrl = `${config.CDN.PUBLIC}/avatar/${ @@ -41,85 +36,69 @@ export default function Winner({ if (prizes[prizeIndex]) prize = prizes[prizeIndex].value; return ( -
-
-
- {winner.placement} +
+
+
+ {formatOrdinals(winner.placement)}
- { - (viewable && isDesign) - ? ( - - ) - : ( -
- -
- LOCKED -
-
+
+ + { + submissionId + && ( +
+ ID: + + # + {getId(submissions, winner.placement)} + +
) - } -
-
-
- -
+ } + { + (winner.submissionDownloadLink && viewable) + && ( - {winner.handle} + Download -
- $ - {prize} + ) + } + { + /* +
+ Submitted on:‌ + ‌{moment(winner.submissionDate).format('MMM DD, YYYY HH:mm')}
-
+ */ + } +
+
+ +
+
+ $ + {numberWithCommas(prize)}
- { - submissionId - && ( -
- ID: - - # - {getId(submissions, winner.placement)} - -
- ) - } - { - (winner.submissionDownloadLink && viewable) - && ( - - Download - - ) - } - { - /* -
- Submitted on:‌ - ‌{moment(winner.submissionDate).format('MMM DD, YYYY HH:mm')} -
- */ - }
); @@ -131,7 +110,6 @@ Winner.defaultProps = { Winner.propTypes = { isDesign: PT.bool.isRequired, - last: PT.bool.isRequired, prizes: PT.arrayOf(PT.number), submissions: PT.arrayOf(PT.object).isRequired, viewable: PT.bool.isRequired, diff --git a/src/shared/components/challenge-detail/Winners/Winner/style.scss b/src/shared/components/challenge-detail/Winners/Winner/style.scss index 5ef87c9ccf..865263cc3a 100644 --- a/src/shared/components/challenge-detail/Winners/Winner/style.scss +++ b/src/shared/components/challenge-detail/Winners/Winner/style.scss @@ -11,10 +11,18 @@ } .avatar { - border-radius: 65px !important; - height: 65px !important; - margin: 5px 15px 0 0 !important; - width: 65px !important; + border-radius: 50% !important; + height: 48px !important; + margin: 5px 15px 0 32px !important; + width: 48px !important; + background-color: #f0f0f0; + + @include xs-to-sm { + width: 40px !important; + height: 40px !important; + margin-top: 0 !important; + margin-left: 16px !important; + } } .flag { @@ -42,81 +50,78 @@ } } -.last { - &:nth-child(2) { - justify-content: center; - } -} - /* TODO: Rename into container. */ .winner { - &.place-1 { - justify-content: center; + @include xs-to-sm { + height: auto; min-width: 100%; + } - .flag { - background-color: $tc-gold; - color: $tc-gold-110; - - &::after { - border-top: solid 20px $tc-gold; - } - } + &:last-child { + border-bottom: 1px solid $tc-gray-10; } - &.place-2 { - border-right: 1px solid $tc-gray-10; + min-width: 50%; + overflow: hidden; + display: flex; + justify-content: space-between; + border-top: 1px solid $tc-gray-10; + padding: 17px 17px 0 17px; - .flag { - background-color: $tc-silver; - color: $tc-silver-110; + @include xs-to-sm { + padding: 16px 0; + } +} - &::after { - border-top: solid 20px $tc-silver; - } - } +.placement { + background-color: #e0faf3; + border-radius: 50%; + width: 56px; + height: 56px; + padding: 8px; + + @include xs-to-sm { + width: 40px; + height: 40px; } - &.place-3 { - .flag { - background-color: $tc-bronze; - color: $tc-bronze-110; + span { + @include roboto-bold; + + font-weight: 500; + font-size: 20px; + line-height: 26px; + text-align: center; + align-self: center; + color: $tc-black; + margin-top: 5px; + display: flex; + flex-direction: column; - &::after { - border-top: solid 20px $tc-bronze; - } + @include xs-to-sm { + font-size: 16px; + line-height: 24px; + margin-top: 0; } } - &:nth-child(2n+4) { - border-left: none; - border-right: 1px solid $tc-gray-10; - } + // background: #e0faf3; + // color: $tco-black; - &:nth-child(2n+3) { - border-left: none; + &.placement-1 { + background: #ffd84d; + color: $tco-black; } - &:nth-child(n + 3) { - max-width: 50%; + &.placement-2 { + background: #d1d0cf; + color: $tco-black; } - @include xs-to-sm { - height: auto; - min-width: 100%; + &.placement-3 { + background: #d98f64; + color: $tco-black; } - - flex: 1; - flex-wrap: wrap; - min-height: 300px; - min-width: 50%; - overflow: hidden; - display: flex; - justify-content: flex-start; - align-items: center; - border-bottom: 1px solid $tc-gray-10; - border-top: none; - padding: 4 * $base-unit; } .thumbnail { @@ -146,27 +151,20 @@ .info { .handle { - color: $tc-dark-blue-110; - display: block; - font-size: 36px; - margin-bottom: 8px; - font-weight: 300; - - @include xs-to-sm { - margin-bottom: 0; - font-size: 28px; - line-height: 35px; - } - } + @include roboto-regular; - .prize { - color: $tc-gray-90; + color: #0d61bf; + display: block; font-size: 24px; - font-weight: 500; + line-height: 32px; + font-weight: 400; @include xs-to-sm { font-size: 20px; - line-height: 30px; + line-height: 28px; + margin-left: 0; + margin-top: 0; + margin-bottom: 0; } } @@ -220,3 +218,24 @@ .checkpoint { flex: none; } + +.left { + display: flex; +} + +.right { + .prize { + color: $tc-black; + font-size: 24px; + line-height: 32px; + font-weight: 400; + margin-top: 10px; + + @include xs-to-sm { + font-size: 20px; + line-height: 30px; + margin-right: 12px; + margin-top: 6px; + } + } +} diff --git a/src/shared/components/challenge-detail/Winners/index.jsx b/src/shared/components/challenge-detail/Winners/index.jsx index 0bc8f9759a..efe57fb954 100644 --- a/src/shared/components/challenge-detail/Winners/index.jsx +++ b/src/shared/components/challenge-detail/Winners/index.jsx @@ -18,11 +18,10 @@ export default function Winners({ return (
{ - winners.map((w, index) => ( + winners.map(w => ( - - - - - - - - \ No newline at end of file + + + diff --git a/src/shared/components/challenge-listing/ChallengeCard/MatchScore/style.scss b/src/shared/components/challenge-listing/ChallengeCard/MatchScore/style.scss index 80d12a53cb..2b69c92b23 100644 --- a/src/shared/components/challenge-listing/ChallengeCard/MatchScore/style.scss +++ b/src/shared/components/challenge-listing/ChallengeCard/MatchScore/style.scss @@ -3,5 +3,7 @@ .matchScoreTag { margin-right: 0; margin-bottom: 4px; + margin-top: -2px; display: inline-block; + white-space: nowrap; } diff --git a/src/shared/components/challenge-listing/ChallengeCard/NumRegistrants/style.scss b/src/shared/components/challenge-listing/ChallengeCard/NumRegistrants/style.scss index 9bc816da96..ead9f5b189 100644 --- a/src/shared/components/challenge-listing/ChallengeCard/NumRegistrants/style.scss +++ b/src/shared/components/challenge-listing/ChallengeCard/NumRegistrants/style.scss @@ -6,7 +6,7 @@ } .link:hover { - color: $tc-dark-blue-110; + color: $tc-black; } .number { @@ -18,9 +18,12 @@ } .tooltip { - font-weight: 500; - font-size: 13px; + font-weight: 400; + font-size: 14px; + line-height: 22px; color: $tc-white; letter-spacing: 0; - padding: 15px; + padding: 10px; + border-radius: 8px; + background-color: #2a2a2a; } diff --git a/src/shared/components/challenge-listing/ChallengeCard/NumSubmissions/style.scss b/src/shared/components/challenge-listing/ChallengeCard/NumSubmissions/style.scss index 9bc816da96..521c7584bb 100644 --- a/src/shared/components/challenge-listing/ChallengeCard/NumSubmissions/style.scss +++ b/src/shared/components/challenge-listing/ChallengeCard/NumSubmissions/style.scss @@ -18,9 +18,12 @@ } .tooltip { - font-weight: 500; - font-size: 13px; + font-weight: 400; + font-size: 14px; + line-height: 22px; color: $tc-white; letter-spacing: 0; - padding: 15px; + padding: 10px; + border-radius: 8px; + background-color: #2a2a2a; } diff --git a/src/shared/components/challenge-listing/ChallengeCard/Prize/Tip/style.scss b/src/shared/components/challenge-listing/ChallengeCard/Prize/Tip/style.scss index 9ef4a445d9..99e318fe0a 100644 --- a/src/shared/components/challenge-listing/ChallengeCard/Prize/Tip/style.scss +++ b/src/shared/components/challenge-listing/ChallengeCard/Prize/Tip/style.scss @@ -5,8 +5,10 @@ $prize-space-10: $base-unit * 2; @include roboto-regular; max-width: 480px; - padding: 15px; + padding: 10px 10px 0 10px; overflow: hidden; + background-color: #2a2a2a; + border-radius: 8px; .bonuses { border-top: 1px solid $tc-gray-70; @@ -15,15 +17,17 @@ $prize-space-10: $base-unit * 2; } h1 { + @include roboto-regular; + border: none; color: $tc-white; - font-size: 15px; - line-height: 15px; + font-size: 14px; + line-height: 16px; margin: 0 0 $prize-space-10; padding: 0; text-align: left; text-transform: none; - font-weight: 700; + font-weight: 500; } } diff --git a/src/shared/components/challenge-listing/ChallengeCard/Prize/index.jsx b/src/shared/components/challenge-listing/ChallengeCard/Prize/index.jsx index 93ab6e034c..c7fdc50fb3 100644 --- a/src/shared/components/challenge-listing/ChallengeCard/Prize/index.jsx +++ b/src/shared/components/challenge-listing/ChallengeCard/Prize/index.jsx @@ -35,6 +35,11 @@ export default function Prize({
); + function placeArrow(TooltipNode) { + const arrow = TooltipNode.querySelector('.rc-tooltip-arrow'); + arrow.style.left = '33%'; + } + const component = (
{((onlyShowTooltipForPrize && !withoutTooltip) ? ( - + {prizeUI} ) diff --git a/src/shared/components/challenge-listing/ChallengeCard/Prize/style.scss b/src/shared/components/challenge-listing/ChallengeCard/Prize/style.scss index 3744719a06..bd8473ba76 100644 --- a/src/shared/components/challenge-listing/ChallengeCard/Prize/style.scss +++ b/src/shared/components/challenge-listing/ChallengeCard/Prize/style.scss @@ -2,10 +2,11 @@ .label { cursor: default; - padding: 0 (2 * $base-unit); - background: $tc-gray-neutral-light; - font-size: 10px; - color: $tc-gray-70; + padding-top: 5px; + font-size: 11px; + font-weight: 500; + line-height: 10px; + color: $tco-black; white-space: nowrap; @include xs-to-sm { @@ -19,5 +20,5 @@ .symbol { display: inline-block; - color: $tc-gray-80; + color: $tco-black; } diff --git a/src/shared/components/challenge-listing/ChallengeCard/Status/index.jsx b/src/shared/components/challenge-listing/ChallengeCard/Status/index.jsx index 0d91283aa5..0b483f6afc 100644 --- a/src/shared/components/challenge-listing/ChallengeCard/Status/index.jsx +++ b/src/shared/components/challenge-listing/ChallengeCard/Status/index.jsx @@ -89,21 +89,24 @@ export default function ChallengeStatus(props) { winners = winners.slice(0, MAX_VISIBLE_WINNERS); winners.push(lastItem); } + const leaderboard = winners && winners.map((winner) => { if (winner.isLastItem) { return ( /* TODO: No, should not reuse avatar for displaying "+1" in * a circle. Should be a separate component for that. */ - ( - setImmediate(() => selectChallengeDetailsTab(DETAIL_TABS.WINNERS)) - )} - openNewTab={openChallengesInNewTabs} - url={detailLink} - plusOne - /> +
+ ( + setImmediate(() => selectChallengeDetailsTab(DETAIL_TABS.WINNERS)) + )} + openNewTab={openChallengesInNewTabs} + url={`${detailLink}?tab=winners`} + plusOne + /> +
); } const userProfile = getProfile(winner); @@ -153,7 +156,7 @@ export default function ChallengeStatus(props) { {timeNote} - to register + to Register ); @@ -227,7 +230,9 @@ export default function ChallengeStatus(props) { if (statusPhase) phaseMessage = statusPhase.name; else if (status === 'Draft') phaseMessage = DRAFT_MSG; - const showRegisterInfo = challenge.registrationOpen === 'Yes' && !challenge.users[userId]; + const users = challenge.users || {}; + + const showRegisterInfo = (challenge.currentPhaseNames || []).includes('Registration') && !users[userId]; return (
@@ -273,10 +278,8 @@ export default function ChallengeStatus(props) { color="green" value={getPhaseProgress(statusPhase)} isLate={moment().isAfter(phaseEndDate(statusPhase))} + timeLeft={getTimeLeft(statusPhase, 'to go').text} /> -
- {getTimeLeft(statusPhase, 'to go').text} -
) : } diff --git a/src/shared/components/challenge-listing/ChallengeCard/Status/style.scss b/src/shared/components/challenge-listing/ChallengeCard/Status/style.scss index 730b05f6b2..86c2ae5a81 100644 --- a/src/shared/components/challenge-listing/ChallengeCard/Status/style.scss +++ b/src/shared/components/challenge-listing/ChallengeCard/Status/style.scss @@ -16,11 +16,13 @@ $status-radius-4: $corner-radius * 2; @include xs-to-md { margin-top: $status-space-20 + 3; + margin-right: 16px; width: 100%; } @include xs-to-sm { margin-top: $status-space-15; + margin-right: 16px; } &.completed { @@ -43,10 +45,12 @@ $status-radius-4: $corner-radius * 2; } .avatar-container { - margin-right: $status-space-15 + 2; + margin-right: 0; + margin-left: 10px; @include xl { - margin-right: 14px; + margin-right: 0; + margin-left: 10px; } > span { @@ -59,7 +63,7 @@ $status-radius-4: $corner-radius * 2; min-width: 100%; &.with-register-button { - padding-right: 108px; + padding-right: 95px; @include xs-to-sm { padding-right: 0; @@ -68,11 +72,14 @@ $status-radius-4: $corner-radius * 2; } .current-phase { + @include roboto-medium; + float: left; - font-size: 13px; - font-weight: 400; - color: $tc-black; - line-height: $status-space-20; + font-size: 11px; + font-weight: 500; + color: $tco-black; + line-height: 10px; + margin-top: 6px; } .time-left { @@ -139,33 +146,37 @@ $status-radius-4: $corner-radius * 2; } // register btn a.register-button { + @include roboto-regular; + + font-weight: 400; display: block; position: absolute; - height: 100%; - background: $tc-gray-neutral-light; + height: 90%; + margin-top: 5px; + background: #f4f4f4; top: 0; right: 0; - width: 108px; - padding-left: $status-space-20; + width: 120px; + padding-left: 16px; text-align: left; - font-size: 13px; - color: $tc-black; - line-height: $status-space-20; + font-size: 14px; + color: $tco-black; + line-height: 24px; @include xs-to-sm { position: absolute; - height: 50px; + height: 42px; width: auto; left: 0; right: 0; top: auto; bottom: 0; text-align: center; - background: $tc-dark-blue-10; + background: #f4f4f4; } span { - font-size: 12px; + font-size: 14px; line-height: $status-space-15; font-weight: 500; display: block; @@ -178,7 +189,7 @@ $status-radius-4: $corner-radius * 2; display: inline-block; position: relative; margin-top: 0; - color: $tc-dark-blue; + color: $tco-black; } } @@ -193,8 +204,8 @@ $status-radius-4: $corner-radius * 2; } &:hover { - background: $tc-dark-blue-10; - color: $tc-dark-blue; + background: #137d60; + color: $tc-white; } } } diff --git a/src/shared/components/challenge-listing/ChallengeCard/style.scss b/src/shared/components/challenge-listing/ChallengeCard/style.scss index 9196473e75..8c19b90fb3 100644 --- a/src/shared/components/challenge-listing/ChallengeCard/style.scss +++ b/src/shared/components/challenge-listing/ChallengeCard/style.scss @@ -17,10 +17,11 @@ $challenge-radius-4: $corner-radius * 2; justify-content: flex-start; position: relative; background: $tc-white; - padding: $challenge-space-20; + padding: $challenge-space-20 0; border-top: 1px solid $tc-gray-10; color: $tc-black; font-size: 15px; + margin-left: 24px; &:last-child { border-bottom: 1px solid $tc-gray-10; @@ -28,7 +29,10 @@ $challenge-radius-4: $corner-radius * 2; @include xs-to-md { flex-wrap: wrap; - padding: $base-unit * 3; + padding: $base-unit * 3 0; + margin-left: 0; + // min-height: 120px; + flex-direction: column; } @include xs-to-sm { @@ -47,10 +51,11 @@ $challenge-radius-4: $corner-radius * 2; .left-panel { display: flex; justify-content: flex-start; - width: 50%; + width: 45.5%; @include xs-to-md { width: 100%; + padding: 0 16px; } } @@ -61,10 +66,11 @@ $challenge-radius-4: $corner-radius * 2; @include xs-to-md { width: 100%; + display: flex; } @include xs-to-sm { - display: block; + display: flex; } } @@ -72,6 +78,7 @@ $challenge-radius-4: $corner-radius * 2; .challenge-track { display: inline-block; vertical-align: top; + border-radius: 4px 4px 0 0; > span:first-child { display: inline-block; @@ -114,7 +121,8 @@ $challenge-radius-4: $corner-radius * 2; // date and technologies .details-footer { width: 100%; - margin-top: $challenge-space-10; + margin-top: 16px; + display: flex; .date { font-size: 12px; @@ -122,6 +130,8 @@ $challenge-radius-4: $corner-radius * 2; margin-right: $challenge-space-10; line-height: ($challenge-space-10) + 2; font-weight: normal; + min-width: 70px; + margin-top: 2px; } .technology { @@ -161,13 +171,14 @@ $challenge-radius-4: $corner-radius * 2; right: 0; top: 20px; margin-right: $challenge-space-20; + width: 30% !important; } @include xs-to-sm { position: relative; width: 100%; - margin-top: $challenge-space-20; - padding-left: $challenge-space-50; + margin-top: 15px; + padding-left: 16px; top: 0; } @@ -271,4 +282,8 @@ $challenge-radius-4: $corner-radius * 2; @extend .animated-placeholder-template; } + + .footer-template { + margin-top: 20px; + } } diff --git a/src/shared/components/challenge-listing/ChallengeProgressBar/index.jsx b/src/shared/components/challenge-listing/ChallengeProgressBar/index.jsx index 36b7b9505c..1856573a4c 100644 --- a/src/shared/components/challenge-listing/ChallengeProgressBar/index.jsx +++ b/src/shared/components/challenge-listing/ChallengeProgressBar/index.jsx @@ -2,11 +2,18 @@ import React from 'react'; import PT from 'prop-types'; import './style.scss'; -function ChallengeProgressBar({ color, value, isLate }) { +function ChallengeProgressBar({ + color, value, isLate, timeLeft, +}) { const prgrWidth = value > 100 ? 100 : value; return ( -
-
+
+
+
+
+
+ {timeLeft} +
); } @@ -15,12 +22,14 @@ ChallengeProgressBar.defaultProps = { color: '', value: 150, isLate: false, + timeLeft: '', }; ChallengeProgressBar.propTypes = { color: PT.string, value: PT.oneOfType([PT.string, PT.number]), isLate: PT.oneOfType([PT.bool, PT.string]), + timeLeft: PT.string, }; export default ChallengeProgressBar; diff --git a/src/shared/components/challenge-listing/ChallengeProgressBar/style.scss b/src/shared/components/challenge-listing/ChallengeProgressBar/style.scss index d4c211d55e..eed1383490 100644 --- a/src/shared/components/challenge-listing/ChallengeProgressBar/style.scss +++ b/src/shared/components/challenge-listing/ChallengeProgressBar/style.scss @@ -3,14 +3,18 @@ $progress-height: $base-unit - 1; $progress-space-3: $base-unit - 2; $progress-space-15: $base-unit * 3; $progress-radius-16: $corner-radius * 8; +$tc-progress-turquiose: #9d41c9; +$tc-progress-red: #ef476f; +$tc-progress-gray: #e9e9e9; +$status-space-15: $base-unit * 3; .challenge-progress-bar { display: block; - height: $progress-height; + height: 6px; background: $tc-gray-neutral-dark; border-radius: $progress-radius-16; position: relative; - margin: $base-unit 0; + margin: 8px 0; .fill { display: inline-block; @@ -23,7 +27,7 @@ $progress-radius-16: $corner-radius * 8; top: -$progress-space-3; &.green { - background: $tc-green; + background: $tc-progress-turquiose; } &.gold { @@ -31,11 +35,24 @@ $progress-radius-16: $corner-radius * 8; } &.gray { - background: $tc-gray-20; + background: $tc-progress-gray; } &.red { - background: $tc-red-70; + background: $tc-progress-red; } } } + +.time-left { + text-align: left; + color: $tc-gray-70; + font-size: 12px; + line-height: $status-space-15; + font-weight: 400; + display: table-cell; + + &.red { + color: $tc-progress-red; + } +} diff --git a/src/shared/components/challenge-listing/ChallengeTab/index.jsx b/src/shared/components/challenge-listing/ChallengeTab/index.jsx new file mode 100644 index 0000000000..a9a4ba1956 --- /dev/null +++ b/src/shared/components/challenge-listing/ChallengeTab/index.jsx @@ -0,0 +1,147 @@ +import React, { useEffect, useState } from 'react'; +import { BUCKETS, isPastBucket } from 'utils/challenge-listing/buckets'; +import cn from 'classnames'; +import { useMediaQuery } from 'react-responsive'; +import ArrowIcon from 'assets/images/ico-arrow-down.svg'; +import PT from 'prop-types'; + +import './style.scss'; + +const ChallengeTab = ({ + activeBucket, + setPreviousBucketOfActiveTab, + setPreviousBucketOfPastChallengesTab, + previousBucketOfPastChallengesTab, + previousBucketOfActiveTab, + selectBucket, +}) => { + const past = isPastBucket(activeBucket); + const [currentSelected, setCurrentSelected] = useState(past); + const [isTabClosed, setIsTabClosed] = useState(true); + + useEffect(() => { + setCurrentSelected(isPastBucket(activeBucket)); + }, [activeBucket]); + + const onActiveClick = () => { + if (!past) { + return; + } + setPreviousBucketOfPastChallengesTab(activeBucket); + setCurrentSelected(0); + setIsTabClosed(true); + if (previousBucketOfActiveTab) { + selectBucket(previousBucketOfActiveTab); + } else { + selectBucket(BUCKETS.OPEN_FOR_REGISTRATION); + } + }; + + const onPastChallengesClick = () => { + if (past) { + return; + } + setPreviousBucketOfActiveTab(activeBucket); + setCurrentSelected(1); + setIsTabClosed(true); + if (previousBucketOfPastChallengesTab) { + selectBucket(previousBucketOfPastChallengesTab); + } else { + selectBucket(BUCKETS.ALL_PAST); + } + }; + + const desktop = useMediaQuery({ minWidth: 1024 }); + + const desktopTab = ( +
    +
  • { + if (e.key !== 'Enter') { + return; + } + onActiveClick(); + }} + role="presentation" + > + ACTIVE CHALLENGES +
  • +
  • { + if (e.key !== 'Enter') { + return; + } + onPastChallengesClick(); + }} + role="presentation" + > + PAST CHALLENGES +
  • +
+ ); + + const mobileTab = ( + +
setIsTabClosed(!isTabClosed)} + > +

{currentSelected ? 'PAST CHALLENGES' : 'ACTIVE CHALLENGES'}

+
setIsTabClosed(!isTabClosed)} + > + +
+
+ { + !isTabClosed && ( +
+
+

ACTIVE CHALLENGES

+
+
+

PAST CHALLENGES

+
+
+ ) + } +
+ ); + + return desktop ? desktopTab : mobileTab; +}; + +ChallengeTab.defaultProps = { + setPreviousBucketOfActiveTab: () => {}, + setPreviousBucketOfPastChallengesTab: () => {}, + previousBucketOfActiveTab: null, + previousBucketOfPastChallengesTab: null, +}; + +ChallengeTab.propTypes = { + activeBucket: PT.string.isRequired, + setPreviousBucketOfActiveTab: PT.func, + setPreviousBucketOfPastChallengesTab: PT.func, + previousBucketOfActiveTab: PT.string, + selectBucket: PT.func.isRequired, + previousBucketOfPastChallengesTab: PT.string, +}; + +export default ChallengeTab; diff --git a/src/shared/components/challenge-listing/ChallengeTab/style.scss b/src/shared/components/challenge-listing/ChallengeTab/style.scss new file mode 100644 index 0000000000..575e052d7c --- /dev/null +++ b/src/shared/components/challenge-listing/ChallengeTab/style.scss @@ -0,0 +1,119 @@ +@import "~styles/mixins"; + +.mobile-tab-expanded { + margin: 0 16px; + background-color: $listing-light-blue; + + .item { + height: 40px; + margin: 0; + + p { + @include barlow-bold; + + font-weight: 600; + color: #555; + font-size: 14px; + line-height: 20px; + text-transform: uppercase; + padding-left: 16px; + padding-top: 10px; + } + } + + .active { + background-color: #bae1f9; + + p { + color: $tco-black; + font-weight: 700; + } + } +} + +.challenge-tab { + display: flex; + height: 42px; + margin-top: 24px; + background-color: $listing-light-blue; + border-radius: 4px 4px 0 0; + border-bottom: 1px solid $listing-light-gray; + + .item { + @include barlow; + + font-weight: 600; + font-size: 14px; + color: $member-gray; + line-height: 20px; + padding: 12px 16px 10px 16px; + cursor: pointer; + display: flex; + justify-content: center; + + &:not(.active):hover { + background-color: #bae1f9; + } + } + + .active { + color: $tc-black; + font-weight: 700; + + &::after { + content: ""; + background-image: url(assets/images/nav-active-item.svg); + height: 10px; + width: 40px; + margin-top: 10px; + justify-content: center; + z-index: 100; + display: block; + position: absolute; + top: 145px; + } + } +} + +.mobile-tab-container { + background-color: $listing-light-blue; + height: 40px; + margin-top: 32px; + display: flex; + justify-content: space-between; + border-radius: 4px 4px 0 0; + border-bottom: 1px solid #d4d4d4; + + .title { + @include barlow-bold; + + font-weight: 700; + color: $tco-black; + font-size: 14px; + line-height: 20px; + text-transform: uppercase; + padding-left: 16px; + padding-top: 10px; + } + + .icon { + width: 16px; + height: 9px; + margin-right: 15px; + display: flex; + flex-direction: column; + justify-content: center; + align-self: center; + cursor: pointer; + transform: scale(1.5); + } + + .down { + transform: scale(1.5) rotate(180deg); + margin-right: 20px !important; + } + + @include xs-to-md { + margin: 0 16px; + } +} diff --git a/src/shared/components/challenge-listing/Filters/Button/index.jsx b/src/shared/components/challenge-listing/Filters/Button/index.jsx new file mode 100644 index 0000000000..df15f56c8e --- /dev/null +++ b/src/shared/components/challenge-listing/Filters/Button/index.jsx @@ -0,0 +1,66 @@ +import React from 'react'; +import PT from 'prop-types'; + +import './styles.scss'; + +/** + * Displays a button. + * + * @param {Object} props component properties + * @returns {JSX.Element} + */ +const Button = ({ + children, + className, + onClick, + isInverted, + isPrimary, + isSelected, + isText, + shade, + size, + style, + disabled, + value, +}) => ( + +); + +Button.defaultProps = { + isInverted: false, + isPrimary: false, + disabled: false, +}; + +Button.propTypes = { + children: PT.node.isRequired, + className: PT.string.isRequired, + onClick: PT.func.isRequired, + isInverted: PT.bool, + isPrimary: PT.bool, + isSelected: PT.bool.isRequired, + isText: PT.bool.isRequired, + shade: PT.oneOf(['dark']).isRequired, + size: PT.string.isRequired, + style: PT.oneOf(['circle']).isRequired, + value: PT.any.isRequired, + disabled: PT.bool, +}; + +export default Button; diff --git a/src/shared/components/challenge-listing/Filters/Button/styles.scss b/src/shared/components/challenge-listing/Filters/Button/styles.scss new file mode 100644 index 0000000000..5b58bd0c45 --- /dev/null +++ b/src/shared/components/challenge-listing/Filters/Button/styles.scss @@ -0,0 +1,91 @@ +@import '~styles/mixins'; + +.button { + @include roboto-bold; + + padding: 8px 13px; + font-size: 12px; + color: $listing-checkbox-green; + line-height: 1; + letter-spacing: 0.8px; + white-space: nowrap; + appearance: none; + background: $tc-white; + border: 1px solid $listing-checkbox-green; + border-radius: 15px; + + &.is-selected { + color: $tc-gray-90; + border-color: $tc-gray-90; + } + + &.button-circle { + display: flex; + justify-content: center; + align-items: center; + padding: 0; + width: 30px; + height: 30px; + } + + &.button-primary { + &.button-inverted { + border: none; + padding: 9px 14px; + } + } +} + +.button-primary { + color: $tc-white; + background-color: $listing-checkbox-green; + + &.button-inverted { + color: $listing-checkbox-green; + background-color: $tc-white; + } +} + +.button-text { + padding: 0; + letter-spacing: 1px; + color: inherit; + border: none; + background: none; +} + +.button-lg { + padding: 12px 20px; + font-size: 12px; + border-radius: 20px; + + &.button-circle { + padding: 0; + width: 40px; + height: 40px; + } + + &.button-primary { + &.button-inverted { + padding: 13px 21px; + } + } +} + +.button-sm { + border-radius: 10px; + padding: 4px 13px; + font-size: 10px; + + &.button-circle { + padding: 0; + width: 20px; + height: 20px; + } + + &.button-primary { + &.button-inverted { + padding: 5px 14px; + } + } +} diff --git a/src/shared/components/challenge-listing/Filters/ChallengeSearchBar/style.scss b/src/shared/components/challenge-listing/Filters/ChallengeSearchBar/style.scss index c1141a4321..a196341a09 100644 --- a/src/shared/components/challenge-listing/Filters/ChallengeSearchBar/style.scss +++ b/src/shared/components/challenge-listing/Filters/ChallengeSearchBar/style.scss @@ -9,12 +9,13 @@ $challenge-radius-1: $corner-radius / 2; $challenge-radius-4: $corner-radius * 2; .container { - background: $tc-gray-neutral-light; border-bottom: 1px solid $tc-gray-30; - padding: 0 $base-unit * 3; + padding-bottom: 16px; + margin: 2px 12px 2px 14px; - @media (max-width: #{$screen-lg - 1px}) { - padding: 0 $base-unit * 2; + @include xs-to-md { + padding: 0; + margin: 0 16px; } } @@ -25,7 +26,7 @@ $challenge-radius-4: $corner-radius * 2; height: 60px; .input-container { - font-size: 12px; + font-size: 14px; display: flex; width: 100%; justify-content: center; @@ -45,8 +46,8 @@ $challenge-radius-4: $corner-radius * 2; @include placeholder { @include roboto-light; - font-size: 15px; - color: $tc-gray-50; + font-size: 14px; + color: $listing-placeholder-gray; text-transform: none; opacity: 1; } @@ -59,7 +60,7 @@ $challenge-radius-4: $corner-radius * 2; .SearchButton { background: $tc-white; cursor: pointer; - padding: $challenge-space-10 + 1 $challenge-space-20 $challenge-space-10 - 2; + padding: 11.4px 5.4px 14.4px 11.4px; border-radius: $challenge-radius-4 0 0 $challenge-radius-4; height: 40px; order: 1; @@ -67,8 +68,9 @@ $challenge-radius-4: $corner-radius * 2; border-right: 0; .zoomIcon { - height: 16px; - width: 16px; + height: 11.2px; + width: 11.2px; + margin-bottom: 6px; } &:hover { diff --git a/src/shared/components/challenge-listing/Filters/ChallengeSearchBar/ui-zoom.svg b/src/shared/components/challenge-listing/Filters/ChallengeSearchBar/ui-zoom.svg index dca2ed444b..8da0f696c3 100644 --- a/src/shared/components/challenge-listing/Filters/ChallengeSearchBar/ui-zoom.svg +++ b/src/shared/components/challenge-listing/Filters/ChallengeSearchBar/ui-zoom.svg @@ -1,5 +1,3 @@ - - - + + + diff --git a/src/shared/components/challenge-listing/Filters/FiltersPanel/index.jsx b/src/shared/components/challenge-listing/Filters/FiltersPanel/index.jsx index 7e354fb936..56da63c1ad 100644 --- a/src/shared/components/challenge-listing/Filters/FiltersPanel/index.jsx +++ b/src/shared/components/challenge-listing/Filters/FiltersPanel/index.jsx @@ -27,18 +27,20 @@ import PT from 'prop-types'; import Select from 'components/Select'; import DateRangePicker from 'components/DateRangePicker'; import moment from 'moment'; -import { Button } from 'topcoder-react-ui-kit'; import Tooltip from 'components/Tooltip'; import { config, Link } from 'topcoder-react-utils'; import { COMPOSE, PRIORITY } from 'react-css-super-themr'; import { REVIEW_OPPORTUNITY_TYPES } from 'utils/tc'; import { isFilterEmpty, isPastBucket, BUCKETS } from 'utils/challenge-listing/buckets'; import SwitchWithLabel from 'components/SwitchWithLabel'; +import ChallengeSearchBar from 'containers/challenge-listing/ChallengeSearchBar'; import { challenge as challengeUtils } from 'topcoder-react-lib'; import { createStaticRanges } from 'utils/challenge-listing/date-range'; -import circleIcon from 'assets/images/icon-circle.png'; +import ArrowIcon from 'assets/images/ico-arrow-down.svg'; +import CircleIcon from 'assets/images/icon-circle.svg'; +import Button from '../Button'; import UiSimpleRemove from '../../Icons/ui-simple-remove.svg'; -import FiltersIcon from '../../Icons/filters-icon.svg'; +import BucketSelector from '../../Sidebar/BucketSelector'; import CheckmarkIcon from './CheckmarkIcon'; import style from './style.scss'; @@ -49,6 +51,8 @@ export default function FiltersPanel({ defaultCommunityId, filterState, // challenges, + disabled, + expanding, hidden, isAuth, auth, @@ -70,7 +74,7 @@ export default function FiltersPanel({ }) { if (hidden && !expanded) { return ( -
{ setExpanded(!expanded); @@ -84,8 +88,8 @@ export default function FiltersPanel({ tabIndex={0} role="button" > - More Filters -
+ More Filters + ); } @@ -347,37 +351,55 @@ export default function FiltersPanel({
*/} +
+
+ +
+
+ +
+
+ +
+
- Track + Challenge Category
switchTrack('Des', on)} /> switchTrack('Dev', on)} /> switchTrack('DS', on)} /> switchTrack('QA', on)} /> @@ -385,6 +407,43 @@ export default function FiltersPanel({
+ { !isReviewOpportunitiesBucket + && ( +
+
+ + Challenge Type + +
+ { + validTypes + .map(mapTypes) + .map(option => ( + + { + let { types } = filterState; + + if (e) { + types = types.concat(option.value); + } else { + types = types.filter(type => type !== option.value); + } + + setFilterState({ ..._.clone(filterState), types }); + }} + /> + + )) + } +
+
+
+ ) + } + { past && (
@@ -442,7 +501,7 @@ export default function FiltersPanel({
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */} { @@ -468,47 +527,6 @@ export default function FiltersPanel({ ) } - { !isReviewOpportunitiesBucket - && ( -
-
- - Type - -
- { - validTypes - .map(mapTypes) - .map(option => ( - - { - let { types } = filterState; - - if (e.target.checked) { - types = types.concat(option.value); - } else { - types = types.filter(type => type !== option.value); - } - - setFilterState({ ..._.clone(filterState), types }); - }} - /> - - - )) - } -
-
-
- ) - } - {/* Only shown when the Review Opportunity bucket is selected */} { isReviewOpportunitiesBucket ? ( @@ -524,16 +542,13 @@ export default function FiltersPanel({ .map(([value, label]) => ({ value, label })) .map(option => ( - { + { let { reviewOpportunityTypes = [] } = filterState; - if (e.target.checked) { + if (e) { reviewOpportunityTypes = reviewOpportunityTypes .concat(option.value); } else { @@ -545,7 +560,6 @@ export default function FiltersPanel({ setFilterState({ ..._.clone(filterState), reviewOpportunityTypes }); }} /> - )) } @@ -560,7 +574,7 @@ export default function FiltersPanel({
{ + onClick(); + }} + /> + {BUCKET_DATA[bucket].name} + {(bucket !== BUCKETS.ALL && count > 0) ? {count} : null}
); } diff --git a/src/shared/components/challenge-listing/Sidebar/BucketSelector/Bucket/style.scss b/src/shared/components/challenge-listing/Sidebar/BucketSelector/Bucket/style.scss index c71a328525..08fff51366 100644 --- a/src/shared/components/challenge-listing/Sidebar/BucketSelector/Bucket/style.scss +++ b/src/shared/components/challenge-listing/Sidebar/BucketSelector/Bucket/style.scss @@ -14,19 +14,68 @@ color: $tc-black; border-radius: 2 * $corner-radius; cursor: pointer; - padding: 0 2 * $base-unit 0 3 * $base-unit; + padding: 9px 10px 0 9px; + display: flex; // @include xs-to-sm { // font-size: 15px; // padding: 2px 0; // } -} -.right { - color: $tc-gray-70; - float: right; - position: static; - font-weight: 700; + & input { + width: 20px !important; + height: 20px !important; + background-color: $tc-white; + border-radius: 50% !important; + appearance: none; + border: 1.5px solid #7f7f7f; + position: relative; + + &:checked { + border-color: $listing-checkbox-green !important; + + &::after { + content: ''; + position: absolute; + left: 23%; + top: 23%; + width: 10px; + height: 10px; + border-radius: 50% !important; + background-color: $listing-checkbox-green !important; + } + } + } + + .bucketName { + @include roboto-regular; + + font-weight: 400; + font-size: 16px; + line-height: 24px; + color: $tco-black; + margin-left: 5px; + } + + .count { + align-self: center; + background-color: $listing-checkbox-blue; + height: 16px; + border-radius: 50px; + color: $tc-white !important; + font-size: 14px; + line-height: 16px; + + @include roboto-regular; + + font-weight: 500; + letter-spacing: 0.5px; + text-transform: capitalize; + text-align: center; + padding: 0 8px; + margin-left: 8px; + margin-bottom: 5px; + } } .errorMsg { diff --git a/src/shared/components/challenge-listing/Sidebar/BucketSelector/index.jsx b/src/shared/components/challenge-listing/Sidebar/BucketSelector/index.jsx index 9d04ac7a03..db92ca637c 100644 --- a/src/shared/components/challenge-listing/Sidebar/BucketSelector/index.jsx +++ b/src/shared/components/challenge-listing/Sidebar/BucketSelector/index.jsx @@ -82,14 +82,13 @@ export default function BucketSelector({ return (!past ? ( -
+
{getBucket(BUCKETS.ALL)} {isAuth ? getBucket(BUCKETS.MY) : null} {/* {extraBucket ? getBucket(extraBucket) : null} */} {getBucket(BUCKETS.OPEN_FOR_REGISTRATION)} {/* DISABLED: Until api receive fix community-app#5073 */} {/* {getBucket(BUCKETS.ONGOING)} */} -
{getBucket(BUCKETS.REVIEW_OPPORTUNITIES)} {/* {getBucket(BUCKETS.PAST)} */} {/* NOTE: We do not show upcoming challenges for now, for various reasons, @@ -118,7 +117,6 @@ export default function BucketSelector({
) : '' } */} -
{/* DISABLED: Until feeds.topcoder.com domain fixed community-app#4606 */} {/*
diff --git a/src/shared/components/challenge-listing/Sidebar/BucketSelector/style.scss b/src/shared/components/challenge-listing/Sidebar/BucketSelector/style.scss index 391caad94d..49e63947ed 100644 --- a/src/shared/components/challenge-listing/Sidebar/BucketSelector/style.scss +++ b/src/shared/components/challenge-listing/Sidebar/BucketSelector/style.scss @@ -63,3 +63,7 @@ padding: 2px 0; } } + +.bucketSelector { + margin-top: 15px; +} diff --git a/src/shared/components/challenge-listing/Sidebar/index.jsx b/src/shared/components/challenge-listing/Sidebar/index.jsx index b6d50b915d..b0ad3de237 100644 --- a/src/shared/components/challenge-listing/Sidebar/index.jsx +++ b/src/shared/components/challenge-listing/Sidebar/index.jsx @@ -18,7 +18,8 @@ import React from 'react'; import PT from 'prop-types'; // import _ from 'lodash'; -import { BUCKETS, isPastBucket } from 'utils/challenge-listing/buckets'; +import { isPastBucket } from 'utils/challenge-listing/buckets'; +import ChallengeSearchBar from 'containers/challenge-listing/ChallengeSearchBar'; import BucketSelector from './BucketSelector'; // import FiltersEditor from './FiltersEditor'; // import Footer from './Footer'; @@ -50,40 +51,13 @@ export default function SideBarFilters({ // updateAllSavedFilters, // updateSavedFilter, // setFilter, - previousBucketOfActiveTab, - previousBucketOfPastChallengesTab, - setPreviousBucketOfActiveTab, - setPreviousBucketOfPastChallengesTab, + setFilterState, }) { const past = isPastBucket(activeBucket); - const onActiveClick = () => { - if (!past) { - return; - } - setPreviousBucketOfPastChallengesTab(activeBucket); - if (previousBucketOfActiveTab) { - selectBucket(previousBucketOfActiveTab); - } else { - selectBucket(BUCKETS.OPEN_FOR_REGISTRATION); - } - }; - - const onPastChallengesClick = () => { - if (past) { - return; - } - setPreviousBucketOfActiveTab(activeBucket); - if (previousBucketOfPastChallengesTab) { - selectBucket(previousBucketOfPastChallengesTab); - } else { - selectBucket(BUCKETS.ALL_PAST); - } - }; - return (
-
    + {/*
    • Past Challenges
    • -
    +
*/}
+ + {/* { editSavedFiltersMode ? ( {/*
*/} +
); } @@ -158,10 +135,6 @@ SideBarFilters.defaultProps = { // hideTcLinksInFooter: false, isAuth: false, expanding: false, - previousBucketOfActiveTab: null, - previousBucketOfPastChallengesTab: null, - setPreviousBucketOfActiveTab: () => {}, - setPreviousBucketOfPastChallengesTab: () => {}, }; SideBarFilters.propTypes = { @@ -191,8 +164,5 @@ SideBarFilters.propTypes = { // updateAllSavedFilters: PT.func.isRequired, // updateSavedFilter: PT.func.isRequired, // setFilter: PT.func.isRequired, - previousBucketOfActiveTab: PT.string, - previousBucketOfPastChallengesTab: PT.string, - setPreviousBucketOfActiveTab: PT.func, - setPreviousBucketOfPastChallengesTab: PT.func, + setFilterState: PT.func.isRequired, }; diff --git a/src/shared/components/challenge-listing/Sidebar/style.scss b/src/shared/components/challenge-listing/Sidebar/style.scss index 211df578c1..563b6c3cc5 100644 --- a/src/shared/components/challenge-listing/Sidebar/style.scss +++ b/src/shared/components/challenge-listing/Sidebar/style.scss @@ -6,6 +6,10 @@ font-size: 13px; line-height: 30px; width: 100%; + background-color: $listing-filter-bg; + border-top-left-radius: 8px; + border-top-right-radius: 8px; + margin-bottom: 0; .StatusBar { display: flex; @@ -33,7 +37,6 @@ } .FilterBox { - background: $tc-white; padding: 2 * $base-unit; padding-bottom: 2 * $base-unit; border-radius: $corner-radius * 2; @@ -42,8 +45,20 @@ color: $tc-gray-10; background: $tc-gray-10; border: 0; - height: 1px; - margin: 2 * $base-unit; + height: 2px; + margin: 12px 12px 0; + } + + @include xs-to-md { + padding: 0; } } } + +hr.hr { + color: $tc-gray-10; + background: $tc-gray-10; + border: 0; + height: 2px; + margin: 0 24px; +} diff --git a/src/shared/components/challenge-listing/Tags.jsx b/src/shared/components/challenge-listing/Tags.jsx index 92acedb091..9f938ee9c3 100644 --- a/src/shared/components/challenge-listing/Tags.jsx +++ b/src/shared/components/challenge-listing/Tags.jsx @@ -13,8 +13,8 @@ import './style.scss'; const VISIBLE_TAGS = 3; /** - * Implements component - */ + * Implements component + */ export default function Tags({ expand, isExpanded, tags, onTechTagClicked, challengesUrl, recommended, verifiedTags, }) { @@ -38,33 +38,33 @@ export default function Tags({ const additionalTags = (items, verifiedTagIndex) => (
{ - items.map((item, index) => { - if (index < verifiedTagIndex) { - return ( - - ); - } - return ( - ( -
- onClick(item.trim())} - key={item} - role="button" - to={tagRedirectLink(item)} - > - {item} - -
- ) - ); - }) - } + items.map((item, index) => { + if (index < verifiedTagIndex) { + return ( + + ); + } + return ( + ( +
+ onClick(item.trim())} + key={item} + role="button" + to={tagRedirectLink(item)} + > + {item} + +
+ ) + ); + }) + }
); @@ -83,57 +83,62 @@ export default function Tags({ display.push(expandItem); } return display.map((item, index) => { - if ((recommended && index < verifiedTags.length) || item[0] === '+') { - return ( - item[0] === '+' ? ( -
- - onClick(item.trim())} - key={item} - role="button" - to={tagRedirectLink(item)} + if (item) { + if ((recommended && index < verifiedTags.length) || item[0] === '+') { + return ( + item[0] === '+' ? ( +
+ - {item} - - -
- ) - : ( - + onClick(item.trim())} + key={item} + role="button" + to={tagRedirectLink(item)} + > + {item} + +
+
) + : ( + + ) + ); + } + + return ( +
+ onClick(item.trim())} + key={item} + role="button" + to={tagRedirectLink(item)} + > + {item} + +
); } - return ( - onClick(item.trim())} - key={item} - role="button" - to={tagRedirectLink(item)} - > - {item} - - ); + return null; }); } return ''; }; return ( - + { renderTags() } ); diff --git a/src/shared/components/challenge-listing/Tooltips/ProgressBarTooltip/index.jsx b/src/shared/components/challenge-listing/Tooltips/ProgressBarTooltip/index.jsx index 65aac9c5f9..b84a76a114 100644 --- a/src/shared/components/challenge-listing/Tooltips/ProgressBarTooltip/index.jsx +++ b/src/shared/components/challenge-listing/Tooltips/ProgressBarTooltip/index.jsx @@ -57,6 +57,7 @@ function Phase({ }) { const limitProgress = parseFloat(_.replace(progress, '%', '')); const limitWidth = limitProgress <= 100 ? limitProgress : 100; + return (
@@ -191,8 +192,6 @@ function placeArrow(TooltipNode) { if (rootTopOffset < tooltipTopOffset) { toolTip.style.top = `${parseInt(toolTip.style.top, 10) - 20}px`; arrow.style.top = '-5px'; - } else { - arrow.style.top = '100%'; } } diff --git a/src/shared/components/challenge-listing/Tooltips/ProgressBarTooltip/style.scss b/src/shared/components/challenge-listing/Tooltips/ProgressBarTooltip/style.scss index 0bba737f0e..af38e9eebd 100644 --- a/src/shared/components/challenge-listing/Tooltips/ProgressBarTooltip/style.scss +++ b/src/shared/components/challenge-listing/Tooltips/ProgressBarTooltip/style.scss @@ -8,16 +8,27 @@ $tip-space-95: $base-unit * 19; $tip-radius-15: $corner-radius * 7 + 1; $tip-radius-4: $corner-radius * 2; +:global { + .rc-tooltip-arrow { + background-color: url(assets/images/tooltip-arrow.svg); + width: 30px; + height: 9px; + position: absolute; + left: 41% !important; + z-index: 10000; + bottom: 0 !important; + border: 0; + } +} + div.progress-bar-tooltip { @include roboto-regular; color: $tc-white; max-width: none; padding: 0 $base-unit * 3; - - .rc-tooltip-inner { - padding: 0 $base-unit * 3; - } + background-color: #2a2a2a !important; + border-radius: 8px; .tip { word-wrap: none; @@ -28,7 +39,7 @@ div.progress-bar-tooltip { line-height: $tip-space-15; min-width: $tip-offset; padding: $tip-space-15 0; - background: $tc-gray-80; + background: #2a2a2a; width: $tip-space-95; &:last-child { @@ -49,13 +60,17 @@ div.progress-bar-tooltip { } .inner-bar { - background: $tc-light-blue; + background: #b671d7; position: relative; border-radius: $corner-radius * 4; border: 2px solid $tc-gray-80; top: -(($tip-space-15) - 1); height: $tip-space-10 - 2; z-index: 1; + + &.red { + background: #ef476f; + } } .point { @@ -72,7 +87,11 @@ div.progress-bar-tooltip { &.started { .point { - background: $tc-light-blue; + background: #b671d7; + + &.red { + background: #ef476f; + } } } } diff --git a/src/shared/components/challenge-listing/Tooltips/TrackAbbreviationTooltip/index.jsx b/src/shared/components/challenge-listing/Tooltips/TrackAbbreviationTooltip/index.jsx index 51d2ed9f9a..9cae10edab 100644 --- a/src/shared/components/challenge-listing/Tooltips/TrackAbbreviationTooltip/index.jsx +++ b/src/shared/components/challenge-listing/Tooltips/TrackAbbreviationTooltip/index.jsx @@ -12,16 +12,16 @@ import Tooltip from 'components/Tooltip'; import './style.scss'; /** - * Renders the tooltip's content. - */ + * Renders the tooltip's content. + */ function Tip({ - track, + // track, type, }) { - const trackStyle = track.replace(' ', '-').toLowerCase(); + // const trackStyle = track.replace(' ', '-').toLowerCase(); return (
-
+
{type.name}
@@ -32,11 +32,11 @@ function Tip({ } Tip.defaultProps = { - track: 'Development', + // track: 'Development', }; Tip.propTypes = { - track: PT.string, + // track: PT.string, type: PT.shape().isRequired, }; @@ -46,8 +46,8 @@ function placeArrow(TooltipNode) { } /** - * Renders the tooltip. - */ + * Renders the tooltip. + */ function TrackAbbreviationTooltip({ children, track, diff --git a/src/shared/components/challenge-listing/Tooltips/TrackAbbreviationTooltip/style.scss b/src/shared/components/challenge-listing/Tooltips/TrackAbbreviationTooltip/style.scss index f73e9db228..2b63ad202d 100644 --- a/src/shared/components/challenge-listing/Tooltips/TrackAbbreviationTooltip/style.scss +++ b/src/shared/components/challenge-listing/Tooltips/TrackAbbreviationTooltip/style.scss @@ -8,32 +8,26 @@ $track-radius-4: $corner-radius * 2; min-width: $base-unit * 45; max-width: $base-unit * 60; line-height: $track-space-20 - 2; - padding: 15px; + padding: 10px; + border-radius: 8px; + background-color: #2a2a2a; .header { - font-weight: 700; - padding-left: $base-unit * 2; - - &.design { - border-left: $track-radius-4 solid $tc-light-blue; - } - - &.development { - border-left: $track-radius-4 solid $tc-green; - } - - &.data-science { - border-left: $track-radius-4 solid $tc-orange; - } - - &.quality-assurance { - border-left: $track-radius-4 solid $tc-purple-120; - } + font-weight: 500; + font-size: 14px; + line-height: 16px; + margin-top: 5px; } .body { - font-weight: 300; - margin-top: $base-unit + 1; - color: $tc-gray-20; + font-weight: 400; + color: $tc-white; + font-size: 14px; + line-height: 22px; + text-transform: lowercase; + } + + .body::first-letter { + text-transform: capitalize; } } diff --git a/src/shared/components/challenge-listing/Tooltips/UserAvatarTooltip/style.scss b/src/shared/components/challenge-listing/Tooltips/UserAvatarTooltip/style.scss index a07f0b1fab..30d06a70b8 100644 --- a/src/shared/components/challenge-listing/Tooltips/UserAvatarTooltip/style.scss +++ b/src/shared/components/challenge-listing/Tooltips/UserAvatarTooltip/style.scss @@ -15,7 +15,9 @@ $avatar-radius-4: $corner-radius * 2; align-items: center; max-width: 640px; overflow: auto; - padding: 15px; + padding: 10px; + background-color: #2a2a2a; + border-radius: 8px; .achievements { border-top: 1px solid $tc-gray-70; @@ -47,18 +49,21 @@ $avatar-radius-4: $corner-radius * 2; .avatar { border-radius: $avatar-radius-50; - width: $base-unit * 10; - height: $base-unit * 10; + width: 32px; + height: 32px; overflow: hidden; + background-color: $listing-avatar-white; } .handle { + @include roboto-regular; + margin-left: $avatar-space-15; display: inline-block; font-weight: 500; - font-size: 20px; - color: $tc-level-4; - line-height: $base-unit * 6; + font-size: 11px; + color: $listing-white; + line-height: 14px; text-shadow: none; } diff --git a/src/shared/components/challenge-listing/VerifiedTag/style.scss b/src/shared/components/challenge-listing/VerifiedTag/style.scss index 113864c000..0cf25d5af2 100644 --- a/src/shared/components/challenge-listing/VerifiedTag/style.scss +++ b/src/shared/components/challenge-listing/VerifiedTag/style.scss @@ -2,13 +2,21 @@ .recommended-challenge-tooltip { display: inline-block; - margin: 3px 0 0 3px; + white-space: nowrap; + margin-bottom: 5px; } .tctooltiptext { - background: $tc-white; - color: $tc-gray-90; - border-radius: 3px; + @include roboto-regular; + + background: $tc-black; + display: inline-block; + max-width: 400px; + font-size: 14px; + color: $tc-white; + line-height: 22px; + font-weight: 500; + border-radius: 8px; padding: 10px; } @@ -23,7 +31,7 @@ margin-left: -5px; border-width: 5px 5px 0; left: 50%; - border-top-color: $tc-white; + border-top-color: $tc-black; z-index: 1000; } diff --git a/src/shared/components/challenge-listing/index.jsx b/src/shared/components/challenge-listing/index.jsx index bc3bf94b7f..9200762e64 100644 --- a/src/shared/components/challenge-listing/index.jsx +++ b/src/shared/components/challenge-listing/index.jsx @@ -5,7 +5,6 @@ // import _ from 'lodash'; import FilterPanel from 'containers/challenge-listing/FilterPanel'; -import ChallengeSearchBar from 'containers/challenge-listing/ChallengeSearchBar'; // import moment from 'moment'; import React from 'react'; import PT from 'prop-types'; @@ -17,7 +16,7 @@ import { useMediaQuery } from 'react-responsive'; import Listing from './Listing'; // import ChallengeCardPlaceholder from './placeholders/ChallengeCard'; -import Banner from './Banner'; +import ChallengeTab from './ChallengeTab'; import './style.scss'; @@ -41,7 +40,7 @@ export default function ChallengeListing(props) { defaultCommunityId, expanding, // extraBucket, - filterState, + // filterState, hideSrm, // hideTcLinksInFooter, keepPastPlaceholders, @@ -50,6 +49,11 @@ export default function ChallengeListing(props) { // isBucketSwitching, isLoggedIn, setSearchText, + selectBucket, + setPreviousBucketOfActiveTab, + setPreviousBucketOfPastChallengesTab, + previousBucketOfPastChallengesTab, + previousBucketOfActiveTab, } = props; // const { challenges } = props; @@ -152,22 +156,24 @@ export default function ChallengeListing(props) { return (
- { - filterState.recommended && activeBucket === 'openForRegistration' - ? null - : ( - - ) - } - +

CHALLENGES

+
+ +
(
-
+
diff --git a/src/shared/components/challenge-listing/style.scss b/src/shared/components/challenge-listing/style.scss index 3e312335dd..bdf577c037 100644 --- a/src/shared/components/challenge-listing/style.scss +++ b/src/shared/components/challenge-listing/style.scss @@ -18,12 +18,43 @@ $challenge-radius-4: $corner-radius * 2; // } .ChallengeFiltersExample { - background: $tc-gray-neutral-dark; + background: $tc-white; flex: 1; + margin: 0 32px; + + @include xs-to-md { + margin: 0; + } + + .tc-title { + @include barlow-condensed; + + color: $tco-black; + font-size: 32px; + margin: 32px 0 24px 0; + line-height: 32px; + font-weight: 600; + text-transform: uppercase; + + @include xs-to-md { + margin: 16px; + } + } + + .tc-seperator { + background-color: $listing-gray; + height: 2px; + opacity: 0.5; + margin: 0; + + @include xs-to-md { + margin: 0 16px; + } + } .tc-content-wrapper { display: flex; - padding: $challenge-space-10; + padding: 0; @include xs-to-md { display: block; @@ -71,26 +102,28 @@ $challenge-radius-4: $corner-radius * 2; .sidebar-container-mobile { margin: $challenge-space-20 $challenge-space-10 $challenge-space-10; display: none; + background-color: $listing-filter-bg; + border-radius: 8px; @include xs-to-md { display: block; - margin: 0; padding: $challenge-space-10; - width: 100%; + padding: 0; + margin-top: 24px; + margin-bottom: 16px; + margin-left: 16px; + margin-right: 16px; + padding-bottom: 16px; } } .sidebar-container-desktop { - margin: $challenge-space-20 $challenge-space-5 $challenge-space-10; - width: 30%; + margin: 35px 0 10px; + width: 23.5%; @include xs-to-md { display: none; } - - > * + * { - margin-top: 12px; - } } .hidden { @@ -98,18 +131,39 @@ $challenge-radius-4: $corner-radius * 2; } } +.tag { + button { + border-radius: 2px; + max-width: 400px; + font-size: 11px; + color: $tco-black; + font-weight: 500; + + &:hover { + background-color: #d4d4d4 !important; + } + } +} + .recommended-plus-tag { margin-left: 3px; display: inline-block; background-color: $tc-white; + + button:hover { + background-color: #d4d4d4 !important; + } } .additionalTagWrapper { - background: $tc-white; + background: $tc-black; display: inline-block; - border-radius: 3px; - padding: 5px 5px 10px 5px; + border-radius: 8px; + padding: 10px; max-width: 400px; + font-size: 11px; + color: $tco-black; + font-weight: 500; } .additionalTagWrapper::after { @@ -123,7 +177,7 @@ $challenge-radius-4: $corner-radius * 2; margin-left: -5px; border-width: 5px 5px 0; left: 50%; - border-top-color: $tc-white; + border-top-color: $tc-black; z-index: 1000; } @@ -131,4 +185,14 @@ $challenge-radius-4: $corner-radius * 2; margin-top: 5px; margin-left: 3px; display: inline-block; + + & > button:hover { + background-color: #d4d4d4 !important; + } +} + +.tagContainer { + display: flex; + margin-top: -2px; + flex-wrap: wrap; } diff --git a/src/shared/components/tco/scoreboard/Header/style.scss b/src/shared/components/tco/scoreboard/Header/style.scss index 5dcc984213..6fb22b5fbb 100644 --- a/src/shared/components/tco/scoreboard/Header/style.scss +++ b/src/shared/components/tco/scoreboard/Header/style.scss @@ -227,10 +227,10 @@ .bonus-div { @include roboto-regular; - text-align: center; + text-align: left; color: $tc-black; line-height: 25px; - margin: 25px 15px 0; + margin: 25px 25px 0; padding-bottom: 20px; .bonus-text { diff --git a/src/shared/containers/Profile.jsx b/src/shared/containers/Profile.jsx index 0e5704037a..fbfade7a9a 100644 --- a/src/shared/containers/Profile.jsx +++ b/src/shared/containers/Profile.jsx @@ -7,22 +7,31 @@ import PT from 'prop-types'; import { connect } from 'react-redux'; import { config } from 'topcoder-react-utils'; import { actions } from 'topcoder-react-lib'; +import shortId from 'shortid'; import MetaTags from 'components/MetaTags'; import Error404 from 'components/Error404'; import LoadingIndicator from 'components/LoadingIndicator'; import ProfilePage from 'components/ProfilePage'; import { loadPublicStatsOnly } from 'utils/memberStats'; +// how many challenges to query per batch +const CHALLENGE_PER_PAGE = 36; + class ProfileContainer extends React.Component { componentDidMount() { const { handleParam, loadProfile, + loadMarathon, meta, auth, + info, } = this.props; loadProfile(handleParam, _.get(meta, 'groupIds', []), auth.tokenV3, loadPublicStatsOnly(meta)); + if (info) { + loadMarathon(handleParam, auth.tokenV3, info.userId); + } // Redirect to the communities own profile page if // - the member whose profile is being viewed is part of one of the configured communities // - the user is not a topcoder user (has an email with @topcoder.com) @@ -53,6 +62,7 @@ class ProfileContainer extends React.Component { handleParam, profileForHandle, loadProfile, + loadMarathon, loadMemberGroups, meta, auth, @@ -69,6 +79,9 @@ class ProfileContainer extends React.Component { loadProfile(handleParam, _.get(meta, 'groupIds', []), auth.tokenV3, loadPublicStatsOnly(meta)); } + if (info && info.userId && info !== prevInfo) { + loadMarathon(handleParam, auth.tokenV3, info.userId); + } if (auth.tokenV3 && auth.user && auth.user.handle !== handleParam && info != null && info.userId != null && (prevInfo == null || info.userId !== prevInfo.userId)) { @@ -158,6 +171,7 @@ ProfileContainer.propTypes = { handleParam: PT.string.isRequired, info: PT.shape(), loadingError: PT.bool.isRequired, + loadMarathon: PT.bool.isRequired, loadProfile: PT.func.isRequired, loadMemberGroups: PT.func.isRequired, profileForHandle: PT.string, @@ -170,6 +184,8 @@ ProfileContainer.propTypes = { }; const mapStateToProps = (state, ownProps) => ({ + challenges: state.members[ownProps.match.params.handle] + ? state.members[ownProps.match.params.handle].subtrackChallenges : null, achievements: state.profile.achievements, copilot: state.profile.copilot, country: state.profile.country, @@ -192,6 +208,7 @@ const mapStateToProps = (state, ownProps) => ({ function mapDispatchToProps(dispatch) { const a = actions.profile; const lookupActions = actions.lookup; + const memberActions = actions.members; return { loadMemberGroups: (userId, tokenV3) => { dispatch(actions.groups.getMemberGroups(userId, tokenV3)); @@ -214,6 +231,19 @@ function mapDispatchToProps(dispatch) { dispatch(a.getStatsDone(handle, showPublicStats ? undefined : groupIds, tokenV3)); dispatch(lookupActions.getCountriesDone()); }, + loadMarathon: (handle, tokenV3, memberId) => { + const uuid = shortId(); + dispatch(memberActions.getUserMarathonInit(handle, uuid)); + dispatch(memberActions.getUserMarathonDone( + uuid, + handle, + memberId, + tokenV3, + 1, + CHALLENGE_PER_PAGE, + true, + )); + }, }; } diff --git a/src/shared/containers/SubmissionManagement/index.jsx b/src/shared/containers/SubmissionManagement/index.jsx index 0e7869781d..32567de682 100644 --- a/src/shared/containers/SubmissionManagement/index.jsx +++ b/src/shared/containers/SubmissionManagement/index.jsx @@ -7,17 +7,16 @@ import _ from 'lodash'; import AccessDenied, { CAUSE as ACCESS_DENIED_REASON } from 'components/tc-communities/AccessDenied'; -import Button from 'components/Button'; import LoadingIndicator from 'components/LoadingIndicator'; import SubmissionManagement from 'components/SubmissionManagement/SubmissionManagement'; import React from 'react'; import PT from 'prop-types'; import { connect } from 'react-redux'; -import { Modal } from 'topcoder-react-ui-kit'; +import { Modal, PrimaryButton } from 'topcoder-react-ui-kit'; import { config } from 'topcoder-react-utils'; import { actions, services } from 'topcoder-react-lib'; -import './styles.scss'; +import style from './styles.scss'; import smpActions from '../../actions/page/submission_management'; const { getService } = services.submissions; @@ -140,14 +139,18 @@ class SubmissionManagementPageContainer extends React.Component { className={deleting ? 'hidden' : ''} styleName="action-btns" > - - +
diff --git a/src/shared/containers/SubmissionManagement/styles.scss b/src/shared/containers/SubmissionManagement/styles.scss index 8694334619..e6a39bbf6e 100644 --- a/src/shared/containers/SubmissionManagement/styles.scss +++ b/src/shared/containers/SubmissionManagement/styles.scss @@ -7,6 +7,7 @@ $sm-space-40: $base-unit * 8; .outer-container { background: $tc-gray-10; padding: 24px; + width: 100%; @include xs-to-sm { padding: 15px; @@ -28,10 +29,46 @@ $sm-space-40: $base-unit * 8; margin: auto; } +.add-sub-btn { + @include roboto-bold; + + font-weight: 700; + font-size: 16px; + line-height: 24px; + border-radius: 50px !important; + background: #137d60 !important; + color: #fff !important; + text-transform: uppercase; + + @include xs-to-md { + font-size: 14px; + line-height: 20px; + } +} + +.add-sub-btn-warning { + @include roboto-bold; + + font-weight: 700; + font-size: 16px; + line-height: 24px; + border-radius: 50px !important; + background: $tc-red-70 !important; + color: #fff !important; + text-transform: uppercase; + + @include xs-to-md { + font-size: 14px; + line-height: 20px; + } +} + .modal-content { @include roboto-regular; text-align: center; + border-radius: 8px; + padding: 20px 0; .are-you-sure { font-weight: 400; diff --git a/src/shared/containers/challenge-detail/index.jsx b/src/shared/containers/challenge-detail/index.jsx index 7fc42608f6..2099b921bf 100644 --- a/src/shared/containers/challenge-detail/index.jsx +++ b/src/shared/containers/challenge-detail/index.jsx @@ -481,6 +481,13 @@ class ChallengeDetailPageContainer extends React.Component { submissionEnded={submissionEnded} mySubmissions={challenge.isRegistered ? mySubmissions : []} openForRegistrationChallenges={openForRegistrationChallenges} + onSort={(currenctSelected, sort) => { + if (currenctSelected === 'submissions') { + this.setState({ submissionsSort: sort }); + } else { + this.setState({ registrantsSort: sort }); + } + }} /> ) } @@ -553,7 +560,9 @@ class ChallengeDetailPageContainer extends React.Component { notFoundCountryFlagUrl[countryInfo.countryCode] = true; this.setState({ notFoundCountryFlagUrl }); }} - onSortChange={sort => this.setState({ submissionsSort: sort })} + onSortChange={(sort) => { + this.setState({ submissionsSort: sort }); + }} hasRegistered={challenge.isRegistered} unregistering={unregistering} isLegacyMM={isLegacyMM} diff --git a/src/shared/containers/challenge-detail/styles.scss b/src/shared/containers/challenge-detail/styles.scss index 5f75cc5054..0c56b4f92d 100644 --- a/src/shared/containers/challenge-detail/styles.scss +++ b/src/shared/containers/challenge-detail/styles.scss @@ -5,7 +5,7 @@ width: 100%; @include xs-to-sm { - padding: 8px 10px 20px; + padding: 0; } @include md { @@ -13,14 +13,13 @@ } @include lg-to-xl { - padding: 30px 64px; + padding: 0; } } .challenge-detail-container { background: $tc-white; border-radius: 3 * $corner-radius; - max-width: 1240px; width: 100%; margin: auto; } diff --git a/src/shared/containers/challenge-listing/ChallengeSearchBar.jsx b/src/shared/containers/challenge-listing/ChallengeSearchBar.jsx index 254d144973..31b5220630 100644 --- a/src/shared/containers/challenge-listing/ChallengeSearchBar.jsx +++ b/src/shared/containers/challenge-listing/ChallengeSearchBar.jsx @@ -7,7 +7,7 @@ import challengeListingActions from 'actions/challenge-listing'; import ChallengeSearchBar from 'components/challenge-listing/Filters/ChallengeSearchBar'; import PT from 'prop-types'; import React from 'react'; -import { isReviewOpportunitiesBucket } from 'utils/challenge-listing/buckets'; +import { isReviewOpportunitiesBucket, isPastBucket } from 'utils/challenge-listing/buckets'; import { connect } from 'react-redux'; import _ from 'lodash'; @@ -34,6 +34,7 @@ export class Container extends React.Component { } = this.props; const isForReviewOpportunities = isReviewOpportunitiesBucket(activeBucket); + const searchPlaceholderText = isPastBucket(activeBucket) ? 'Search Past Challenges' : 'Search Active Challenges'; return ( ); diff --git a/src/shared/containers/challenge-listing/Listing/index.jsx b/src/shared/containers/challenge-listing/Listing/index.jsx index 9750569253..d7f8bc97b6 100644 --- a/src/shared/containers/challenge-listing/Listing/index.jsx +++ b/src/shared/containers/challenge-listing/Listing/index.jsx @@ -40,6 +40,15 @@ const { mapToBackend } = challengeUtils.filter; let mounted = false; export class ListingContainer extends React.Component { + constructor(props) { + super(props); + + this.state = { + previousBucketOfActiveTab: null, + previousBucketOfPastChallengesTab: null, + }; + } + componentDidMount() { const { activeBucket, @@ -63,7 +72,7 @@ export class ListingContainer extends React.Component { } if (!communitiesList.loadingUuid - && (Date.now() - communitiesList.timestamp > USER_GROUP_MAXAGE)) { + && (Date.now() - communitiesList.timestamp > USER_GROUP_MAXAGE)) { getCommunitiesList(auth); } @@ -75,7 +84,9 @@ export class ListingContainer extends React.Component { if (mounted) { logger.error('Attempt to mount multiple instances of ChallengeListingPageContainer at the same time!'); - } else mounted = true; + } else { + mounted = true; + } // if (BUCKETS.PAST !== activeBucket) { // dropChallenges(); @@ -86,7 +97,11 @@ export class ListingContainer extends React.Component { const groups = selectedCommunity.groupIds && selectedCommunity.groupIds.length ? [selectedCommunity.groupIds[0]] : []; // update the challenge listing filter for selected community - setFilter({ ..._.clone(filter), groups, events: [] }); + setFilter({ + ..._.clone(filter), + groups, + events: [], + }); } // } } @@ -144,8 +159,16 @@ export class ListingContainer extends React.Component { const f = this.getBackendFilter(); const fA = { - back: { ..._.clone(f.back), startDateEnd: null, endDateStart: null }, - front: { ..._.clone(f.front), startDateEnd: null, endDateStart: null }, + back: { + ..._.clone(f.back), + startDateEnd: null, + endDateStart: null, + }, + front: { + ..._.clone(f.front), + startDateEnd: null, + endDateStart: null, + }, }; if (prevProps.filterState.recommended !== filterState.recommended && filterState.recommended) { @@ -241,8 +264,9 @@ export class ListingContainer extends React.Component { } componentWillUnmount() { - if (mounted) mounted = false; - else { + if (mounted) { + mounted = false; + } else { logger.error('A mounted instance of ChallengeListingPageContainer is not tracked as mounted!'); } if (this.autoRefreshTimerId) clearTimeout(this.autoRefreshTimerId); @@ -470,6 +494,11 @@ export class ListingContainer extends React.Component { filterState, } = this.props; + const { + previousBucketOfActiveTab, + previousBucketOfPastChallengesTab, + } = this.state; + const { tokenV3 } = auth; const handle = _.get(auth, 'user.handle'); @@ -642,6 +671,14 @@ export class ListingContainer extends React.Component { isLoggedIn={isLoggedIn} meta={meta} setSearchText={setSearchText} + previousBucketOfActiveTab={previousBucketOfActiveTab} + previousBucketOfPastChallengesTab={previousBucketOfPastChallengesTab} + setPreviousBucketOfActiveTab={(bucket) => { + this.setState({ previousBucketOfActiveTab: bucket }); + }} + setPreviousBucketOfPastChallengesTab={(bucket) => { + this.setState({ previousBucketOfPastChallengesTab: bucket }); + }} />
); diff --git a/src/shared/utils/challenge-detail/helper.jsx b/src/shared/utils/challenge-detail/helper.jsx index 562f91f066..c307e5f66a 100644 --- a/src/shared/utils/challenge-detail/helper.jsx +++ b/src/shared/utils/challenge-detail/helper.jsx @@ -76,7 +76,7 @@ export function getTimeLeft( else format = 'm[min] s[s]'; time = moment.duration(time).format(format); - time = late ? `Late by ${time}` : `${time} ${toGoText}`; + time = late ? `${time} Past Due` : `${time} ${toGoText}`; return { late, text: time }; } @@ -222,3 +222,31 @@ export function getDisplayRecommendedChallenges( } export default getEndDate; + +/** + * Format number to ordinals. + * @param {Number} n + */ +export const formatOrdinals = (n) => { + let ord = ''; + switch (n) { + case '1': ord = '1st'; + break; + case '2': ord = '2nd'; + break; + case '3': ord = '3rd'; + break; + default: + ord = `${n}th`; + } + + return ord; +}; + +/** + * Format number to currency format. + * @param {Number} n + */ +export function numberWithCommas(x) { + return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); +} diff --git a/src/shared/utils/challenge-listing/buckets.js b/src/shared/utils/challenge-listing/buckets.js index 55883e82a0..31ed78007a 100644 --- a/src/shared/utils/challenge-listing/buckets.js +++ b/src/shared/utils/challenge-listing/buckets.js @@ -56,7 +56,7 @@ export const BUCKET_DATA = { // status: ['Active'], // }, // hideCount: false, - name: 'Open for registration', + name: 'Open for Registration', sorts: [ // SORTS.BEST_MATCH, SORTS.MOST_RECENT_START_DATE, @@ -109,7 +109,7 @@ export const BUCKET_DATA = { [BUCKETS.REVIEW_OPPORTUNITIES]: { filter: {}, // hideCount: true, - name: 'Open for review', + name: 'Open for Review', sorts: [ SORTS.REVIEW_OPPORTUNITIES_START_DATE, SORTS.REVIEW_OPPORTUNITIES_PAYMENT, @@ -141,15 +141,15 @@ export const BUCKET_DATA = { }; export const NO_LIVE_CHALLENGES_CONFIG = { - [BUCKETS.ALL]: 'No Live Challenges found in All Challenges', - [BUCKETS.MY]: 'No challenges found in My Challenges', - [BUCKETS.OPEN_FOR_REGISTRATION]: 'No challenges found in Open for Registration Challenges', - [BUCKETS.ONGOING]: 'No challenges found in Ongoing Challenges', + [BUCKETS.ALL]: 'No Live Challenges found', + [BUCKETS.MY]: 'No challenges found', + [BUCKETS.OPEN_FOR_REGISTRATION]: 'No challenges found', + [BUCKETS.ONGOING]: 'No challenges found', // [BUCKETS.PAST]: 'No challenges found in Past Challenges', // [BUCKETS.SAVED_FILTER]: 'No challenges found in Saved filter Challenges', // [BUCKETS.UPCOMING]: 'No challenges found in Upcoming Challenges', - [BUCKETS.ALL_PAST]: 'No challenges found in All Past Challenges', - [BUCKETS.MY_PAST]: 'No challenges found in My Past Challenges', + [BUCKETS.ALL_PAST]: 'No challenges found', + [BUCKETS.MY_PAST]: 'No challenges found', }; /** diff --git a/src/shared/utils/challenge-listing/date-range.js b/src/shared/utils/challenge-listing/date-range.js index ead001ec34..fcf923e53a 100644 --- a/src/shared/utils/challenge-listing/date-range.js +++ b/src/shared/utils/challenge-listing/date-range.js @@ -33,19 +33,13 @@ export function createStaticRanges() { endDate: now.clone().endOf('day').toDate(), }, { - label: 'Past 6 Months', - startDate: past6Months.startOf('day').toDate(), + label: 'Past 3 Months', + startDate: past3Months.startOf('day').toDate(), endDate: now.clone().endOf('day').toDate(), }, { - label: 'Custom Date', - startDate: null, - endDate: null, - isCustom: true, - }, - { - label: 'Past 3 Month', - startDate: past3Months.startOf('day').toDate(), + label: 'Past 6 Months', + startDate: past6Months.startOf('day').toDate(), endDate: now.clone().endOf('day').toDate(), }, { @@ -53,7 +47,12 @@ export function createStaticRanges() { startDate: pastYear.startOf('day').toDate(), endDate: now.clone().endOf('day').toDate(), }, - + { + label: 'Custom Date', + startDate: null, + endDate: null, + isCustom: true, + }, ]; return ranges.map(range => ({ ...staticRangeHandler, ...range })); diff --git a/src/shared/utils/challenge-listing/helper.js b/src/shared/utils/challenge-listing/helper.js index df0df26fe2..edef24bfec 100644 --- a/src/shared/utils/challenge-listing/helper.js +++ b/src/shared/utils/challenge-listing/helper.js @@ -41,3 +41,24 @@ export function phaseStartDate(phase) { export function calculateScore(score) { return Math.ceil(parseFloat(score) * 100.0); } + +/** + * Format number to ordinals. + * @param {Number} n + */ +export const formatOrdinals = (n) => { + let ord = ''; + const place = String(n); + switch (place) { + case '1': ord = '1st'; + break; + case '2': ord = '2nd'; + break; + case '3': ord = '3rd'; + break; + default: + ord = `${n}th`; + } + + return ord; +}; diff --git a/src/styles/_mixins/_variables.scss b/src/styles/_mixins/_variables.scss index e41271f4f1..33656d5a95 100644 --- a/src/styles/_mixins/_variables.scss +++ b/src/styles/_mixins/_variables.scss @@ -27,3 +27,14 @@ $dashboard-light-blue: #67aed6; $dashboard-blue: #009dce; $dashboard-border: #c4c4c4; $dashboard-text: #adadad; + +/* challenge listing colors */ +$listing-gray: #e5e5e5; +$listing-light-gray: #d4d4d4; +$listing-light-blue: #eaf6fd; +$listing-filter-bg: #f4f4f4; +$listing-placeholder-gray: #767676; +$listing-checkbox-green: #137d60; +$listing-checkbox-blue: #2c95d7; +$listing-white: #fff; +$listing-avatar-white: #f0f0f0;