diff --git a/components/organization/bounties/manage/BountyApplicationsPanel.tsx b/components/organization/bounties/manage/BountyApplicationsPanel.tsx index e7229a8e..eebf109e 100644 --- a/components/organization/bounties/manage/BountyApplicationsPanel.tsx +++ b/components/organization/bounties/manage/BountyApplicationsPanel.tsx @@ -104,6 +104,14 @@ export default function BountyApplicationsPanel({ a.applicationStatus === 'SUBMITTED'; const busy = select.isPending || shortlist.isPending || decline.isPending; + // `checked` can hold ids that have since left SUBMITTED (e.g. a checked + // application was declined, unmounting its checkbox), so derive the + // effective selection from the live list: the sticky-bar count and the + // shortlist payload must never include a non-actionable application. + const selectedIds = [...checked].filter(id => + applications.some(a => a.id === id && actionable(a)) + ); + const toggleCheck = (id: string) => setChecked(prev => { const next = new Set(prev); @@ -122,7 +130,7 @@ export default function BountyApplicationsPanel({ ); const onShortlist = () => { - const applicationIds = [...checked]; + const applicationIds = selectedIds; if ( overview.shortlistSize != null && applicationIds.length > overview.shortlistSize @@ -171,19 +179,19 @@ export default function BountyApplicationsPanel({ {isCompetition && (
- {checked.size} selected + {selectedIds.length} selected {overview.shortlistSize != null ? ` (max ${overview.shortlistSize})` : ''} {shortlist.isPending ? ( ) : ( - `Approve shortlist (${checked.size})` + `Approve shortlist (${selectedIds.length})` )}