diff --git a/src/components/ChallengeEditor/ChallengeReviewer-Field/AiReviewerTab/utils.js b/src/components/ChallengeEditor/ChallengeReviewer-Field/AiReviewerTab/utils.js index a9b2b134..9fd84ab9 100644 --- a/src/components/ChallengeEditor/ChallengeReviewer-Field/AiReviewerTab/utils.js +++ b/src/components/ChallengeEditor/ChallengeReviewer-Field/AiReviewerTab/utils.js @@ -4,3 +4,7 @@ export const isAIReviewer = (reviewer) => { (reviewer.isMemberReview === false) ) } + +export const hasAiReviewers = (reviewers) => { + return Array.isArray(reviewers) && reviewers.some(isAIReviewer) +} diff --git a/src/components/ChallengeEditor/ChallengeView/index.js b/src/components/ChallengeEditor/ChallengeView/index.js index 8637bd6a..97764ef9 100644 --- a/src/components/ChallengeEditor/ChallengeView/index.js +++ b/src/components/ChallengeEditor/ChallengeView/index.js @@ -26,9 +26,11 @@ import { DEV_TRACK_ID, MARATHON_TYPE_ID, CHALLENGE_TYPE_ID, - COMMUNITY_APP_URL + COMMUNITY_APP_URL, + AI_SCREENING_PHASE_NAME } from '../../../config/constants' import PhaseInput from '../../PhaseInput' +import { hasAiReviewers } from '../ChallengeReviewer-Field/AiReviewerTab/utils' import CheckpointPrizesField from '../CheckpointPrizes-Field' import { isBetaMode } from '../../../util/localstorage' import WiproAllowedField from '../WiproAllowedField' @@ -224,21 +226,41 @@ const ChallengeView = ({ { - challenge.legacy.subTrack === 'WEB_DESIGNS' && challenge.phases.length === 8 ? phases.map((phase, index) => ( - - )) : _.sortBy(phases, ['scheduledEndDate']).map((phase, index) => ( - - )) + (() => { + const phaseList = challenge.legacy.subTrack === 'WEB_DESIGNS' && challenge.phases.length === 8 + ? phases + : _.sortBy(phases, ['scheduledEndDate']) + const hasRealAiScreeningPhase = phaseList.some(p => p.name === AI_SCREENING_PHASE_NAME) + const showVirtualAiScreening = hasAiReviewers(challenge.reviewers) && !hasRealAiScreeningPhase + const submissionIndex = phaseList.findIndex(p => p.name === 'Submission') + return ( + <> + {phaseList.map((phase, index) => ( + + + {showVirtualAiScreening && index === submissionIndex && ( + + )} + + ))} + {showVirtualAiScreening && submissionIndex === -1 && ( + + )} + + ) + })() } {showTimeline && ( { - phases.map((phase, index) => ( - { - this.onUpdatePhaseDate(item, index) - }} - /> - ) - ) + (() => { + const hasRealAiScreeningPhase = phases.some(p => p.name === AI_SCREENING_PHASE_NAME) + const showVirtualAiScreening = hasAiReviewers(challenge.reviewers) && !hasRealAiScreeningPhase + const submissionIndex = phases.findIndex(p => p.name === 'Submission') + return ( + <> + {phases.map((phase, index) => ( + + { + this.onUpdatePhaseDate(item, index) + }} + /> + {showVirtualAiScreening && index === submissionIndex && ( + + )} + + ))} + {showVirtualAiScreening && submissionIndex === -1 && ( + + )} + + ) + })() } )} diff --git a/src/components/PhaseInput/index.js b/src/components/PhaseInput/index.js index 7c362563..3cd7c239 100644 --- a/src/components/PhaseInput/index.js +++ b/src/components/PhaseInput/index.js @@ -14,12 +14,39 @@ const inputDateFormat = 'MM/dd/yyyy' const inputTimeFormat = 'HH:mm' const MAX_LENGTH = 5 -const PhaseInput = ({ onUpdatePhase, phase, readOnly, phaseIndex }) => { +const PhaseInput = ({ onUpdatePhase, phase, readOnly, phaseIndex, isVirtual }) => { const { scheduledStartDate: startDate, scheduledEndDate: endDate, duration, isStartTimeActive, isDurationActive } = phase const durationHoursMinutes = useMemo(() => getPhaseHoursMinutes(duration), [duration]) const endDateInputRef = useRef() + useEffect(() => { + if (!startDate && onUpdatePhase && !isVirtual) { + let startDate = moment().format(dateFormat) + let endDate = getPhaseEndDate(startDate, duration) + onUpdatePhase({ + startDate, + endDate, + duration + }) + } + }, [startDate]) + + if (isVirtual && readOnly) { + return ( +
+
+
+ +
+
+ Automated (AI) +
+
+
+ ) + } + const onStartDateChange = (e) => { let startDate = moment(e).format(dateFormat) let endDate = getPhaseEndDate(startDate, duration) @@ -44,18 +71,6 @@ const PhaseInput = ({ onUpdatePhase, phase, readOnly, phaseIndex }) => { } } - useEffect(() => { - if (!startDate && onUpdatePhase) { - let startDate = moment().format(dateFormat) - let endDate = getPhaseEndDate(startDate, duration) - onUpdatePhase({ - startDate, - endDate, - duration - }) - } - }, [startDate]) - const onDurationChange = (e, isBlur = false) => { if (`${e}`.length > MAX_LENGTH) return null @@ -144,13 +159,16 @@ const PhaseInput = ({ onUpdatePhase, phase, readOnly, phaseIndex }) => { PhaseInput.defaultProps = { endDate: null, - readOnly: false + readOnly: false, + isVirtual: false, + phaseIndex: -1 } PhaseInput.propTypes = { phase: PropTypes.shape().isRequired, onUpdatePhase: PropTypes.func, readOnly: PropTypes.bool, - phaseIndex: PropTypes.number.isRequired + phaseIndex: PropTypes.number, + isVirtual: PropTypes.bool } export default PhaseInput diff --git a/src/config/constants.js b/src/config/constants.js index 59b422ca..ef3b852d 100644 --- a/src/config/constants.js +++ b/src/config/constants.js @@ -56,6 +56,7 @@ export const SKILLS_OPTIONAL_BILLING_ACCOUNT_IDS = ['80000062'] */ export const AI_WORKFLOW_POLL_INTERVAL = 1000 // 1 second in milliseconds export const AI_WORKFLOW_POLL_TIMEOUT = 5 * 60000 // 5 * 60 seconds in milliseconds +export const AI_SCREENING_PHASE_NAME = 'AI Screening' /** * Filepicker config