diff --git a/src/shared/actions/challenge-listing/index.js b/src/shared/actions/challenge-listing/index.js
index 1971fead28..a33623e9b7 100644
--- a/src/shared/actions/challenge-listing/index.js
+++ b/src/shared/actions/challenge-listing/index.js
@@ -339,7 +339,7 @@ function getUserChallengesInit(uuid) {
function getUserChallengesDone(userId, tokenV3) {
const service = getService(tokenV3);
- return service.getUserResources(userId)
+ return service.getUserResources(userId, 1, 10000)
.then(item => item)
.catch((error) => {
fireErrorMessage('Error Getting User Challenges', error.content || error);
diff --git a/src/shared/components/challenge-detail/Header/DeadlinesPanel/index.jsx b/src/shared/components/challenge-detail/Header/DeadlinesPanel/index.jsx
index fdf53200d5..cd8abc1e5c 100644
--- a/src/shared/components/challenge-detail/Header/DeadlinesPanel/index.jsx
+++ b/src/shared/components/challenge-detail/Header/DeadlinesPanel/index.jsx
@@ -6,14 +6,15 @@ import moment from 'moment-timezone';
import PT from 'prop-types';
import React from 'react';
+import { phaseEndDate, phaseStartDate } from 'utils/challenge-listing/helper';
import Card from './Card';
import './style.scss';
export default function DeadlinesPanel({ deadlines }) {
/* Calculates challenge start time. */
let start = deadlines[0] || {};
- start = start.actualStartDate || start.scheduledStartDate;
- const started = moment(start).isBefore(moment());
+ start = phaseStartDate(start);
+ const started = moment(start).isBefore();
return (
@@ -29,7 +30,7 @@ export default function DeadlinesPanel({ deadlines }) {
{ deadlines.map((d, index) => (
))}
diff --git a/src/shared/components/challenge-detail/Header/index.jsx b/src/shared/components/challenge-detail/Header/index.jsx
index 0a6594ea8f..fe2c2d47c7 100644
--- a/src/shared/components/challenge-detail/Header/index.jsx
+++ b/src/shared/components/challenge-detail/Header/index.jsx
@@ -15,6 +15,7 @@ import React from 'react';
import { DangerButton, 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';
import LeftArrow from 'assets/images/arrow-prev.svg';
@@ -69,16 +70,17 @@ export default function ChallengeHeader(props) {
numOfRegistrants,
numOfCheckpointSubmissions,
numOfSubmissions,
- endDate,
status,
type,
track,
} = challenge;
const tags = challenge.tags || [];
- const appealsEndDate = endDate;
const allPhases = challenge.phases || [];
+ const sortedAllPhases = _.cloneDeep(allPhases)
+ .sort((a, b) => moment(phaseEndDate(a)).diff(phaseEndDate(b)));
+
const { prizes } = prizeSets && prizeSets.length ? prizeSets[0] : [];
const checkpointPrizes = _.find(prizeSets, { type: 'checkpoint' });
@@ -122,14 +124,14 @@ export default function ChallengeHeader(props) {
*/
const hasSubmissions = !_.isEmpty(mySubmissions);
- let nextPhase = allPhases.filter(p => p.isOpen)
- .sort((a, b) => moment(a.scheduledEndDate).diff(b.scheduledEndDate))[0];
- if (hasRegistered && allPhases[0] && allPhases[0].name === 'Registration') {
- nextPhase = allPhases[1] || {};
+ const openPhases = sortedAllPhases.filter(p => p.isOpen);
+ let nextPhase = openPhases[0];
+ if (hasRegistered && openPhases[0] && openPhases[0].name === 'Registration') {
+ nextPhase = openPhases[1] || {};
}
const nextDeadline = nextPhase && nextPhase.name;
- const deadlineEnd = moment(nextPhase && nextPhase.scheduledEndDate);
+ const deadlineEnd = moment(nextPhase && phaseEndDate(nextPhase));
const currentTime = moment();
let timeLeft = deadlineEnd.isAfter(currentTime)
@@ -147,8 +149,8 @@ export default function ChallengeHeader(props) {
if (showDeadlineDetail) {
relevantPhases = (allPhases || []).filter((phase) => {
if (phase.name === 'Iterative Review') {
- const end = phase.actualEndDate || phase.scheduledEndDate;
- return moment(end).isAfter(moment());
+ const end = phaseEndDate(phase);
+ return moment(end).isAfter();
}
const phaseLowerCase = phase.name.toLowerCase();
if (phaseLowerCase.includes('screening') || phaseLowerCase.includes('specification')) {
@@ -168,30 +170,34 @@ export default function ChallengeHeader(props) {
if (b.name.toLowerCase().includes('registration')) {
return 1;
}
- return (new Date(a.scheduledEndDate || a.actualEndDate)).getTime()
- - (new Date(b.scheduledEndDate || b.actualEndDate)).getTime();
+ const aEndDate = phaseEndDate(a);
+ const bEndDate = phaseEndDate(b);
+ return moment(aEndDate).diff(bEndDate);
});
if (type === 'First2Finish' && status === 'Completed') {
const phases2 = allPhases.filter(p => p.name === 'Iterative Review' && !p.isOpen);
- const endPhaseDate = Math.max(...phases2.map(d => new Date(d.scheduledEndDate)));
+ const endPhaseDate = Math.max(...phases2.map(d => phaseEndDate(d)));
relevantPhases = _.filter(relevantPhases, p => (p.name.toLowerCase().includes('registration')
- || new Date(p.scheduledEndDate).getTime() < endPhaseDate));
+ || phaseEndDate(p).getTime() < endPhaseDate));
relevantPhases.push({
id: -1,
name: 'Winners',
+ isOpen: false,
+ actualEndDate: endPhaseDate,
scheduledEndDate: endPhaseDate,
});
} else if (relevantPhases.length > 1) {
const lastPhase = relevantPhases[relevantPhases.length - 1];
- const lastPhaseTime = (
- new Date(lastPhase.actualEndDate || lastPhase.scheduledEndDate)
- ).getTime();
+ const lastPhaseTime = phaseEndDate(lastPhase).getTime();
- const appealsEnd = (new Date(appealsEndDate).getTime());
- if (lastPhaseTime < appealsEnd && lastPhase.name !== 'Review') {
+ const appealsEndDate = phaseEndDate(sortedAllPhases[sortedAllPhases.length - 1]);
+ const appealsEnd = appealsEndDate.getTime();
+ if (lastPhaseTime < appealsEnd) {
relevantPhases.push({
id: -1,
name: 'Winners',
+ isOpen: false,
+ actualEndDate: appealsEndDate,
scheduledEndDate: appealsEndDate,
});
}
@@ -495,7 +501,6 @@ ChallengeHeader.propTypes = {
numOfCheckpointSubmissions: PT.any,
numOfSubmissions: PT.any,
status: PT.any,
- endDate: PT.any,
phases: PT.any,
roundId: PT.any,
prizeSets: PT.any,
diff --git a/src/shared/utils/challenge-listing/helper.js b/src/shared/utils/challenge-listing/helper.js
index 192dafcc04..765fed8af0 100644
--- a/src/shared/utils/challenge-listing/helper.js
+++ b/src/shared/utils/challenge-listing/helper.js
@@ -9,7 +9,11 @@ export function phaseEndDate(phase) {
// Case 1: phase is still open. take the `scheduledEndDate`
// Case 2: phase is not open but `scheduledStartDate` is a future date.
// This means phase is not yet started. So take the `scheduledEndDate`
- if (phase.isOpen || moment(phase.scheduledStartDate).isAfter()) {
+ // Case 3: phase is not open & `scheduledStartDate` is a past date,
+ // but the phase is `Iterative Review`. It will take the `scheduledEndDate`
+ // as it's a valid scenario for iterative review,
+ // there might not be any submission yet to open the phase
+ if (phase.isOpen || moment(phase.scheduledStartDate).isAfter() || phase.name === 'Iterative Review') {
return new Date(phase.scheduledEndDate);
}
// for other cases, take the `actualEndDate` as phase is already closed