@@ -7,6 +7,7 @@ import { ActionLoading } from '~/apps/admin/src/lib'
77
88import { ChallengeDetailContext } from '../../contexts'
99import {
10+ BackendPhase ,
1011 BackendSubmission ,
1112 ChallengeInfo ,
1213 MappingReviewAppeal ,
@@ -46,6 +47,33 @@ const normalizeType = (value?: string): string => (
4647 : ''
4748)
4849
50+ const resolvePhaseNameFromId = (
51+ phaseId ?: string ,
52+ phases ?: BackendPhase [ ] ,
53+ ) : string | undefined => {
54+ if ( ! phaseId || ! Array . isArray ( phases ) ) {
55+ return undefined
56+ }
57+
58+ const normalizedPhaseId = `${ phaseId } ` . trim ( )
59+ . toLowerCase ( )
60+ if ( ! normalizedPhaseId ) {
61+ return undefined
62+ }
63+
64+ const matchingPhase = phases . find ( phase => {
65+ const candidates = [ phase . id , phase . phaseId ]
66+
67+ return candidates . some ( candidate => (
68+ typeof candidate === 'string'
69+ && candidate . trim ( )
70+ . toLowerCase ( ) === normalizedPhaseId
71+ ) )
72+ } )
73+
74+ return matchingPhase ?. name
75+ }
76+
4977const EXCLUDED_REVIEW_TYPES = [
5078 'approval' ,
5179 'checkpoint' ,
@@ -55,17 +83,84 @@ const EXCLUDED_REVIEW_TYPES = [
5583 'specification' ,
5684] as const
5785
58- const shouldIncludeInReviewPhase = ( submission ?: SubmissionInfo ) : boolean => {
86+ const shouldIncludeInReviewPhase = (
87+ submission ?: SubmissionInfo ,
88+ phases ?: BackendPhase [ ] ,
89+ ) : boolean => {
5990 if ( ! submission ) {
6091 return false
6192 }
6293
63- const normalizedType = normalizeType ( submission . reviewTypeId )
64- if ( ! normalizedType ) {
94+ const normalizedCandidates = new Set < string > ( )
95+ const registerCandidate = ( candidate ?: string | null ) : void => {
96+ if ( typeof candidate !== 'string' ) {
97+ return
98+ }
99+
100+ const normalized = normalizeType ( candidate )
101+ if ( normalized ) {
102+ normalizedCandidates . add ( normalized )
103+ }
104+ }
105+
106+ registerCandidate ( submission . reviewTypeId )
107+ registerCandidate ( submission . review ?. phaseName )
108+ registerCandidate ( submission . review ?. reviewType )
109+ registerCandidate ( resolvePhaseNameFromId ( submission . review ?. phaseId , phases ) )
110+
111+ const metadata = submission . review ?. metadata
112+ if ( metadata && typeof metadata === 'object' ) {
113+ const metadataHints : unknown [ ] = [
114+ ( metadata as { type ?: unknown } ) . type ,
115+ ( metadata as { reviewType ?: unknown } ) . reviewType ,
116+ ( metadata as { review_type ?: unknown } ) . review_type ,
117+ ( metadata as { phase ?: unknown } ) . phase ,
118+ ( metadata as { phaseName ?: unknown } ) . phaseName ,
119+ ( metadata as { reviewPhase ?: unknown } ) . reviewPhase ,
120+ ]
121+
122+ metadataHints . forEach ( hint => {
123+ if ( typeof hint === 'string' ) {
124+ registerCandidate ( hint )
125+ }
126+ } )
127+ }
128+
129+ if ( ! normalizedCandidates . size ) {
130+ if ( process . env . NODE_ENV !== 'production' ) {
131+ // eslint-disable-next-line no-console
132+ console . debug ( '[ReviewTab] shouldIncludeInReviewPhase' , {
133+ normalizedCandidates : [ ] ,
134+ reviewPhaseName : submission . review ?. phaseName ,
135+ reviewType : submission . review ?. reviewType ,
136+ reviewTypeId : submission . reviewTypeId ,
137+ submissionId : submission . id ?? submission . review ?. submissionId ,
138+ verdict : 'included (no candidates)' ,
139+ } )
140+ }
141+
65142 return true
66143 }
67144
68- return ! EXCLUDED_REVIEW_TYPES . some ( fragment => normalizedType . includes ( fragment ) )
145+ const normalizedCandidateList = Array . from ( normalizedCandidates )
146+ const isExcluded = normalizedCandidateList
147+ . some ( normalizedType => (
148+ EXCLUDED_REVIEW_TYPES . some ( fragment => normalizedType . includes ( fragment ) )
149+ ) )
150+
151+ if ( process . env . NODE_ENV !== 'production' ) {
152+ // eslint-disable-next-line no-console
153+ console . debug ( '[ReviewTab] shouldIncludeInReviewPhase' , {
154+ normalizedCandidates : normalizedCandidateList ,
155+ reviewPhaseName : submission . review ?. phaseName ,
156+ reviewType : submission . review ?. reviewType ,
157+ reviewTypeId : submission . reviewTypeId ,
158+ submissionId : submission . id ?? submission . review ?. submissionId ,
159+ verdict : isExcluded ? 'excluded' : 'included' ,
160+ } )
161+ }
162+
163+ return ! isExcluded
69164}
70165
71166interface Props {
@@ -248,8 +343,11 @@ export const ChallengeDetailsContent: FC<Props> = (props: Props) => {
248343 [ challengeInfo ?. phases ] ,
249344 )
250345 const passesReviewTabGuards : ( submission : SubmissionInfo ) => boolean = useMemo (
251- ( ) => ( submission : SubmissionInfo ) : boolean => shouldIncludeInReviewPhase ( submission ) ,
252- [ ] ,
346+ ( ) => ( submission : SubmissionInfo ) : boolean => shouldIncludeInReviewPhase (
347+ submission ,
348+ challengeInfo ?. phases ,
349+ ) ,
350+ [ challengeInfo ?. phases ] ,
253351 )
254352 const {
255353 reviews : reviewTabReviews ,
0 commit comments