From 99bcd43e144199c828c31bf9e0a0e6b1a60bb2fd Mon Sep 17 00:00:00 2001 From: "sentry-junior[bot]" <264270552+sentry-junior[bot]@users.noreply.github.com> Date: Fri, 21 Aug 2026 20:03:43 +0000 Subject: [PATCH 1/3] fix(projects): Preserve group filter on return MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Paul Jaffré --- src/app/components/ProjectCard.tsx | 4 ++- src/app/routes/ProjectDetailsPage.tsx | 9 +++-- src/app/routes/ProjectsPage.tsx | 23 ++++++++---- test/app/routes.test.tsx | 51 +++++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 11 deletions(-) diff --git a/src/app/components/ProjectCard.tsx b/src/app/components/ProjectCard.tsx index 3c1edb2..43d351a 100644 --- a/src/app/components/ProjectCard.tsx +++ b/src/app/components/ProjectCard.tsx @@ -12,12 +12,14 @@ export function ProjectCard({ project, view = 'grid', voteCategories = [], + detailsSearch, }: { project: ProjectSummary; view?: 'grid' | 'list'; voteCategories?: string[]; + detailsSearch?: string; }) { - const projectLink = `/years/${project.yearId}/projects/${project.id}`; + const projectLink = `/years/${project.yearId}/projects/${project.id}${detailsSearch ? `?${detailsSearch}` : ''}`; if (view === 'list') { return ( diff --git a/src/app/routes/ProjectDetailsPage.tsx b/src/app/routes/ProjectDetailsPage.tsx index 1222567..ce44beb 100644 --- a/src/app/routes/ProjectDetailsPage.tsx +++ b/src/app/routes/ProjectDetailsPage.tsx @@ -1,6 +1,6 @@ import {useState, type ChangeEvent} from 'react'; import {useQuery} from '@tanstack/react-query'; -import {Link, useLocation, useParams} from 'wouter'; +import {Link, useLocation, useParams, useSearchParams} from 'wouter'; import {QueryState} from '../components/AppLayout'; import {Markdown} from '../components/Markdown'; @@ -21,6 +21,9 @@ export function ProjectDetailsPage() { projectId: string; }>(); const [, navigate] = useLocation(); + const [searchParams] = useSearchParams(); + const group = searchParams.get('group'); + const projectsHref = `/years/${yearId}/projects${group ? `?group=${encodeURIComponent(group)}` : ''}`; const project = useProject(projectId); const ballotYearId = project.data?.project.yearId ?? yearId; const ballot = useBallotStatus(ballotYearId, project.data?.project.kind === 'project'); @@ -49,7 +52,7 @@ export function ProjectDetailsPage() {
- + ← {yearId} projects
@@ -88,7 +91,7 @@ export function ProjectDetailsPage() { if (!window.confirm('Withdraw this project from the archive?')) return; withdraw.mutate(projectId, { - onSuccess: () => navigate(`/years/${yearId}/projects`), + onSuccess: () => navigate(projectsHref), onError: (error) => setActionError(error.message), }); }} diff --git a/src/app/routes/ProjectsPage.tsx b/src/app/routes/ProjectsPage.tsx index 62d9067..4383c48 100644 --- a/src/app/routes/ProjectsPage.tsx +++ b/src/app/routes/ProjectsPage.tsx @@ -1,5 +1,5 @@ import {useEffect, useRef, useState} from 'react'; -import {Link, useParams} from 'wouter'; +import {Link, useParams, useSearchParams} from 'wouter'; import type {BallotStatusResponse} from '../../shared/administration'; import {getAwardCategoryDescription} from '../awardCategories'; @@ -34,8 +34,9 @@ function saveProjectsView(view: ProjectsView) { export function ProjectsPage({isAdmin = false}: {isAdmin?: boolean}) { const {yearId} = useParams<{yearId: string}>(); + const [searchParams, setSearchParams] = useSearchParams(); const [kind, setKind] = useState<'project' | 'idea'>('project'); - const [group, setGroup] = useState(''); + const group = searchParams.get('group') ?? ''; const [searchInput, setSearchInput] = useState(''); const [search, setSearch] = useState(''); const [cursor, setCursor] = useState(); @@ -72,6 +73,16 @@ export function ProjectsPage({isAdmin = false}: {isAdmin?: boolean}) { setCursorHistory([]); }; + const selectGroup = (groupId: string) => { + setSearchParams((current) => { + const next = new URLSearchParams(current); + if (groupId) next.set('group', groupId); + else next.delete('group'); + return next; + }); + resetPagination(); + }; + useEffect(() => { const timeout = window.setTimeout(() => { setSearch(searchInput.trim()); @@ -212,10 +223,7 @@ export function ProjectsPage({isAdmin = false}: {isAdmin?: boolean}) { Group