Skip to content

Commit bab9630

Browse files
committed
Sole screener / review view fix
1 parent b0b97d5 commit bab9630

File tree

10 files changed

+906
-48
lines changed

10 files changed

+906
-48
lines changed
Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,31 @@
1+
@import '@libs/ui/styles/includes';
2+
13
.container {
24
display: flex;
35
flex-direction: column;
4-
gap: 1.5rem;
6+
gap: $sp-6;
7+
}
8+
9+
.headerButtons {
10+
display: flex;
11+
flex-wrap: wrap;
12+
gap: $sp-3;
13+
justify-content: flex-end;
14+
}
15+
16+
.tableSection {
17+
display: flex;
18+
flex-direction: column;
19+
gap: $sp-3;
20+
}
21+
22+
.sectionHeading {
23+
font-size: 1.25rem;
24+
font-weight: 600;
25+
margin: 0;
26+
}
27+
28+
.errorMessage {
29+
color: $red-110;
30+
font-weight: 500;
531
}

src/apps/admin/src/challenge-management/ManageMarathonMatchPage/ManageMarathonMatchPage.tsx

Lines changed: 214 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,237 @@
1-
import { FC } from 'react'
1+
import {
2+
FC,
3+
useCallback,
4+
useMemo,
5+
useState,
6+
} from 'react'
27
import { useParams } from 'react-router-dom'
8+
import { toast } from 'react-toastify'
9+
import _ from 'lodash'
310
import classNames from 'classnames'
411

5-
import { LinkButton } from '~/libs/ui'
12+
import { Button, LinkButton } from '~/libs/ui'
613

7-
import { PageWrapper } from '../../lib'
14+
import {
15+
ActionLoading,
16+
PageWrapper,
17+
TableLoading,
18+
TableNoRecord,
19+
} from '../../lib'
20+
import {
21+
useDownloadSubmission,
22+
useDownloadSubmissionProps,
23+
useManageBusEvent,
24+
useManageBusEventProps,
25+
useManageMarathonMatch,
26+
useManageMarathonMatchProps,
27+
} from '../../lib/hooks'
28+
import { IsRemovingType } from '../../lib/models'
29+
import { removeReviewSummations } from '../../lib/services/reviews.service'
30+
import { removeSubmission } from '../../lib/services/submissions.service'
31+
import { handleError } from '../../lib/utils'
832

33+
import { MarathonMatchScoreTable } from './MarathonMatchScoreTable'
934
import styles from './ManageMarathonMatchPage.module.scss'
1035

1136
interface Props {
1237
className?: string
1338
}
1439

1540
export const ManageMarathonMatchPage: FC<Props> = (props: Props) => {
16-
const { challengeId = '' }: { challengeId?: string } = useParams<{
17-
challengeId: string
18-
}>()
41+
const { challengeId = '' }: { challengeId?: string }
42+
= useParams<{ challengeId: string }>()
43+
44+
const {
45+
error,
46+
finalScoresData,
47+
isLoading,
48+
provisionalScores,
49+
}: useManageMarathonMatchProps = useManageMarathonMatch(challengeId)
50+
51+
const {
52+
doPostBusEvent,
53+
isRunningTest,
54+
isRunningTestBool,
55+
}: useManageBusEventProps = useManageBusEvent()
56+
57+
const {
58+
downloadSubmission,
59+
isLoading: isDownloadingSubmission,
60+
isLoadingBool: isDownloadingSubmissionBool,
61+
}: useDownloadSubmissionProps = useDownloadSubmission()
62+
63+
const [isRemovingSubmission, setIsRemovingSubmission]
64+
= useState<IsRemovingType>({})
65+
const isRemovingSubmissionBool = useMemo(
66+
() => _.some(isRemovingSubmission, value => value === true),
67+
[isRemovingSubmission],
68+
)
69+
70+
const [isRemovingReviewSummations, setIsRemovingReviewSummations]
71+
= useState<IsRemovingType>({})
72+
const isRemovingReviewSummationsBool = useMemo(
73+
() => _.some(isRemovingReviewSummations, value => value === true),
74+
[isRemovingReviewSummations],
75+
)
76+
77+
const doRemoveSubmission = useCallback(
78+
(submissionId: string) => {
79+
if (!submissionId) {
80+
return
81+
}
82+
83+
setIsRemovingSubmission(prev => ({
84+
...prev,
85+
[submissionId]: true,
86+
}))
87+
88+
removeSubmission(submissionId)
89+
.then(() => {
90+
toast.success('Submission removed successfully', {
91+
toastId: 'Remove submission',
92+
})
93+
})
94+
.catch(handleError)
95+
.finally(() => {
96+
setIsRemovingSubmission(prev => ({
97+
...prev,
98+
[submissionId]: false,
99+
}))
100+
})
101+
},
102+
[],
103+
)
104+
105+
const doRemoveReviewSummations = useCallback(
106+
(reviewSummationId?: string) => {
107+
if (!reviewSummationId) {
108+
return
109+
}
110+
111+
setIsRemovingReviewSummations(prev => ({
112+
...prev,
113+
[reviewSummationId]: true,
114+
}))
115+
116+
removeReviewSummations([reviewSummationId])
117+
.then(() => {
118+
toast.success('Review summation removed successfully', {
119+
toastId: 'Remove review summation',
120+
})
121+
})
122+
.catch(handleError)
123+
.finally(() => {
124+
setIsRemovingReviewSummations(prev => ({
125+
...prev,
126+
[reviewSummationId]: false,
127+
}))
128+
})
129+
},
130+
[],
131+
)
132+
133+
const isActionInProgress = useMemo(
134+
() => (
135+
isDownloadingSubmissionBool
136+
|| isRemovingSubmissionBool
137+
|| isRunningTestBool
138+
|| isRemovingReviewSummationsBool
139+
),
140+
[
141+
isDownloadingSubmissionBool,
142+
isRemovingReviewSummationsBool,
143+
isRemovingSubmissionBool,
144+
isRunningTestBool,
145+
],
146+
)
147+
148+
const renderScoresSection = (
149+
heading: string,
150+
content: JSX.Element,
151+
hasRecords: boolean,
152+
): JSX.Element => (
153+
<section className={styles.tableSection}>
154+
<h3 className={styles.sectionHeading}>{heading}</h3>
155+
{hasRecords ? content : <TableNoRecord />}
156+
</section>
157+
)
158+
159+
let pageContent: JSX.Element | undefined
160+
161+
if (isLoading) {
162+
pageContent = <TableLoading />
163+
} else if (error) {
164+
pageContent = (
165+
<div className={styles.errorMessage}>
166+
{error.message || 'Unable to load marathon match data.'}
167+
</div>
168+
)
169+
} else {
170+
pageContent = (
171+
<>
172+
{renderScoresSection(
173+
'Provisional Scores',
174+
(
175+
<MarathonMatchScoreTable
176+
data={provisionalScores}
177+
testType='provisional'
178+
isRunningTest={isRunningTest}
179+
doPostBusEvent={doPostBusEvent}
180+
isRemovingSubmission={isRemovingSubmission}
181+
doRemoveSubmission={doRemoveSubmission}
182+
doRemoveReviewSummations={doRemoveReviewSummations}
183+
isRemovingReviewSummations={isRemovingReviewSummations}
184+
isDownloadingSubmission={isDownloadingSubmission}
185+
downloadSubmission={downloadSubmission}
186+
/>
187+
),
188+
provisionalScores.length > 0,
189+
)}
190+
191+
{renderScoresSection(
192+
'Final Scores',
193+
(
194+
<MarathonMatchScoreTable
195+
data={finalScoresData}
196+
testType='system'
197+
isFinalScores
198+
isRunningTest={isRunningTest}
199+
doPostBusEvent={doPostBusEvent}
200+
isRemovingSubmission={isRemovingSubmission}
201+
doRemoveSubmission={doRemoveSubmission}
202+
doRemoveReviewSummations={doRemoveReviewSummations}
203+
isRemovingReviewSummations={isRemovingReviewSummations}
204+
isDownloadingSubmission={isDownloadingSubmission}
205+
downloadSubmission={downloadSubmission}
206+
/>
207+
),
208+
finalScoresData.length > 0,
209+
)}
210+
</>
211+
)
212+
}
19213

20214
return (
21215
<PageWrapper
22216
pageTitle='Marathon Match Management'
23217
className={classNames(styles.container, props.className)}
24218
headerActions={(
25-
<LinkButton primary light to='./../..' size='lg'>
26-
Back
27-
</LinkButton>
219+
<div className={styles.headerButtons}>
220+
<Button primary size='lg' disabled>
221+
Run all system tests
222+
</Button>
223+
<Button size='lg' disabled>
224+
Close challenge
225+
</Button>
226+
<LinkButton primary light to='./../..' size='lg'>
227+
Back
228+
</LinkButton>
229+
</div>
28230
)}
29231
>
30-
<div>Marathon Match management content will be implemented here.</div>
31-
<div>
32-
Challenge ID:
33-
{' '}
34-
{challengeId}
35-
</div>
232+
{pageContent}
233+
234+
{isActionInProgress && <ActionLoading />}
36235
</PageWrapper>
37236
)
38237
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
@import '@libs/ui/styles/includes';
2+
3+
.container {
4+
width: 100%;
5+
overflow-x: auto;
6+
}
7+
8+
.table {
9+
width: 100%;
10+
}
11+
12+
.downloadLink {
13+
background: none;
14+
border: none;
15+
color: $link-blue;
16+
cursor: pointer;
17+
font: inherit;
18+
padding: 0;
19+
text-align: left;
20+
text-decoration: underline;
21+
22+
&:hover:not(:disabled) {
23+
color: $link-blue-dark;
24+
text-decoration: none;
25+
}
26+
27+
&:focus-visible {
28+
outline: 2px solid $blue-120;
29+
outline-offset: 2px;
30+
}
31+
32+
&:disabled {
33+
color: $black-60;
34+
cursor: default;
35+
text-decoration: none;
36+
}
37+
}
38+
39+
.isDownloading {
40+
color: $black-60;
41+
cursor: default;
42+
}
43+
44+
.noScore {
45+
color: $black-60;
46+
}

0 commit comments

Comments
 (0)