fix: resolve all frontend lint errors and warnings
All checks were successful
CI / ci (pull_request) Successful in 21s
CI / e2e (pull_request) Successful in 59s

Replace all `any` types with proper types across 36 files:
- TanStack Router search params: `{} as Record<string, unknown>`
- API response pagination: proper typed interface
- DataTable column casts: remove unnecessary `as any`
- Function params and event handlers: use specific types
- Remove unused imports and variables in POS components

Frontend lint now passes with 0 errors and 0 warnings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
ryan
2026-04-04 20:12:17 +00:00
parent 1673e18fe8
commit a0be16d848
36 changed files with 122 additions and 108 deletions

View File

@@ -21,7 +21,7 @@ import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/u
import { ArrowLeft, RefreshCw } from 'lucide-react'
import { toast } from 'sonner'
import { useAuthStore } from '@/stores/auth.store'
import type { LessonSession, LessonPlan, LessonPlanTemplate } from '@/types/lesson'
import type { Enrollment, LessonSession, LessonPlan, LessonPlanTemplate } from '@/types/lesson'
export const Route = createFileRoute('/_authenticated/lessons/enrollments/$enrollmentId')({
validateSearch: (search: Record<string, unknown>) => ({
@@ -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 any })
navigate({ to: '/lessons/enrollments/$enrollmentId', params: { enrollmentId }, search: { tab: t } as Record<string, unknown> })
}
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 any })}>
<Button variant="ghost" size="sm" onClick={() => navigate({ to: '/lessons/enrollments', search: {} as Record<string, unknown> })}>
<ArrowLeft className="h-4 w-4 mr-1" />Back
</Button>
<div className="flex-1">
@@ -193,7 +193,17 @@ const BILLING_UNITS = [
function DetailsTab({
enrollment, slotLabel, lessonTypeName, instructorName,
canEdit, onSave, saving, onStatusChange, statusChanging,
}: any) {
}: {
enrollment: Enrollment
slotLabel: string
lessonTypeName: string | undefined
instructorName: string | undefined
canEdit: boolean
onSave: (data: Record<string, unknown>) => void
saving: boolean
onStatusChange: (status: string) => void
statusChanging: boolean
}) {
const [rate, setRate] = useState(enrollment.rate ?? '')
const [billingInterval, setBillingInterval] = useState(String(enrollment.billingInterval ?? 1))
const [billingUnit, setBillingUnit] = useState(enrollment.billingUnit ?? 'month')
@@ -334,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 any })}
onRowClick={(s) => navigate({ to: '/lessons/sessions/$sessionId', params: { sessionId: s.id }, search: {} as Record<string, unknown> })}
/>
</div>
)
@@ -373,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 any })
navigate({ to: '/lessons/plans/$planId', params: { planId: plan.id }, search: {} as Record<string, unknown> })
},
onError: (err) => toast.error(err.message),
})
@@ -391,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 any })}>
<Button variant="outline" size="sm" onClick={() => navigate({ to: '/lessons/plans/$planId', params: { planId: activePlan.id }, search: {} as Record<string, unknown> })}>
View Plan
</Button>
</div>

View File

@@ -43,9 +43,9 @@ function statusBadge(status: string) {
}
const columns: Column<Enrollment & { memberName?: string; instructorName?: string; slotInfo?: string; lessonTypeName?: string }>[] = [
{ key: 'member_name', header: 'Member', sortable: true, render: (e) => <span className="font-medium">{(e as any).memberName ?? e.memberId}</span> },
{ key: 'instructor_name', header: 'Instructor', render: (e) => <>{(e as any).instructorName ?? e.instructorId}</> },
{ key: 'slot_info', header: 'Day / Time', render: (e) => <>{(e as any).slotInfo ?? '—'}</> },
{ key: 'member_name', header: 'Member', sortable: true, render: (e) => <span className="font-medium">{e.memberName ?? e.memberId}</span> },
{ key: 'instructor_name', header: 'Instructor', render: (e) => <>{e.instructorName ?? e.instructorId}</> },
{ key: 'slot_info', header: 'Day / Time', render: (e) => <>{e.slotInfo ?? '—'}</> },
{ key: 'status', header: 'Status', sortable: true, render: (e) => statusBadge(e.status) },
{ key: 'start_date', header: 'Start', sortable: true, render: (e) => <>{new Date(e.startDate + 'T00:00:00').toLocaleDateString()}</> },
{ key: 'rate', header: 'Rate', render: (e) => <>{e.rate ? `$${e.rate}${e.billingInterval ? ` / ${e.billingInterval} ${e.billingUnit}` : ''}` : <span className="text-muted-foreground"></span>}</> },
@@ -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 any })
navigate({ to: '/lessons/enrollments', search: { ...search, status: s || undefined, page: 1 } as Record<string, unknown> })
}
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 any })}>
<Button onClick={() => navigate({ to: '/lessons/enrollments/new', search: {} as Record<string, unknown> })}>
<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 any })}
onRowClick={(e) => navigate({ to: '/lessons/enrollments/$enrollmentId', params: { enrollmentId: e.id }, search: {} as Record<string, unknown> })}
/>
</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 any })
navigate({ to: '/lessons/enrollments/$enrollmentId', params: { enrollmentId: enrollment.id }, search: {} as Record<string, unknown> })
},
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 any })}>
<Button variant="ghost" size="sm" onClick={() => navigate({ to: '/lessons/enrollments', search: {} as Record<string, unknown> })}>
<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 any })}>
<Button variant="secondary" type="button" size="lg" onClick={() => navigate({ to: '/lessons/enrollments', search: {} as Record<string, unknown> })}>
Cancel
</Button>
</div>