diff --git a/src/apps/work/src/pages/challenges/ChallengeEditorPage/components/SubmissionsSection/SubmissionsSection.spec.tsx b/src/apps/work/src/pages/challenges/ChallengeEditorPage/components/SubmissionsSection/SubmissionsSection.spec.tsx
index f0d58c0b4..df35ddd99 100644
--- a/src/apps/work/src/pages/challenges/ChallengeEditorPage/components/SubmissionsSection/SubmissionsSection.spec.tsx
+++ b/src/apps/work/src/pages/challenges/ChallengeEditorPage/components/SubmissionsSection/SubmissionsSection.spec.tsx
@@ -131,8 +131,8 @@ const submissions: Submission[] = [
challengeId: 'challenge-1',
createdAt: '2026-07-01T10:00:00.000Z',
createdBy: 'member-1',
- id: 'system-submission',
- memberHandle: 'system-user',
+ id: 'alpha-system-submission',
+ memberHandle: 'alpha',
reviewSummation: [
{
metadata: {
@@ -146,8 +146,8 @@ const submissions: Submission[] = [
challengeId: 'challenge-1',
createdAt: '2026-07-01T11:00:00.000Z',
createdBy: 'member-2',
- id: 'provisional-submission',
- memberHandle: 'provisional-user',
+ id: 'bravo-provisional-submission',
+ memberHandle: 'bravo',
reviewSummation: [
{
metadata: {
@@ -161,8 +161,9 @@ const submissions: Submission[] = [
challengeId: 'challenge-1',
createdAt: '2026-07-01T12:00:00.000Z',
createdBy: 'member-3',
- id: 'example-submission',
- memberHandle: 'example-user',
+ id: 'charlie-example-submission',
+ legacySubmissionId: 'legacy-charlie-id',
+ memberHandle: 'charlie',
reviewSummation: [
{
metadata: {
@@ -199,6 +200,43 @@ describe('SubmissionsSection', () => {
mockFetchMembersByUserIds.mockResolvedValue([])
})
+ it('filters submissions by current or legacy submission ID', () => {
+ render(
+ ,
+ )
+
+ fireEvent.change(screen.getByLabelText('Submission ID'), {
+ target: {
+ value: 'BRAVO',
+ },
+ })
+
+ expect(screen.getByText('bravo-provisional-submission'))
+ .toBeTruthy()
+ expect(screen.queryByText('alpha-system-submission'))
+ .toBeNull()
+ expect(screen.queryByText('charlie-example-submission'))
+ .toBeNull()
+ expect(screen.getByTestId('pagination-total').textContent)
+ .toBe('1')
+
+ fireEvent.change(screen.getByLabelText('Submission ID'), {
+ target: {
+ value: 'legacy-charlie',
+ },
+ })
+
+ expect(screen.getByText('charlie-example-submission'))
+ .toBeTruthy()
+ expect(screen.queryByText('alpha-system-submission'))
+ .toBeNull()
+ expect(screen.queryByText('bravo-provisional-submission'))
+ .toBeNull()
+ })
+
it('filters marathon submissions by test type', () => {
render(
{
},
})
- expect(screen.getByText('system-submission'))
+ expect(screen.getByText('alpha-system-submission'))
.toBeTruthy()
- expect(screen.queryByText('provisional-submission'))
+ expect(screen.queryByText('bravo-provisional-submission'))
.toBeNull()
- expect(screen.queryByText('example-submission'))
+ expect(screen.queryByText('charlie-example-submission'))
.toBeNull()
expect(screen.getByTestId('pagination-total').textContent)
.toBe('1')
@@ -228,11 +266,11 @@ describe('SubmissionsSection', () => {
},
})
- expect(screen.getByText('example-submission'))
+ expect(screen.getByText('charlie-example-submission'))
.toBeTruthy()
- expect(screen.queryByText('system-submission'))
+ expect(screen.queryByText('alpha-system-submission'))
.toBeNull()
- expect(screen.queryByText('provisional-submission'))
+ expect(screen.queryByText('bravo-provisional-submission'))
.toBeNull()
})
})
diff --git a/src/apps/work/src/pages/challenges/ChallengeEditorPage/components/SubmissionsSection/SubmissionsSection.tsx b/src/apps/work/src/pages/challenges/ChallengeEditorPage/components/SubmissionsSection/SubmissionsSection.tsx
index f73961cd5..ace5be142 100644
--- a/src/apps/work/src/pages/challenges/ChallengeEditorPage/components/SubmissionsSection/SubmissionsSection.tsx
+++ b/src/apps/work/src/pages/challenges/ChallengeEditorPage/components/SubmissionsSection/SubmissionsSection.tsx
@@ -58,6 +58,7 @@ interface FilterState {
handle: string
minScore: string
startDate: string
+ submissionId: string
testType: string
}
@@ -332,6 +333,33 @@ function matchesFilterHandle(submission: Submission, handleFilter: string): bool
.includes(normalizedHandleFilter)
}
+/**
+ * Checks whether a submission matches the submission ID filter.
+ * @param submission Submission row being evaluated.
+ * @param submissionIdFilter Case-insensitive partial submission ID entered by the user.
+ * @returns True when the filter is empty or matches the submission's current or legacy ID.
+ * Used by `matchesFilters` before the submissions table is sorted and paginated.
+ */
+function matchesFilterSubmissionId(
+ submission: Submission,
+ submissionIdFilter: string,
+): boolean {
+ if (!submissionIdFilter) {
+ return true
+ }
+
+ const normalizedSubmissionIdFilter = normalizeValue(submissionIdFilter)
+ .toLowerCase()
+
+ return [
+ submission.id,
+ submission.legacySubmissionId,
+ ]
+ .some(submissionId => normalizeValue(submissionId)
+ .toLowerCase()
+ .includes(normalizedSubmissionIdFilter))
+}
+
/**
* Checks whether a submission matches the selected marathon test type.
* @param submission Submission row being evaluated.
@@ -372,6 +400,10 @@ function matchesFilters(
return false
}
+ if (!matchesFilterSubmissionId(submission, filters.submissionId)) {
+ return false
+ }
+
if (!matchesFilterDateRange(submission, filters.startDate, filters.endDate)) {
return false
}
@@ -398,6 +430,7 @@ export const SubmissionsSection: FC = (
handle: '',
minScore: '',
startDate: '',
+ submissionId: '',
testType: '',
})
const [memberCache, setMemberCache] = useState({})
@@ -682,6 +715,19 @@ export const SubmissionsSection: FC = (
/>
+
+
{isMarathonMatch
? (