Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion admin-redesign/src/app/services/elections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,20 @@ export const electionsApi = api.injectEndpoints({
}),
}),
getImpossibilitiesReport: builder.query<
{ type: string; name: string; passed: boolean; message: string; ids: number[] }[],
// Most checks can group offending IDs by election. One check
// ('polling_place_noms_not_attached_to_a_polling_place') has no election
// FK to traverse (the noms record is detached), so it returns a flat 'ids'
// list instead. The UI discriminates on 'ids_by_election' in item.
(
| {
type: string;
name: string;
passed: boolean;
message: string;
ids_by_election: { election_id: number; election_name: string; ids: number[] }[];
}
| { type: string; name: string; passed: boolean; message: string; ids: number[] }
)[],
void
>({
query: () => ({
Expand Down
100 changes: 71 additions & 29 deletions admin-redesign/src/features/impossibilities/QualityAssuranceReport.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,37 +42,79 @@ function QualityAssuranceReport() {
the system.
</Typography>

{qaReport.map((item) => (
<Box
key={item.type}
sx={{
display: 'flex',
alignItems: 'center',
backgroundColor: item.passed === false ? red[100] : undefined,
p: 1,
mb: 1,
}}
>
<Typography variant="h4">{item.ids.length}</Typography>
{qaReport.map((item) => {
const isGrouped = 'ids_by_election' in item;
const totalCount = isGrouped ? item.ids_by_election.reduce((sum, g) => sum + g.ids.length, 0) : item.ids.length;

<ListItem
secondaryAction={
item.passed === false && isClipboardApiSupported() === true ? (
<IconButton edge="end" onClick={onCopyToClipboard(item.ids)}>
<ContentCopy />
</IconButton>
) : undefined
}
sx={{ pt: 0, pb: 0 }}
return (
<Box
key={item.type}
sx={{
backgroundColor: item.passed === false ? red[100] : undefined,
p: 1,
mb: 1,
}}
>
<ListItemText
primary={item.name}
secondary={item.ids.join(', ') || 'Everything is fine 🎉'}
sx={{ flexGrow: 1 }}
/>
</ListItem>
</Box>
))}
{/* Header row: count + check name */}
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Typography variant="h4">{totalCount}</Typography>

{isGrouped ? (
<ListItem sx={{ pt: 0, pb: 0 }}>
<ListItemText primary={item.name} sx={{ flexGrow: 1 }} />
</ListItem>
) : (
<ListItem
secondaryAction={
item.passed === false && isClipboardApiSupported() === true ? (
<IconButton edge="end" onClick={onCopyToClipboard(item.ids)}>
<ContentCopy />
</IconButton>
) : undefined
}
sx={{ pt: 0, pb: 0 }}
>
<ListItemText
primary={item.name}
secondary={item.ids.join(', ') || 'Everything is fine 🎉'}
sx={{ flexGrow: 1 }}
/>
</ListItem>
)}
</Box>

{/* Grouped: per-election sub-rows */}
{isGrouped && item.ids_by_election.length === 0 && (
<Typography variant="body2" sx={{ pl: 7, pb: 0.5, color: 'text.secondary' }}>
Everything is fine 🎉
</Typography>
)}

{isGrouped &&
item.ids_by_election.map((group) => (
<Box key={group.election_id} sx={{ display: 'flex', alignItems: 'center' }}>
<ListItem
secondaryAction={
isClipboardApiSupported() === true ? (
<IconButton edge="end" onClick={onCopyToClipboard(group.ids)}>
<ContentCopy />
</IconButton>
) : undefined
}
sx={{ pt: 0.5, pb: 0.5 }}
>
<ListItemText
primary={group.election_name}
primaryTypographyProps={{ variant: 'body2' }}
secondary={group.ids.join(', ')}
sx={{ flexGrow: 1 }}
/>
</ListItem>
</Box>
))}
</Box>
);
})}
</PageWrapper>
);
}
Expand Down
Loading