fix: replace invalid TanStack Router search casts with typed defaults
Some checks failed
Build & Release / build (push) Failing after 32s

Newer TanStack Router enforces strict types on search params — 'search: {} as Record<string, unknown>' no longer satisfies routes with validateSearch. Replace all occurrences with the correct search shape for each destination route (pagination defaults for list routes, tab/field defaults for detail routes).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Ryan Moon
2026-04-05 10:33:36 -05:00
parent b8e39369f1
commit a84530e80e
29 changed files with 68 additions and 68 deletions

View File

@@ -81,7 +81,7 @@ function EnrollmentDetailPage() {
const tab = search.tab
function setTab(t: string) {
navigate({ to: '/lessons/enrollments/$enrollmentId', params: { enrollmentId }, search: { tab: t } as Record<string, unknown> })
navigate({ to: '/lessons/enrollments/$enrollmentId', params: { enrollmentId }, search: { tab: t } })
}
const { data: enrollment, isLoading } = useQuery(enrollmentDetailOptions(enrollmentId))
@@ -131,7 +131,7 @@ function EnrollmentDetailPage() {
return (
<div className="space-y-6">
<div className="flex items-center gap-4">
<Button variant="ghost" size="sm" onClick={() => navigate({ to: '/lessons/enrollments', search: {} as Record<string, unknown> })}>
<Button variant="ghost" size="sm" onClick={() => navigate({ to: '/lessons/enrollments', search: { page: 1, limit: 25, q: undefined, sort: undefined, order: 'asc' as const } })}>
<ArrowLeft className="h-4 w-4 mr-1" />Back
</Button>
<div className="flex-1">
@@ -344,7 +344,7 @@ function SessionsTab({ enrollmentId, onGenerate, generating }: { enrollmentId: s
total={data?.data?.length ?? 0}
onPageChange={() => {}}
onSort={() => {}}
onRowClick={(s) => navigate({ to: '/lessons/sessions/$sessionId', params: { sessionId: s.id }, search: {} as Record<string, unknown> })}
onRowClick={(s) => navigate({ to: '/lessons/sessions/$sessionId', params: { sessionId: s.id }, search: { page: 1, limit: 25, q: undefined, sort: undefined, order: 'asc' as const } })}
/>
</div>
)
@@ -383,7 +383,7 @@ function LessonPlanTab({ enrollmentId, memberId, canEdit }: { enrollmentId: stri
queryClient.invalidateQueries({ queryKey: lessonPlanKeys.all })
toast.success('Plan created from template')
setTemplatePickerOpen(false)
navigate({ to: '/lessons/plans/$planId', params: { planId: plan.id }, search: {} as Record<string, unknown> })
navigate({ to: '/lessons/plans/$planId', params: { planId: plan.id }, search: { page: 1, limit: 25, q: undefined, sort: undefined, order: 'asc' as const } })
},
onError: (err) => toast.error(err.message),
})
@@ -401,7 +401,7 @@ function LessonPlanTab({ enrollmentId, memberId, canEdit }: { enrollmentId: stri
{Math.round(activePlan.progress)}% complete
</p>
</div>
<Button variant="outline" size="sm" onClick={() => navigate({ to: '/lessons/plans/$planId', params: { planId: activePlan.id }, search: {} as Record<string, unknown> })}>
<Button variant="outline" size="sm" onClick={() => navigate({ to: '/lessons/plans/$planId', params: { planId: activePlan.id }, search: { page: 1, limit: 25, q: undefined, sort: undefined, order: 'asc' as const } })}>
View Plan
</Button>
</div>

View File

@@ -72,7 +72,7 @@ function EnrollmentsListPage() {
function handleStatusChange(v: string) {
const s = v === 'all' ? '' : v
setStatusFilter(s)
navigate({ to: '/lessons/enrollments', search: { ...search, status: s || undefined, page: 1 } as Record<string, unknown> })
navigate({ to: '/lessons/enrollments', search: { ...search, status: s || undefined, page: 1 } })
}
return (
@@ -80,7 +80,7 @@ function EnrollmentsListPage() {
<div className="flex items-center justify-between">
<h1 className="text-2xl font-bold">Enrollments</h1>
{hasPermission('lessons.edit') && (
<Button onClick={() => navigate({ to: '/lessons/enrollments/new', search: {} as Record<string, unknown> })}>
<Button onClick={() => navigate({ to: '/lessons/enrollments/new', search: { page: 1, limit: 25, q: undefined, sort: undefined, order: 'asc' as const } })}>
<Plus className="mr-2 h-4 w-4" />New Enrollment
</Button>
)}
@@ -125,7 +125,7 @@ function EnrollmentsListPage() {
order={params.order}
onPageChange={setPage}
onSort={setSort}
onRowClick={(e) => navigate({ to: '/lessons/enrollments/$enrollmentId', params: { enrollmentId: e.id }, search: {} as Record<string, unknown> })}
onRowClick={(e) => navigate({ to: '/lessons/enrollments/$enrollmentId', params: { enrollmentId: e.id }, search: { page: 1, limit: 25, q: undefined, sort: undefined, order: 'asc' as const } })}
/>
</div>
)

View File

@@ -108,7 +108,7 @@ function NewEnrollmentPage() {
},
onSuccess: (enrollment) => {
toast.success('Enrollment created')
navigate({ to: '/lessons/enrollments/$enrollmentId', params: { enrollmentId: enrollment.id }, search: {} as Record<string, unknown> })
navigate({ to: '/lessons/enrollments/$enrollmentId', params: { enrollmentId: enrollment.id }, search: { page: 1, limit: 25, q: undefined, sort: undefined, order: 'asc' as const } })
},
onError: (err) => toast.error(err.message),
})
@@ -141,7 +141,7 @@ function NewEnrollmentPage() {
return (
<div className="space-y-6 max-w-2xl">
<div className="flex items-center gap-3">
<Button variant="ghost" size="sm" onClick={() => navigate({ to: '/lessons/enrollments', search: {} as Record<string, unknown> })}>
<Button variant="ghost" size="sm" onClick={() => navigate({ to: '/lessons/enrollments', search: { page: 1, limit: 25, q: undefined, sort: undefined, order: 'asc' as const } })}>
<ArrowLeft className="h-4 w-4" />
</Button>
<h1 className="text-2xl font-bold">New Enrollment</h1>
@@ -282,7 +282,7 @@ function NewEnrollmentPage() {
<Button type="submit" disabled={mutation.isPending || !selectedMember || !selectedSlotId || !startDate} size="lg">
{mutation.isPending ? 'Creating...' : 'Create Enrollment'}
</Button>
<Button variant="secondary" type="button" size="lg" onClick={() => navigate({ to: '/lessons/enrollments', search: {} as Record<string, unknown> })}>
<Button variant="secondary" type="button" size="lg" onClick={() => navigate({ to: '/lessons/enrollments', search: { page: 1, limit: 25, q: undefined, sort: undefined, order: 'asc' as const } })}>
Cancel
</Button>
</div>

View File

@@ -93,7 +93,7 @@ function LessonPlanDetailPage() {
return (
<div className="space-y-6 max-w-3xl">
<div className="flex items-center gap-3">
<Button variant="ghost" size="sm" onClick={() => navigate({ to: '/lessons/plans', search: {} as Record<string, unknown> })}>
<Button variant="ghost" size="sm" onClick={() => navigate({ to: '/lessons/plans', search: { page: 1, limit: 25, q: undefined, sort: undefined, order: 'asc' as const } })}>
<ArrowLeft className="h-4 w-4" />
</Button>
<div className="flex-1">

View File

@@ -84,7 +84,7 @@ function LessonPlansPage() {
order={params.order}
onPageChange={setPage}
onSort={setSort}
onRowClick={(p) => navigate({ to: '/lessons/plans/$planId', params: { planId: p.id }, search: {} as Record<string, unknown> })}
onRowClick={(p) => navigate({ to: '/lessons/plans/$planId', params: { planId: p.id }, search: { page: 1, limit: 25, q: undefined, sort: undefined, order: 'asc' as const } })}
/>
</div>
)

View File

@@ -49,7 +49,7 @@ function ScheduleHubPage() {
const canAdmin = hasPermission('lessons.admin')
function setTab(t: string) {
navigate({ to: '/lessons/schedule', search: { ...search, tab: t, page: 1 } as Record<string, unknown> })
navigate({ to: '/lessons/schedule', search: { ...search, tab: t, page: 1 } })
}
return (
@@ -152,7 +152,7 @@ function InstructorsTab({ canAdmin, search: _search }: { canAdmin: boolean; sear
order={params.order}
onPageChange={setPage}
onSort={setSort}
onRowClick={(i) => navigate({ to: '/lessons/schedule/instructors/$instructorId', params: { instructorId: i.id }, search: {} as Record<string, unknown> })}
onRowClick={(i) => navigate({ to: '/lessons/schedule/instructors/$instructorId', params: { instructorId: i.id }, search: { page: 1, limit: 25, q: undefined, sort: undefined, order: 'asc' as const } })}
/>
</div>
)

View File

@@ -42,7 +42,7 @@ function InstructorDetailPage() {
const tab = search.tab
function setTab(t: string) {
navigate({ to: '/lessons/schedule/instructors/$instructorId', params: { instructorId }, search: { tab: t } as Record<string, unknown> })
navigate({ to: '/lessons/schedule/instructors/$instructorId', params: { instructorId }, search: { tab: t } })
}
const { data: instructor, isLoading } = useQuery(instructorDetailOptions(instructorId))
@@ -62,7 +62,7 @@ function InstructorDetailPage() {
return (
<div className="space-y-6">
<div className="flex items-center gap-4">
<Button variant="ghost" size="sm" onClick={() => navigate({ to: '/lessons/schedule', search: { tab: 'instructors' } as Record<string, unknown> })}>
<Button variant="ghost" size="sm" onClick={() => navigate({ to: '/lessons/schedule', search: { tab: 'instructors', page: 1, limit: 25, q: undefined, sort: undefined, order: 'asc' as const } })}>
<ArrowLeft className="h-4 w-4 mr-1" />Back
</Button>
<div className="flex-1">

View File

@@ -126,7 +126,7 @@ function SessionDetailPage() {
return (
<div className="space-y-6 max-w-3xl">
<div className="flex items-center gap-3">
<Button variant="ghost" size="sm" onClick={() => navigate({ to: '/lessons/sessions', search: {} as Record<string, unknown> })}>
<Button variant="ghost" size="sm" onClick={() => navigate({ to: '/lessons/sessions', search: { page: 1, limit: 25, q: undefined, sort: undefined, order: 'asc' as const } })}>
<ArrowLeft className="h-4 w-4" />
</Button>
<div className="flex-1">
@@ -137,7 +137,7 @@ function SessionDetailPage() {
<Link
to="/lessons/enrollments/$enrollmentId"
params={{ enrollmentId: enrollment.id }}
search={{} as Record<string, unknown>}
search={{ tab: 'details' }}
className="text-sm text-primary hover:underline"
>
View Enrollment

View File

@@ -92,13 +92,13 @@ function SessionsPage() {
const weekEnd = endOfWeek(weekStart, { weekStartsOn: 0 })
function setView(v: 'list' | 'week') {
navigate({ to: '/lessons/sessions', search: { ...search, view: v, page: 1 } as Record<string, unknown> })
navigate({ to: '/lessons/sessions', search: { ...search, view: v, page: 1 } })
}
function handleStatusChange(v: string) {
const s = v === 'all' ? '' : v
setStatusFilter(s)
navigate({ to: '/lessons/sessions', search: { ...search, status: s || undefined, page: 1 } as Record<string, unknown> })
navigate({ to: '/lessons/sessions', search: { ...search, status: s || undefined, page: 1 } })
}
// List query
@@ -189,7 +189,7 @@ function SessionsPage() {
order={params.order}
onPageChange={setPage}
onSort={setSort}
onRowClick={(s) => navigate({ to: '/lessons/sessions/$sessionId', params: { sessionId: s.id }, search: {} as Record<string, unknown> })}
onRowClick={(s) => navigate({ to: '/lessons/sessions/$sessionId', params: { sessionId: s.id }, search: { page: 1, limit: 25, q: undefined, sort: undefined, order: 'asc' as const } })}
/>
</>
)}
@@ -249,7 +249,7 @@ function SessionsPage() {
{daySessions.map((s) => (
<button
key={s.id}
onClick={() => navigate({ to: '/lessons/sessions/$sessionId', params: { sessionId: s.id }, search: {} as Record<string, unknown> })}
onClick={() => navigate({ to: '/lessons/sessions/$sessionId', params: { sessionId: s.id }, search: { page: 1, limit: 25, q: undefined, sort: undefined, order: 'asc' as const } })}
className={`w-full text-left rounded border px-1.5 py-1 text-xs hover:opacity-80 transition-opacity ${STATUS_COLORS[s.status] ?? STATUS_COLORS.scheduled}`}
>
<p className="font-semibold">{formatTime(s.scheduledTime)}</p>

View File

@@ -42,7 +42,7 @@ function TemplateDetailPage() {
return (
<div className="space-y-6 max-w-3xl">
<div className="flex items-center gap-3">
<Button variant="ghost" size="sm" onClick={() => navigate({ to: '/lessons/templates', search: {} as Record<string, unknown> })}>
<Button variant="ghost" size="sm" onClick={() => navigate({ to: '/lessons/templates', search: { page: 1, limit: 25, q: undefined, sort: undefined, order: 'asc' as const } })}>
<ArrowLeft className="h-4 w-4" />
</Button>
<div className="flex-1">
@@ -218,7 +218,7 @@ function InstantiateDialog({ template, templateId, open, onClose }: {
}),
onSuccess: (plan) => {
toast.success('Plan created from template')
navigate({ to: '/lessons/plans/$planId', params: { planId: plan.id }, search: {} as Record<string, unknown> })
navigate({ to: '/lessons/plans/$planId', params: { planId: plan.id }, search: { page: 1, limit: 25, q: undefined, sort: undefined, order: 'asc' as const } })
},
onError: (err) => toast.error(err.message),
})

View File

@@ -96,7 +96,7 @@ function TemplatesListPage() {
<div className="flex items-center justify-between">
<h1 className="text-2xl font-bold">Lesson Plan Templates</h1>
{canAdmin && (
<Button onClick={() => navigate({ to: '/lessons/templates/new', search: {} as Record<string, unknown> })}>
<Button onClick={() => navigate({ to: '/lessons/templates/new', search: { page: 1, limit: 25, q: undefined, sort: undefined, order: 'asc' as const } })}>
<Plus className="mr-2 h-4 w-4" />New Template
</Button>
)}
@@ -126,7 +126,7 @@ function TemplatesListPage() {
order={params.order}
onPageChange={setPage}
onSort={setSort}
onRowClick={(t) => navigate({ to: '/lessons/templates/$templateId', params: { templateId: t.id }, search: {} as Record<string, unknown> })}
onRowClick={(t) => navigate({ to: '/lessons/templates/$templateId', params: { templateId: t.id }, search: { page: 1, limit: 25, q: undefined, sort: undefined, order: 'asc' as const } })}
/>
</div>
)

View File

@@ -45,7 +45,7 @@ function NewTemplatePage() {
}),
onSuccess: (template) => {
toast.success('Template created')
navigate({ to: '/lessons/templates/$templateId', params: { templateId: template.id }, search: {} as Record<string, unknown> })
navigate({ to: '/lessons/templates/$templateId', params: { templateId: template.id }, search: { page: 1, limit: 25, q: undefined, sort: undefined, order: 'asc' as const } })
},
onError: (err) => toast.error(err.message),
})
@@ -63,7 +63,7 @@ function NewTemplatePage() {
return (
<form onSubmit={handleSubmit} className="space-y-6 max-w-3xl">
<div className="flex items-center gap-3">
<Button type="button" variant="ghost" size="sm" onClick={() => navigate({ to: '/lessons/templates', search: {} as Record<string, unknown> })}>
<Button type="button" variant="ghost" size="sm" onClick={() => navigate({ to: '/lessons/templates', search: { page: 1, limit: 25, q: undefined, sort: undefined, order: 'asc' as const } })}>
<ArrowLeft className="h-4 w-4" />
</Button>
<h1 className="text-2xl font-bold">New Template</h1>
@@ -112,7 +112,7 @@ function NewTemplatePage() {
<Button type="submit" disabled={mutation.isPending || !name.trim() || !allSectionsValid} size="lg">
{mutation.isPending ? 'Creating...' : 'Create Template'}
</Button>
<Button type="button" variant="secondary" size="lg" onClick={() => navigate({ to: '/lessons/templates', search: {} as Record<string, unknown> })}>
<Button type="button" variant="secondary" size="lg" onClick={() => navigate({ to: '/lessons/templates', search: { page: 1, limit: 25, q: undefined, sort: undefined, order: 'asc' as const } })}>
Cancel
</Button>
</div>