Skip to content

Conversation

@jmgasper
Copy link
Collaborator

Fix for handles not showing in challenges with many submissions, and a fix for a reported Topgear issue with regards to submission visibility for iterative reviewers. New feature for searching groups in system-admin app

@jmgasper jmgasper requested a review from kkartunov as a code owner November 10, 2025 22:19
@jmgasper jmgasper merged commit a4a8626 into master Nov 10, 2025
8 of 9 checks passed
usersMapping,
)

const filteredGroups = useMemo(() => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ correctness]
Using useMemo for filteredGroups is appropriate to avoid unnecessary recalculations, but ensure that groups is not being mutated elsewhere in the component, as it could lead to unexpected results.

return id.includes(normalized) || name.includes(normalized)
})
}, [groups, searchTerm])
const hasSearchTerm = useMemo(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[💡 performance]
The useMemo for hasSearchTerm is not necessary here since the computation is trivial. Removing it could simplify the code without impacting performance.

[myResources],
)
const allowTopgearSubmissionList = useMemo(
() => actionChallengeRole !== SUBMITTER || hasIterativeReviewerRole,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[💡 performance]
The useMemo hook is used here to determine allowTopgearSubmissionList, but the logic is simple and doesn't involve heavy computation. Consider removing useMemo to simplify the code unless there's a specific performance concern.

}: ChallengeDetailContextModel = useContext(ChallengeDetailContext)
const { actionChallengeRole }: useRoleProps = useRole()
const hasIterativeReviewerRole = useMemo(
() => myResources.some(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[💡 performance]
The useMemo hook is used to compute hasIterativeReviewerRole, but the computation is straightforward and not computationally expensive. Consider removing useMemo to simplify the code unless there's a specific performance concern.

timeLeftColor: displayTimeLeftColor,
timeLeftStatus: displayTimeLeftStatus,
}: PhaseDisplayInfo = useMemo(
() => computePhaseDisplayInfo(props.challengeInfo),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[💡 performance]
The useMemo hook is used here to compute PhaseDisplayInfo, but if computePhaseDisplayInfo is not computationally expensive, it might be unnecessary. Consider whether memoization is needed, as it adds complexity and can lead to stale values if dependencies are not managed correctly.

function selectPhaseForDisplay(data?: ChallengeInfo): BackendPhase | undefined {
if (!data) return undefined

const phases = Array.isArray(data.phases) ? data.phases : []

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ correctness]
The selectPhaseForDisplay function assumes that data.phases is always an array if it exists. Consider adding a type guard or validation to ensure data.phases is indeed an array before proceeding, to avoid potential runtime errors.

return {}
}

const endDate = new Date(rawEndDate)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ correctness]
The computePhaseTiming function creates a Date object from rawEndDate without checking its format. Ensure rawEndDate is a valid date string or timestamp to prevent NaN errors when creating a Date object.

} from '../models'

const resourceBaseUrl = `${EnvironmentConfig.API.V6}`
const DEFAULT_PER_PAGE = 1000

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ performance]
The DEFAULT_PER_PAGE constant is set to 1000, which might be too high depending on the API's performance and the server's capacity. Consider evaluating the optimal number for perPage to balance between performance and data load.

const firstPage = await xhrGetPaginatedAsync<BackendResource[]>(
`${resourceBaseUrl}/resources?${qs.stringify(baseQuery)}`,
)
const totalPages = firstPage.totalPages ?? 0

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ correctness]
The use of firstPage.totalPages ?? 0 assumes that totalPages is either defined or defaults to 0. Ensure that the API always returns a valid totalPages value to avoid unexpected behavior.

)
}

const remainingPages = await Promise.all(remainingPagePromises)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ performance]
Using Promise.all to fetch all remaining pages concurrently is efficient, but be cautious of potential rate limits or server strain if totalPages is large. Consider implementing a mechanism to handle API rate limits or errors gracefully.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants