[{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/404/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/500/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/actions/logoutAction.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/admin/AdminDashboardWrapper.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/admin/actions.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/admin/layout.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/admin/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/admin/users/AdminUsersWrapper.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/admin/users/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/auth/forgot-password/ForgotPasswordClient.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/auth/forgot-password/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/auth/layout.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/auth/login/LoginClient.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/auth/login/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/auth/reset-password/ResetPasswordClient.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/auth/reset-password/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/auth/signup/SignupClient.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/auth/signup/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/dashboard/layout.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/dashboard/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/drivers/DriversPageClient.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/drivers/[id]/DriverProfilePageClient.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/drivers/[id]/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/drivers/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/error.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/global-error.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/layout.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/leaderboards/LeaderboardsPageClient.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/leaderboards/drivers/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/leaderboards/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/leagues/LeaguesPageClient.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/leagues/[id]/layout.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/leagues/[id]/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/leagues/[id]/roster/admin/RosterAdminPage.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/leagues/[id]/roster/admin/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/leagues/[id]/rulebook/LeagueRulebookPageClient.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/leagues/[id]/rulebook/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/leagues/[id]/schedule/admin/LeagueAdminSchedulePageClient.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/leagues/[id]/schedule/admin/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/leagues/[id]/schedule/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/leagues/[id]/settings/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/leagues/[id]/sponsorships/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/leagues/[id]/standings/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/leagues/[id]/stewarding/StewardingPageClient.tsx","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":50,"column":10,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":50,"endColumn":13,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2242,2245],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2242,2245],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":65,"column":10,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":65,"endColumn":13,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2739,2742],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2739,2742],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":75,"column":12,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":75,"endColumn":15,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3004,3007],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3004,3007],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":90,"column":12,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":90,"endColumn":15,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3358,3361],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3358,3361],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":234,"column":16,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":234,"endColumn":19,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[8075,8078],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[8075,8078],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":5,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\n\nimport { PenaltyFAB } from '@/ui/PenaltyFAB';\nimport { QuickPenaltyModal } from '@/components/leagues/QuickPenaltyModal';\nimport { ReviewProtestModal } from '@/components/leagues/ReviewProtestModal';\nimport { StewardingStats } from '@/components/leagues/StewardingStats';\nimport { Button } from '@/ui/Button';\nimport { Card } from '@/ui/Card';\nimport { useLeagueStewardingMutations } from \"@/hooks/league/useLeagueStewardingMutations\";\nimport { useMemo, useState } from 'react';\nimport { PendingProtestsList } from '@/components/leagues/PendingProtestsList';\nimport { PenaltyHistoryList } from '@/components/leagues/PenaltyHistoryList';\nimport { Box } from '@/ui/Box';\nimport { Stack } from '@/ui/Stack';\nimport { Text } from '@/ui/Text';\nimport { Heading } from '@/ui/Heading';\nimport type { StewardingViewData } from '@/lib/view-data/leagues/StewardingViewData';\nimport { ProtestViewModel } from '@/lib/view-models/ProtestViewModel';\nimport { RaceViewModel } from '@/lib/view-models/RaceViewModel';\nimport { DriverViewModel } from '@/lib/view-models/DriverViewModel';\n\ninterface StewardingTemplateProps {\n data: StewardingViewData;\n leagueId: string;\n currentDriverId: string;\n onRefetch: () => void;\n}\n\nexport function StewardingPageClient({ data, leagueId, currentDriverId, onRefetch }: StewardingTemplateProps) {\n const [activeTab, setActiveTab] = useState<'pending' | 'history'>('pending');\n const [selectedProtest, setSelectedProtest] = useState(null);\n const [showQuickPenaltyModal, setShowQuickPenaltyModal] = useState(false);\n\n // Mutations using domain hook\n const { acceptProtestMutation, rejectProtestMutation } = useLeagueStewardingMutations(onRefetch);\n\n // Flatten protests for the specialized list components\n const allPendingProtests = useMemo(() => {\n return data.races.flatMap(r => r.pendingProtests.map(p => new ProtestViewModel({\n id: p.id,\n protestingDriverId: p.protestingDriverId,\n accusedDriverId: p.accusedDriverId,\n description: p.incident.description,\n submittedAt: p.filedAt,\n status: p.status,\n raceId: r.id,\n incident: p.incident,\n proofVideoUrl: p.proofVideoUrl,\n decisionNotes: p.decisionNotes,\n } as any)));\n }, [data.races]);\n\n const allResolvedProtests = useMemo(() => {\n return data.races.flatMap(r => r.resolvedProtests.map(p => new ProtestViewModel({\n id: p.id,\n protestingDriverId: p.protestingDriverId,\n accusedDriverId: p.accusedDriverId,\n description: p.incident.description,\n submittedAt: p.filedAt,\n status: p.status,\n raceId: r.id,\n incident: p.incident,\n proofVideoUrl: p.proofVideoUrl,\n decisionNotes: p.decisionNotes,\n } as any)));\n }, [data.races]);\n\n const racesMap = useMemo(() => {\n const map: Record = {};\n data.races.forEach(r => {\n map[r.id] = new RaceViewModel({\n id: r.id,\n track: r.track,\n date: r.scheduledAt,\n } as any);\n });\n return map;\n }, [data.races]);\n\n const driverMap = useMemo(() => {\n const map: Record = {};\n data.drivers.forEach(d => {\n map[d.id] = new DriverViewModel({\n id: d.id,\n name: d.name,\n iracingId: '',\n country: '',\n joinedAt: '',\n avatarUrl: null,\n } as any);\n });\n return map;\n }, [data.drivers]);\n\n const handleAcceptProtest = async (\n protestId: string,\n penaltyType: string,\n penaltyValue: number,\n stewardNotes: string\n ) => {\n // Find the protest to get details for penalty\n let foundProtest: { raceId: string; accusedDriverId: string; incident: { description: string } } | undefined;\n data.races.forEach((raceData) => {\n const p = raceData.pendingProtests.find((pr) => pr.id === protestId) ||\n raceData.resolvedProtests.find((pr) => pr.id === protestId);\n if (p) foundProtest = { \n raceId: raceData.id, \n accusedDriverId: p.accusedDriverId,\n incident: { description: p.incident.description }\n };\n });\n\n if (foundProtest) {\n acceptProtestMutation.mutate({\n protestId,\n penaltyType,\n penaltyValue,\n stewardNotes,\n raceId: foundProtest.raceId,\n accusedDriverId: foundProtest.accusedDriverId,\n reason: foundProtest.incident.description,\n });\n }\n };\n\n const handleRejectProtest = async (protestId: string, stewardNotes: string) => {\n rejectProtestMutation.mutate({\n protestId,\n stewardNotes,\n });\n };\n\n return (\n \n \n \n \n \n Stewarding\n \n \n Quick overview of protests and penalties across all races\n \n \n \n \n\n {/* Stats summary */}\n \n\n {/* Tab navigation */}\n \n \n \n setActiveTab('pending')}\n rounded=\"none\"\n >\n \n Pending Protests\n {data.totalPending > 0 && (\n \n {data.totalPending}\n \n )}\n \n \n \n \n setActiveTab('history')}\n rounded=\"none\"\n >\n History\n \n \n \n \n\n {/* Content */}\n {activeTab === 'pending' ? (\n \n ) : (\n \n )}\n \n \n\n {activeTab === 'history' && (\n setShowQuickPenaltyModal(true)} />\n )}\n\n {selectedProtest && (\n setSelectedProtest(null)}\n onAccept={handleAcceptProtest}\n onReject={handleRejectProtest}\n />\n )}\n\n {showQuickPenaltyModal && (\n new DriverViewModel({\n id: d.id,\n name: d.name,\n iracingId: '',\n country: '',\n joinedAt: '',\n avatarUrl: null,\n } as any))}\n onClose={() => setShowQuickPenaltyModal(false)}\n adminId={currentDriverId || ''}\n races={data.races.map(r => ({ id: r.id, track: r.track, scheduledAt: new Date(r.scheduledAt) }))}\n />\n )}\n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/leagues/[id]/stewarding/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/leagues/[id]/stewarding/protests/[protestId]/ProtestDetailPageClient.tsx","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":52,"column":9,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":52,"endColumn":12,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1511,1514],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1511,1514],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":102,"column":81,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":102,"endColumn":84,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2915,2918],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2915,2918],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":138,"column":37,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":138,"endColumn":40,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[4437,4440],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[4437,4440],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":153,"column":34,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":153,"endColumn":37,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[4796,4799],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[4796,4799],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":202,"column":64,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":202,"endColumn":67,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[6461,6464],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[6461,6464],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":319,"column":13,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":319,"endColumn":16,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[10546,10549],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[10546,10549],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":572,"column":31,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":588,"endColumn":33},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":572,"column":31,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":588,"endColumn":33},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":577,"column":33,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":587,"endColumn":35},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":591,"column":64,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":591,"endColumn":98},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":633,"column":59,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":633,"endColumn":127},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":653,"column":33,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":658,"endColumn":35},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":668,"column":33,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":673,"endColumn":35},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":694,"column":67,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":694,"endColumn":70,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[32662,32665],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[32662,32665],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":705,"column":45,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":710,"endColumn":47},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":716,"column":79,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":716,"endColumn":107},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":730,"column":41,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":745,"endColumn":43},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":730,"column":41,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":745,"endColumn":43},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":735,"column":43,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":744,"endColumn":45},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":756,"column":31,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":772,"endColumn":33},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":756,"column":31,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":772,"endColumn":33},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":761,"column":33,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":771,"endColumn":35},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":795,"column":57,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":795,"endColumn":92}],"suppressedMessages":[],"errorCount":23,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\n\nimport { Button } from '@/ui/Button';\nimport { Card } from '@/ui/Card';\nimport { useEffectiveDriverId } from \"@/hooks/useEffectiveDriverId\";\nimport { useInject } from '@/lib/di/hooks/useInject';\nimport { PROTEST_SERVICE_TOKEN } from '@/lib/di/tokens';\nimport { ProtestDecisionCommandModel } from '@/lib/command-models/protests/ProtestDecisionCommandModel';\nimport {\n AlertTriangle,\n ArrowLeft,\n Calendar,\n CheckCircle,\n ChevronDown,\n Clock,\n ExternalLink,\n Flag,\n Gavel,\n Grid3x3,\n MapPin,\n MessageCircle,\n Send,\n Shield,\n ShieldAlert,\n TrendingDown,\n User,\n Video,\n XCircle,\n AlertCircle\n} from 'lucide-react';\nimport { useParams, useRouter } from 'next/navigation';\nimport { useMemo, useState, useEffect } from 'react';\n\n// Shared state components\nimport { StateContainer } from '@/components/shared/state/StateContainer';\nimport { LoadingWrapper } from '@/components/shared/state/LoadingWrapper';\nimport { useLeagueAdminStatus } from \"@/hooks/league/useLeagueAdminStatus\";\nimport { useProtestDetail } from \"@/hooks/league/useProtestDetail\";\nimport { Box } from '@/ui/Box';\nimport { Stack } from '@/ui/Stack';\nimport { Text } from '@/ui/Text';\nimport { Heading } from '@/ui/Heading';\nimport { Grid } from '@/ui/Grid';\nimport { GridItem } from '@/ui/GridItem';\nimport { Icon as UIIcon } from '@/ui/Icon';\nimport { Link as UILink } from '@/ui/Link';\nimport { routes } from '@/lib/routing/RouteConfig';\n\ntype PenaltyUiConfig = {\n label: string;\n description: string;\n icon: any;\n color: string;\n defaultValue?: number;\n};\n\nconst PENALTY_UI: Record = {\n time_penalty: {\n label: 'Time Penalty',\n description: 'Add seconds to race result',\n icon: Clock,\n color: 'text-blue-400 bg-blue-500/10 border-blue-500/20',\n defaultValue: 5,\n },\n grid_penalty: {\n label: 'Grid Penalty',\n description: 'Grid positions for next race',\n icon: Grid3x3,\n color: 'text-purple-400 bg-purple-500/10 border-purple-500/20',\n defaultValue: 3,\n },\n points_deduction: {\n label: 'Points Deduction',\n description: 'Deduct championship points',\n icon: TrendingDown,\n color: 'text-red-400 bg-red-500/10 border-red-500/20',\n defaultValue: 5,\n },\n disqualification: {\n label: 'Disqualification',\n description: 'Disqualify from race',\n icon: XCircle,\n color: 'text-red-500 bg-red-500/10 border-red-500/20',\n defaultValue: 0,\n },\n warning: {\n label: 'Warning',\n description: 'Official warning only',\n icon: AlertTriangle,\n color: 'text-yellow-400 bg-yellow-500/10 border-yellow-500/20',\n defaultValue: 0,\n },\n license_points: {\n label: 'License Points',\n description: 'Safety rating penalty',\n icon: ShieldAlert,\n color: 'text-orange-400 bg-orange-500/10 border-orange-500/20',\n defaultValue: 2,\n },\n};\n\nexport function ProtestDetailPageClient({ initialViewData }: { initialViewData: any }) {\n const params = useParams();\n const router = useRouter();\n const leagueId = params.id as string;\n const protestId = params.protestId as string;\n const currentDriverId = useEffectiveDriverId();\n const protestService = useInject(PROTEST_SERVICE_TOKEN);\n\n // Decision state\n const [showDecisionPanel, setShowDecisionPanel] = useState(false);\n const [decision, setDecision] = useState<'uphold' | 'dismiss' | null>(null);\n const [penaltyType, setPenaltyType] = useState('time_penalty');\n const [penaltyValue, setPenaltyValue] = useState(5);\n const [stewardNotes, setStewardNotes] = useState('');\n const [submitting, setSubmitting] = useState(false);\n const [newComment, setNewComment] = useState('');\n\n // Check admin status using hook\n const { data: isAdmin, isLoading: adminLoading } = useLeagueAdminStatus(leagueId, currentDriverId || '');\n\n // Load protest detail using hook\n const { data: detail, isLoading: detailLoading, error, retry } = useProtestDetail(leagueId, protestId, isAdmin || false);\n\n // Use initial data if available\n const protestDetail = detail || initialViewData;\n\n // Set initial penalty values when data loads\n useEffect(() => {\n if (protestDetail?.initialPenaltyType) {\n setPenaltyType(protestDetail.initialPenaltyType);\n setPenaltyValue(protestDetail.initialPenaltyValue);\n }\n }, [protestDetail]);\n\n const penaltyTypes = useMemo(() => {\n const referenceItems = protestDetail?.penaltyTypes ?? [];\n return referenceItems.map((ref: any) => {\n const ui = PENALTY_UI[ref.type] ?? {\n icon: Gavel,\n color: 'text-gray-400 bg-gray-500/10 border-gray-500/20',\n };\n\n return {\n ...ref,\n icon: ui.icon,\n color: ui.color,\n };\n });\n }, [protestDetail?.penaltyTypes]);\n\n const selectedPenalty = useMemo(() => {\n return penaltyTypes.find((p: any) => p.type === penaltyType);\n }, [penaltyTypes, penaltyType]);\n\n const handleSubmitDecision = async () => {\n if (!decision || !stewardNotes.trim() || !protestDetail || !currentDriverId) return;\n\n setSubmitting(true);\n try {\n const protest = protestDetail.protest || protestDetail;\n\n const defaultUpheldReason = protestDetail.defaultReasons?.upheld;\n const defaultDismissedReason = protestDetail.defaultReasons?.dismissed;\n\n if (decision === 'uphold') {\n const requiresValue = selectedPenalty?.requiresValue ?? true;\n\n const commandModel = new ProtestDecisionCommandModel({\n decision,\n penaltyType,\n penaltyValue,\n stewardNotes,\n });\n\n const options: {\n requiresValue?: boolean;\n defaultUpheldReason?: string;\n defaultDismissedReason?: string;\n } = { requiresValue };\n\n if (defaultUpheldReason) {\n options.defaultUpheldReason = defaultUpheldReason;\n }\n if (defaultDismissedReason) {\n options.defaultDismissedReason = defaultDismissedReason;\n }\n\n const penaltyCommand = commandModel.toApplyPenaltyCommand(\n protest.raceId || protestDetail.race?.id,\n protest.accusedDriverId || protestDetail.accusedDriver?.id,\n currentDriverId,\n protest.id || protestDetail.protestId,\n options,\n );\n\n const result = await protestService.applyPenalty(penaltyCommand);\n if (result.isErr()) {\n throw new Error(result.getError().message);\n }\n } else {\n const warningRef = protestDetail.penaltyTypes.find((p: any) => p.type === 'warning');\n const requiresValue = warningRef?.requiresValue ?? false;\n\n const commandModel = new ProtestDecisionCommandModel({\n decision,\n penaltyType: 'warning',\n penaltyValue: 0,\n stewardNotes,\n });\n\n const options: {\n requiresValue?: boolean;\n defaultUpheldReason?: string;\n defaultDismissedReason?: string;\n } = { requiresValue };\n\n if (defaultUpheldReason) {\n options.defaultUpheldReason = defaultUpheldReason;\n }\n if (defaultDismissedReason) {\n options.defaultDismissedReason = defaultDismissedReason;\n }\n\n const penaltyCommand = commandModel.toApplyPenaltyCommand(\n protest.raceId || protestDetail.race?.id,\n protest.accusedDriverId || protestDetail.accusedDriver?.id,\n currentDriverId,\n protest.id || protestDetail.protestId,\n options,\n );\n\n const result = await protestService.applyPenalty(penaltyCommand);\n if (result.isErr()) {\n throw new Error(result.getError().message);\n }\n }\n\n router.push(routes.league.stewarding(leagueId));\n } catch (err) {\n alert(err instanceof Error ? err.message : 'Failed to submit decision');\n } finally {\n setSubmitting(false);\n }\n };\n\n const handleRequestDefense = async () => {\n if (!protestDetail || !currentDriverId) return;\n\n try {\n // Request defense\n const result = await protestService.requestDefense({\n protestId: protestDetail.protest?.id || protestDetail.protestId,\n stewardId: currentDriverId,\n });\n if (result.isErr()) {\n throw new Error(result.getError().message);\n }\n\n // Reload page to show updated status\n window.location.reload();\n } catch (err) {\n alert(err instanceof Error ? err.message : 'Failed to request defense');\n }\n };\n\n const getStatusConfig = (status: string) => {\n switch (status) {\n case 'pending':\n return { label: 'Pending Review', bg: 'bg-warning-amber/20', color: 'text-warning-amber', borderColor: 'border-warning-amber/30', icon: Clock };\n case 'under_review':\n return { label: 'Under Review', bg: 'bg-blue-500/20', color: 'text-blue-400', borderColor: 'border-blue-500/30', icon: Shield };\n case 'awaiting_defense':\n return { label: 'Awaiting Defense', bg: 'bg-purple-500/20', color: 'text-purple-400', borderColor: 'border-purple-500/30', icon: MessageCircle };\n case 'upheld':\n return { label: 'Upheld', bg: 'bg-red-500/20', color: 'text-red-400', borderColor: 'border-red-500/30', icon: CheckCircle };\n case 'dismissed':\n return { label: 'Dismissed', bg: 'bg-gray-500/20', color: 'text-gray-400', borderColor: 'border-gray-500/30', icon: XCircle };\n default:\n return { label: status, bg: 'bg-gray-500/20', color: 'text-gray-400', borderColor: 'border-gray-500/30', icon: AlertCircle };\n }\n };\n\n // Show loading for admin check\n if (adminLoading) {\n return ;\n }\n\n // Show access denied if not admin\n if (!isAdmin) {\n return (\n \n \n \n \n \n Admin Access Required\n \n \n Only league admins can review protests.\n \n \n \n \n );\n }\n\n return (\n \n {(pd: any) => {\n if (!pd) return null;\n \n const protest = pd.protest || pd;\n const race = pd.race;\n const protestingDriver = pd.protestingDriver;\n const accusedDriver = pd.accusedDriver;\n\n const statusConfig = getStatusConfig(protest.status);\n const StatusIcon = statusConfig.icon;\n const isPending = protest.status === 'pending';\n const submittedAt = protest.submittedAt || pd.submittedAt;\n const daysSinceFiled = Math.floor((Date.now() - new Date(submittedAt).getTime()) / (1000 * 60 * 60 * 24));\n\n return (\n \n {/* Compact Header */}\n \n \n \n \n \n \n Protest Review\n \n \n {statusConfig.label}\n \n {daysSinceFiled > 2 && isPending && (\n \n \n {daysSinceFiled}d old\n \n )}\n \n \n \n\n {/* Main Layout: Feed + Sidebar */}\n \n {/* Left Sidebar - Incident Info */}\n \n \n {/* Drivers Involved */}\n \n \n Parties Involved\n \n \n {/* Protesting Driver */}\n \n \n \n \n \n \n Protesting\n {protestingDriver?.name || 'Unknown'}\n \n \n \n \n\n {/* Accused Driver */}\n \n \n \n \n \n \n Accused\n {accusedDriver?.name || 'Unknown'}\n \n \n \n \n \n \n \n\n {/* Race Info */}\n \n \n Race Details\n \n \n \n \n {race?.name || 'Unknown Race'}\n \n \n \n \n\n \n \n \n {race?.name || 'Unknown Track'}\n \n \n \n {race?.formattedDate || (race?.scheduledAt ? new Date(race.scheduledAt).toLocaleDateString() : 'Unknown Date')}\n \n {protest.incident?.lap && (\n \n \n Lap {protest.incident.lap}\n \n )}\n \n \n \n\n {protest.proofVideoUrl && (\n \n \n Evidence\n \n \n \n Watch Video\n \n \n \n \n \n )}\n\n {/* Quick Stats */}\n \n \n Timeline\n \n \n Filed\n {new Date(submittedAt).toLocaleDateString()}\n \n \n Age\n 2 ? 'text-red-400' : 'text-gray-300'}>{daysSinceFiled} days\n \n {protest.reviewedAt && (\n \n Resolved\n {new Date(protest.reviewedAt).toLocaleDateString()}\n \n )}\n \n \n \n \n \n\n {/* Center - Discussion Feed */}\n \n \n {/* Timeline / Feed */}\n \n \n Discussion\n \n\n \n {/* Initial Protest Filing */}\n \n \n \n \n \n \n \n {protestingDriver?.name || 'Unknown'}\n filed protest\n \n {new Date(submittedAt).toLocaleString()}\n \n \n \n {protest.description || pd.incident?.description}\n\n {(protest.comment || pd.comment) && (\n \n Additional details:\n {protest.comment || pd.comment}\n \n )}\n \n \n \n \n\n {/* Defense placeholder */}\n {protest.status === 'awaiting_defense' && (\n \n \n \n \n \n \n Defense Requested\n Waiting for {accusedDriver?.name || 'the accused driver'} to submit their defense...\n \n \n \n )}\n\n {/* Decision (if resolved) */}\n {(protest.status === 'upheld' || protest.status === 'dismissed') && protest.decisionNotes && (\n \n \n \n \n \n \n \n Steward Decision\n \n {protest.status === 'upheld' ? 'Protest Upheld' : 'Protest Dismissed'}\n \n {protest.reviewedAt && (\n <>\n \n {new Date(protest.reviewedAt).toLocaleString()}\n \n )}\n \n \n \n {protest.decisionNotes}\n \n \n \n \n )}\n \n\n {/* Add Comment */}\n {isPending && (\n \n \n \n \n \n \n setNewComment(e.target.value)}\n placeholder=\"Add a comment or request more information...\"\n rows={2}\n style={{\n width: '100%',\n padding: '0.75rem 1rem',\n backgroundColor: '#181B1F',\n border: '1px solid #22262A',\n borderRadius: '0.5rem',\n color: 'white',\n fontSize: '0.875rem',\n resize: 'none',\n outline: 'none'\n }}\n />\n \n \n \n \n \n \n )}\n \n \n \n\n {/* Right Sidebar - Actions */}\n \n \n {isPending && (\n <>\n {/* Quick Actions */}\n \n \n Actions\n \n \n \n \n \n Request Defense\n \n \n \n setShowDecisionPanel(!showDecisionPanel)}\n >\n \n \n Make Decision\n \n \n \n \n \n \n \n \n\n {/* Decision Panel */}\n {showDecisionPanel && (\n \n \n Stewarding Decision\n \n {/* Decision Selection */}\n \n setDecision('uphold')}\n style={{ \n padding: '0.75rem',\n border: '2px solid',\n borderColor: decision === 'uphold' ? '#EF4444' : '#22262A',\n backgroundColor: decision === 'uphold' ? 'rgba(239, 68, 68, 0.1)' : 'transparent'\n }}\n >\n \n \n Uphold\n \n \n setDecision('dismiss')}\n style={{ \n padding: '0.75rem',\n border: '2px solid',\n borderColor: decision === 'dismiss' ? '#4B5563' : '#22262A',\n backgroundColor: decision === 'dismiss' ? 'rgba(75, 85, 99, 0.1)' : 'transparent'\n }}\n >\n \n \n Dismiss\n \n \n \n\n {/* Penalty Selection (if upholding) */}\n {decision === 'uphold' && (\n \n Penalty Type\n\n {penaltyTypes.length === 0 ? (\n \n Loading penalty types...\n \n ) : (\n <>\n \n {penaltyTypes.map((penalty: any) => {\n const Icon = penalty.icon;\n const isSelected = penaltyType === penalty.type;\n return (\n {\n setPenaltyType(penalty.type);\n setPenaltyValue(penalty.defaultValue);\n }}\n style={{ \n padding: '0.5rem',\n border: '1px solid',\n borderColor: isSelected ? undefined : '#22262A',\n backgroundColor: isSelected ? undefined : 'rgba(24, 27, 31, 0.3)'\n }}\n color={isSelected ? penalty.color : undefined}\n title={penalty.description}\n >\n \n \n \n {penalty.label}\n \n \n \n );\n })}\n \n\n {selectedPenalty?.requiresValue && (\n \n \n Value ({selectedPenalty.valueLabel})\n \n setPenaltyValue(Number(e.target.value))}\n min=\"1\"\n style={{\n width: '100%',\n padding: '0.5rem 0.75rem',\n backgroundColor: '#181B1F',\n border: '1px solid #22262A',\n borderRadius: '0.5rem',\n color: 'white',\n fontSize: '0.875rem',\n outline: 'none'\n }}\n />\n \n )}\n \n )}\n \n )}\n\n {/* Steward Notes */}\n \n Decision Reasoning *\n setStewardNotes(e.target.value)}\n placeholder=\"Explain your decision...\"\n rows={4}\n style={{\n width: '100%',\n padding: '0.5rem 0.75rem',\n backgroundColor: '#181B1F',\n border: '1px solid #22262A',\n borderRadius: '0.5rem',\n color: 'white',\n fontSize: '0.875rem',\n resize: 'none',\n outline: 'none'\n }}\n />\n \n\n {/* Submit */}\n \n {submitting ? 'Submitting...' : 'Submit Decision'}\n \n \n \n )}\n \n )}\n\n {/* Already Resolved Info */}\n {!isPending && (\n \n \n \n \n Case Closed\n \n {protest.status === 'upheld' ? 'Protest was upheld' : 'Protest was dismissed'}\n \n \n \n \n )}\n \n \n \n \n );\n }}\n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/leagues/[id]/stewarding/protests/[protestId]/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/leagues/[id]/wallet/LeagueWalletPageClient.tsx","messages":[{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`'` can be escaped with `'`, `‘`, `'`, `’`.","line":62,"column":57,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"'"},"fix":{"range":[2066,2107],"text":"Manage your league's finances and payouts"},"desc":"Replace with `'`."},{"messageId":"replaceWithAlt","data":{"alt":"‘"},"fix":{"range":[2066,2107],"text":"Manage your league‘s finances and payouts"},"desc":"Replace with `‘`."},{"messageId":"replaceWithAlt","data":{"alt":"'"},"fix":{"range":[2066,2107],"text":"Manage your league's finances and payouts"},"desc":"Replace with `'`."},{"messageId":"replaceWithAlt","data":{"alt":"’"},"fix":{"range":[2066,2107],"text":"Manage your league’s finances and payouts"},"desc":"Replace with `’`."}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":67,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":67,"endColumn":44},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":77,"column":29,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":77,"endColumn":48},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":88,"column":28,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":88,"endColumn":82},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":103,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":103,"endColumn":67},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":117,"column":29,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":117,"endColumn":66},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":131,"column":29,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":131,"endColumn":67},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":145,"column":24,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":145,"endColumn":59},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":160,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":170,"endColumn":20},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":160,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":164,"endColumn":12},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":163,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":163,"endColumn":155},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":165,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":165,"endColumn":33},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":166,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":166,"endColumn":41},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":167,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":167,"endColumn":40},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":168,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":168,"endColumn":40},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":169,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":169,"endColumn":35},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":175,"column":67,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":175,"endColumn":100},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":288,"column":67,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":288,"endColumn":108},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":291,"column":23,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":298,"endColumn":25},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":291,"column":23,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":298,"endColumn":25},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":296,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":296,"endColumn":169},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":309,"column":21,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":311,"endColumn":30},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":309,"column":21,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":309,"endColumn":169},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":309,"column":29,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":309,"endColumn":168},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":310,"column":23,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":310,"endColumn":31}],"suppressedMessages":[],"errorCount":25,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\n\nimport React, { useState, useMemo } from 'react';\nimport { Card } from '@/ui/Card';\nimport { Button } from '@/ui/Button';\nimport { TransactionRow } from '@/components/leagues/TransactionRow';\nimport type { LeagueWalletViewData } from '@/lib/view-data/leagues/LeagueWalletViewData';\nimport { Box } from '@/ui/Box';\nimport { Stack } from '@/ui/Stack';\nimport { Text } from '@/ui/Text';\nimport { Heading } from '@/ui/Heading';\nimport { Container } from '@/ui/Container';\nimport { Grid } from '@/ui/Grid';\nimport { Icon as UIIcon } from '@/ui/Icon';\nimport {\n Wallet,\n DollarSign,\n ArrowUpRight,\n Clock,\n AlertTriangle,\n Download,\n TrendingUp\n} from 'lucide-react';\n\ninterface WalletTemplateProps {\n viewData: LeagueWalletViewData;\n onWithdraw?: (amount: number) => void;\n onExport?: () => void;\n mutationLoading?: boolean;\n}\n\nexport function LeagueWalletPageClient({ viewData, onWithdraw, onExport, mutationLoading = false }: WalletTemplateProps) {\n const [withdrawAmount, setWithdrawAmount] = useState('');\n const [showWithdrawModal, setShowWithdrawModal] = useState(false);\n const [filterType, setFilterType] = useState<'all' | 'sponsorship' | 'membership' | 'withdrawal' | 'prize'>('all');\n\n const filteredTransactions = useMemo(() => {\n if (filterType === 'all') return viewData.transactions;\n return viewData.transactions.filter(t => t.type === filterType);\n }, [viewData.transactions, filterType]);\n\n const handleWithdrawClick = () => {\n const amount = parseFloat(withdrawAmount);\n if (!amount || amount <= 0) return;\n \n if (onWithdraw) {\n onWithdraw(amount);\n setShowWithdrawModal(false);\n setWithdrawAmount('');\n }\n };\n\n const canWithdraw = viewData.balance > 0;\n const withdrawalBlockReason = !canWithdraw ? 'Balance is zero' : undefined;\n\n return (\n \n {/* Header */}\n \n \n League Wallet\n Manage your league's finances and payouts\n \n \n \n setShowWithdrawModal(true)}\n disabled={!canWithdraw || !onWithdraw}\n >\n \n \n Withdraw\n \n \n \n \n\n {/* Withdrawal Warning */}\n {!canWithdraw && withdrawalBlockReason && (\n \n \n \n \n Withdrawals Temporarily Unavailable\n {withdrawalBlockReason}\n \n \n \n )}\n\n {/* Stats Grid */}\n \n \n \n \n \n \n \n \n {viewData.formattedBalance}\n Available Balance\n \n \n \n \n\n \n \n \n \n \n \n \n {viewData.formattedTotalRevenue}\n Total Revenue\n \n \n \n \n\n \n \n \n \n \n \n \n {viewData.formattedTotalFees}\n Platform Fees (10%)\n \n \n \n \n\n \n \n \n \n \n \n \n {viewData.formattedPendingPayouts}\n Pending Payouts\n \n \n \n \n \n\n {/* Transactions */}\n \n \n Transaction History\n setFilterType(e.target.value as typeof filterType)}\n className=\"px-3 py-1.5 rounded-lg border border-charcoal-outline bg-iron-gray text-white text-sm focus:border-primary-blue focus:outline-none\"\n >\n \n \n \n \n \n \n \n\n {filteredTransactions.length === 0 ? (\n \n \n No Transactions\n \n \n {filterType === 'all' \n ? 'Revenue from sponsorships and fees will appear here.'\n : `No ${filterType} transactions found.`}\n \n \n \n ) : (\n \n {filteredTransactions.map((transaction) => (\n \n ))}\n \n )}\n \n\n {/* Revenue Breakdown */}\n \n \n \n Revenue Breakdown\n \n \n \n \n Sponsorships\n \n $1,600.00\n \n \n \n \n Membership Fees\n \n $1,600.00\n \n \n Total Gross Revenue\n $3,200.00\n \n \n Platform Fee (10%)\n -$320.00\n \n \n Net Revenue\n $2,880.00\n \n \n \n \n\n \n \n Payout Schedule\n \n \n \n Season 2 Prize Pool\n Pending\n \n \n Distributed after season completion to top 3 drivers\n \n \n \n \n Available for Withdrawal\n {viewData.formattedBalance}\n \n \n Available after Season 2 ends (estimated: Jan 15, 2026)\n \n \n \n \n \n \n\n {/* Withdraw Modal */}\n {showWithdrawModal && onWithdraw && (\n \n \n \n Withdraw Funds\n \n {!canWithdraw ? (\n \n {withdrawalBlockReason}\n \n ) : (\n \n \n \n Amount to Withdraw\n \n \n \n $\n \n setWithdrawAmount(e.target.value)}\n max={viewData.balance}\n className=\"w-full pl-8 pr-4 py-2 rounded-lg border border-charcoal-outline bg-iron-gray text-white focus:border-primary-blue focus:outline-none\"\n placeholder=\"0.00\"\n />\n \n \n Available: {viewData.formattedBalance}\n \n \n\n \n \n Destination\n \n \n \n \n )}\n\n \n setShowWithdrawModal(false)}\n fullWidth\n >\n Cancel\n \n \n {mutationLoading ? 'Processing...' : 'Withdraw'}\n \n \n \n \n \n )}\n\n {/* Alpha Notice */}\n \n \n Alpha Note: Wallet management is demonstration-only.\n Real payment processing and bank integrations will be available when the payment system is fully implemented.\n The 10% platform fee and season-based withdrawal restrictions are enforced in the actual implementation.\n \n \n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/leagues/[id]/wallet/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/leagues/create/CreateLeagueWizard.tsx","messages":[{"ruleId":"import/no-unresolved","severity":2,"message":"Unable to resolve path to module './LeagueBasicsSection'.","line":31,"column":37,"nodeType":"Literal","endLine":31,"endColumn":60},{"ruleId":"import/no-unresolved","severity":2,"message":"Unable to resolve path to module './LeagueDropSection'.","line":32,"column":35,"nodeType":"Literal","endLine":32,"endColumn":56},{"ruleId":"import/no-unresolved","severity":2,"message":"Unable to resolve path to module './LeagueScoringSection'.","line":36,"column":8,"nodeType":"Literal","endLine":36,"endColumn":32},{"ruleId":"import/no-unresolved","severity":2,"message":"Unable to resolve path to module './LeagueStewardingSection'.","line":37,"column":41,"nodeType":"Literal","endLine":37,"endColumn":68},{"ruleId":"import/no-unresolved","severity":2,"message":"Unable to resolve path to module './LeagueStructureSection'.","line":38,"column":40,"nodeType":"Literal","endLine":38,"endColumn":66},{"ruleId":"import/no-unresolved","severity":2,"message":"Unable to resolve path to module './LeagueTimingsSection'.","line":39,"column":38,"nodeType":"Literal","endLine":39,"endColumn":62},{"ruleId":"import/no-unresolved","severity":2,"message":"Unable to resolve path to module './LeagueVisibilitySection'.","line":40,"column":41,"nodeType":"Literal","endLine":40,"endColumn":68},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":288,"column":34,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":288,"endColumn":37,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[8095,8098],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[8095,8098],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":319,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":319,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[8985,8988],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[8985,8988],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":368,"column":99,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":368,"endColumn":102,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[11470,11473],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[11470,11473],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":412,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":412,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[12713,12716],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[12713,12716],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'submit' is assigned a value but never used.","line":474,"column":15,"nodeType":"Identifier","messageId":"unusedVar","endLine":474,"endColumn":21},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":590,"column":5,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":983,"endColumn":12},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":590,"column":5,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":590,"endColumn":70},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":590,"column":35,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":590,"endColumn":69},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":592,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":609,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":592,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":592,"endColumn":29},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":592,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":592,"endColumn":28},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":593,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":608,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":593,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":593,"endColumn":55},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":593,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":593,"endColumn":54},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":594,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":596,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":594,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":594,"endColumn":169},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":594,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":594,"endColumn":168},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":595,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":595,"endColumn":60},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":597,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":597,"endColumn":16},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":598,"column":32,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":598,"endColumn":64},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":601,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":603,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":601,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":601,"endColumn":50},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":601,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":601,"endColumn":49},{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`'` can be escaped with `'`, `‘`, `'`, `’`.","line":602,"column":17,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"'"},"fix":{"range":[19876,19930],"text":"\n We'll also set up your first season in "},"desc":"Replace with `'`."},{"messageId":"replaceWithAlt","data":{"alt":"‘"},"fix":{"range":[19876,19930],"text":"\n We‘ll also set up your first season in "},"desc":"Replace with `‘`."},{"messageId":"replaceWithAlt","data":{"alt":"'"},"fix":{"range":[19876,19930],"text":"\n We'll also set up your first season in "},"desc":"Replace with `'`."},{"messageId":"replaceWithAlt","data":{"alt":"’"},"fix":{"range":[19876,19930],"text":"\n We’ll also set up your first season in "},"desc":"Replace with `’`."}]},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":604,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":606,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":604,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":604,"endColumn":55},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":604,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":604,"endColumn":54},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":612,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":677,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":612,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":612,"endColumn":45},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":612,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":612,"endColumn":44},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":613,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":676,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":613,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":613,"endColumn":35},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":613,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":613,"endColumn":34},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":615,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":615,"endColumn":99},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":615,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":615,"endColumn":99},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":615,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":615,"endColumn":96},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":617,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":620,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":617,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":620,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":618,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":618,"endColumn":150},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":619,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":619,"endColumn":90},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":622,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":675,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":622,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":622,"endColumn":58},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":622,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":622,"endColumn":57},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":630,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":672,"endColumn":26},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":630,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":636,"endColumn":18},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":635,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":635,"endColumn":124},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":637,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":656,"endColumn":25},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":637,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":650,"endColumn":20},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":638,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":649,"endColumn":23},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":652,"column":30,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":652,"endColumn":49},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":654,"column":33,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":654,"endColumn":52},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":657,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":671,"endColumn":25},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":657,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":657,"endColumn":53},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":657,"column":24,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":657,"endColumn":52},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":658,"column":21,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":670,"endColumn":25},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":658,"column":21,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":668,"endColumn":22},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":659,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":667,"endColumn":26},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":680,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":713,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":680,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":680,"endColumn":39},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":680,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":680,"endColumn":38},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":681,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":689,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":681,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":681,"endColumn":65},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":681,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":681,"endColumn":64},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":682,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":685,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":682,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":682,"endColumn":52},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":682,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":682,"endColumn":51},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":683,"column":30,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":683,"endColumn":67},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":684,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":684,"endColumn":93},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":684,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":684,"endColumn":62},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":684,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":684,"endColumn":61},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":686,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":688,"endColumn":18},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":686,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":686,"endColumn":51},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":686,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":686,"endColumn":50},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":690,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":695,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":690,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":690,"endColumn":81},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":690,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":690,"endColumn":80},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":691,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":694,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":691,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":694,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":692,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":692,"endColumn":129},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":693,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":693,"endColumn":65},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":697,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":712,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":697,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":697,"endColumn":59},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":697,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":697,"endColumn":58},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":699,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":710,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":699,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":710,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":701,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":709,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":716,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":716,"endColumn":49},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":718,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":718,"endColumn":128},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":718,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":718,"endColumn":128},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":718,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":718,"endColumn":125},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":721,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":743,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":721,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":721,"endColumn":54},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":721,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":721,"endColumn":53},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":722,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":724,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":722,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":722,"endColumn":144},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":722,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":722,"endColumn":143},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":723,"column":30,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":723,"endColumn":67},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":725,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":737,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":725,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":725,"endColumn":43},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":725,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":725,"endColumn":42},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":726,"column":32,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":726,"endColumn":88},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":727,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":732,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":727,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":727,"endColumn":66},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":727,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":727,"endColumn":65},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":728,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":728,"endColumn":23},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":729,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":731,"endColumn":24},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":729,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":729,"endColumn":170},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":729,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":729,"endColumn":169},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":734,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":736,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":734,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":734,"endColumn":55},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":734,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":734,"endColumn":54},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":738,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":742,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":738,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":738,"endColumn":137},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":738,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":738,"endColumn":136},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":739,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":739,"endColumn":64},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":739,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":739,"endColumn":53},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":739,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":739,"endColumn":52},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":740,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":740,"endColumn":77},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":740,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":740,"endColumn":64},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":740,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":740,"endColumn":63},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":741,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":741,"endColumn":76},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":741,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":741,"endColumn":53},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":741,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":741,"endColumn":52},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":746,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":746,"endColumn":108},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":746,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":746,"endColumn":108},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":746,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":746,"endColumn":105},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":749,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":915,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":749,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":749,"endColumn":40},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":749,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":749,"endColumn":39},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":751,"column":12,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":787,"endColumn":18},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":751,"column":12,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":751,"endColumn":55},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":751,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":751,"endColumn":54},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":757,"column":14,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":786,"endColumn":20},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":757,"column":14,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":757,"endColumn":93},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":757,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":757,"endColumn":92},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":758,"column":16,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":767,"endColumn":22},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":758,"column":16,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":758,"endColumn":78},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":758,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":758,"endColumn":77},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":759,"column":18,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":759,"endColumn":23},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":760,"column":20,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":762,"endColumn":24},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":760,"column":20,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":760,"endColumn":95},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":760,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":760,"endColumn":94},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":763,"column":20,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":765,"endColumn":24},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":763,"column":20,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":763,"endColumn":57},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":763,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":763,"endColumn":56},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":768,"column":16,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":785,"endColumn":22},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":768,"column":16,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":768,"endColumn":48},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":768,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":768,"endColumn":47},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":769,"column":18,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":771,"endColumn":26},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":769,"column":18,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":769,"endColumn":71},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":769,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":769,"endColumn":70},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":782,"column":18,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":784,"endColumn":22},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":782,"column":18,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":782,"endColumn":55},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":782,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":782,"endColumn":54},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":791,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":801,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":791,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":791,"endColumn":46},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":791,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":791,"endColumn":45},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":805,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":819,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":805,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":805,"endColumn":56},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":805,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":805,"endColumn":55},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":806,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":813,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":806,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":806,"endColumn":37},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":806,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":806,"endColumn":36},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":807,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":809,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":807,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":807,"endColumn":54},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":807,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":807,"endColumn":53},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":810,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":812,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":810,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":810,"endColumn":54},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":810,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":810,"endColumn":53},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":823,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":837,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":823,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":823,"endColumn":56},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":823,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":823,"endColumn":55},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":824,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":831,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":824,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":824,"endColumn":37},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":824,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":824,"endColumn":36},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":825,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":827,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":825,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":825,"endColumn":54},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":825,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":825,"endColumn":53},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":828,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":830,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":828,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":828,"endColumn":54},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":828,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":828,"endColumn":53},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":841,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":883,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":841,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":841,"endColumn":56},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":841,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":841,"endColumn":55},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":842,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":849,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":842,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":842,"endColumn":37},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":842,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":842,"endColumn":36},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":843,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":845,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":843,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":843,"endColumn":54},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":843,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":843,"endColumn":53},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":846,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":848,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":846,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":846,"endColumn":54},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":846,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":846,"endColumn":53},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":869,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":869,"endColumn":109},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":869,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":869,"endColumn":109},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":869,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":869,"endColumn":106},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":872,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":875,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":872,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":872,"endColumn":70},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":872,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":872,"endColumn":69},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":878,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":881,"endColumn":23},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":878,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":878,"endColumn":123},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":878,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":878,"endColumn":122},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":879,"column":32,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":879,"endColumn":86},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":880,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":880,"endColumn":80},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":880,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":880,"endColumn":61},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":880,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":880,"endColumn":60},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":887,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":901,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":887,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":887,"endColumn":56},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":887,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":887,"endColumn":55},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":888,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":895,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":888,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":888,"endColumn":37},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":888,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":888,"endColumn":36},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":889,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":891,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":889,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":889,"endColumn":54},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":889,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":889,"endColumn":53},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":892,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":894,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":892,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":892,"endColumn":54},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":892,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":892,"endColumn":53},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":905,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":913,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":905,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":905,"endColumn":56},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":905,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":905,"endColumn":55},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":908,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":911,"endColumn":23},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":908,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":908,"endColumn":123},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":908,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":908,"endColumn":122},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":909,"column":32,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":909,"endColumn":86},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":910,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":910,"endColumn":80},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":910,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":910,"endColumn":61},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":910,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":910,"endColumn":60},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":919,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":977,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":919,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":919,"endColumn":63},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":919,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":919,"endColumn":62},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":925,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":925,"endColumn":46},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":927,"column":24,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":927,"endColumn":43},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":928,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":928,"endColumn":57},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":928,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":928,"endColumn":46},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":928,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":928,"endColumn":45},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":931,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":976,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":931,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":931,"endColumn":50},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":931,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":931,"endColumn":49},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":933,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":943,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":933,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":933,"endColumn":62},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":933,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":933,"endColumn":61},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":935,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":941,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":935,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":941,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":937,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":940,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":951,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":951,"endColumn":50},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":953,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":953,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":954,"column":29,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":954,"endColumn":48},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":961,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":961,"endColumn":79},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":965,"column":28,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":965,"endColumn":60},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":966,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":966,"endColumn":25},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":970,"column":29,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":970,"endColumn":48},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":971,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":971,"endColumn":25},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":980,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":982,"endColumn":11},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":980,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":980,"endColumn":61},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":980,"column":10,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":980,"endColumn":60}],"suppressedMessages":[],"errorCount":263,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\n\nimport { LeagueReviewSummary } from '@/components/leagues/LeagueReviewSummary';\nimport { Button } from '@/ui/Button';\nimport { Card } from '@/ui/Card';\nimport { Heading } from '@/ui/Heading';\nimport { Input } from '@/ui/Input';\nimport { useAuth } from '@/lib/auth/AuthContext';\nimport {\n AlertCircle,\n Award,\n Calendar,\n Check,\n CheckCircle2,\n ChevronLeft,\n ChevronRight,\n FileText,\n Loader2,\n Scale,\n Sparkles,\n Trophy,\n Users,\n} from 'lucide-react';\nimport { useRouter } from 'next/navigation';\nimport { FormEvent, useCallback, useEffect, useState } from 'react';\n\nimport { LeagueWizardCommandModel } from '@/lib/command-models/leagues/LeagueWizardCommandModel';\n\nimport { useCreateLeagueWizard } from \"@/hooks/useLeagueWizardService\";\nimport { useLeagueScoringPresets } from \"@/hooks/useLeagueScoringPresets\";\nimport { LeagueBasicsSection } from './LeagueBasicsSection';\nimport { LeagueDropSection } from './LeagueDropSection';\nimport {\n ChampionshipsSection,\n ScoringPatternSection\n} from './LeagueScoringSection';\nimport { LeagueStewardingSection } from './LeagueStewardingSection';\nimport { LeagueStructureSection } from './LeagueStructureSection';\nimport { LeagueTimingsSection } from './LeagueTimingsSection';\nimport { LeagueVisibilitySection } from './LeagueVisibilitySection';\nimport type { LeagueConfigFormModel } from '@/lib/types/LeagueConfigFormModel';\nimport type { LeagueScoringPresetViewModel } from '@/lib/view-models/LeagueScoringPresetViewModel';\nimport type { Weekday } from '@/lib/types/Weekday';\nimport type { WizardErrors } from '@/lib/types/WizardErrors';\n\n// ============================================================================\n// LOCAL STORAGE PERSISTENCE\n// ============================================================================\n\nconst STORAGE_KEY = 'gridpilot_league_wizard_draft';\nconst STORAGE_HIGHEST_STEP_KEY = 'gridpilot_league_wizard_highest_step';\n\n// TODO there is a better place for this\nfunction saveFormToStorage(form: LeagueWizardFormModel): void {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(form));\n } catch {\n // Ignore storage errors (quota exceeded, etc.)\n }\n}\n\n// TODO there is a better place for this\nfunction loadFormFromStorage(): LeagueWizardFormModel | null {\n try {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (stored) {\n const parsed = JSON.parse(stored) as LeagueWizardFormModel;\n if (!parsed.seasonName) {\n const seasonStartDate = parsed.timings?.seasonStartDate;\n parsed.seasonName = getDefaultSeasonName(seasonStartDate);\n }\n return parsed;\n }\n } catch {\n // Ignore parse errors\n }\n return null;\n}\n\nfunction clearFormStorage(): void {\n try {\n localStorage.removeItem(STORAGE_KEY);\n localStorage.removeItem(STORAGE_HIGHEST_STEP_KEY);\n } catch {\n // Ignore storage errors\n }\n}\n\nfunction saveHighestStep(step: number): void {\n try {\n const current = getHighestStep();\n if (step > current) {\n localStorage.setItem(STORAGE_HIGHEST_STEP_KEY, String(step));\n }\n } catch {\n // Ignore storage errors\n }\n}\n\nfunction getHighestStep(): number {\n try {\n const stored = localStorage.getItem(STORAGE_HIGHEST_STEP_KEY);\n return stored ? parseInt(stored, 10) : 1;\n } catch {\n return 1;\n }\n}\n\ntype Step = 1 | 2 | 3 | 4 | 5 | 6 | 7;\n\ntype StepName = 'basics' | 'visibility' | 'structure' | 'schedule' | 'scoring' | 'stewarding' | 'review';\n\ntype LeagueWizardFormModel = LeagueConfigFormModel & {\n seasonName?: string;\n};\n\ninterface CreateLeagueWizardProps {\n stepName: StepName;\n onStepChange: (stepName: StepName) => void;\n}\n\nfunction stepNameToStep(stepName: StepName): Step {\n switch (stepName) {\n case 'basics':\n return 1;\n case 'visibility':\n return 2;\n case 'structure':\n return 3;\n case 'schedule':\n return 4;\n case 'scoring':\n return 5;\n case 'stewarding':\n return 6;\n case 'review':\n return 7;\n }\n}\n\nfunction stepToStepName(step: Step): StepName {\n switch (step) {\n case 1:\n return 'basics';\n case 2:\n return 'visibility';\n case 3:\n return 'structure';\n case 4:\n return 'schedule';\n case 5:\n return 'scoring';\n case 6:\n return 'stewarding';\n case 7:\n return 'review';\n }\n}\n\nfunction getDefaultSeasonStartDate(): string {\n // Default to next Saturday\n const now = new Date();\n const daysUntilSaturday = (6 - now.getDay() + 7) % 7 || 7;\n const nextSaturday = new Date(now);\n nextSaturday.setDate(now.getDate() + daysUntilSaturday);\n const [datePart] = nextSaturday.toISOString().split('T');\n return datePart ?? '';\n}\n\nfunction getDefaultSeasonName(seasonStartDate?: string): string {\n if (seasonStartDate) {\n const parsed = new Date(seasonStartDate);\n if (!Number.isNaN(parsed.getTime())) {\n const year = parsed.getFullYear();\n return `Season 1 (${year})`;\n }\n }\n const fallbackYear = new Date().getFullYear();\n return `Season 1 (${fallbackYear})`;\n}\n\nfunction createDefaultForm(): LeagueWizardFormModel {\n const defaultPatternId = 'sprint-main-driver';\n const defaultSeasonStartDate = getDefaultSeasonStartDate();\n\n return {\n basics: {\n name: '',\n description: '',\n visibility: 'public',\n gameId: 'iracing',\n },\n structure: {\n mode: 'solo',\n maxDrivers: 24,\n multiClassEnabled: false,\n },\n championships: {\n enableDriverChampionship: true,\n enableTeamChampionship: false,\n enableNationsChampionship: false,\n enableTrophyChampionship: false,\n },\n scoring: {\n patternId: defaultPatternId,\n customScoringEnabled: false,\n },\n dropPolicy: {\n strategy: 'bestNResults',\n n: 6,\n },\n timings: {\n practiceMinutes: 20,\n qualifyingMinutes: 30,\n sprintRaceMinutes: 20,\n mainRaceMinutes: 40,\n sessionCount: 2,\n roundsPlanned: 8,\n // Default to Saturday races, weekly, starting next week\n weekdays: ['Sat'] as Weekday[],\n recurrenceStrategy: 'weekly' as const,\n timezoneId: 'UTC',\n seasonStartDate: defaultSeasonStartDate,\n },\n stewarding: {\n decisionMode: 'admin_only',\n requiredVotes: 2,\n requireDefense: false,\n defenseTimeLimit: 48,\n voteTimeLimit: 72,\n protestDeadlineHours: 48,\n stewardingClosesHours: 168,\n notifyAccusedOnProtest: true,\n notifyOnVoteRequired: true,\n },\n seasonName: getDefaultSeasonName(defaultSeasonStartDate),\n };\n}\n\nexport function CreateLeagueWizard({ stepName, onStepChange }: CreateLeagueWizardProps) {\n const router = useRouter();\n const { session } = useAuth();\n\n const step = stepNameToStep(stepName);\n const [loading, setLoading] = useState(false);\n const [presetsLoading, setPresetsLoading] = useState(true);\n const [presets, setPresets] = useState([]);\n const [errors, setErrors] = useState({});\n const [highestCompletedStep, setHighestCompletedStep] = useState(1);\n const [isHydrated, setIsHydrated] = useState(false);\n \n // Initialize form from localStorage or defaults\n const [form, setForm] = useState(() =>\n createDefaultForm(),\n );\n\n // Hydrate from localStorage on mount\n useEffect(() => {\n const stored = loadFormFromStorage();\n if (stored) {\n setForm(stored);\n }\n setHighestCompletedStep(getHighestStep());\n setIsHydrated(true);\n }, []);\n\n // Save form to localStorage whenever it changes (after hydration)\n useEffect(() => {\n if (isHydrated) {\n saveFormToStorage(form);\n }\n }, [form, isHydrated]);\n\n // Track highest step reached\n useEffect(() => {\n if (isHydrated) {\n saveHighestStep(step);\n setHighestCompletedStep((prev) => Math.max(prev, step));\n }\n }, [step, isHydrated]);\n\n // Use the react-query hook for scoring presets\n const { data: queryPresets, error: presetsError } = useLeagueScoringPresets();\n\n // Sync presets from query to local state\n useEffect(() => {\n if (queryPresets) {\n setPresets(queryPresets as any);\n const firstPreset = queryPresets[0];\n if (firstPreset && !form.scoring?.patternId) {\n setForm((prev) => ({\n ...prev,\n scoring: {\n ...prev.scoring,\n patternId: firstPreset.id,\n customScoringEnabled: false,\n },\n }));\n }\n setPresetsLoading(false);\n }\n }, [queryPresets, form.scoring?.patternId]);\n\n // Handle presets error\n useEffect(() => {\n if (presetsError) {\n setErrors((prev) => ({\n ...prev,\n submit: presetsError instanceof Error ? presetsError.message : 'Failed to load scoring presets',\n }));\n }\n }, [presetsError]);\n\n // Use the create league mutation\n const createLeagueMutation = useCreateLeagueWizard();\n\n const validateStep = (currentStep: Step): boolean => {\n // Convert form to LeagueWizardFormData for validation\n const formData: any = {\n leagueId: form.leagueId || '',\n basics: {\n name: form.basics?.name || '',\n description: form.basics?.description || '',\n visibility: (form.basics?.visibility as 'public' | 'private' | 'unlisted') || 'public',\n gameId: form.basics?.gameId || 'iracing',\n },\n structure: {\n mode: (form.structure?.mode as 'solo' | 'fixedTeams') || 'solo',\n maxDrivers: form.structure?.maxDrivers || 0,\n maxTeams: form.structure?.maxTeams || 0,\n driversPerTeam: form.structure?.driversPerTeam || 0,\n },\n championships: {\n enableDriverChampionship: form.championships?.enableDriverChampionship ?? true,\n enableTeamChampionship: form.championships?.enableTeamChampionship ?? false,\n enableNationsChampionship: form.championships?.enableNationsChampionship ?? false,\n enableTrophyChampionship: form.championships?.enableTrophyChampionship ?? false,\n },\n scoring: {\n patternId: form.scoring?.patternId || '',\n customScoringEnabled: form.scoring?.customScoringEnabled ?? false,\n },\n dropPolicy: {\n strategy: (form.dropPolicy?.strategy as 'none' | 'bestNResults' | 'dropWorstN') || 'bestNResults',\n n: form.dropPolicy?.n || 6,\n },\n timings: {\n practiceMinutes: form.timings?.practiceMinutes || 0,\n qualifyingMinutes: form.timings?.qualifyingMinutes || 0,\n sprintRaceMinutes: form.timings?.sprintRaceMinutes || 0,\n mainRaceMinutes: form.timings?.mainRaceMinutes || 0,\n sessionCount: form.timings?.sessionCount || 0,\n roundsPlanned: form.timings?.roundsPlanned || 0,\n },\n stewarding: {\n decisionMode: (form.stewarding?.decisionMode as 'owner_only' | 'admin_vote' | 'steward_panel') || 'admin_only',\n requiredVotes: form.stewarding?.requiredVotes || 0,\n requireDefense: form.stewarding?.requireDefense ?? false,\n defenseTimeLimit: form.stewarding?.defenseTimeLimit || 0,\n voteTimeLimit: form.stewarding?.voteTimeLimit || 0,\n protestDeadlineHours: form.stewarding?.protestDeadlineHours || 0,\n stewardingClosesHours: form.stewarding?.stewardingClosesHours || 0,\n notifyAccusedOnProtest: form.stewarding?.notifyAccusedOnProtest ?? true,\n notifyOnVoteRequired: form.stewarding?.notifyOnVoteRequired ?? true,\n },\n };\n\n const stepErrors = LeagueWizardCommandModel.validateLeagueWizardStep(formData, currentStep as any);\n setErrors((prev) => ({\n ...prev,\n ...stepErrors,\n }));\n return !LeagueWizardCommandModel.hasWizardErrors(stepErrors);\n };\n\n const goToNextStep = () => {\n if (!validateStep(step)) {\n return;\n }\n const nextStep = (step < 7 ? ((step + 1) as Step) : step);\n saveHighestStep(nextStep);\n setHighestCompletedStep((prev) => Math.max(prev, nextStep));\n onStepChange(stepToStepName(nextStep));\n };\n\n const goToPreviousStep = () => {\n const prevStep = (step > 1 ? ((step - 1) as Step) : step);\n onStepChange(stepToStepName(prevStep));\n };\n\n // Navigate to a specific step (only if it's been reached before)\n const goToStep = useCallback((targetStep: Step) => {\n if (targetStep <= highestCompletedStep) {\n onStepChange(stepToStepName(targetStep));\n }\n }, [highestCompletedStep, onStepChange]);\n\n const handleSubmit = async (event: FormEvent) => {\n event.preventDefault();\n if (loading) return;\n\n const ownerId = session?.user.userId;\n if (!ownerId) {\n setErrors((prev) => ({\n ...prev,\n submit: 'You must be logged in to create a league',\n }));\n return;\n }\n\n // Convert form to LeagueWizardFormData for validation\n const formData: any = {\n leagueId: form.leagueId || '',\n basics: {\n name: form.basics?.name || '',\n description: form.basics?.description || '',\n visibility: (form.basics?.visibility as 'public' | 'private' | 'unlisted') || 'public',\n gameId: form.basics?.gameId || 'iracing',\n },\n structure: {\n mode: (form.structure?.mode as 'solo' | 'fixedTeams') || 'solo',\n maxDrivers: form.structure?.maxDrivers || 0,\n maxTeams: form.structure?.maxTeams || 0,\n driversPerTeam: form.structure?.driversPerTeam || 0,\n },\n championships: {\n enableDriverChampionship: form.championships?.enableDriverChampionship ?? true,\n enableTeamChampionship: form.championships?.enableTeamChampionship ?? false,\n enableNationsChampionship: form.championships?.enableNationsChampionship ?? false,\n enableTrophyChampionship: form.championships?.enableTrophyChampionship ?? false,\n },\n scoring: {\n patternId: form.scoring?.patternId || '',\n customScoringEnabled: form.scoring?.customScoringEnabled ?? false,\n },\n dropPolicy: {\n strategy: (form.dropPolicy?.strategy as 'none' | 'bestNResults' | 'dropWorstN') || 'bestNResults',\n n: form.dropPolicy?.n || 6,\n },\n timings: {\n practiceMinutes: form.timings?.practiceMinutes || 0,\n qualifyingMinutes: form.timings?.qualifyingMinutes || 0,\n sprintRaceMinutes: form.timings?.sprintRaceMinutes || 0,\n mainRaceMinutes: form.timings?.mainRaceMinutes || 0,\n sessionCount: form.timings?.sessionCount || 0,\n roundsPlanned: form.timings?.roundsPlanned || 0,\n },\n stewarding: {\n decisionMode: (form.stewarding?.decisionMode as 'owner_only' | 'admin_vote' | 'steward_panel') || 'admin_only',\n requiredVotes: form.stewarding?.requiredVotes || 0,\n requireDefense: form.stewarding?.requireDefense ?? false,\n defenseTimeLimit: form.stewarding?.defenseTimeLimit || 0,\n voteTimeLimit: form.stewarding?.voteTimeLimit || 0,\n protestDeadlineHours: form.stewarding?.protestDeadlineHours || 0,\n stewardingClosesHours: form.stewarding?.stewardingClosesHours || 0,\n notifyAccusedOnProtest: form.stewarding?.notifyAccusedOnProtest ?? true,\n notifyOnVoteRequired: form.stewarding?.notifyOnVoteRequired ?? true,\n },\n };\n\n const allErrors = LeagueWizardCommandModel.validateAllLeagueWizardSteps(formData);\n setErrors((prev) => ({\n ...prev,\n ...allErrors,\n }));\n\n if (LeagueWizardCommandModel.hasWizardErrors(allErrors)) {\n onStepChange('basics');\n return;\n }\n\n setLoading(true);\n setErrors((prev) => {\n const { submit, ...rest } = prev;\n return rest;\n });\n\n try {\n // Use the mutation to create the league\n const result = await createLeagueMutation.mutateAsync({ form, ownerId });\n \n // Clear the draft on successful creation\n clearFormStorage();\n \n // Navigate to the new league\n router.push(`/leagues/${result.leagueId}`);\n } catch (err) {\n const message =\n err instanceof Error ? err.message : 'Failed to create league';\n setErrors((prev) => ({\n ...prev,\n submit: message,\n }));\n setLoading(false);\n }\n };\n\n // Handler for scoring preset selection (timings default from API)\n const handleScoringPresetChange = (patternId: string) => {\n setForm((prev) => {\n const selectedPreset = presets.find((p) => p.id === patternId);\n\n return {\n ...prev,\n scoring: {\n ...prev.scoring,\n patternId,\n customScoringEnabled: false,\n },\n timings: selectedPreset\n ? {\n ...prev.timings,\n practiceMinutes: prev.timings?.practiceMinutes ?? selectedPreset.defaultTimings.practiceMinutes,\n qualifyingMinutes: prev.timings?.qualifyingMinutes ?? selectedPreset.defaultTimings.qualifyingMinutes,\n sprintRaceMinutes: prev.timings?.sprintRaceMinutes ?? selectedPreset.defaultTimings.sprintRaceMinutes,\n mainRaceMinutes: prev.timings?.mainRaceMinutes ?? selectedPreset.defaultTimings.mainRaceMinutes,\n sessionCount: selectedPreset.defaultTimings.sessionCount,\n }\n : prev.timings,\n };\n });\n };\n \n const steps = [\n { id: 1 as Step, label: 'Basics', icon: FileText, shortLabel: 'Name' },\n { id: 2 as Step, label: 'Visibility', icon: Award, shortLabel: 'Type' },\n { id: 3 as Step, label: 'Structure', icon: Users, shortLabel: 'Mode' },\n { id: 4 as Step, label: 'Schedule', icon: Calendar, shortLabel: 'Time' },\n { id: 5 as Step, label: 'Scoring', icon: Trophy, shortLabel: 'Points' },\n { id: 6 as Step, label: 'Stewarding', icon: Scale, shortLabel: 'Rules' },\n { id: 7 as Step, label: 'Review', icon: CheckCircle2, shortLabel: 'Done' },\n ];\n\n const getStepTitle = (currentStep: Step): string => {\n switch (currentStep) {\n case 1:\n return 'Name your league';\n case 2:\n return 'Choose your destiny';\n case 3:\n return 'Choose the structure';\n case 4:\n return 'Set the schedule';\n case 5:\n return 'Scoring & championships';\n case 6:\n return 'Stewarding & protests';\n case 7:\n return 'Review & create';\n default:\n return '';\n }\n };\n\n const getStepSubtitle = (currentStep: Step): string => {\n switch (currentStep) {\n case 1:\n return 'Give your league a memorable name and tell your story.';\n case 2:\n return 'Will you compete for global rankings or race with friends?';\n case 3:\n return 'Define how races in this season will run.';\n case 4:\n return 'Plan when this season’s races happen.';\n case 5:\n return 'Choose how points and drop scores work for this season.';\n case 6:\n return 'Set how protests and stewarding work for this season.';\n case 7:\n return 'Review your league and first season before launching.';\n default:\n return '';\n }\n };\n\n const getStepContextLabel = (currentStep: Step): string => {\n if (currentStep === 1 || currentStep === 2) {\n return 'League setup';\n }\n if (currentStep >= 3 && currentStep <= 6) {\n return 'Season setup';\n }\n return 'League & Season summary';\n };\n\n const currentStepData = steps.find((s) => s.id === step);\n const CurrentStepIcon = currentStepData?.icon ?? FileText;\n\n return (\n
\n {/* Header with icon */}\n
\n
\n
\n \n
\n
\n \n Create a new league\n \n

\n We'll also set up your first season in {steps.length} easy steps.\n

\n

\n A league is your long-term brand. Each season is a block of races you can run again and again.\n

\n
\n
\n
\n\n {/* Desktop Progress Bar */}\n
\n
\n {/* Background track */}\n
\n {/* Progress fill */}\n \n\n
\n {steps.map((wizardStep) => {\n const isCompleted = wizardStep.id < step;\n const isCurrent = wizardStep.id === step;\n const isAccessible = wizardStep.id <= highestCompletedStep;\n const StepIcon = wizardStep.icon;\n\n return (\n goToStep(wizardStep.id)}\n disabled={!isAccessible}\n className=\"flex flex-col items-center bg-transparent border-0 cursor-pointer disabled:cursor-not-allowed\"\n >\n \n {isCompleted ? (\n \n ) : (\n \n )}\n
\n
\n \n {wizardStep.label}\n

\n
\n \n );\n })}\n
\n
\n
\n\n {/* Mobile Progress */}\n
\n
\n
\n \n {currentStepData?.label}\n
\n \n {step}/{steps.length}\n \n
\n
\n \n
\n {/* Step dots */}\n
\n {steps.map((s) => (\n \n ))}\n
\n
\n\n {/* Main Card */}\n \n {/* Top gradient accent */}\n
\n\n {/* Step header */}\n
\n
\n \n
\n
\n \n
\n {getStepTitle(step)}\n \n {getStepContextLabel(step)}\n \n
\n
\n

\n {getStepSubtitle(step)}\n

\n
\n
\n Step\n {step}\n / {steps.length}\n
\n
\n\n {/* Divider */}\n
\n\n {/* Step content with min-height for consistency */}\n
\n {step === 1 && (\n
\n \n
\n
\n
\n

\n First season\n

\n

\n Name the first season that will run in this league.\n

\n
\n
\n
\n \n \n setForm((prev) => ({\n ...prev,\n seasonName: e.target.value,\n }))\n }\n placeholder=\"e.g., Season 1 (2025)\"\n />\n

\n Seasons are the individual competitive runs inside your league. You can run Season 2, Season 3, or parallel seasons later.\n

\n
\n
\n
\n )}\n\n {step === 2 && (\n
\n \n
\n )}\n\n {step === 3 && (\n
\n
\n

\n Applies to: First season of this league.\n

\n

\n These settings only affect this season. Future seasons can use different formats.\n

\n
\n \n
\n )}\n\n {step === 4 && (\n
\n
\n

\n Applies to: First season of this league.\n

\n

\n These settings only affect this season. Future seasons can use different formats.\n

\n
\n \n
\n )}\n\n {step === 5 && (\n
\n
\n

\n Applies to: First season of this league.\n

\n

\n These settings only affect this season. Future seasons can use different formats.\n

\n
\n {/* Scoring Pattern Selection */}\n \n setForm((prev) => ({\n ...prev,\n scoring: {\n ...prev.scoring,\n customScoringEnabled: !(prev.scoring?.customScoringEnabled),\n },\n }))\n }\n />\n\n {/* Divider */}\n
\n \n {/* Championships & Drop Rules side by side on larger screens */}\n
\n \n \n
\n\n {errors.submit && (\n
\n \n

{errors.submit}

\n
\n )}\n
\n )}\n\n {step === 6 && (\n
\n
\n

\n Applies to: First season of this league.\n

\n

\n These settings only affect this season. Future seasons can use different formats.\n

\n
\n \n
\n )}\n\n {step === 7 && (\n
\n \n {errors.submit && (\n
\n \n

{errors.submit}

\n
\n )}\n
\n )}\n
\n \n\n {/* Navigation */}\n
\n \n \n Back\n \n\n
\n {/* Mobile step dots */}\n
\n {steps.map((s) => (\n \n ))}\n
\n\n {step < 7 ? (\n \n Continue\n \n \n ) : (\n \n {loading ? (\n <>\n \n Creating…\n \n ) : (\n <>\n \n Create League\n \n )}\n \n )}\n
\n
\n\n {/* Helper text */}\n

\n This will create your league and its first season. You can edit both later.\n

\n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/leagues/create/page.tsx","messages":[{"ruleId":"import/no-unresolved","severity":2,"message":"Unable to resolve path to module '@/components/leagues/CreateLeagueWizard'.","line":5,"column":32,"nodeType":"Literal","endLine":5,"endColumn":73},{"ruleId":"gridpilot-rules/rsc-no-local-helpers","severity":2,"message":"Local helper functions forbidden (only assert*/invariant* allowed) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":11,"column":1,"nodeType":"FunctionDeclaration","messageId":"message","endLine":24,"endColumn":2},{"ruleId":"gridpilot-rules/no-hardcoded-search-params","severity":2,"message":"Manual search param access with get(). Use SearchParamParser instead: import { SearchParamParser } from \"@/lib/routing/search-params\"","line":32,"column":9,"nodeType":"MemberExpression","messageId":"manualGetParam","endLine":32,"endColumn":25},{"ruleId":"gridpilot-rules/rsc-no-local-helpers","severity":2,"message":"Local helper functions forbidden (only assert*/invariant* allowed) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":36,"column":9,"nodeType":"VariableDeclarator","messageId":"message","endLine":46,"endColumn":4},{"ruleId":"gridpilot-rules/rsc-no-object-construction","severity":2,"message":"Object construction with new forbidden (use PageQueries) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":37,"column":20,"nodeType":"NewExpression","messageId":"message","endLine":41,"endColumn":6},{"ruleId":"gridpilot-rules/no-hardcoded-search-params","severity":2,"message":"Manual URLSearchParams construction. Use SearchParamBuilder instead: import { SearchParamBuilder } from \"@/lib/routing/search-params\"","line":37,"column":20,"nodeType":"NewExpression","messageId":"manualSearchParams","endLine":41,"endColumn":6},{"ruleId":"gridpilot-rules/no-hardcoded-search-params","severity":2,"message":"Manual search param setting with set(). Use SearchParamBuilder instead","line":42,"column":5,"nodeType":"CallExpression","messageId":"manualSetParam","endLine":42,"endColumn":33},{"ruleId":"gridpilot-rules/no-hardcoded-search-params","severity":2,"message":"Manual search param setting with set(). Use SearchParamBuilder instead","line":42,"column":5,"nodeType":"MemberExpression","messageId":"manualSetParam","endLine":42,"endColumn":15}],"suppressedMessages":[],"errorCount":8,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\n\nimport React from 'react';\nimport { useRouter, useSearchParams } from 'next/navigation';\nimport CreateLeagueWizard from '@/components/leagues/CreateLeagueWizard';\nimport { Section } from '@/ui/Section';\nimport { Container } from '@/ui/Container';\n\ntype StepName = 'basics' | 'visibility' | 'structure' | 'schedule' | 'scoring' | 'stewarding' | 'review';\n\nfunction normalizeStepName(raw: string | null): StepName {\n switch (raw) {\n case 'basics':\n case 'visibility':\n case 'structure':\n case 'schedule':\n case 'scoring':\n case 'stewarding':\n case 'review':\n return raw;\n default:\n return 'basics';\n }\n}\n\nexport default function CreateLeaguePage() {\n const router = useRouter();\n const searchParams = useSearchParams();\n\n const currentStepName = normalizeStepName(\n searchParams && typeof searchParams.get === 'function'\n ? searchParams.get('step')\n : null,\n );\n\n const handleStepChange = (stepName: StepName) => {\n const params = new URLSearchParams(\n searchParams && typeof searchParams.toString === 'function'\n ? searchParams.toString()\n : '',\n );\n params.set('step', stepName);\n const query = params.toString();\n const href = query ? `/leagues/create?${query}` : '/leagues/create';\n router.push(href);\n };\n\n return (\n
\n \n \n \n
\n );\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/leagues/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/media/avatar/[driverId]/route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/media/categories/[categoryId]/icon/route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/media/leagues/[leagueId]/cover/route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/media/leagues/[leagueId]/logo/route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/media/sponsors/[sponsorId]/logo/route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/media/teams/[teamId]/logo/route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/media/tracks/[trackId]/image/route.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/not-found.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/onboarding/OnboardingLayoutProps.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/onboarding/OnboardingWizardClient.tsx","messages":[{"ruleId":"import/no-unresolved","severity":2,"message":"Unable to resolve path to module './OnboardingWizard'.","line":3,"column":34,"nodeType":"Literal","endLine":3,"endColumn":54}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\n\nimport { OnboardingWizard } from './OnboardingWizard';\nimport { routes } from '@/lib/routing/RouteConfig';\nimport { completeOnboardingAction } from '@/app/onboarding/completeOnboardingAction';\nimport { generateAvatarsAction } from '@/app/onboarding/generateAvatarsAction';\nimport { useAuth } from '@/lib/auth/AuthContext';\n\nexport function OnboardingWizardClient() {\n const { session } = useAuth();\n\n const handleCompleteOnboarding = async (input: {\n firstName: string;\n lastName: string;\n displayName: string;\n country: string;\n timezone?: string;\n }) => {\n try {\n const result = await completeOnboardingAction(input);\n\n if (result.isErr()) {\n return { success: false, error: result.getError() };\n }\n\n window.location.href = routes.protected.dashboard;\n return { success: true };\n } catch (error) {\n return { success: false, error: 'Failed to complete onboarding' };\n }\n };\n\n const handleGenerateAvatars = async (params: {\n facePhotoData: string;\n suitColor: string;\n }) => {\n if (!session?.user?.userId) {\n return { success: false, error: 'Not authenticated' };\n }\n\n try {\n const result = await generateAvatarsAction({\n userId: session.user.userId,\n facePhotoData: params.facePhotoData,\n suitColor: params.suitColor,\n });\n\n if (result.isErr()) {\n return { success: false, error: result.getError() };\n }\n\n const data = result.unwrap();\n return { success: true, data };\n } catch (error) {\n return { success: false, error: 'Failed to generate avatars' };\n }\n };\n\n return (\n {\n window.location.href = routes.protected.dashboard;\n }}\n onCompleteOnboarding={handleCompleteOnboarding}\n onGenerateAvatars={handleGenerateAvatars}\n />\n );\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/onboarding/completeOnboardingAction.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/onboarding/generateAvatarsAction.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/onboarding/layout.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/onboarding/page.tsx","messages":[{"ruleId":"import/no-unresolved","severity":2,"message":"Unable to resolve path to module '@/components/onboarding/OnboardingWizardClient'.","line":2,"column":40,"nodeType":"Literal","endLine":2,"endColumn":88}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { redirect } from 'next/navigation';\nimport { OnboardingWizardClient } from '@/components/onboarding/OnboardingWizardClient';\nimport { OnboardingPageQuery } from '@/lib/page-queries/OnboardingPageQuery';\nimport { SearchParamBuilder } from '@/lib/routing/search-params/SearchParamBuilder';\nimport { routes } from '@/lib/routing/RouteConfig';\n\n/**\n * Onboarding Page\n *\n * Server Component that handles authentication and authorization.\n * Redirects to login if not authenticated.\n * Redirects to dashboard if already onboarded.\n */\nexport default async function OnboardingPage() {\n // Use PageQuery to check if user is already onboarded\n const result = await OnboardingPageQuery.execute();\n \n if (result.isErr()) {\n const error = result.getError();\n \n if (error === 'unauthorized') {\n redirect(`${routes.auth.login}${SearchParamBuilder.auth(routes.protected.onboarding)}`);\n } else if (error === 'serverError' || error === 'networkError') {\n // Show error page or let them proceed with a warning\n // For now, we'll let them proceed\n }\n } else {\n const viewData = result.unwrap();\n \n if (viewData.isAlreadyOnboarded) {\n redirect(routes.protected.dashboard);\n }\n }\n\n return ;\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/page.tsx","messages":[{"ruleId":"gridpilot-rules/rsc-no-unsafe-services","severity":2,"message":"Services import must be explicitly marked as server-safe - see apps/website/lib/contracts/view-models/ViewModel.ts","line":4,"column":1,"nodeType":"ImportDeclaration","messageId":"message","endLine":4,"endColumn":63}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { PageWrapper } from '@/components/shared/state/PageWrapper';\nimport { HomeTemplate, type HomeViewData } from '@/templates/HomeTemplate';\nimport { PageDataFetcher } from '@/lib/page/PageDataFetcher';\nimport { getHomeData } from '@/lib/services/home/getHomeData';\nimport { notFound } from 'next/navigation';\n\nexport default async function Page() {\n const data = await PageDataFetcher.fetchManual(async () => getHomeData());\n \n if (!data) {\n notFound();\n }\n \n const Template = ({ data }: { data: HomeViewData }) => ;\n \n return ;\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/profile/ProfilePageClient.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/profile/actions.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/profile/layout.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/profile/leagues/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/profile/liveries/page.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'Card' is defined but never used.","line":3,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":3,"endColumn":14},{"ruleId":"gridpilot-rules/rsc-no-object-construction","severity":2,"message":"Object construction with new forbidden (use PageQueries) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":17,"column":19,"nodeType":"NewExpression","messageId":"message","endLine":17,"endColumn":29},{"ruleId":"gridpilot-rules/rsc-no-object-construction","severity":2,"message":"Object construction with new forbidden (use PageQueries) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":25,"column":19,"nodeType":"NewExpression","messageId":"message","endLine":25,"endColumn":29},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":32,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":40,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":32,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":32,"endColumn":63},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":32,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":32,"endColumn":62},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":33,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":33,"endColumn":14},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":35,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":35,"endColumn":80},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":35,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":35,"endColumn":45},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":35,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":35,"endColumn":44},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":48,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":52,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":48,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":48,"endColumn":30},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":48,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":48,"endColumn":29}],"suppressedMessages":[],"errorCount":13,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import Link from 'next/link';\nimport { Button } from '@/ui/Button';\nimport { Card } from '@/ui/Card';\nimport { Container } from '@/ui/Container';\nimport { Heading } from '@/ui/Heading';\nimport { Grid } from '@/ui/Grid';\nimport { routes } from '@/lib/routing/RouteConfig';\nimport { LiveryCard } from '@/ui/LiveryCard';\n\nexport default async function ProfileLiveriesPage() {\n const mockLiveries = [\n {\n id: '1',\n carId: 'gt3-r',\n carName: 'Porsche 911 GT3 R (992)',\n thumbnailUrl: '',\n uploadedAt: new Date(),\n isValidated: true,\n },\n {\n id: '2',\n carId: 'f3',\n carName: 'Dallara F3',\n thumbnailUrl: '',\n uploadedAt: new Date(),\n isValidated: false,\n }\n ];\n\n return (\n \n
\n
\n My Liveries\n

Manage your custom car liveries

\n
\n \n \n \n
\n\n \n {mockLiveries.map((livery) => (\n \n ))}\n \n\n
\n \n \n \n
\n
\n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/profile/liveries/upload/page.tsx","messages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":13,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":13,"endColumn":12}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import Link from 'next/link';\nimport { Button } from '@/ui/Button';\nimport { Card } from '@/ui/Card';\nimport { Container } from '@/ui/Container';\nimport { Heading } from '@/ui/Heading';\nimport { routes } from '@/lib/routing/RouteConfig';\n\nexport default async function ProfileLiveryUploadPage() {\n return (\n \n Upload livery\n \n

Livery upload is currently unavailable.

\n \n \n \n
\n
\n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/profile/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/profile/settings/page.tsx","messages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":13,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":13,"endColumn":12}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import Link from 'next/link';\nimport { Button } from '@/ui/Button';\nimport { Card } from '@/ui/Card';\nimport { Container } from '@/ui/Container';\nimport { Heading } from '@/ui/Heading';\nimport { routes } from '@/lib/routing/RouteConfig';\n\nexport default async function ProfileSettingsPage() {\n return (\n \n Settings\n \n

Settings are currently unavailable.

\n \n \n \n
\n
\n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/profile/sponsorship-requests/SponsorshipRequestsClient.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/profile/sponsorship-requests/SponsorshipRequestsPageClient.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/profile/sponsorship-requests/actions.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/profile/sponsorship-requests/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/races/RacesPageClient.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/races/[id]/RaceDetailPageClient.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'showProtestModal' is assigned a value but never used.","line":37,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":37,"endColumn":26},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'setShowProtestModal' is assigned a value but never used.","line":37,"column":28,"nodeType":"Identifier","messageId":"unusedVar","endLine":37,"endColumn":47},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'showEndRaceModal' is assigned a value but never used.","line":38,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":38,"endColumn":26},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'setShowEndRaceModal' is assigned a value but never used.","line":38,"column":28,"nodeType":"Identifier","messageId":"unusedVar","endLine":38,"endColumn":47}],"suppressedMessages":[],"errorCount":4,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\n\nimport React, { useState, useEffect } from 'react';\nimport { RaceDetailTemplate, type RaceDetailViewData } from '@/templates/RaceDetailTemplate';\n\ninterface RaceDetailPageClientProps {\n viewData: RaceDetailViewData;\n onBack: () => void;\n onRegister: () => void;\n onWithdraw: () => void;\n onCancel: () => void;\n onReopen: () => void;\n onEndRace: () => void;\n onFileProtest: () => void;\n onResultsClick: () => void;\n onStewardingClick: () => void;\n onLeagueClick: (id: string) => void;\n onDriverClick: (id: string) => void;\n isOwnerOrAdmin: boolean;\n}\n\nexport function RaceDetailPageClient({\n viewData,\n onBack,\n onRegister,\n onWithdraw,\n onCancel,\n onReopen,\n onEndRace,\n onFileProtest,\n onResultsClick,\n onStewardingClick,\n onLeagueClick,\n onDriverClick,\n isOwnerOrAdmin\n}: RaceDetailPageClientProps) {\n const [showProtestModal, setShowProtestModal] = useState(false);\n const [showEndRaceModal, setShowEndRaceModal] = useState(false);\n const [animatedRatingChange, setAnimatedRatingChange] = useState(0);\n\n const ratingChange = viewData.userResult?.ratingChange ?? null;\n\n useEffect(() => {\n if (ratingChange !== null) {\n let start = 0;\n const end = ratingChange;\n const duration = 1000;\n const startTime = performance.now();\n\n const animate = (currentTime: number) => {\n const elapsed = currentTime - startTime;\n const progress = Math.min(elapsed / duration, 1);\n const eased = 1 - Math.pow(1 - progress, 3);\n const current = Math.round(start + (end - start) * eased);\n setAnimatedRatingChange(current);\n\n if (progress < 1) {\n requestAnimationFrame(animate);\n }\n };\n\n requestAnimationFrame(animate);\n }\n }, [ratingChange]);\n\n return (\n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/races/[id]/page.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_data' is defined but never used.","line":35,"column":32,"nodeType":"Identifier","messageId":"unusedVar","endLine":35,"endColumn":37},{"ruleId":"gridpilot-rules/rsc-no-object-construction","severity":2,"message":"Object construction with new forbidden (use PageQueries) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":39,"column":24,"nodeType":"NewExpression","messageId":"message","endLine":39,"endColumn":64},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_data' is defined but never used.","line":80,"column":26,"nodeType":"Identifier","messageId":"unusedVar","endLine":80,"endColumn":31}],"suppressedMessages":[],"errorCount":3,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { notFound } from 'next/navigation';\nimport { PageWrapper } from '@/components/shared/state/PageWrapper';\nimport { RaceDetailTemplate } from '@/templates/RaceDetailTemplate';\nimport { RaceDetailPageQuery } from '@/lib/page-queries/races/RaceDetailPageQuery';\n\ninterface RaceDetailPageProps {\n params: {\n id: string;\n };\n}\n\nexport default async function RaceDetailPage({ params }: RaceDetailPageProps) {\n const raceId = params.id;\n \n if (!raceId) {\n notFound();\n }\n\n // Execute PageQuery\n const result = await RaceDetailPageQuery.execute({ raceId, driverId: '' });\n \n if (result.isErr()) {\n const error = result.getError();\n \n switch (error) {\n case 'notFound':\n notFound();\n case 'redirect':\n notFound();\n default:\n // Pass error to template via PageWrapper\n return (\n (\n {}}\n onRegister={() => {}}\n onWithdraw={() => {}}\n onCancel={() => {}}\n onReopen={() => {}}\n onEndRace={() => {}}\n onFileProtest={() => {}}\n onResultsClick={() => {}}\n onStewardingClick={() => {}}\n onLeagueClick={() => {}}\n onDriverClick={() => {}}\n isOwnerOrAdmin={false}\n animatedRatingChange={0}\n mutationLoading={{\n register: false,\n withdraw: false,\n cancel: false,\n reopen: false,\n complete: false,\n }}\n />\n )}\n loading={{ variant: 'skeleton', message: 'Loading race details...' }}\n errorConfig={{ variant: 'full-screen' }}\n empty={{\n icon: require('lucide-react').Flag,\n title: 'Race not found',\n description: 'The race may have been cancelled or deleted',\n action: { label: 'Back to Races', onClick: () => {} }\n }}\n />\n );\n }\n }\n \n const viewData = result.unwrap();\n \n return (\n (\n {}}\n onRegister={() => {}}\n onWithdraw={() => {}}\n onCancel={() => {}}\n onReopen={() => {}}\n onEndRace={() => {}}\n onFileProtest={() => {}}\n onResultsClick={() => {}}\n onStewardingClick={() => {}}\n onLeagueClick={() => {}}\n onDriverClick={() => {}}\n isOwnerOrAdmin={false}\n animatedRatingChange={0}\n mutationLoading={{\n register: false,\n withdraw: false,\n cancel: false,\n reopen: false,\n complete: false,\n }}\n />\n )}\n loading={{ variant: 'skeleton', message: 'Loading race details...' }}\n errorConfig={{ variant: 'full-screen' }}\n empty={{\n icon: require('lucide-react').Flag,\n title: 'Race not found',\n description: 'The race may have been cancelled or deleted',\n action: { label: 'Back to Races', onClick: () => {} }\n }}\n />\n );\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/races/[id]/results/page.tsx","messages":[{"ruleId":"gridpilot-rules/rsc-no-object-construction","severity":2,"message":"Object construction with new forbidden (use PageQueries) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":37,"column":20,"nodeType":"NewExpression","messageId":"message","endLine":37,"endColumn":60},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_data' is defined but never used.","line":39,"column":32,"nodeType":"Identifier","messageId":"unusedVar","endLine":39,"endColumn":37},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_data' is defined but never used.","line":88,"column":26,"nodeType":"Identifier","messageId":"unusedVar","endLine":88,"endColumn":31}],"suppressedMessages":[],"errorCount":3,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { notFound } from 'next/navigation';\nimport { StatefulPageWrapper } from '@/components/shared/state/StatefulPageWrapper';\nimport { RaceResultsTemplate } from '@/templates/RaceResultsTemplate';\nimport { RaceResultsPageQuery } from '@/lib/page-queries/races/RaceResultsPageQuery';\nimport { Trophy } from 'lucide-react';\n\ninterface RaceResultsPageProps {\n params: {\n id: string;\n };\n}\n\nexport default async function RaceResultsPage({ params }: RaceResultsPageProps) {\n const raceId = params.id;\n \n if (!raceId) {\n notFound();\n }\n\n // Execute PageQuery\n const result = await RaceResultsPageQuery.execute({ raceId });\n \n if (result.isErr()) {\n const error = result.getError();\n \n switch (error) {\n case 'notFound':\n notFound();\n case 'redirect':\n notFound();\n default:\n // Pass error to template via StatefulPageWrapper\n return (\n Promise.resolve()}\n Template={({ data: _data }) => (\n {}}\n onImportResults={() => Promise.resolve()}\n onPenaltyClick={() => {}}\n importing={false}\n importSuccess={false}\n importError={null}\n showImportForm={false}\n setShowImportForm={() => {}}\n />\n )}\n loading={{ variant: 'skeleton', message: 'Loading race results...' }}\n errorConfig={{ variant: 'full-screen' }}\n empty={{\n icon: Trophy,\n title: 'No results available',\n description: 'Race results will appear here once the race is completed',\n action: { label: 'Back to Race', onClick: () => {} }\n }}\n />\n );\n }\n }\n \n const viewData = result.unwrap();\n\n return (\n Promise.resolve()}\n Template={({ data: _data }) => (\n {}}\n onImportResults={() => Promise.resolve()}\n onPenaltyClick={() => {}}\n importing={false}\n importSuccess={false}\n importError={null}\n showImportForm={false}\n setShowImportForm={() => {}}\n />\n )}\n loading={{ variant: 'skeleton', message: 'Loading race results...' }}\n errorConfig={{ variant: 'full-screen' }}\n empty={{\n icon: Trophy,\n title: 'No results available',\n description: 'Race results will appear here once the race is completed',\n action: { label: 'Back to Race', onClick: () => {} }\n }}\n />\n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/races/[id]/stewarding/page.tsx","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":25,"column":44,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":25,"endColumn":47,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[755,758],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[755,758],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"gridpilot-rules/rsc-no-local-helpers","severity":2,"message":"Local helper functions forbidden (only assert*/invariant* allowed) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":30,"column":9,"nodeType":"VariableDeclarator","messageId":"message","endLine":47,"endColumn":4},{"ruleId":"gridpilot-rules/rsc-no-object-construction","severity":2,"message":"Object construction with new forbidden (use PageQueries) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":38,"column":15,"nodeType":"NewExpression","messageId":"message","endLine":38,"endColumn":59},{"ruleId":"gridpilot-rules/rsc-no-object-construction","severity":2,"message":"Object construction with new forbidden (use PageQueries) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":43,"column":45,"nodeType":"NewExpression","messageId":"message","endLine":43,"endColumn":71},{"ruleId":"react-hooks/exhaustive-deps","severity":2,"message":"React Hook useEffect has a missing dependency: 'fetchData'. Either include it or remove the dependency array.","line":51,"column":6,"nodeType":"ArrayExpression","endLine":51,"endColumn":14,"suggestions":[{"desc":"Update the dependencies array to be: [fetchData, raceId]","fix":{"range":[1399,1407],"text":"[fetchData, raceId]"}}]},{"ruleId":"gridpilot-rules/rsc-no-local-helpers","severity":2,"message":"Local helper functions forbidden (only assert*/invariant* allowed) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":54,"column":9,"nodeType":"VariableDeclarator","messageId":"message","endLine":56,"endColumn":4},{"ruleId":"gridpilot-rules/rsc-no-local-helpers","severity":2,"message":"Local helper functions forbidden (only assert*/invariant* allowed) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":58,"column":9,"nodeType":"VariableDeclarator","messageId":"message","endLine":62,"endColumn":4}],"suppressedMessages":[],"errorCount":7,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\n\nimport { notFound } from 'next/navigation';\nimport { PageWrapper } from '@/components/shared/state/PageWrapper';\nimport { RaceStewardingTemplate, type StewardingTab } from '@/templates/RaceStewardingTemplate';\nimport { RaceStewardingPageQuery } from '@/lib/page-queries/races/RaceStewardingPageQuery';\nimport { Gavel } from 'lucide-react';\nimport { useState, useEffect } from 'react';\n\ninterface RaceStewardingPageProps {\n params: {\n id: string;\n };\n}\n\nexport default function RaceStewardingPage({ params }: RaceStewardingPageProps) {\n const raceId = params.id;\n const [activeTab, setActiveTab] = useState('pending');\n \n if (!raceId) {\n notFound();\n }\n\n // Data state\n const [pageData, setPageData] = useState(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState(null);\n\n // Fetch function\n const fetchData = async () => {\n setIsLoading(true);\n setError(null);\n \n try {\n const result = await RaceStewardingPageQuery.execute({ raceId });\n \n if (result.isErr()) {\n throw new Error('Failed to fetch stewarding data');\n }\n \n setPageData(result.unwrap());\n } catch (err) {\n setError(err instanceof Error ? err : new Error('Unknown error'));\n } finally {\n setIsLoading(false);\n }\n };\n\n useEffect(() => {\n fetchData();\n }, [raceId]);\n\n // Actions\n const handleBack = () => {\n window.history.back();\n };\n\n const handleReviewProtest = (protestId: string) => {\n if (pageData?.league?.id) {\n window.location.href = `/leagues/${pageData.league.id}/stewarding/protests/${protestId}`;\n }\n };\n\n return (\n (\n \n )}\n loading={{ variant: 'skeleton', message: 'Loading stewarding data...' }}\n errorConfig={{ variant: 'full-screen' }}\n empty={{\n icon: Gavel,\n title: 'No stewarding data',\n description: 'No protests or penalties for this race',\n action: { label: 'Back to Race', onClick: handleBack }\n }}\n />\n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/races/all/RacesAllPageClient.tsx","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":26,"column":76,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":26,"endColumn":79,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[776,779],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[776,779],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":38,"column":44,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":38,"endColumn":47,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1344,1347],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1344,1347],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"react-hooks/exhaustive-deps","severity":2,"message":"React Hook useEffect has a missing dependency: 'fetchData'. Either include it or remove the dependency array.","line":68,"column":6,"nodeType":"ArrayExpression","endLine":68,"endColumn":23,"suggestions":[{"desc":"Update the dependencies array to be: [fetchData, initialViewData]","fix":{"range":[2129,2146],"text":"[fetchData, initialViewData]"}}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":71,"column":52,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":71,"endColumn":55,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2221,2224],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2221,2224],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_data' is defined but never used.","line":128,"column":26,"nodeType":"Identifier","messageId":"unusedVar","endLine":128,"endColumn":31},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":131,"column":36,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":131,"endColumn":39,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[4034,4037],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[4034,4037],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":6,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\n\nimport { useState, useEffect } from 'react';\nimport { useRouter } from 'next/navigation';\nimport { StatefulPageWrapper } from '@/components/shared/state/StatefulPageWrapper';\nimport { RacesAllTemplate } from '@/templates/RacesAllTemplate';\nimport { RacesAllPageQuery } from '@/lib/page-queries/races/RacesAllPageQuery';\nimport { Flag } from 'lucide-react';\n\nimport { routes } from '@/lib/routing/RouteConfig';\n\nconst ITEMS_PER_PAGE = 10;\n\ninterface Race {\n id: string;\n track: string;\n car: string;\n scheduledAt: string;\n status: 'scheduled' | 'running' | 'completed' | 'cancelled';\n sessionType: string;\n leagueId?: string;\n leagueName?: string;\n strengthOfField?: number;\n}\n\nexport function RacesAllPageClient({ initialViewData }: { initialViewData: any }) {\n const router = useRouter();\n \n // Client-side state for filters and pagination\n const [currentPage, setCurrentPage] = useState(1);\n const [statusFilter, setStatusFilter] = useState<'scheduled' | 'running' | 'completed' | 'cancelled' | 'all'>('all');\n const [leagueFilter, setLeagueFilter] = useState('all');\n const [searchQuery, setSearchQuery] = useState('');\n const [showFilters, setShowFilters] = useState(false);\n const [showFilterModal, setShowFilterModal] = useState(false);\n\n // Data state\n const [pageData, setPageData] = useState(initialViewData);\n const [isLoading, setIsLoading] = useState(!initialViewData);\n const [error, setError] = useState(null);\n\n // Fetch data\n const fetchData = async () => {\n if (pageData && !isLoading) return; // Already have data from server\n setIsLoading(true);\n setError(null);\n \n try {\n const result = await RacesAllPageQuery.execute();\n \n if (result.isErr()) {\n throw new Error('Failed to fetch races');\n }\n \n setPageData(result.unwrap());\n } catch (err) {\n setError(err instanceof Error ? err : new Error('Unknown error'));\n } finally {\n setIsLoading(false);\n }\n };\n\n // Fetch on mount if no initial data\n useEffect(() => {\n if (!initialViewData) {\n fetchData();\n }\n }, [initialViewData]);\n\n // Transform data\n const races: Race[] = pageData?.races.map((race: any) => ({\n id: race.id,\n track: race.track || '',\n car: race.car || '',\n scheduledAt: race.scheduledAt,\n status: race.status as 'scheduled' | 'running' | 'completed' | 'cancelled',\n sessionType: 'race',\n leagueId: race.leagueId,\n leagueName: race.leagueName,\n strengthOfField: race.strengthOfField ?? undefined,\n })) ?? [];\n\n // Filter and paginate (Note: This should be done by API per contract)\n const filteredRaces = races.filter((race: Race) => {\n if (statusFilter !== 'all' && race.status !== statusFilter) {\n return false;\n }\n\n if (leagueFilter !== 'all' && race.leagueId !== leagueFilter) {\n return false;\n }\n\n if (searchQuery) {\n const query = searchQuery.toLowerCase();\n const matchesTrack = race.track.toLowerCase().includes(query);\n const matchesCar = race.car.toLowerCase().includes(query);\n const matchesLeague = race.leagueName?.toLowerCase().includes(query);\n if (!matchesTrack && !matchesCar && !matchesLeague) {\n return false;\n }\n }\n\n return true;\n });\n\n const totalPages = Math.ceil(filteredRaces.length / ITEMS_PER_PAGE);\n const paginatedRaces = filteredRaces.slice((currentPage - 1) * ITEMS_PER_PAGE, currentPage * ITEMS_PER_PAGE);\n\n // Actions\n const handleRaceClick = (raceId: string) => {\n router.push(routes.race.detail(raceId));\n };\n\n const handleLeagueClick = (leagueId: string) => {\n router.push(routes.league.detail(leagueId));\n };\n\n const handlePageChange = (page: number) => {\n setCurrentPage(page);\n };\n\n return (\n (\n \n )}\n loading={{ variant: 'skeleton', message: 'Loading races...' }}\n errorConfig={{ variant: 'full-screen' }}\n empty={{\n icon: Flag,\n title: 'No races found',\n description: 'There are no races available at the moment',\n }}\n />\n );\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/races/all/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/races/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/sponsor/billing/page.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'StatusBadge' is defined but never used.","line":9,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":9,"endColumn":21},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'ArrowRight' is defined but never used.","line":23,"column":3,"nodeType":"Identifier","messageId":"unusedVar","endLine":23,"endColumn":13},{"ruleId":"gridpilot-rules/rsc-no-local-helpers","severity":2,"message":"Local helper functions forbidden (only assert*/invariant* allowed) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":40,"column":1,"nodeType":"FunctionDeclaration","messageId":"message","endLine":116,"endColumn":2},{"ruleId":"gridpilot-rules/rsc-no-local-helpers","severity":2,"message":"Local helper functions forbidden (only assert*/invariant* allowed) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":51,"column":9,"nodeType":"VariableDeclarator","messageId":"message","endLine":54,"endColumn":4},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":67,"column":5,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":76,"endColumn":6},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":71,"column":7,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":75,"endColumn":10},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":77,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":113,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":77,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":77,"endColumn":58},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":77,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":77,"endColumn":57},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":78,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":102,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":78,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":78,"endColumn":50},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":78,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":78,"endColumn":49},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":79,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":83,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":79,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":81,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":79,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":81,"endColumn":14},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":82,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":82,"endColumn":100},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":84,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":84,"endColumn":16},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":85,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":92,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":85,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":85,"endColumn":54},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":85,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":85,"endColumn":53},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":86,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":86,"endColumn":77},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":86,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":86,"endColumn":56},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":86,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":86,"endColumn":55},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":88,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":90,"endColumn":24},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":88,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":88,"endColumn":117},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":88,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":88,"endColumn":116},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":94,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":96,"endColumn":22},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":94,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":94,"endColumn":55},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":94,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":94,"endColumn":54},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":99,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":99,"endColumn":79},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":99,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":99,"endColumn":55},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":99,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":99,"endColumn":54},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":103,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":112,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":103,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":103,"endColumn":50},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":103,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":103,"endColumn":49},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":105,"column":64,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":105,"endColumn":83},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":109,"column":58,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":109,"endColumn":113},{"ruleId":"gridpilot-rules/rsc-no-local-helpers","severity":2,"message":"Local helper functions forbidden (only assert*/invariant* allowed) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":118,"column":1,"nodeType":"FunctionDeclaration","messageId":"message","endLine":213,"endColumn":2},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":164,"column":5,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":169,"endColumn":6},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":168,"column":7,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":168,"endColumn":154},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":170,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":189,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":170,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":170,"endColumn":55},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":170,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":170,"endColumn":54},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":171,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":173,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":171,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":171,"endColumn":93},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":171,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":171,"endColumn":92},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":172,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":172,"endColumn":53},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":174,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":188,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":174,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":174,"endColumn":41},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":174,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":174,"endColumn":40},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":175,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":180,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":175,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":175,"endColumn":59},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":175,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":175,"endColumn":58},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":176,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":176,"endColumn":91},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":176,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":176,"endColumn":63},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":176,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":176,"endColumn":62},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":177,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":179,"endColumn":20},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":177,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":177,"endColumn":100},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":177,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":177,"endColumn":99},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":181,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":187,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":181,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":181,"endColumn":74},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":181,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":181,"endColumn":73},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":182,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":182,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":183,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":183,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":184,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":184,"endColumn":19},{"ruleId":"gridpilot-rules/rsc-no-intl","severity":2,"message":"Intl.* or toLocale* usage forbidden in presentation paths - see apps/website/lib/contracts/view-models/ViewModel.ts","line":185,"column":16,"nodeType":"MemberExpression","messageId":"message","endLine":185,"endColumn":57},{"ruleId":"gridpilot-rules/rsc-no-object-construction","severity":2,"message":"Object construction with new forbidden (use PageQueries) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":185,"column":16,"nodeType":"NewExpression","messageId":"message","endLine":185,"endColumn":38},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":191,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":210,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":191,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":191,"endColumn":48},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":191,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":191,"endColumn":47},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":192,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":199,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":192,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":192,"endColumn":37},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":192,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":192,"endColumn":36},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":193,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":195,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":193,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":193,"endColumn":53},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":193,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":193,"endColumn":52},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":196,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":198,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":196,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":196,"endColumn":50},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":196,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":196,"endColumn":49},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":201,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":204,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":201,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":201,"endColumn":152},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":201,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":201,"endColumn":151},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":202,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":202,"endColumn":42},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":206,"column":37,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":206,"endColumn":109},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":207,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":207,"endColumn":45},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":227,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":232,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":227,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":227,"endColumn":99},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":227,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":227,"endColumn":98},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":228,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":231,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":228,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":228,"endColumn":38},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":228,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":228,"endColumn":37},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":229,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":229,"endColumn":127},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":229,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":229,"endColumn":127},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":229,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":229,"endColumn":124},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":230,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":230,"endColumn":67},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":230,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":230,"endColumn":40},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":230,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":230,"endColumn":39},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":238,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":247,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":238,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":238,"endColumn":99},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":238,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":238,"endColumn":98},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":239,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":246,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":239,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":239,"endColumn":38},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":239,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":239,"endColumn":37},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":240,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":240,"endColumn":91},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":240,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":240,"endColumn":40},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":240,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":240,"endColumn":39},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":242,"column":57,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":242,"endColumn":73},{"ruleId":"gridpilot-rules/rsc-no-local-helpers","severity":2,"message":"Local helper functions forbidden (only assert*/invariant* allowed) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":253,"column":9,"nodeType":"VariableDeclarator","messageId":"message","endLine":256,"endColumn":4},{"ruleId":"gridpilot-rules/rsc-no-local-helpers","severity":2,"message":"Local helper functions forbidden (only assert*/invariant* allowed) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":258,"column":9,"nodeType":"VariableDeclarator","messageId":"message","endLine":263,"endColumn":4},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":281,"column":5,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":286,"endColumn":6},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":282,"column":7,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":282,"endColumn":46},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":288,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":288,"endColumn":43},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":299,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":299,"endColumn":113},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":299,"column":43,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":299,"endColumn":112},{"ruleId":"gridpilot-rules/rsc-no-sorting-filtering","severity":2,"message":"Sorting/filtering/reduce operations forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts","line":311,"column":24,"nodeType":"CallExpression","messageId":"message","endLine":311,"endColumn":121},{"ruleId":"gridpilot-rules/rsc-no-intl","severity":2,"message":"Intl.* or toLocale* usage forbidden in presentation paths - see apps/website/lib/contracts/view-models/ViewModel.ts","line":317,"column":18,"nodeType":"MemberExpression","messageId":"message","endLine":317,"endColumn":73},{"ruleId":"gridpilot-rules/rsc-no-object-construction","severity":2,"message":"Object construction with new forbidden (use PageQueries) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":317,"column":18,"nodeType":"NewExpression","messageId":"message","endLine":317,"endColumn":54},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":331,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":331,"endColumn":43},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":332,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":332,"endColumn":47},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":337,"column":43,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":337,"endColumn":62},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":338,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":338,"endColumn":47},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":343,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":352,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":343,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":343,"endColumn":42},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":343,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":343,"endColumn":41},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":353,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":358,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":353,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":353,"endColumn":38},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":353,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":353,"endColumn":37},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":355,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":355,"endColumn":108},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":355,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":355,"endColumn":35},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":355,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":355,"endColumn":34},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":356,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":356,"endColumn":18},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":363,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":363,"endColumn":43},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":364,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":364,"endColumn":47},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":370,"column":43,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":370,"endColumn":62},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":371,"column":27,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":371,"endColumn":51},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":376,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":376,"endColumn":16},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":382,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":391,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":382,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":382,"endColumn":67},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":382,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":382,"endColumn":66},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":385,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":385,"endColumn":35},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":389,"column":31,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":389,"endColumn":116},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":397,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":397,"endColumn":93},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":397,"column":43,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":397,"endColumn":92},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":399,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":399,"endColumn":42},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":400,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":407,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":400,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":400,"endColumn":115},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":400,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":400,"endColumn":114},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":401,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":406,"endColumn":18},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":401,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":401,"endColumn":78},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":401,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":401,"endColumn":77},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":402,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":404,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":402,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":402,"endColumn":63},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":402,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":402,"endColumn":62},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":403,"column":26,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":403,"endColumn":63},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":408,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":420,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":408,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":408,"endColumn":32},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":408,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":408,"endColumn":31},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":409,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":411,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":409,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":409,"endColumn":65},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":409,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":409,"endColumn":64},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":412,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":414,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":412,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":412,"endColumn":55},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":412,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":412,"endColumn":54},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":415,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":419,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":415,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":415,"endColumn":62},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":415,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":415,"endColumn":61},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":416,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":416,"endColumn":18},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":417,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":417,"endColumn":18},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":418,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":418,"endColumn":18},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":424,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":424,"endColumn":42},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":425,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":432,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":425,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":425,"endColumn":115},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":425,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":425,"endColumn":114},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":426,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":431,"endColumn":18},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":426,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":426,"endColumn":78},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":426,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":426,"endColumn":77},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":427,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":429,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":427,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":427,"endColumn":63},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":427,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":427,"endColumn":62},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":428,"column":26,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":428,"endColumn":68},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":433,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":450,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":433,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":433,"endColumn":32},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":433,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":433,"endColumn":31},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":434,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":436,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":434,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":434,"endColumn":55},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":434,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":434,"endColumn":54},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":437,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":446,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":437,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":437,"endColumn":48},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":437,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":437,"endColumn":47},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":438,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":441,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":438,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":438,"endColumn":107},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":438,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":438,"endColumn":106},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":439,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":439,"endColumn":73},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":439,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":439,"endColumn":49},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":439,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":439,"endColumn":48},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":440,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":440,"endColumn":95},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":440,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":440,"endColumn":58},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":440,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":440,"endColumn":57},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":442,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":445,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":442,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":442,"endColumn":71},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":442,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":442,"endColumn":70},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":443,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":443,"endColumn":74},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":443,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":443,"endColumn":49},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":443,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":443,"endColumn":48},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":444,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":444,"endColumn":86},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":444,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":444,"endColumn":70},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":444,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":444,"endColumn":69},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":447,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":449,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":447,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":447,"endColumn":55},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":447,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":447,"endColumn":54},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":455,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":455,"endColumn":60},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":455,"column":43,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":455,"endColumn":59},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":456,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":456,"endColumn":30},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":457,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":473,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":457,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":457,"endColumn":62},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":457,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":457,"endColumn":61},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":458,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":468,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":458,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":458,"endColumn":54},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":458,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":458,"endColumn":53},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":459,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":461,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":459,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":459,"endColumn":60},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":459,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":459,"endColumn":59},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":460,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":460,"endColumn":56},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":462,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":462,"endColumn":20},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":463,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":463,"endColumn":84},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":463,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":463,"endColumn":56},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":463,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":463,"endColumn":55},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":464,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":466,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":464,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":464,"endColumn":54},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":464,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":464,"endColumn":53},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":471,"column":29,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":471,"endColumn":53}],"suppressedMessages":[],"errorCount":231,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\n\nimport { useState } from 'react';\nimport { motion, useReducedMotion } from 'framer-motion';\nimport { Card } from '@/ui/Card';\nimport { Button } from '@/ui/Button';\nimport { StatCard } from '@/ui/StatCard';\nimport { SectionHeader } from '@/ui/SectionHeader';\nimport { StatusBadge } from '@/ui/StatusBadge';\nimport { InfoBanner } from '@/ui/InfoBanner';\nimport { PageHeader } from '@/ui/PageHeader';\nimport { siteConfig } from '@/lib/siteConfig';\nimport { useSponsorBilling } from \"@/hooks/sponsor/useSponsorBilling\";\nimport {\n CreditCard,\n DollarSign,\n Calendar,\n Download,\n Plus,\n Check,\n AlertTriangle,\n FileText,\n ArrowRight,\n TrendingUp,\n Receipt,\n Building2,\n Wallet,\n Clock,\n ChevronRight,\n Info,\n ExternalLink,\n Percent\n} from 'lucide-react';\nimport type { PaymentMethodDTO, InvoiceDTO } from '@/lib/types/tbd/SponsorBillingDTO';\n\n// ============================================================================\n// Components\n// ============================================================================\n\nfunction PaymentMethodCard({\n method,\n onSetDefault,\n onRemove\n}: {\n method: PaymentMethodDTO;\n onSetDefault: () => void;\n onRemove: () => void;\n}) {\n const shouldReduceMotion = useReducedMotion();\n \n const getIcon = () => {\n if (method.type === 'sepa') return Building2;\n return CreditCard;\n };\n \n const Icon = getIcon();\n \n const displayLabel = method.type === 'sepa' && method.bankName\n ? `${method.bankName} •••• ${method.last4}`\n : `${method.brand} •••• ${method.last4}`;\n\n const expiryDisplay = method.expiryMonth && method.expiryYear\n ? `${method.expiryMonth}/${method.expiryYear}`\n : null;\n\n return (\n \n
\n
\n
\n \n
\n
\n
\n {displayLabel}\n {method.isDefault && (\n \n Default\n \n )}\n
\n {expiryDisplay && (\n \n Expires {expiryDisplay}\n \n )}\n {method.type === 'sepa' && (\n SEPA Direct Debit\n )}\n
\n
\n
\n {!method.isDefault && (\n \n )}\n \n
\n
\n \n );\n}\n\nfunction InvoiceRow({ invoice, index }: { invoice: InvoiceDTO; index: number }) {\n const shouldReduceMotion = useReducedMotion();\n \n const statusConfig = {\n paid: {\n icon: Check,\n label: 'Paid',\n color: 'text-performance-green',\n bg: 'bg-performance-green/10',\n border: 'border-performance-green/30'\n },\n pending: {\n icon: Clock,\n label: 'Pending',\n color: 'text-warning-amber',\n bg: 'bg-warning-amber/10',\n border: 'border-warning-amber/30'\n },\n overdue: {\n icon: AlertTriangle,\n label: 'Overdue',\n color: 'text-racing-red',\n bg: 'bg-racing-red/10',\n border: 'border-racing-red/30'\n },\n failed: {\n icon: AlertTriangle,\n label: 'Failed',\n color: 'text-racing-red',\n bg: 'bg-racing-red/10',\n border: 'border-racing-red/30'\n },\n };\n\n const typeLabels = {\n league: 'League',\n team: 'Team',\n driver: 'Driver',\n race: 'Race',\n platform: 'Platform',\n };\n\n const status = statusConfig[invoice.status as keyof typeof statusConfig];\n const StatusIcon = status.icon;\n\n return (\n \n
\n
\n \n
\n
\n
\n {invoice.description}\n \n {typeLabels[invoice.sponsorshipType as keyof typeof typeLabels]}\n \n
\n
\n {invoice.invoiceNumber}\n \n \n {new Date(invoice.date).toLocaleDateString()}\n \n
\n
\n
\n \n
\n
\n
\n ${invoice.totalAmount.toFixed(2)}\n
\n
\n incl. ${invoice.vatAmount.toFixed(2)} VAT\n
\n
\n\n
\n \n {status.label}\n
\n \n \n
\n \n );\n}\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\nexport default function SponsorBillingPage() {\n const shouldReduceMotion = useReducedMotion();\n const [showAllInvoices, setShowAllInvoices] = useState(false);\n\n const { data: billingData, isLoading, error, retry } = useSponsorBilling('demo-sponsor-1');\n\n if (isLoading) {\n return (\n
\n
\n
\n

Loading billing data...

\n
\n
\n );\n }\n\n if (error || !billingData) {\n return (\n
\n
\n

{error?.message || 'No billing data available'}

\n {error && (\n \n )}\n
\n
\n );\n }\n\n const data = billingData;\n\n const handleSetDefault = (methodId: string) => {\n // In a real app, this would call an API\n console.log('Setting default payment method:', methodId);\n };\n\n const handleRemoveMethod = (methodId: string) => {\n if (confirm('Remove this payment method?')) {\n // In a real app, this would call an API\n console.log('Removing payment method:', methodId);\n }\n };\n\n const containerVariants = {\n hidden: { opacity: 0 },\n visible: {\n opacity: 1,\n transition: {\n staggerChildren: shouldReduceMotion ? 0 : 0.1,\n },\n },\n };\n\n const itemVariants = {\n hidden: { opacity: 0, y: 20 },\n visible: { opacity: 1, y: 0 },\n };\n\n return (\n \n {/* Header */}\n \n \n \n\n {/* Stats Grid */}\n \n \n i.status === 'pending' || i.status === 'overdue').length} invoices`}\n variant=\"orange\"\n />\n \n \n \n\n {/* Payment Methods */}\n \n \n \n \n Add Payment Method\n \n }\n />\n
\n {data.paymentMethods.map((method: PaymentMethodDTO) => (\n handleSetDefault(method.id)}\n onRemove={() => handleRemoveMethod(method.id)}\n />\n ))}\n
\n
\n \n

We support Visa, Mastercard, American Express, and SEPA Direct Debit.

\n

All payment information is securely processed and stored by our payment provider.

\n
\n
\n
\n
\n\n {/* Billing History */}\n \n \n \n \n Export All\n \n }\n />\n
\n {data.invoices.slice(0, showAllInvoices ? data.invoices.length : 4).map((invoice: InvoiceDTO, index: number) => (\n \n ))}\n
\n {data.invoices.length > 4 && (\n
\n setShowAllInvoices(!showAllInvoices)}\n >\n {showAllInvoices ? 'Show Less' : `View All ${data.invoices.length} Invoices`}\n \n \n
\n )}\n
\n
\n\n {/* Platform Fee & VAT Information */}\n \n {/* Platform Fee */}\n \n
\n

\n
\n \n
\n Platform Fee\n

\n
\n
\n
\n {siteConfig.fees.platformFeePercent}%\n
\n

\n {siteConfig.fees.description}\n

\n
\n

• Applied to all sponsorship payments

\n

• Covers platform maintenance and analytics

\n

• Ensures quality sponsorship placements

\n
\n
\n
\n\n {/* VAT Information */}\n \n
\n

\n
\n \n
\n VAT Information\n

\n
\n
\n

\n {siteConfig.vat.notice}\n

\n
\n
\n Standard VAT Rate\n {siteConfig.vat.standardRate}%\n
\n
\n B2B Reverse Charge\n Available\n
\n
\n

\n Enter your VAT ID in Settings to enable reverse charge for B2B transactions.\n

\n
\n
\n
\n\n {/* Billing Support */}\n \n \n
\n
\n
\n \n
\n
\n

Need help with billing?

\n

\n Contact our billing support for questions about invoices, payments, or refunds.\n

\n
\n
\n \n
\n
\n
\n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/sponsor/campaigns/page.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'AnimatePresence' is defined but never used.","line":5,"column":36,"nodeType":"Identifier","messageId":"unusedVar","endLine":5,"endColumn":51},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'Filter' is defined but never used.","line":26,"column":3,"nodeType":"Identifier","messageId":"unusedVar","endLine":26,"endColumn":9},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'AlertCircle' is defined but never used.","line":31,"column":3,"nodeType":"Identifier","messageId":"unusedVar","endLine":31,"endColumn":14},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'Handshake' is defined but never used.","line":36,"column":3,"nodeType":"Identifier","messageId":"unusedVar","endLine":36,"endColumn":12},{"ruleId":"gridpilot-rules/rsc-no-local-helpers","severity":2,"message":"Local helper functions forbidden (only assert*/invariant* allowed) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":101,"column":1,"nodeType":"FunctionDeclaration","messageId":"message","endLine":327,"endColumn":2},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":101,"column":58,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":101,"endColumn":61,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3026,3029],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3026,3029],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"gridpilot-rules/rsc-no-local-helpers","severity":2,"message":"Local helper functions forbidden (only assert*/invariant* allowed) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":115,"column":9,"nodeType":"VariableDeclarator","messageId":"message","endLine":123,"endColumn":4},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":126,"column":5,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":131,"endColumn":6},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":132,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":136,"endColumn":10},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":138,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":164,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":138,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":138,"endColumn":64},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":138,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":138,"endColumn":63},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":139,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":159,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":139,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":139,"endColumn":52},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":139,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":139,"endColumn":51},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":140,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":142,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":140,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":140,"endColumn":108},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":140,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":140,"endColumn":107},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":141,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":141,"endColumn":66},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":143,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":143,"endColumn":18},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":144,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":157,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":144,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":144,"endColumn":66},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":144,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":144,"endColumn":65},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":145,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":147,"endColumn":24},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":145,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":145,"endColumn":119},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":145,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":145,"endColumn":118},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":149,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":155,"endColumn":26},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":149,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":153,"endColumn":23},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":149,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":153,"endColumn":22},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":160,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":163,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":160,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":160,"endColumn":180},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":160,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":160,"endColumn":179},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":161,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":161,"endColumn":44},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":167,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":167,"endColumn":92},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":167,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":167,"endColumn":63},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":167,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":167,"endColumn":62},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":169,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":169,"endColumn":78},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":169,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":169,"endColumn":53},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":169,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":169,"endColumn":52},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":174,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":186,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":174,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":174,"endColumn":98},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":174,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":174,"endColumn":97},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":175,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":178,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":175,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":175,"endColumn":86},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":175,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":175,"endColumn":85},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":176,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":176,"endColumn":40},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":177,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":177,"endColumn":71},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":177,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":177,"endColumn":45},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":177,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":177,"endColumn":44},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":179,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":182,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":179,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":179,"endColumn":55},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":179,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":179,"endColumn":54},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":180,"column":23,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":180,"endColumn":87},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":180,"column":23,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":180,"endColumn":55},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":180,"column":29,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":180,"endColumn":54},{"ruleId":"gridpilot-rules/rsc-no-intl","severity":2,"message":"Intl.* or toLocale* usage forbidden in presentation paths - see apps/website/lib/contracts/view-models/ViewModel.ts","line":181,"column":16,"nodeType":"MemberExpression","messageId":"message","endLine":181,"endColumn":63},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":184,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":184,"endColumn":97},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":184,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":184,"endColumn":59},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":184,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":184,"endColumn":58},{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`\"` can be escaped with `"`, `“`, `"`, `”`.","line":184,"column":59,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"""},"fix":{"range":[6921,6922],"text":"""},"desc":"Replace with `"`."},{"messageId":"replaceWithAlt","data":{"alt":"“"},"fix":{"range":[6921,6922],"text":"“"},"desc":"Replace with `“`."},{"messageId":"replaceWithAlt","data":{"alt":"""},"fix":{"range":[6921,6922],"text":"""},"desc":"Replace with `"`."},{"messageId":"replaceWithAlt","data":{"alt":"”"},"fix":{"range":[6921,6922],"text":"”"},"desc":"Replace with `”`."}]},{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`\"` can be escaped with `"`, `“`, `"`, `”`.","line":184,"column":92,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"""},"fix":{"range":[6954,6955],"text":"""},"desc":"Replace with `"`."},{"messageId":"replaceWithAlt","data":{"alt":"“"},"fix":{"range":[6954,6955],"text":"“"},"desc":"Replace with `“`."},{"messageId":"replaceWithAlt","data":{"alt":"""},"fix":{"range":[6954,6955],"text":"""},"desc":"Replace with `"`."},{"messageId":"replaceWithAlt","data":{"alt":"”"},"fix":{"range":[6954,6955],"text":"”"},"desc":"Replace with `”`."}]},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":190,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":202,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":190,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":190,"endColumn":96},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":190,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":190,"endColumn":95},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":191,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":194,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":191,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":191,"endColumn":85},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":191,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":191,"endColumn":84},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":192,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":192,"endColumn":44},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":193,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":193,"endColumn":61},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":193,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":193,"endColumn":45},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":193,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":193,"endColumn":44},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":195,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":198,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":195,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":195,"endColumn":50},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":195,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":195,"endColumn":49},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":196,"column":27,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":196,"endColumn":91},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":196,"column":27,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":196,"endColumn":59},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":196,"column":33,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":196,"endColumn":58},{"ruleId":"gridpilot-rules/rsc-no-intl","severity":2,"message":"Intl.* or toLocale* usage forbidden in presentation paths - see apps/website/lib/contracts/view-models/ViewModel.ts","line":197,"column":16,"nodeType":"MemberExpression","messageId":"message","endLine":197,"endColumn":60},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":199,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":201,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":199,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":199,"endColumn":55},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":199,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":199,"endColumn":54},{"ruleId":"gridpilot-rules/rsc-no-intl","severity":2,"message":"Intl.* or toLocale* usage forbidden in presentation paths - see apps/website/lib/contracts/view-models/ViewModel.ts","line":200,"column":23,"nodeType":"MemberExpression","messageId":"message","endLine":200,"endColumn":63},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":206,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":220,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":206,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":206,"endColumn":92},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":206,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":206,"endColumn":91},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":207,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":210,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":207,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":207,"endColumn":83},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":207,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":207,"endColumn":82},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":208,"column":27,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":208,"endColumn":46},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":209,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":209,"endColumn":72},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":209,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":209,"endColumn":45},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":209,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":209,"endColumn":44},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":212,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":214,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":212,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":212,"endColumn":57},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":212,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":212,"endColumn":56},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":213,"column":25,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":213,"endColumn":93},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":213,"column":25,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":213,"endColumn":57},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":213,"column":31,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":213,"endColumn":56},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":216,"column":41,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":216,"endColumn":65},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":217,"column":26,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":217,"endColumn":50},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":225,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":271,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":225,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":225,"endColumn":71},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":225,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":225,"endColumn":70},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":226,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":242,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":226,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":226,"endColumn":61},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":226,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":226,"endColumn":60},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":227,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":230,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":227,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":227,"endColumn":83},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":227,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":227,"endColumn":82},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":228,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":228,"endColumn":41},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":231,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":241,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":231,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":231,"endColumn":56},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":231,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":231,"endColumn":55},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":232,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":232,"endColumn":101},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":232,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":232,"endColumn":60},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":232,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":232,"endColumn":59},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":234,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":239,"endColumn":26},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":234,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":236,"endColumn":23},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":234,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":236,"endColumn":22},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":237,"column":72,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":237,"endColumn":91},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":237,"column":113,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":237,"endColumn":132},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":245,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":251,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":245,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":245,"endColumn":63},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":245,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":245,"endColumn":62},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":246,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":249,"endColumn":23},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":246,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":246,"endColumn":85},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":246,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":246,"endColumn":84},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":247,"column":31,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":247,"endColumn":50},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":250,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":250,"endColumn":90},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":250,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":250,"endColumn":59},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":250,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":250,"endColumn":58},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":254,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":262,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":254,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":254,"endColumn":61},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":254,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":254,"endColumn":60},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":255,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":258,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":255,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":255,"endColumn":83},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":255,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":255,"endColumn":82},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":256,"column":27,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":256,"endColumn":46},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":259,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":261,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":259,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":259,"endColumn":65},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":259,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":259,"endColumn":64},{"ruleId":"gridpilot-rules/rsc-no-intl","severity":2,"message":"Intl.* or toLocale* usage forbidden in presentation paths - see apps/website/lib/contracts/view-models/ViewModel.ts","line":260,"column":18,"nodeType":"MemberExpression","messageId":"message","endLine":260,"endColumn":58},{"ruleId":"gridpilot-rules/rsc-no-intl","severity":2,"message":"Intl.* or toLocale* usage forbidden in presentation paths - see apps/website/lib/contracts/view-models/ViewModel.ts","line":260,"column":109,"nodeType":"MemberExpression","messageId":"message","endLine":260,"endColumn":147},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":264,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":270,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":264,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":264,"endColumn":61},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":264,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":264,"endColumn":60},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":265,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":268,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":265,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":265,"endColumn":83},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":265,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":265,"endColumn":82},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":266,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":266,"endColumn":44},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":269,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":269,"endColumn":91},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":269,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":269,"endColumn":57},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":269,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":269,"endColumn":56},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":276,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":285,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":276,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":276,"endColumn":65},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":276,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":276,"endColumn":64},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":277,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":280,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":277,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":277,"endColumn":68},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":277,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":277,"endColumn":67},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":278,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":278,"endColumn":48},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":281,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":284,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":281,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":281,"endColumn":68},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":281,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":281,"endColumn":67},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":282,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":282,"endColumn":46},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":289,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":323,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":289,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":289,"endColumn":101},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":289,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":289,"endColumn":100},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":290,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":301,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":290,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":290,"endColumn":52},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":290,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":290,"endColumn":51},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":292,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":294,"endColumn":22},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":292,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":292,"endColumn":102},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":292,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":292,"endColumn":101},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":297,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":299,"endColumn":22},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":297,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":297,"endColumn":55},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":297,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":297,"endColumn":54},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":302,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":322,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":302,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":302,"endColumn":52},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":302,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":302,"endColumn":51},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":305,"column":45,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":305,"endColumn":64},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":306,"column":33,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":306,"endColumn":57},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":312,"column":43,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":312,"endColumn":101},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":317,"column":43,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":317,"endColumn":62},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":319,"column":31,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":319,"endColumn":55},{"ruleId":"gridpilot-rules/no-hardcoded-search-params","severity":2,"message":"Manual search param access with get(). Use SearchParamParser instead: import { SearchParamParser } from \"@/lib/routing/search-params\"","line":337,"column":24,"nodeType":"MemberExpression","messageId":"manualGetParam","endLine":337,"endColumn":40},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":346,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":351,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":346,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":346,"endColumn":99},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":346,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":346,"endColumn":98},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":347,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":350,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":347,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":347,"endColumn":38},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":347,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":347,"endColumn":37},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":348,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":348,"endColumn":127},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":348,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":348,"endColumn":127},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":348,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":348,"endColumn":124},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":349,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":349,"endColumn":67},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":349,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":349,"endColumn":40},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":349,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":349,"endColumn":39},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":357,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":366,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":357,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":357,"endColumn":99},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":357,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":357,"endColumn":98},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":358,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":365,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":358,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":358,"endColumn":38},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":358,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":358,"endColumn":37},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":359,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":359,"endColumn":105},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":359,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":359,"endColumn":40},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":359,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":359,"endColumn":39},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":361,"column":57,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":361,"endColumn":73},{"ruleId":"gridpilot-rules/rsc-no-sorting-filtering","severity":2,"message":"Sorting/filtering/reduce operations forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts","line":373,"column":32,"nodeType":"CallExpression","messageId":"message","endLine":378,"endColumn":5},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":373,"column":61,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":373,"endColumn":64,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[14875,14878],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[14875,14878],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"gridpilot-rules/rsc-no-sorting-filtering","severity":2,"message":"Sorting/filtering/reduce operations forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts","line":383,"column":13,"nodeType":"CallExpression","messageId":"message","endLine":383,"endColumn":72},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":383,"column":42,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":383,"endColumn":45,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[15272,15275],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[15272,15275],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"gridpilot-rules/rsc-no-sorting-filtering","severity":2,"message":"Sorting/filtering/reduce operations forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts","line":384,"column":14,"nodeType":"CallExpression","messageId":"message","endLine":384,"endColumn":83},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":384,"column":43,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":384,"endColumn":46,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[15353,15356],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[15353,15356],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"gridpilot-rules/rsc-no-sorting-filtering","severity":2,"message":"Sorting/filtering/reduce operations forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts","line":385,"column":15,"nodeType":"CallExpression","messageId":"message","endLine":385,"endColumn":76},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":385,"column":44,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":385,"endColumn":47,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[15445,15448],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[15445,15448],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"gridpilot-rules/rsc-no-sorting-filtering","severity":2,"message":"Sorting/filtering/reduce operations forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts","line":386,"column":15,"nodeType":"CallExpression","messageId":"message","endLine":386,"endColumn":76},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":386,"column":44,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":386,"endColumn":47,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[15529,15532],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[15529,15532],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"gridpilot-rules/rsc-no-sorting-filtering","severity":2,"message":"Sorting/filtering/reduce operations forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts","line":387,"column":22,"nodeType":"CallExpression","messageId":"message","endLine":387,"endColumn":131},{"ruleId":"gridpilot-rules/rsc-no-sorting-filtering","severity":2,"message":"Sorting/filtering/reduce operations forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts","line":387,"column":22,"nodeType":"CallExpression","messageId":"message","endLine":387,"endColumn":81},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":387,"column":51,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":387,"endColumn":54,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[15620,15623],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[15620,15623],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":387,"column":106,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":387,"endColumn":109,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[15675,15678],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[15675,15678],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"gridpilot-rules/rsc-no-sorting-filtering","severity":2,"message":"Sorting/filtering/reduce operations forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts","line":388,"column":23,"nodeType":"CallExpression","messageId":"message","endLine":388,"endColumn":96},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":388,"column":65,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":388,"endColumn":68,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[15766,15769],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[15766,15769],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"gridpilot-rules/rsc-no-sorting-filtering","severity":2,"message":"Sorting/filtering/reduce operations forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts","line":393,"column":14,"nodeType":"CallExpression","messageId":"message","endLine":393,"endColumn":72},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":393,"column":43,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":393,"endColumn":46,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[15890,15893],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[15890,15893],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"gridpilot-rules/rsc-no-sorting-filtering","severity":2,"message":"Sorting/filtering/reduce operations forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts","line":394,"column":12,"nodeType":"CallExpression","messageId":"message","endLine":394,"endColumn":68},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":394,"column":41,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":394,"endColumn":44,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[15968,15971],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[15968,15971],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"gridpilot-rules/rsc-no-sorting-filtering","severity":2,"message":"Sorting/filtering/reduce operations forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts","line":395,"column":14,"nodeType":"CallExpression","messageId":"message","endLine":395,"endColumn":72},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":395,"column":43,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":395,"endColumn":46,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[16046,16049],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[16046,16049],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"gridpilot-rules/rsc-no-sorting-filtering","severity":2,"message":"Sorting/filtering/reduce operations forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts","line":396,"column":12,"nodeType":"CallExpression","messageId":"message","endLine":396,"endColumn":68},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":396,"column":41,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":396,"endColumn":44,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[16124,16127],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[16124,16127],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"gridpilot-rules/rsc-no-sorting-filtering","severity":2,"message":"Sorting/filtering/reduce operations forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts","line":397,"column":15,"nodeType":"CallExpression","messageId":"message","endLine":397,"endColumn":74},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":397,"column":44,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":397,"endColumn":47,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[16203,16206],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[16203,16206],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":401,"column":5,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":613,"endColumn":11},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":401,"column":5,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":401,"endColumn":50},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":401,"column":10,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":401,"endColumn":49},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":403,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":419,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":403,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":403,"endColumn":93},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":403,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":403,"endColumn":92},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":404,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":404,"endColumn":14},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":405,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":408,"endColumn":16},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":405,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":405,"endColumn":81},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":405,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":405,"endColumn":80},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":406,"column":24,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":406,"endColumn":61},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":409,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":409,"endColumn":101},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":409,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":409,"endColumn":45},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":409,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":409,"endColumn":44},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":411,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":418,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":411,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":411,"endColumn":50},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":411,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":411,"endColumn":49},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":414,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":414,"endColumn":45},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":423,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":427,"endColumn":10},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":426,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":426,"endColumn":27},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":429,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":429,"endColumn":16},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":430,"column":24,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":430,"endColumn":131},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":430,"column":24,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":430,"endColumn":55},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":430,"column":32,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":430,"endColumn":54},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":438,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":498,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":438,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":438,"endColumn":67},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":438,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":438,"endColumn":66},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":439,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":442,"endColumn":10},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":443,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":443,"endColumn":32},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":444,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":444,"endColumn":79},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":444,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":444,"endColumn":60},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":444,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":444,"endColumn":59},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":445,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":445,"endColumn":63},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":445,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":445,"endColumn":52},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":445,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":445,"endColumn":51},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":448,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":452,"endColumn":10},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":453,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":453,"endColumn":32},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":454,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":454,"endColumn":92},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":454,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":454,"endColumn":72},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":454,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":454,"endColumn":71},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":455,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":455,"endColumn":64},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":455,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":455,"endColumn":52},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":455,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":455,"endColumn":51},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":458,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":462,"endColumn":10},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":463,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":463,"endColumn":88},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":464,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":464,"endColumn":89},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":464,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":464,"endColumn":68},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":464,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":464,"endColumn":67},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":465,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":465,"endColumn":65},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":465,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":465,"endColumn":52},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":465,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":465,"endColumn":51},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":468,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":472,"endColumn":10},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":473,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":473,"endColumn":32},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":474,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":474,"endColumn":89},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":474,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":474,"endColumn":67},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":474,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":474,"endColumn":66},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":475,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":475,"endColumn":66},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":475,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":475,"endColumn":52},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":475,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":475,"endColumn":51},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":478,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":482,"endColumn":10},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":483,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":483,"endColumn":32},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":484,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":484,"endColumn":107},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":484,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":484,"endColumn":60},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":484,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":484,"endColumn":59},{"ruleId":"gridpilot-rules/rsc-no-intl","severity":2,"message":"Intl.* or toLocale* usage forbidden in presentation paths - see apps/website/lib/contracts/view-models/ViewModel.ts","line":484,"column":62,"nodeType":"MemberExpression","messageId":"message","endLine":484,"endColumn":98},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":485,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":485,"endColumn":75},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":485,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":485,"endColumn":52},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":485,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":485,"endColumn":51},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":488,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":492,"endColumn":10},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":493,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":493,"endColumn":32},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":494,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":494,"endColumn":118},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":494,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":494,"endColumn":67},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":494,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":494,"endColumn":66},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":495,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":495,"endColumn":69},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":495,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":495,"endColumn":52},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":495,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":495,"endColumn":51},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":501,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":573,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":501,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":501,"endColumn":61},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":501,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":501,"endColumn":60},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":503,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":512,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":503,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":503,"endColumn":42},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":503,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":503,"endColumn":41},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":504,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":504,"endColumn":93},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":505,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":511,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":505,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":511,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":510,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":510,"endColumn":181},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":515,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":540,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":515,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":515,"endColumn":79},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":515,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":515,"endColumn":78},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":521,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":537,"endColumn":24},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":521,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":529,"endColumn":16},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":524,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":528,"endColumn":20},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":530,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":530,"endColumn":42},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":532,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":536,"endColumn":24},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":532,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":534,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":532,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":534,"endColumn":20},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":543,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":572,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":543,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":543,"endColumn":66},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":543,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":543,"endColumn":65},{"ruleId":"gridpilot-rules/rsc-no-sorting-filtering","severity":2,"message":"Sorting/filtering/reduce operations forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts","line":550,"column":17,"nodeType":"CallExpression","messageId":"message","endLine":550,"endColumn":74},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":550,"column":46,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":550,"endColumn":49,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[22560,22563],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[22560,22563],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":552,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":569,"endColumn":24},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":552,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":560,"endColumn":16},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":555,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":559,"endColumn":20},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":563,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":567,"endColumn":26},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":563,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":565,"endColumn":23},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":563,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":565,"endColumn":22},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":577,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":577,"endColumn":44},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":578,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":578,"endColumn":70},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":579,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":579,"endColumn":91},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":579,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":579,"endColumn":65},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":579,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":579,"endColumn":64},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":580,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":584,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":580,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":580,"endColumn":62},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":580,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":580,"endColumn":61},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":585,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":604,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":585,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":585,"endColumn":75},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":585,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":585,"endColumn":74},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":588,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":588,"endColumn":49},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":594,"column":24,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":594,"endColumn":48},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":600,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":600,"endColumn":46},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":607,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":611,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":607,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":607,"endColumn":64},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":607,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":607,"endColumn":63},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":608,"column":51,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":608,"endColumn":54,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[24938,24941],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[24938,24941],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":358,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\n\nimport { useState } from 'react';\nimport { useSearchParams } from 'next/navigation';\nimport { motion, useReducedMotion, AnimatePresence } from 'framer-motion';\nimport Link from 'next/link';\nimport { Card } from '@/ui/Card';\nimport { Button } from '@/ui/Button';\nimport { InfoBanner } from '@/ui/InfoBanner';\nimport { useSponsorSponsorships } from \"@/hooks/sponsor/useSponsorSponsorships\";\nimport {\n Megaphone,\n Trophy,\n Users,\n Eye,\n Calendar,\n ExternalLink,\n Plus,\n ChevronRight,\n Check,\n Clock,\n XCircle,\n Car,\n Flag,\n Search,\n Filter,\n TrendingUp,\n BarChart3,\n ArrowUpRight,\n ArrowDownRight,\n AlertCircle,\n Send,\n ThumbsUp,\n ThumbsDown,\n RefreshCw,\n Handshake\n} from 'lucide-react';\n\n// ============================================================================\n// Types\n// ============================================================================\n\ntype SponsorshipType = 'all' | 'leagues' | 'teams' | 'drivers' | 'races' | 'platform';\ntype SponsorshipStatus = 'all' | 'active' | 'pending_approval' | 'approved' | 'rejected' | 'expired';\n\n// ============================================================================\n// Configuration\n// ============================================================================\n\nconst TYPE_CONFIG = {\n leagues: { icon: Trophy, color: 'text-primary-blue', bgColor: 'bg-primary-blue/10', label: 'League' },\n teams: { icon: Users, color: 'text-purple-400', bgColor: 'bg-purple-400/10', label: 'Team' },\n drivers: { icon: Car, color: 'text-performance-green', bgColor: 'bg-performance-green/10', label: 'Driver' },\n races: { icon: Flag, color: 'text-warning-amber', bgColor: 'bg-warning-amber/10', label: 'Race' },\n platform: { icon: Megaphone, color: 'text-racing-red', bgColor: 'bg-racing-red/10', label: 'Platform' },\n all: { icon: BarChart3, color: 'text-gray-400', bgColor: 'bg-gray-400/10', label: 'All' },\n};\n\nconst STATUS_CONFIG = {\n active: {\n icon: Check,\n color: 'text-performance-green',\n bgColor: 'bg-performance-green/10',\n borderColor: 'border-performance-green/30',\n label: 'Active'\n },\n pending_approval: {\n icon: Clock,\n color: 'text-warning-amber',\n bgColor: 'bg-warning-amber/10',\n borderColor: 'border-warning-amber/30',\n label: 'Awaiting Approval'\n },\n approved: {\n icon: ThumbsUp,\n color: 'text-primary-blue',\n bgColor: 'bg-primary-blue/10',\n borderColor: 'border-primary-blue/30',\n label: 'Approved'\n },\n rejected: {\n icon: ThumbsDown,\n color: 'text-racing-red',\n bgColor: 'bg-racing-red/10',\n borderColor: 'border-racing-red/30',\n label: 'Declined'\n },\n expired: {\n icon: XCircle,\n color: 'text-gray-400',\n bgColor: 'bg-gray-400/10',\n borderColor: 'border-gray-400/30',\n label: 'Expired'\n },\n};\n\n// ============================================================================\n// Components\n// ============================================================================\n\nfunction SponsorshipCard({ sponsorship }: { sponsorship: any }) {\n const shouldReduceMotion = useReducedMotion();\n \n const typeConfig = TYPE_CONFIG[sponsorship.type as keyof typeof TYPE_CONFIG];\n const statusConfig = STATUS_CONFIG[sponsorship.status as keyof typeof STATUS_CONFIG];\n const TypeIcon = typeConfig.icon;\n const StatusIcon = statusConfig.icon;\n\n const daysRemaining = Math.ceil((sponsorship.endDate.getTime() - Date.now()) / (1000 * 60 * 60 * 24));\n const isExpiringSoon = daysRemaining > 0 && daysRemaining <= 30;\n const isPending = sponsorship.status === 'pending_approval';\n const isRejected = sponsorship.status === 'rejected';\n const isApproved = sponsorship.status === 'approved';\n\n const getEntityLink = () => {\n switch (sponsorship.type) {\n case 'leagues': return `/leagues/${sponsorship.entityId}`;\n case 'teams': return `/teams/${sponsorship.entityId}`;\n case 'drivers': return `/drivers/${sponsorship.entityId}`;\n case 'races': return `/races/${sponsorship.entityId}`;\n default: return '#';\n }\n };\n\n return (\n \n \n {/* Header */}\n
\n
\n
\n \n
\n
\n
\n \n {typeConfig.label}\n \n {sponsorship.tier && (\n \n {sponsorship.tier === 'main' ? 'Main Sponsor' : 'Secondary'}\n \n )}\n
\n
\n
\n
\n \n {statusConfig.label}\n
\n
\n\n {/* Entity Name */}\n

{sponsorship.entityName}

\n {sponsorship.details && (\n

{sponsorship.details}

\n )}\n\n {/* Application/Approval Info for non-active states */}\n {isPending && (\n
\n
\n \n Application Pending\n
\n

\n Sent to {sponsorship.entityOwner} on{' '}\n {sponsorship.applicationDate?.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })}\n

\n {sponsorship.applicationMessage && (\n

\"{sponsorship.applicationMessage}\"

\n )}\n
\n )}\n\n {isApproved && (\n
\n
\n \n Approved!\n
\n

\n Approved by {sponsorship.entityOwner} on{' '}\n {sponsorship.approvalDate?.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })}\n

\n

\n Starts {sponsorship.startDate.toLocaleDateString('en-US', { month: 'short', day: 'numeric' })}\n

\n
\n )}\n\n {isRejected && (\n
\n
\n \n Application Declined\n
\n {sponsorship.rejectionReason && (\n

\n Reason: {sponsorship.rejectionReason}\n

\n )}\n \n
\n )}\n\n {/* Metrics Grid - Only show for active sponsorships */}\n {sponsorship.status === 'active' && (\n
\n
\n
\n \n Impressions\n
\n
\n {sponsorship.formattedImpressions}\n {sponsorship.impressionsChange !== undefined && sponsorship.impressionsChange !== 0 && (\n 0 ? 'text-performance-green' : 'text-racing-red'\n }`}>\n {sponsorship.impressionsChange > 0 ? : }\n {Math.abs(sponsorship.impressionsChange)}%\n \n )}\n
\n
\n \n {sponsorship.engagement && (\n
\n
\n \n Engagement\n
\n
{sponsorship.engagement}%
\n
\n )}\n \n
\n
\n \n Period\n
\n
\n {sponsorship.startDate.toLocaleDateString('en-US', { month: 'short', year: 'numeric' })} - {sponsorship.endDate.toLocaleDateString('en-US', { month: 'short', year: 'numeric' })}\n
\n
\n \n
\n
\n \n Investment\n
\n
{sponsorship.formattedPrice}
\n
\n
\n )}\n\n {/* Basic info for non-active */}\n {sponsorship.status !== 'active' && (\n
\n
\n \n {sponsorship.periodDisplay}\n
\n
\n \n {sponsorship.formattedPrice}\n
\n
\n )}\n\n {/* Footer */}\n
\n
\n {sponsorship.status === 'active' && (\n \n {daysRemaining > 0 ? `${daysRemaining} days remaining` : 'Ended'}\n \n )}\n {isPending && (\n \n Waiting for response...\n \n )}\n
\n
\n {sponsorship.type !== 'platform' && (\n \n \n \n )}\n {isPending && (\n \n )}\n {sponsorship.status === 'active' && (\n \n )}\n
\n
\n
\n \n );\n}\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\nexport default function SponsorCampaignsPage() {\n const searchParams = useSearchParams();\n const shouldReduceMotion = useReducedMotion();\n\n const initialType = (searchParams.get('type') as SponsorshipType) || 'all';\n const [typeFilter, setTypeFilter] = useState(initialType);\n const [statusFilter, setStatusFilter] = useState('all');\n const [searchQuery, setSearchQuery] = useState('');\n\n const { data: sponsorshipsData, isLoading, error, retry } = useSponsorSponsorships('demo-sponsor-1');\n\n if (isLoading) {\n return (\n
\n
\n
\n

Loading sponsorships...

\n
\n
\n );\n }\n\n if (error || !sponsorshipsData) {\n return (\n
\n
\n

{error?.getUserMessage() || 'No sponsorships data available'}

\n {error && (\n \n )}\n
\n
\n );\n }\n\n const data = sponsorshipsData;\n\n // Filter sponsorships\n const filteredSponsorships = data.sponsorships.filter((s: any) => {\n if (typeFilter !== 'all' && s.type !== typeFilter) return false;\n if (statusFilter !== 'all' && s.status !== statusFilter) return false;\n if (searchQuery && !s.entityName.toLowerCase().includes(searchQuery.toLowerCase())) return false;\n return true;\n });\n\n // Calculate stats\n const stats = {\n total: data.sponsorships.length,\n active: data.sponsorships.filter((s: any) => s.status === 'active').length,\n pending: data.sponsorships.filter((s: any) => s.status === 'pending_approval').length,\n approved: data.sponsorships.filter((s: any) => s.status === 'approved').length,\n rejected: data.sponsorships.filter((s: any) => s.status === 'rejected').length,\n totalInvestment: data.sponsorships.filter((s: any) => s.status === 'active').reduce((sum: number, s: any) => sum + s.price, 0),\n totalImpressions: data.sponsorships.reduce((sum: number, s: any) => sum + s.impressions, 0),\n };\n\n // Stats by type\n const statsByType = {\n leagues: data.sponsorships.filter((s: any) => s.type === 'leagues').length,\n teams: data.sponsorships.filter((s: any) => s.type === 'teams').length,\n drivers: data.sponsorships.filter((s: any) => s.type === 'drivers').length,\n races: data.sponsorships.filter((s: any) => s.type === 'races').length,\n platform: data.sponsorships.filter((s: any) => s.type === 'platform').length,\n };\n\n return (\n
\n {/* Header */}\n
\n
\n

\n \n My Sponsorships\n

\n

Manage applications and active sponsorship campaigns

\n
\n
\n \n \n \n
\n
\n\n {/* Info Banner about how sponsorships work */}\n {stats.pending > 0 && (\n \n \n

\n You have {stats.pending} pending application{stats.pending !== 1 ? 's' : ''} waiting for approval.\n League admins, team owners, and drivers review applications before accepting sponsorships.\n

\n
\n \n )}\n\n {/* Quick Stats */}\n
\n \n \n
{stats.total}
\n
Total
\n
\n \n \n \n
{stats.active}
\n
Active
\n
\n \n \n 0 ? 'border-warning-amber/30' : ''}`}>\n
{stats.pending}
\n
Pending
\n
\n \n \n \n
{stats.approved}
\n
Approved
\n
\n \n \n \n
${stats.totalInvestment.toLocaleString()}
\n
Active Investment
\n
\n \n \n \n
{(stats.totalImpressions / 1000).toFixed(0)}k
\n
Impressions
\n
\n \n
\n\n {/* Filters */}\n
\n {/* Search */}\n
\n \n setSearchQuery(e.target.value)}\n className=\"w-full pl-10 pr-4 py-2.5 rounded-lg border border-charcoal-outline bg-iron-gray text-white placeholder-gray-500 focus:border-primary-blue focus:outline-none\"\n />\n
\n \n {/* Type Filter */}\n
\n {(['all', 'leagues', 'teams', 'drivers', 'races', 'platform'] as const).map((type) => {\n const config = TYPE_CONFIG[type];\n const Icon = config.icon;\n const count = type === 'all' ? stats.total : statsByType[type];\n return (\n setTypeFilter(type)}\n className={`flex items-center gap-2 px-3 py-2 rounded-lg text-sm font-medium whitespace-nowrap transition-colors ${\n typeFilter === type\n ? 'bg-primary-blue text-white'\n : 'bg-iron-gray/50 text-gray-400 hover:bg-iron-gray'\n }`}\n >\n \n {config.label}\n \n {count}\n \n \n );\n })}\n
\n\n {/* Status Filter */}\n
\n {(['all', 'active', 'pending_approval', 'approved', 'rejected'] as const).map((status) => {\n const config = status === 'all'\n ? { label: 'All', color: 'text-gray-400' }\n : STATUS_CONFIG[status];\n const count = status === 'all'\n ? stats.total\n : data.sponsorships.filter((s: any) => s.status === status).length;\n return (\n setStatusFilter(status)}\n className={`px-3 py-2 rounded-lg text-sm font-medium transition-colors whitespace-nowrap ${\n statusFilter === status\n ? 'bg-iron-gray text-white border border-charcoal-outline'\n : 'text-gray-500 hover:text-gray-300'\n }`}\n >\n {config.label}\n {count > 0 && status !== 'all' && (\n \n {count}\n \n )}\n \n );\n })}\n
\n
\n\n {/* Sponsorship List */}\n {filteredSponsorships.length === 0 ? (\n \n \n

No sponsorships found

\n

\n {searchQuery || typeFilter !== 'all' || statusFilter !== 'all'\n ? 'Try adjusting your filters to see more results.'\n : 'Start sponsoring leagues, teams, or drivers to grow your brand visibility.'}\n

\n
\n \n \n \n \n \n \n \n \n \n
\n
\n ) : (\n
\n {filteredSponsorships.map((sponsorship: any) => (\n \n ))}\n
\n )}\n
\n );\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/sponsor/dashboard/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/sponsor/layout.tsx","messages":[{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":26,"column":5,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":28,"endColumn":11},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":26,"column":5,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":26,"endColumn":52},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":26,"column":10,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":26,"endColumn":51}],"suppressedMessages":[],"errorCount":3,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { headers } from 'next/headers';\nimport { redirect } from 'next/navigation';\nimport { createRouteGuard } from '@/lib/auth/createRouteGuard';\n\ninterface SponsorLayoutProps {\n children: React.ReactNode;\n}\n\n/**\n * Sponsor Layout\n *\n * Provides authentication protection for all sponsor-related routes.\n * Uses RouteGuard to enforce access control server-side.\n */\nexport default async function SponsorLayout({ children }: SponsorLayoutProps) {\n const headerStore = await headers();\n const pathname = headerStore.get('x-pathname') || '/';\n \n const guard = createRouteGuard();\n const result = await guard.enforce({ pathname });\n if (result.type === 'redirect') {\n redirect(result.to);\n }\n \n return (\n
\n {children}\n
\n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/sponsor/leagues/SponsorLeaguesPageClient.tsx","messages":[{"ruleId":"import/no-default-export","severity":2,"message":"Prefer named exports.","line":6,"column":8,"nodeType":"ExportDefaultDeclaration","endLine":6,"endColumn":15},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":6,"column":68,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":6,"endColumn":71,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[269,272],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[269,272],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'setTierFilter' is assigned a value but never used.","line":8,"column":22,"nodeType":"Identifier","messageId":"unusedVar","endLine":8,"endColumn":35},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'setAvailabilityFilter' is assigned a value but never used.","line":9,"column":30,"nodeType":"Identifier","messageId":"unusedVar","endLine":9,"endColumn":51},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'setSortBy' is assigned a value but never used.","line":10,"column":18,"nodeType":"Identifier","messageId":"unusedVar","endLine":10,"endColumn":27},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":15,"column":24,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":15,"endColumn":27,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[677,680],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[677,680],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":30,"column":17,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":30,"endColumn":20,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1201,1204],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1201,1204],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":30,"column":25,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":30,"endColumn":28,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1209,1212],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1209,1212],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":8,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\n\nimport React, { useState, useMemo } from 'react';\nimport { SponsorLeaguesTemplate, type SortOption, type TierFilter, type AvailabilityFilter } from '@/templates/SponsorLeaguesTemplate';\n\nexport default function SponsorLeaguesPageClient({ data }: { data: any }) {\n const [searchQuery, setSearchQuery] = useState('');\n const [tierFilter, setTierFilter] = useState('all');\n const [availabilityFilter, setAvailabilityFilter] = useState('all');\n const [sortBy, setSortBy] = useState('rating');\n\n const filteredLeagues = useMemo(() => {\n if (!data?.leagues) return [];\n return data.leagues\n .filter((league: any) => {\n if (searchQuery && !league.name.toLowerCase().includes(searchQuery.toLowerCase())) {\n return false;\n }\n if (tierFilter !== 'all' && league.tier !== tierFilter) {\n return false;\n }\n if (availabilityFilter === 'main' && !league.mainSponsorSlot.available) {\n return false;\n }\n if (availabilityFilter === 'secondary' && league.secondarySlots.available === 0) {\n return false;\n }\n return true;\n })\n .sort((a: any, b: any) => {\n switch (sortBy) {\n case 'rating': return b.rating - a.rating;\n case 'drivers': return b.drivers - a.drivers;\n case 'price': return a.mainSponsorSlot.price - b.mainSponsorSlot.price;\n case 'views': return b.avgViewsPerRace - a.avgViewsPerRace;\n default: return 0;\n }\n });\n }, [data?.leagues, searchQuery, tierFilter, availabilityFilter, sortBy]);\n\n return (\n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/sponsor/leagues/[id]/SponsorLeagueDetailPageClient.tsx","messages":[{"ruleId":"import/no-default-export","severity":2,"message":"Prefer named exports.","line":6,"column":8,"nodeType":"ExportDefaultDeclaration","endLine":6,"endColumn":15},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":6,"column":73,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":6,"endColumn":76,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[216,219],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[216,219],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\n\nimport React, { useState } from 'react';\nimport { SponsorLeagueDetailTemplate } from '@/templates/SponsorLeagueDetailTemplate';\n\nexport default function SponsorLeagueDetailPageClient({ data }: { data: any }) {\n const [activeTab, setActiveTab] = useState<'overview' | 'drivers' | 'races' | 'sponsor'>('overview');\n const [selectedTier, setSelectedTier] = useState<'main' | 'secondary'>('main');\n\n return (\n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/sponsor/leagues/[id]/page.tsx","messages":[{"ruleId":"gridpilot-rules/rsc-no-object-construction","severity":2,"message":"Object construction with new forbidden (use PageQueries) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":12,"column":18,"nodeType":"NewExpression","messageId":"message","endLine":12,"endColumn":37},{"ruleId":"gridpilot-rules/rsc-no-object-construction","severity":2,"message":"Object construction with new forbidden (use PageQueries) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":13,"column":25,"nodeType":"NewExpression","messageId":"message","endLine":17,"endColumn":5},{"ruleId":"gridpilot-rules/rsc-no-object-construction","severity":2,"message":"Object construction with new forbidden (use PageQueries) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":20,"column":21,"nodeType":"NewExpression","messageId":"message","endLine":20,"endColumn":74}],"suppressedMessages":[],"errorCount":3,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { notFound } from 'next/navigation';\nimport { PageWrapper } from '@/components/shared/state/PageWrapper';\nimport SponsorLeagueDetailPageClient from './SponsorLeagueDetailPageClient';\nimport { SponsorsApiClient } from '@/lib/api/sponsors/SponsorsApiClient';\nimport { EnhancedErrorReporter } from '@/lib/infrastructure/EnhancedErrorReporter';\nimport { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';\nimport { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl';\n\nexport default async function Page({ params }: { params: { id: string } }) {\n // Manual wiring: create dependencies\n const baseUrl = getWebsiteApiBaseUrl();\n const logger = new ConsoleLogger();\n const errorReporter = new EnhancedErrorReporter(logger, {\n showUserNotifications: true,\n logToConsole: true,\n reportToExternal: process.env.NODE_ENV === 'production',\n });\n\n // Create API client\n const apiClient = new SponsorsApiClient(baseUrl, errorReporter, logger);\n\n // Fetch data\n const data = await apiClient.getLeagueDetail(params.id);\n \n if (!data) notFound();\n \n // Data is already in the right format from API client\n return ;\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/sponsor/leagues/page.tsx","messages":[{"ruleId":"gridpilot-rules/rsc-no-object-construction","severity":2,"message":"Object construction with new forbidden (use PageQueries) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":11,"column":18,"nodeType":"NewExpression","messageId":"message","endLine":11,"endColumn":37},{"ruleId":"gridpilot-rules/rsc-no-object-construction","severity":2,"message":"Object construction with new forbidden (use PageQueries) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":12,"column":25,"nodeType":"NewExpression","messageId":"message","endLine":16,"endColumn":5},{"ruleId":"gridpilot-rules/rsc-no-object-construction","severity":2,"message":"Object construction with new forbidden (use PageQueries) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":19,"column":21,"nodeType":"NewExpression","messageId":"message","endLine":19,"endColumn":74},{"ruleId":"gridpilot-rules/rsc-no-sorting-filtering","severity":2,"message":"Sorting/filtering/reduce operations forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts","line":32,"column":20,"nodeType":"CallExpression","messageId":"message","endLine":32,"endColumn":79},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":32,"column":43,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":32,"endColumn":46,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1279,1282],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1279,1282],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"gridpilot-rules/rsc-no-sorting-filtering","severity":2,"message":"Sorting/filtering/reduce operations forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts","line":33,"column":25,"nodeType":"CallExpression","messageId":"message","endLine":33,"endColumn":105},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":33,"column":61,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":33,"endColumn":64,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1384,1387],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1384,1387],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"gridpilot-rules/rsc-no-sorting-filtering","severity":2,"message":"Sorting/filtering/reduce operations forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts","line":34,"column":19,"nodeType":"CallExpression","messageId":"message","endLine":34,"endColumn":82},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":34,"column":55,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":34,"endColumn":58,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1484,1487],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1484,1487],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"gridpilot-rules/rsc-no-sorting-filtering","severity":2,"message":"Sorting/filtering/reduce operations forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts","line":36,"column":7,"nodeType":"CallExpression","messageId":"message","endLine":36,"endColumn":66},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":36,"column":43,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":36,"endColumn":46,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1579,1582],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1579,1582],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":11,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { PageWrapper } from '@/components/shared/state/PageWrapper';\nimport SponsorLeaguesPageClient from './SponsorLeaguesPageClient';\nimport { SponsorsApiClient } from '@/lib/api/sponsors/SponsorsApiClient';\nimport { EnhancedErrorReporter } from '@/lib/infrastructure/EnhancedErrorReporter';\nimport { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';\nimport { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl';\n\nexport default async function Page() {\n // Manual wiring: create dependencies\n const baseUrl = getWebsiteApiBaseUrl();\n const logger = new ConsoleLogger();\n const errorReporter = new EnhancedErrorReporter(logger, {\n showUserNotifications: true,\n logToConsole: true,\n reportToExternal: process.env.NODE_ENV === 'production',\n });\n\n // Create API client\n const apiClient = new SponsorsApiClient(baseUrl, errorReporter, logger);\n\n // Fetch data\n const leaguesData = await apiClient.getAvailableLeagues();\n \n // Process data - move business logic to template\n if (!leaguesData) {\n return ;\n }\n \n // Calculate summary stats (business logic moved from view model)\n const stats = {\n total: leaguesData.length,\n mainAvailable: leaguesData.filter((l: any) => l.mainSponsorSlot.available).length,\n secondaryAvailable: leaguesData.reduce((sum: number, l: any) => sum + l.secondarySlots.available, 0),\n totalDrivers: leaguesData.reduce((sum: number, l: any) => sum + l.drivers, 0),\n avgCpm: Math.round(\n leaguesData.reduce((sum: number, l: any) => sum + l.cpm, 0) / leaguesData.length\n ),\n };\n\n const processedData = {\n leagues: leaguesData,\n stats,\n };\n \n return ;\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/sponsor/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/sponsor/settings/page.tsx","messages":[{"ruleId":"gridpilot-rules/rsc-no-local-helpers","severity":2,"message":"Local helper functions forbidden (only assert*/invariant* allowed) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":139,"column":1,"nodeType":"FunctionDeclaration","messageId":"message","endLine":153,"endColumn":2},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":143,"column":5,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":148,"endColumn":6},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":147,"column":7,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":147,"endColumn":65},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":149,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":149,"endColumn":39},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":150,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":150,"endColumn":65},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":150,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":150,"endColumn":45},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":150,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":150,"endColumn":44},{"ruleId":"gridpilot-rules/rsc-no-local-helpers","severity":2,"message":"Local helper functions forbidden (only assert*/invariant* allowed) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":167,"column":9,"nodeType":"VariableDeclarator","messageId":"message","endLine":173,"endColumn":4},{"ruleId":"gridpilot-rules/rsc-no-object-construction","severity":2,"message":"Object construction with new forbidden (use PageQueries) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":169,"column":11,"nodeType":"NewExpression","messageId":"message","endLine":169,"endColumn":59},{"ruleId":"gridpilot-rules/rsc-no-local-helpers","severity":2,"message":"Local helper functions forbidden (only assert*/invariant* allowed) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":175,"column":9,"nodeType":"VariableDeclarator","messageId":"message","endLine":187,"endColumn":4},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":205,"column":5,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":210,"endColumn":6},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":206,"column":7,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":206,"endColumn":46},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":212,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":212,"endColumn":43},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":222,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":222,"endColumn":43},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":223,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":223,"endColumn":47},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":229,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":484,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":229,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":229,"endColumn":42},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":229,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":229,"endColumn":41},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":231,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":252,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":231,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":231,"endColumn":68},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":231,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":231,"endColumn":67},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":242,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":250,"endColumn":26},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":242,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":246,"endColumn":18},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":245,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":245,"endColumn":158},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":248,"column":21,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":248,"endColumn":61},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":255,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":296,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":255,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":255,"endColumn":71},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":255,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":255,"endColumn":70},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":256,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":258,"endColumn":20},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":256,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":256,"endColumn":97},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":256,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":256,"endColumn":96},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":259,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":295,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":259,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":259,"endColumn":70},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":259,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":259,"endColumn":69},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":299,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":363,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":299,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":299,"endColumn":71},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":299,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":299,"endColumn":70},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":300,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":302,"endColumn":20},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":300,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":300,"endColumn":97},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":300,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":300,"endColumn":96},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":303,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":362,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":303,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":303,"endColumn":70},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":303,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":303,"endColumn":69},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":304,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":316,"endColumn":23},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":304,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":304,"endColumn":48},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":304,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":304,"endColumn":47},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":366,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":379,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":366,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":366,"endColumn":71},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":366,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":366,"endColumn":70},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":368,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":374,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":368,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":374,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":373,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":373,"endColumn":191},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":375,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":377,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":375,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":375,"endColumn":59},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":375,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":375,"endColumn":58},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":382,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":423,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":382,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":382,"endColumn":71},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":382,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":382,"endColumn":70},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":383,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":385,"endColumn":20},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":383,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":383,"endColumn":97},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":383,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":383,"endColumn":96},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":386,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":422,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":386,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":386,"endColumn":70},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":386,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":386,"endColumn":69},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":426,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":461,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":426,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":426,"endColumn":71},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":426,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":426,"endColumn":70},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":428,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":459,"endColumn":23},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":428,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":428,"endColumn":57},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":428,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":428,"endColumn":56},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":429,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":435,"endColumn":25},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":429,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":429,"endColumn":203},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":429,"column":24,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":429,"endColumn":202},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":433,"column":34,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":433,"endColumn":69},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":436,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":458,"endColumn":25},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":436,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":436,"endColumn":43},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":436,"column":24,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":436,"endColumn":42},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":437,"column":21,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":454,"endColumn":27},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":437,"column":21,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":437,"endColumn":62},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":437,"column":26,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":437,"endColumn":61},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":438,"column":23,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":448,"endColumn":31},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":438,"column":23,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":438,"endColumn":57},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":438,"column":30,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":438,"endColumn":56},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":439,"column":25,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":443,"endColumn":27},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":439,"column":25,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":443,"endColumn":27},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":442,"column":27,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":442,"endColumn":45},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":444,"column":25,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":447,"endColumn":31},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":444,"column":25,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":444,"endColumn":189},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":444,"column":30,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":444,"endColumn":188},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":445,"column":35,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":445,"endColumn":54},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":450,"column":53,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":450,"endColumn":86},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":455,"column":21,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":457,"endColumn":25},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":455,"column":21,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":455,"endColumn":63},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":455,"column":24,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":455,"endColumn":62},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":464,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":483,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":464,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":464,"endColumn":104},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":464,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":464,"endColumn":103},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":469,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":469,"endColumn":42},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":472,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":475,"endColumn":26},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":472,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":472,"endColumn":61},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":472,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":472,"endColumn":60},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":473,"column":21,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":473,"endColumn":115},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":473,"column":21,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":473,"endColumn":115},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":473,"column":27,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":473,"endColumn":112},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":477,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":480,"endColumn":26},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":477,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":477,"endColumn":61},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":477,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":477,"endColumn":60},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":478,"column":27,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":478,"endColumn":46},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":489,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":489,"endColumn":43},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":490,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":490,"endColumn":47},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":497,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":536,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":497,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":497,"endColumn":32},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":497,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":497,"endColumn":31},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":498,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":535,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":498,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":498,"endColumn":40},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":498,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":498,"endColumn":39},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":541,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":541,"endColumn":43},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":542,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":542,"endColumn":47},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":549,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":576,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":549,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":549,"endColumn":32},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":549,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":549,"endColumn":31},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":550,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":575,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":550,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":550,"endColumn":40},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":550,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":550,"endColumn":39},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":581,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":581,"endColumn":43},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":582,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":582,"endColumn":47},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":589,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":634,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":589,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":589,"endColumn":42},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":589,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":589,"endColumn":41},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":590,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":603,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":590,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":590,"endColumn":105},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":590,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":590,"endColumn":104},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":591,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":599,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":591,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":591,"endColumn":56},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":591,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":591,"endColumn":55},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":592,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":594,"endColumn":23},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":592,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":592,"endColumn":62},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":592,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":592,"endColumn":61},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":593,"column":24,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":593,"endColumn":57},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":595,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":595,"endColumn":22},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":596,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":596,"endColumn":72},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":596,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":596,"endColumn":60},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":596,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":596,"endColumn":59},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":597,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":597,"endColumn":85},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":597,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":597,"endColumn":56},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":597,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":597,"endColumn":55},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":605,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":618,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":605,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":605,"endColumn":105},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":605,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":605,"endColumn":104},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":606,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":614,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":606,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":606,"endColumn":56},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":606,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":606,"endColumn":55},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":607,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":609,"endColumn":23},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":607,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":607,"endColumn":62},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":607,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":607,"endColumn":61},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":608,"column":31,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":608,"endColumn":64},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":610,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":610,"endColumn":22},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":611,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":611,"endColumn":89},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":611,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":611,"endColumn":60},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":611,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":611,"endColumn":59},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":612,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":612,"endColumn":106},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":612,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":612,"endColumn":56},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":612,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":612,"endColumn":55},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":620,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":633,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":620,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":620,"endColumn":69},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":620,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":620,"endColumn":68},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":621,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":629,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":621,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":621,"endColumn":56},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":621,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":621,"endColumn":55},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":622,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":624,"endColumn":23},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":622,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":622,"endColumn":62},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":622,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":622,"endColumn":61},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":623,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":623,"endColumn":58},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":625,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":625,"endColumn":22},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":626,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":626,"endColumn":79},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":626,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":626,"endColumn":60},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":626,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":626,"endColumn":59},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":627,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":627,"endColumn":97},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":627,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":627,"endColumn":56},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":627,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":627,"endColumn":55},{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`'` can be escaped with `'`, `‘`, `'`, `’`.","line":627,"column":80,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"'"},"fix":{"range":[23710,23747],"text":"Manage devices where you're logged in"},"desc":"Replace with `'`."},{"messageId":"replaceWithAlt","data":{"alt":"‘"},"fix":{"range":[23710,23747],"text":"Manage devices where you‘re logged in"},"desc":"Replace with `‘`."},{"messageId":"replaceWithAlt","data":{"alt":"'"},"fix":{"range":[23710,23747],"text":"Manage devices where you're logged in"},"desc":"Replace with `'`."},{"messageId":"replaceWithAlt","data":{"alt":"’"},"fix":{"range":[23710,23747],"text":"Manage devices where you’re logged in"},"desc":"Replace with `’`."}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":639,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":639,"endColumn":43},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":640,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":640,"endColumn":63},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":641,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":648,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":641,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":641,"endColumn":113},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":641,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":641,"endColumn":112},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":642,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":647,"endColumn":18},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":642,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":642,"endColumn":91},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":642,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":642,"endColumn":90},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":643,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":645,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":643,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":643,"endColumn":64},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":643,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":643,"endColumn":63},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":644,"column":30,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":644,"endColumn":65},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":649,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":671,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":649,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":649,"endColumn":32},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":649,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":649,"endColumn":31},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":650,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":670,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":650,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":650,"endColumn":64},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":650,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":650,"endColumn":63},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":651,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":662,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":651,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":651,"endColumn":56},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":651,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":651,"endColumn":55},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":652,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":654,"endColumn":23},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":652,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":652,"endColumn":66},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":652,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":652,"endColumn":65},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":653,"column":27,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":653,"endColumn":62},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":655,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":655,"endColumn":22},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":656,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":656,"endColumn":86},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":656,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":656,"endColumn":60},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":656,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":656,"endColumn":59},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":657,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":660,"endColumn":23},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":657,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":657,"endColumn":56},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":657,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":657,"endColumn":55},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":666,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":666,"endColumn":88}],"suppressedMessages":[],"errorCount":214,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\n\nimport { useState } from 'react';\nimport { motion, useReducedMotion } from 'framer-motion';\nimport { Card } from '@/ui/Card';\nimport { Button } from '@/ui/Button';\nimport { Input } from '@/ui/Input';\nimport { Toggle } from '@/ui/Toggle';\nimport { SectionHeader } from '@/ui/SectionHeader';\nimport { FormField } from '@/ui/FormField';\nimport { PageHeader } from '@/ui/PageHeader';\nimport { Image } from '@/ui/Image';\nimport {\n Settings,\n Building2,\n Mail,\n Globe,\n Upload,\n Save,\n Bell,\n Shield,\n Eye,\n Trash2,\n CheckCircle,\n User,\n Phone,\n MapPin,\n FileText,\n Link as LinkIcon,\n Image as ImageIcon,\n Lock,\n Key,\n Smartphone,\n AlertCircle\n} from 'lucide-react';\nimport { logoutAction } from '@/app/actions/logoutAction';\n\n// ============================================================================\n// Types\n// ============================================================================\n\ninterface SponsorProfile {\n companyName: string;\n contactName: string;\n contactEmail: string;\n contactPhone: string;\n website: string;\n description: string;\n logoUrl: string | null;\n industry: string;\n address: {\n street: string;\n city: string;\n country: string;\n postalCode: string;\n };\n taxId: string;\n socialLinks: {\n twitter: string;\n linkedin: string;\n instagram: string;\n };\n}\n\ninterface NotificationSettings {\n emailNewSponsorships: boolean;\n emailWeeklyReport: boolean;\n emailRaceAlerts: boolean;\n emailPaymentAlerts: boolean;\n emailNewOpportunities: boolean;\n emailContractExpiry: boolean;\n}\n\ninterface PrivacySettings {\n publicProfile: boolean;\n showStats: boolean;\n showActiveSponsorships: boolean;\n allowDirectContact: boolean;\n}\n\n// ============================================================================\n// Mock Data\n// ============================================================================\n\nconst MOCK_PROFILE: SponsorProfile = {\n companyName: 'Acme Racing Co.',\n contactName: 'John Smith',\n contactEmail: 'sponsor@acme-racing.com',\n contactPhone: '+1 (555) 123-4567',\n website: 'https://acme-racing.com',\n description: 'Premium sim racing equipment and accessories for competitive drivers. We specialize in high-performance steering wheels, pedals, and cockpit systems used by professionals worldwide.',\n logoUrl: null,\n industry: 'Racing Equipment',\n address: {\n street: '123 Racing Boulevard',\n city: 'Indianapolis',\n country: 'United States',\n postalCode: '46222',\n },\n taxId: 'US12-3456789',\n socialLinks: {\n twitter: '@acmeracing',\n linkedin: 'acme-racing-co',\n instagram: '@acmeracing',\n },\n};\n\nconst MOCK_NOTIFICATIONS: NotificationSettings = {\n emailNewSponsorships: true,\n emailWeeklyReport: true,\n emailRaceAlerts: false,\n emailPaymentAlerts: true,\n emailNewOpportunities: true,\n emailContractExpiry: true,\n};\n\nconst MOCK_PRIVACY: PrivacySettings = {\n publicProfile: true,\n showStats: false,\n showActiveSponsorships: true,\n allowDirectContact: true,\n};\n\nconst INDUSTRY_OPTIONS = [\n 'Racing Equipment',\n 'Automotive',\n 'Technology',\n 'Gaming & Esports',\n 'Energy Drinks',\n 'Apparel',\n 'Financial Services',\n 'Other',\n];\n\n// ============================================================================\n// Components\n// ============================================================================\n\nfunction SavedIndicator({ visible }: { visible: boolean }) {\n const shouldReduceMotion = useReducedMotion();\n \n return (\n \n \n Changes saved\n \n );\n}\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\nexport default function SponsorSettingsPage() {\n const shouldReduceMotion = useReducedMotion();\n const [profile, setProfile] = useState(MOCK_PROFILE);\n const [notifications, setNotifications] = useState(MOCK_NOTIFICATIONS);\n const [privacy, setPrivacy] = useState(MOCK_PRIVACY);\n const [saving, setSaving] = useState(false);\n const [saved, setSaved] = useState(false);\n\n const handleSaveProfile = async () => {\n setSaving(true);\n await new Promise(resolve => setTimeout(resolve, 800));\n setSaving(false);\n setSaved(true);\n setTimeout(() => setSaved(false), 3000);\n };\n\n const handleDeleteAccount = async () => {\n if (confirm('Are you sure you want to delete your sponsor account? This action cannot be undone. All sponsorship data will be permanently removed.')) {\n // Call the logout action and handle result\n const result = await logoutAction();\n if (result.isErr()) {\n console.error('Logout failed:', result.getError());\n // Could show error toast here\n return;\n }\n // Redirect to login after successful logout\n window.location.href = '/auth/login';\n }\n };\n\n const containerVariants = {\n hidden: { opacity: 0 },\n visible: {\n opacity: 1,\n transition: {\n staggerChildren: shouldReduceMotion ? 0 : 0.1,\n },\n },\n };\n\n const itemVariants = {\n hidden: { opacity: 0, y: 20 },\n visible: { opacity: 1, y: 0 },\n };\n\n return (\n \n {/* Header */}\n \n }\n />\n \n\n {/* Company Profile */}\n \n \n \n
\n {/* Company Basic Info */}\n
\n \n setProfile({ ...profile, companyName: e.target.value })}\n placeholder=\"Your company name\"\n />\n \n\n \n setProfile({ ...profile, industry: e.target.value })}\n className=\"w-full px-3 py-2 bg-iron-gray border border-charcoal-outline rounded-lg text-white focus:outline-none focus:border-primary-blue\"\n >\n {INDUSTRY_OPTIONS.map(industry => (\n \n ))}\n \n \n
\n\n {/* Contact Information */}\n
\n

\n Contact Information\n

\n
\n \n setProfile({ ...profile, contactName: e.target.value })}\n placeholder=\"Full name\"\n />\n \n\n \n setProfile({ ...profile, contactEmail: e.target.value })}\n placeholder=\"sponsor@company.com\"\n />\n \n\n \n setProfile({ ...profile, contactPhone: e.target.value })}\n placeholder=\"+1 (555) 123-4567\"\n />\n \n\n \n setProfile({ ...profile, website: e.target.value })}\n placeholder=\"https://company.com\"\n />\n \n
\n
\n\n {/* Address */}\n
\n

\n Business Address\n

\n
\n
\n \n setProfile({\n ...profile,\n address: { ...profile.address, street: e.target.value }\n })}\n placeholder=\"123 Main Street\"\n />\n \n
\n\n \n setProfile({\n ...profile,\n address: { ...profile.address, city: e.target.value }\n })}\n placeholder=\"City\"\n />\n \n\n \n setProfile({\n ...profile,\n address: { ...profile.address, postalCode: e.target.value }\n })}\n placeholder=\"12345\"\n />\n \n\n \n setProfile({\n ...profile,\n address: { ...profile.address, country: e.target.value }\n })}\n placeholder=\"Country\"\n />\n \n\n \n setProfile({ ...profile, taxId: e.target.value })}\n placeholder=\"XX12-3456789\"\n />\n \n
\n
\n\n {/* Description */}\n
\n \n setProfile({ ...profile, description: e.target.value })}\n placeholder=\"Tell potential sponsorship partners about your company, products, and what you're looking for in sponsorship opportunities...\"\n rows={4}\n className=\"w-full px-4 py-3 bg-iron-gray border border-charcoal-outline rounded-lg text-white placeholder-gray-500 focus:outline-none focus:border-primary-blue resize-none\"\n />\n

\n This description appears on your public sponsor profile.\n

\n
\n
\n\n {/* Social Links */}\n
\n

\n Social Media\n

\n
\n \n setProfile({\n ...profile,\n socialLinks: { ...profile.socialLinks, twitter: e.target.value }\n })}\n placeholder=\"@username\"\n />\n \n\n \n setProfile({\n ...profile,\n socialLinks: { ...profile.socialLinks, linkedin: e.target.value }\n })}\n placeholder=\"company-name\"\n />\n \n\n \n setProfile({\n ...profile,\n socialLinks: { ...profile.socialLinks, instagram: e.target.value }\n })}\n placeholder=\"@username\"\n />\n \n
\n
\n\n {/* Logo Upload */}\n
\n \n
\n
\n {profile.logoUrl ? (\n \"Company\n ) : (\n \n )}\n
\n
\n
\n \n {profile.logoUrl && (\n \n )}\n
\n

\n PNG, JPEG, or SVG. Max 2MB. Recommended size: 400x400px.\n

\n
\n
\n
\n
\n\n {/* Save Button */}\n
\n \n {saving ? (\n \n \n Saving...\n \n ) : (\n \n \n Save Profile\n \n )}\n \n
\n
\n
\n
\n\n {/* Notification Preferences */}\n \n \n \n
\n
\n setNotifications({ ...notifications, emailNewSponsorships: checked })}\n label=\"Sponsorship Approvals\"\n description=\"Receive confirmation when your sponsorship requests are approved\"\n />\n setNotifications({ ...notifications, emailWeeklyReport: checked })}\n label=\"Weekly Analytics Report\"\n description=\"Get a weekly summary of your sponsorship performance\"\n />\n setNotifications({ ...notifications, emailRaceAlerts: checked })}\n label=\"Race Day Alerts\"\n description=\"Be notified when sponsored leagues have upcoming races\"\n />\n setNotifications({ ...notifications, emailPaymentAlerts: checked })}\n label=\"Payment & Invoice Notifications\"\n description=\"Receive invoices and payment confirmations\"\n />\n setNotifications({ ...notifications, emailNewOpportunities: checked })}\n label=\"New Sponsorship Opportunities\"\n description=\"Get notified about new leagues and drivers seeking sponsors\"\n />\n setNotifications({ ...notifications, emailContractExpiry: checked })}\n label=\"Contract Expiry Reminders\"\n description=\"Receive reminders before your sponsorship contracts expire\"\n />\n
\n
\n
\n
\n\n {/* Privacy & Visibility */}\n \n \n \n
\n
\n setPrivacy({ ...privacy, publicProfile: checked })}\n label=\"Public Profile\"\n description=\"Allow leagues, teams, and drivers to view your sponsor profile\"\n />\n setPrivacy({ ...privacy, showStats: checked })}\n label=\"Show Sponsorship Statistics\"\n description=\"Display your total sponsorships and investment amounts\"\n />\n setPrivacy({ ...privacy, showActiveSponsorships: checked })}\n label=\"Show Active Sponsorships\"\n description=\"Let others see which leagues and teams you currently sponsor\"\n />\n setPrivacy({ ...privacy, allowDirectContact: checked })}\n label=\"Allow Direct Contact\"\n description=\"Enable leagues and teams to send you sponsorship proposals\"\n />\n
\n
\n
\n
\n\n {/* Security */}\n \n \n \n
\n
\n
\n
\n \n
\n
\n

Password

\n

Last changed 3 months ago

\n
\n
\n \n
\n\n
\n
\n
\n \n
\n
\n

Two-Factor Authentication

\n

Add an extra layer of security to your account

\n
\n
\n \n
\n\n
\n
\n
\n \n
\n
\n

Active Sessions

\n

Manage devices where you're logged in

\n
\n
\n \n
\n
\n
\n
\n\n {/* Danger Zone */}\n \n \n
\n

\n
\n \n
\n Danger Zone\n

\n
\n
\n
\n
\n
\n \n
\n
\n

Delete Sponsor Account

\n

\n Permanently delete your account and all associated sponsorship data.\n This action cannot be undone.\n

\n
\n
\n \n Delete Account\n \n
\n
\n
\n
\n \n );\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/sponsor/signup/page.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'Star' is defined but never used.","line":28,"column":3,"nodeType":"Identifier","messageId":"unusedVar","endLine":28,"endColumn":7},{"ruleId":"gridpilot-rules/rsc-no-local-helpers","severity":2,"message":"Local helper functions forbidden (only assert*/invariant* allowed) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":141,"column":9,"nodeType":"VariableDeclarator","messageId":"message","endLine":227,"endColumn":4},{"ruleId":"gridpilot-rules/rsc-no-object-construction","severity":2,"message":"Object construction with new forbidden (use PageQueries) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":203,"column":15,"nodeType":"NewExpression","messageId":"message","endLine":203,"endColumn":62},{"ruleId":"gridpilot-rules/rsc-no-object-construction","severity":2,"message":"Object construction with new forbidden (use PageQueries) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":216,"column":15,"nodeType":"NewExpression","messageId":"message","endLine":216,"endColumn":45},{"ruleId":"gridpilot-rules/rsc-no-local-helpers","severity":2,"message":"Local helper functions forbidden (only assert*/invariant* allowed) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":229,"column":9,"nodeType":"VariableDeclarator","messageId":"message","endLine":236,"endColumn":4},{"ruleId":"gridpilot-rules/rsc-no-sorting-filtering","severity":2,"message":"Sorting/filtering/reduce operations forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts","line":233,"column":11,"nodeType":"CallExpression","messageId":"message","endLine":233,"endColumn":47},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":241,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":429,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":241,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":241,"endColumn":54},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":241,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":241,"endColumn":53},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":247,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":264,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":247,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":247,"endColumn":75},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":247,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":247,"endColumn":74},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":251,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":251,"endColumn":36},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":253,"column":26,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":253,"endColumn":50},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":259,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":259,"endColumn":36},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":262,"column":27,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":262,"endColumn":51},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":268,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":284,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":268,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":268,"endColumn":69},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":268,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":268,"endColumn":68},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":269,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":283,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":269,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":269,"endColumn":66},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":269,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":269,"endColumn":65},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":271,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":276,"endColumn":16},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":277,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":277,"endColumn":83},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":278,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":278,"endColumn":101},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":278,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":278,"endColumn":83},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":278,"column":24,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":278,"endColumn":82},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":279,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":279,"endColumn":87},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":279,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":279,"endColumn":69},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":279,"column":24,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":279,"endColumn":68},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":287,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":331,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":287,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":287,"endColumn":68},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":287,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":287,"endColumn":67},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":288,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":296,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":288,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":288,"endColumn":46},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":288,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":288,"endColumn":45},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":289,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":291,"endColumn":18},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":289,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":289,"endColumn":76},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":289,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":289,"endColumn":75},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":292,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":295,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":292,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":292,"endColumn":60},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":292,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":292,"endColumn":59},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":298,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":330,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":298,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":298,"endColumn":81},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":298,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":298,"endColumn":80},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":300,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":305,"endColumn":16},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":306,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":306,"endColumn":104},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":307,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":315,"endColumn":25},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":307,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":307,"endColumn":64},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":307,"column":24,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":307,"endColumn":63},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":308,"column":21,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":310,"endColumn":27},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":308,"column":21,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":308,"endColumn":191},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":308,"column":26,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":308,"endColumn":190},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":309,"column":23,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":309,"endColumn":72},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":309,"column":34,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":309,"endColumn":69},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":311,"column":21,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":311,"endColumn":26},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":312,"column":23,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":312,"endColumn":89},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":312,"column":23,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":312,"endColumn":72},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":312,"column":27,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":312,"endColumn":71},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":313,"column":23,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":313,"endColumn":97},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":313,"column":23,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":313,"endColumn":76},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":313,"column":26,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":313,"endColumn":75},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":317,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":317,"endColumn":83},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":317,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":317,"endColumn":61},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":317,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":317,"endColumn":60},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":319,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":326,"endColumn":24},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":319,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":319,"endColumn":45},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":319,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":319,"endColumn":44},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":321,"column":23,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":324,"endColumn":28},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":321,"column":23,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":321,"endColumn":93},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":321,"column":35,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":321,"endColumn":92},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":322,"column":39,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":322,"endColumn":95},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":334,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":347,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":334,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":334,"endColumn":61},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":334,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":334,"endColumn":60},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":335,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":346,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":335,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":335,"endColumn":51},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":335,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":335,"endColumn":50},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":336,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":343,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":336,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":336,"endColumn":48},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":336,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":336,"endColumn":47},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":337,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":339,"endColumn":20},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":337,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":337,"endColumn":78},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":337,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":337,"endColumn":77},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":340,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":342,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":340,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":340,"endColumn":62},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":340,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":340,"endColumn":61},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":350,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":399,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":350,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":350,"endColumn":68},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":350,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":350,"endColumn":67},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":351,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":358,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":351,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":351,"endColumn":46},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":351,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":351,"endColumn":45},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":352,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":354,"endColumn":18},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":352,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":352,"endColumn":76},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":352,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":352,"endColumn":75},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":355,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":357,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":355,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":355,"endColumn":60},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":355,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":355,"endColumn":59},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":360,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":398,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":360,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":360,"endColumn":81},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":360,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":360,"endColumn":80},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":402,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":428,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":402,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":402,"endColumn":80},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":402,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":402,"endColumn":79},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":403,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":405,"endColumn":16},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":403,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":403,"endColumn":74},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":403,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":403,"endColumn":73},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":406,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":408,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":406,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":406,"endColumn":63},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":406,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":406,"endColumn":62},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":409,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":427,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":409,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":409,"endColumn":75},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":409,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":409,"endColumn":74},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":413,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":413,"endColumn":36},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":415,"column":26,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":415,"endColumn":50},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":422,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":422,"endColumn":36},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":424,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":424,"endColumn":45},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":436,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":523,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":436,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":436,"endColumn":98},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":436,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":436,"endColumn":97},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":437,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":522,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":437,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":437,"endColumn":42},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":437,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":437,"endColumn":41},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":438,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":455,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":438,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":438,"endColumn":33},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":438,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":438,"endColumn":32},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":439,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":445,"endColumn":22},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":439,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":442,"endColumn":14},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":441,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":441,"endColumn":94},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":443,"column":27,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":443,"endColumn":57},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":446,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":454,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":446,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":446,"endColumn":59},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":446,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":446,"endColumn":58},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":447,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":449,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":447,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":447,"endColumn":136},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":447,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":447,"endColumn":135},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":448,"column":28,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":448,"endColumn":65},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":450,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":450,"endColumn":20},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":451,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":451,"endColumn":83},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":451,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":451,"endColumn":63},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":451,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":451,"endColumn":62},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":452,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":452,"endColumn":87},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":452,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":452,"endColumn":54},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":452,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":452,"endColumn":53},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":457,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":457,"endColumn":32},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":458,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":508,"endColumn":20},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":458,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":458,"endColumn":65},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":458,"column":43,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":458,"endColumn":64},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":459,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":459,"endColumn":20},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":460,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":465,"endColumn":25},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":460,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":460,"endColumn":81},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":460,"column":24,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":460,"endColumn":80},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":461,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":464,"endColumn":25},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":461,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":461,"endColumn":60},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":461,"column":24,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":461,"endColumn":59},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":462,"column":27,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":462,"endColumn":60},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":476,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":476,"endColumn":20},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":477,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":479,"endColumn":25},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":477,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":477,"endColumn":81},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":477,"column":24,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":477,"endColumn":80},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":490,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":498,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":490,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":490,"endColumn":74},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":490,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":490,"endColumn":73},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":491,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":494,"endColumn":25},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":491,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":491,"endColumn":74},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":491,"column":24,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":491,"endColumn":73},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":492,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":492,"endColumn":101},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":492,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":492,"endColumn":101},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":492,"column":42,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":492,"endColumn":98},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":495,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":497,"endColumn":26},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":495,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":495,"endColumn":85},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":495,"column":39,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":495,"endColumn":84},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":504,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":504,"endColumn":35},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":510,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":520,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":510,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":510,"endColumn":73},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":510,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":510,"endColumn":72},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":511,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":519,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":511,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":511,"endColumn":69},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":511,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":511,"endColumn":68},{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`'` can be escaped with `'`, `‘`, `'`, `’`.","line":512,"column":20,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"'"},"fix":{"range":[17950,17989],"text":"\n Don't have an account?"},"desc":"Replace with `'`."},{"messageId":"replaceWithAlt","data":{"alt":"‘"},"fix":{"range":[17950,17989],"text":"\n Don‘t have an account?"},"desc":"Replace with `‘`."},{"messageId":"replaceWithAlt","data":{"alt":"'"},"fix":{"range":[17950,17989],"text":"\n Don't have an account?"},"desc":"Replace with `'`."},{"messageId":"replaceWithAlt","data":{"alt":"’"},"fix":{"range":[17950,17989],"text":"\n Don’t have an account?"},"desc":"Replace with `’`."}]},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":513,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":518,"endColumn":26},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":513,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":516,"endColumn":18},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":515,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":515,"endColumn":64},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":529,"column":5,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":783,"endColumn":11},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":529,"column":5,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":529,"endColumn":63},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":529,"column":10,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":529,"endColumn":62},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":530,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":782,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":530,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":530,"endColumn":42},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":530,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":530,"endColumn":41},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":532,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":549,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":532,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":532,"endColumn":31},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":532,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":532,"endColumn":30},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":533,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":539,"endColumn":20},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":533,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":536,"endColumn":12},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":535,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":535,"endColumn":92},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":537,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":537,"endColumn":55},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":540,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":548,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":540,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":540,"endColumn":57},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":540,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":540,"endColumn":56},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":541,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":543,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":541,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":541,"endColumn":134},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":541,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":541,"endColumn":133},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":542,"column":26,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":542,"endColumn":63},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":544,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":544,"endColumn":18},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":545,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":545,"endColumn":88},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":545,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":545,"endColumn":61},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":545,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":545,"endColumn":60},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":546,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":546,"endColumn":104},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":546,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":546,"endColumn":52},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":546,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":546,"endColumn":51},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":551,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":551,"endColumn":30},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":552,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":768,"endColumn":18},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":552,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":552,"endColumn":63},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":552,"column":41,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":552,"endColumn":62},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":554,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":554,"endColumn":18},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":555,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":558,"endColumn":20},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":555,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":555,"endColumn":93},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":555,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":555,"endColumn":92},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":556,"column":28,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":556,"endColumn":65},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":560,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":606,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":560,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":560,"endColumn":70},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":560,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":560,"endColumn":69},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":561,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":573,"endColumn":23},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":561,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":561,"endColumn":48},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":561,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":561,"endColumn":47},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":562,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":564,"endColumn":27},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":562,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":562,"endColumn":83},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":562,"column":26,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":562,"endColumn":82},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":575,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":575,"endColumn":22},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":576,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":581,"endColumn":27},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":576,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":576,"endColumn":83},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":576,"column":26,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":576,"endColumn":82},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":577,"column":21,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":580,"endColumn":27},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":577,"column":21,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":577,"endColumn":62},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":577,"column":26,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":577,"endColumn":61},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":578,"column":29,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":578,"endColumn":62},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":592,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":592,"endColumn":22},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":593,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":598,"endColumn":27},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":593,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":593,"endColumn":83},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":593,"column":26,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":593,"endColumn":82},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":594,"column":21,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":597,"endColumn":27},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":594,"column":21,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":594,"endColumn":62},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":594,"column":26,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":594,"endColumn":61},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":595,"column":30,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":595,"endColumn":63},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":610,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":610,"endColumn":18},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":611,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":614,"endColumn":20},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":611,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":611,"endColumn":93},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":611,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":611,"endColumn":92},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":612,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":612,"endColumn":60},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":615,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":617,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":615,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":615,"endColumn":57},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":615,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":615,"endColumn":56},{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`'` can be escaped with `'`, `‘`, `'`, `’`.","line":616,"column":53,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"'"},"fix":{"range":[22120,22216],"text":"\n Select the types of sponsorships you're interested in (optional)\n "},"desc":"Replace with `'`."},{"messageId":"replaceWithAlt","data":{"alt":"‘"},"fix":{"range":[22120,22216],"text":"\n Select the types of sponsorships you‘re interested in (optional)\n "},"desc":"Replace with `‘`."},{"messageId":"replaceWithAlt","data":{"alt":"'"},"fix":{"range":[22120,22216],"text":"\n Select the types of sponsorships you're interested in (optional)\n "},"desc":"Replace with `'`."},{"messageId":"replaceWithAlt","data":{"alt":"’"},"fix":{"range":[22120,22216],"text":"\n Select the types of sponsorships you’re interested in (optional)\n "},"desc":"Replace with `’`."}]},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":619,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":642,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":619,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":619,"endColumn":70},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":619,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":619,"endColumn":69},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":623,"column":21,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":639,"endColumn":30},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":623,"column":21,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":634,"endColumn":22},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":627,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":633,"endColumn":25},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":635,"column":23,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":635,"endColumn":108},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":635,"column":34,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":635,"endColumn":105},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":636,"column":23,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":638,"endColumn":27},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":636,"column":23,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":636,"endColumn":107},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":636,"column":26,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":636,"endColumn":106},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":646,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":646,"endColumn":18},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":647,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":652,"endColumn":23},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":647,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":647,"endColumn":79},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":647,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":647,"endColumn":78},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":648,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":651,"endColumn":23},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":648,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":648,"endColumn":58},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":648,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":648,"endColumn":57},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":649,"column":27,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":649,"endColumn":60},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":653,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":671,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":653,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":653,"endColumn":56},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":653,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":653,"endColumn":55},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":654,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":656,"endColumn":23},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":654,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":654,"endColumn":146},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":654,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":654,"endColumn":145},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":655,"column":30,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":655,"endColumn":63},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":657,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":670,"endColumn":23},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":657,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":657,"endColumn":41},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":657,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":657,"endColumn":40},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":658,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":666,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":658,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":666,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":665,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":665,"endColumn":238},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":667,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":669,"endColumn":23},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":667,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":667,"endColumn":61},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":667,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":667,"endColumn":60},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":675,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":675,"endColumn":18},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":676,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":679,"endColumn":20},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":676,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":676,"endColumn":93},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":676,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":676,"endColumn":92},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":677,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":677,"endColumn":67},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":681,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":709,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":681,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":681,"endColumn":70},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":681,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":681,"endColumn":69},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":682,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":682,"endColumn":22},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":683,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":685,"endColumn":27},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":683,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":683,"endColumn":83},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":683,"column":26,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":683,"endColumn":82},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":696,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":696,"endColumn":22},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":697,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":699,"endColumn":27},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":697,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":697,"endColumn":83},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":697,"column":26,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":697,"endColumn":82},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":713,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":747,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":713,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":713,"endColumn":78},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":713,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":713,"endColumn":77},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":714,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":728,"endColumn":23},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":714,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":714,"endColumn":72},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":714,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":714,"endColumn":71},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":715,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":720,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":715,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":720,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":719,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":719,"endColumn":122},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":721,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":727,"endColumn":24},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":721,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":721,"endColumn":57},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":721,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":721,"endColumn":56},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":723,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":723,"endColumn":108},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":723,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":723,"endColumn":88},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":723,"column":42,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":723,"endColumn":87},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":725,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":725,"endColumn":108},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":725,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":725,"endColumn":90},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":725,"column":44,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":725,"endColumn":89},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":730,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":730,"endColumn":83},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":730,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":730,"endColumn":59},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":730,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":730,"endColumn":58},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":733,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":743,"endColumn":23},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":733,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":733,"endColumn":72},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":733,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":733,"endColumn":71},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":734,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":739,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":734,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":739,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":738,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":738,"endColumn":122},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":740,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":742,"endColumn":24},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":740,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":740,"endColumn":57},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":740,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":740,"endColumn":56},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":745,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":745,"endColumn":81},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":745,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":745,"endColumn":59},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":745,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":745,"endColumn":58},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":750,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":767,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":750,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":750,"endColumn":46},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":750,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":750,"endColumn":45},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":755,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":755,"endColumn":35},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":770,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":780,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":770,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":770,"endColumn":83},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":770,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":770,"endColumn":82},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":771,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":779,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":771,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":771,"endColumn":50},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":771,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":771,"endColumn":49},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in app/ is forbidden. Use components/ or ui/ elements.","line":773,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInApp","endLine":778,"endColumn":24},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":773,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":776,"endColumn":16},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":775,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":775,"endColumn":62}],"suppressedMessages":[],"errorCount":351,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\n\nimport { useState } from 'react';\nimport { motion, useReducedMotion } from 'framer-motion';\nimport { Card } from '@/ui/Card';\nimport { Button } from '@/ui/Button';\nimport { Input } from '@/ui/Input';\nimport { SponsorHero } from '@/components/sponsors/SponsorHero';\nimport { SponsorWorkflowMockup } from '@/components/sponsors/SponsorWorkflowMockup';\nimport { SponsorBenefitCard } from '@/components/sponsors/SponsorBenefitCard';\nimport { siteConfig } from '@/lib/siteConfig';\nimport {\n Building2,\n Mail,\n Globe,\n Upload,\n Eye,\n TrendingUp,\n Users,\n ArrowRight,\n Trophy,\n Car,\n Flag,\n Target,\n BarChart3,\n Shield,\n CheckCircle2,\n Star,\n Megaphone\n} from 'lucide-react';\n\n// Sponsorship type definitions\ninterface SponsorshipType {\n id: string;\n title: string;\n icon: typeof Trophy;\n description: string;\n benefits: string[];\n priceRange: string;\n color: string;\n}\n\nconst SPONSORSHIP_TYPES: SponsorshipType[] = [\n {\n id: 'leagues',\n title: 'League Sponsorship',\n icon: Trophy,\n description: 'Sponsor entire racing leagues and get your brand in front of all participants and viewers.',\n benefits: [\n 'Logo on all participant liveries',\n 'League page banner placement',\n 'Results page branding',\n 'Social media mentions'\n ],\n priceRange: '$200 - $2,000/season',\n color: 'text-primary-blue',\n },\n {\n id: 'teams',\n title: 'Team Sponsorship',\n icon: Users,\n description: 'Partner with competitive racing teams to build long-term brand associations.',\n benefits: [\n 'Team livery logo placement',\n 'Team profile visibility',\n 'Driver association',\n 'Event representation'\n ],\n priceRange: '$100 - $800/season',\n color: 'text-purple-400',\n },\n {\n id: 'drivers',\n title: 'Driver Sponsorship',\n icon: Car,\n description: 'Support individual drivers and grow with rising sim racing talent.',\n benefits: [\n 'Personal livery branding',\n 'Driver profile sponsor badge',\n 'Race results association',\n 'Direct driver partnership'\n ],\n priceRange: '$50 - $300/season',\n color: 'text-performance-green',\n },\n {\n id: 'races',\n title: 'Race Sponsorship',\n icon: Flag,\n description: 'Sponsor individual race events for targeted, high-impact exposure.',\n benefits: [\n 'Race title naming rights',\n 'Event page branding',\n 'Results page placement',\n 'Social media features'\n ],\n priceRange: '$50 - $500/race',\n color: 'text-warning-amber',\n },\n {\n id: 'platform',\n title: 'Platform Advertising',\n icon: Megaphone,\n description: 'Reach the entire GridPilot audience with strategic platform placements.',\n benefits: [\n 'Homepage banner ads',\n 'Sidebar placements',\n 'Newsletter inclusion',\n 'Cross-platform exposure'\n ],\n priceRange: '$100 - $1,000/month',\n color: 'text-racing-red',\n },\n];\n\n// Stats for social proof\nconst PLATFORM_STATS = [\n { value: '50,000+', label: 'Monthly Race Views' },\n { value: '12,000+', label: 'Active Drivers' },\n { value: '500+', label: 'Racing Leagues' },\n { value: '4.8%', label: 'Avg. Engagement Rate' },\n];\n\nexport default function SponsorSignupPage() {\n const shouldReduceMotion = useReducedMotion();\n const [mode, setMode] = useState<'landing' | 'signup' | 'login'>('landing');\n const [formData, setFormData] = useState({\n companyName: '',\n contactEmail: '',\n websiteUrl: '',\n logoFile: null as File | null,\n password: '',\n confirmPassword: '',\n interests: [] as string[],\n acceptTerms: false,\n acceptVat: false,\n });\n const [errors, setErrors] = useState>({});\n const [submitting, setSubmitting] = useState(false);\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n \n const newErrors: Record = {};\n \n if (!formData.companyName.trim()) {\n newErrors.companyName = 'Company name required';\n }\n \n if (!formData.contactEmail.trim()) {\n newErrors.contactEmail = 'Contact email required';\n } else if (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(formData.contactEmail)) {\n newErrors.contactEmail = 'Invalid email format';\n }\n\n if (mode === 'signup') {\n if (!formData.password.trim()) {\n newErrors.password = 'Password required';\n } else if (formData.password.length < 8) {\n newErrors.password = 'Password must be at least 8 characters';\n }\n \n if (formData.password !== formData.confirmPassword) {\n newErrors.confirmPassword = 'Passwords do not match';\n }\n\n if (!formData.acceptTerms) {\n newErrors.acceptTerms = 'You must accept the terms and conditions';\n }\n\n if (!formData.acceptVat) {\n newErrors.acceptVat = 'You must acknowledge the VAT policy';\n }\n }\n \n if (Object.keys(newErrors).length > 0) {\n setErrors(newErrors);\n return;\n }\n \n setSubmitting(true);\n \n try {\n // Note: Business logic for auth should be moved to a mutation\n // This is a temporary implementation for contract compliance\n const response = await fetch('/api/auth/signup', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n email: formData.contactEmail,\n password: formData.password,\n displayName: formData.companyName,\n sponsorData: {\n companyName: formData.companyName,\n websiteUrl: formData.websiteUrl,\n interests: formData.interests,\n },\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n throw new Error(errorData.message || 'Signup failed');\n }\n\n const loginResponse = await fetch('/api/auth/login', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n email: formData.contactEmail,\n password: formData.password,\n }),\n });\n\n if (!loginResponse.ok) {\n throw new Error('Auto-login failed');\n }\n\n // Navigate to dashboard\n window.location.href = '/sponsor/dashboard';\n } catch (err) {\n console.error('Sponsor signup failed:', err);\n alert('Registration failed. ' + (err instanceof Error ? err.message : 'Try again.'));\n } finally {\n setSubmitting(false);\n }\n };\n\n const toggleInterest = (id: string) => {\n setFormData(prev => ({\n ...prev,\n interests: prev.interests.includes(id)\n ? prev.interests.filter(i => i !== id)\n : [...prev.interests, id]\n }));\n };\n\n // Landing page for sponsors\n if (mode === 'landing') {\n return (\n
\n {/* Hero Section */}\n \n
\n setMode('signup')}\n className=\"px-8 py-3\"\n >\n \n Create Sponsor Account\n \n setMode('login')}\n className=\"px-8 py-3\"\n >\n Sign In\n \n \n
\n \n\n {/* Platform Stats */}\n
\n
\n {PLATFORM_STATS.map((stat, index) => (\n \n \n
{stat.value}
\n
{stat.label}
\n
\n \n ))}\n
\n
\n\n {/* Sponsorship Types Section */}\n
\n
\n

\n Sponsorship Opportunities\n

\n

\n Choose how you want to connect with the sim racing community.\n Multiple sponsorship tiers and types to fit every budget and goal.\n

\n
\n\n
\n {SPONSORSHIP_TYPES.map((type, index) => (\n \n \n
\n
\n \n
\n
\n

{type.title}

\n

{type.priceRange}

\n
\n
\n \n

{type.description}

\n \n
    \n {type.benefits.map((benefit, i) => (\n
  • \n \n {benefit}\n
  • \n ))}\n
\n
\n \n ))}\n
\n
\n\n {/* Workflow Mockup Section */}\n
\n
\n
\n

\n How It Works\n

\n

\n From discovery to results tracking — a seamless sponsorship experience.\n

\n
\n \n \n
\n
\n\n {/* Benefits Grid */}\n
\n
\n

\n Why Sponsor on GridPilot?\n

\n

\n Professional tools and genuine community engagement make your sponsorship worthwhile.\n

\n
\n\n
\n \n \n \n \n \n \n
\n
\n\n {/* CTA Section */}\n
\n

\n Ready to Grow Your Brand?\n

\n

\n Join sponsors connecting with sim racing communities worldwide.\n

\n
\n setMode('signup')}\n className=\"px-8 py-3\"\n >\n \n Get Started Now\n \n \n \n Contact Sales\n \n
\n
\n
\n );\n }\n\n // Login form\n if (mode === 'login') {\n return (\n
\n
\n
\n setMode('landing')}\n className=\"text-sm text-gray-400 hover:text-white mb-6 flex items-center gap-2\"\n >\n \n Back to overview\n \n
\n
\n \n
\n
\n

Sponsor Sign In

\n

Access your sponsor dashboard

\n
\n
\n
\n\n \n
\n
\n \n setFormData({ ...formData, contactEmail: e.target.value })}\n placeholder=\"sponsor@company.com\"\n variant={errors.contactEmail ? 'error' : 'default'}\n errorMessage={errors.contactEmail}\n />\n
\n\n
\n \n setFormData({ ...formData, password: e.target.value })}\n placeholder=\"••••••••\"\n variant={errors.password ? 'error' : 'default'}\n errorMessage={errors.password}\n />\n
\n\n
\n \n \n
\n\n \n {submitting ? 'Signing in...' : 'Sign In'}\n \n \n\n
\n

\n Don't have an account?{' '}\n setMode('signup')}\n className=\"text-primary-blue hover:underline\"\n >\n Create one\n \n

\n
\n
\n
\n
\n );\n }\n\n // Signup form\n return (\n
\n
\n {/* Header */}\n
\n setMode('landing')}\n className=\"text-sm text-gray-400 hover:text-white mb-6 flex items-center gap-2\"\n >\n \n Back to overview\n \n
\n
\n \n
\n
\n

Create Sponsor Account

\n

Register your company to sponsor racing entities

\n
\n
\n
\n\n \n
\n {/* Company Information */}\n
\n

\n \n Company Information\n

\n \n
\n
\n \n setFormData({ ...formData, companyName: e.target.value })}\n placeholder=\"Your company name\"\n variant={errors.companyName ? 'error' : 'default'}\n errorMessage={errors.companyName}\n />\n
\n\n
\n \n setFormData({ ...formData, contactEmail: e.target.value })}\n placeholder=\"sponsor@company.com\"\n variant={errors.contactEmail ? 'error' : 'default'}\n errorMessage={errors.contactEmail}\n />\n
\n\n
\n \n setFormData({ ...formData, websiteUrl: e.target.value })}\n placeholder=\"https://company.com\"\n />\n
\n
\n
\n\n {/* Sponsorship Interests */}\n
\n

\n \n Sponsorship Interests\n

\n

\n Select the types of sponsorships you're interested in (optional)\n

\n \n
\n {SPONSORSHIP_TYPES.map((type) => {\n const isSelected = formData.interests.includes(type.id);\n return (\n toggleInterest(type.id)}\n className={`\n p-3 rounded-lg border text-left transition-all\n ${isSelected\n ? 'bg-primary-blue/10 border-primary-blue/50'\n : 'bg-iron-gray/50 border-charcoal-outline hover:border-charcoal-outline/80'\n }\n `}\n >\n \n

\n {type.title.replace(' Sponsorship', '').replace(' Advertising', '')}\n

\n \n );\n })}\n
\n
\n\n {/* Company Logo */}\n
\n \n
\n
\n \n
\n
\n {\n const file = e.target.files?.[0] || null;\n setFormData({ ...formData, logoFile: file });\n }}\n className=\"block w-full text-sm text-gray-400 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-primary-blue/10 file:text-primary-blue hover:file:bg-primary-blue/20\"\n />\n

\n PNG, JPEG, or SVG. Recommended: 500x500px transparent background.\n

\n
\n
\n
\n\n {/* Account Security */}\n
\n

\n \n Account Security\n

\n \n
\n
\n \n setFormData({ ...formData, password: e.target.value })}\n placeholder=\"Min. 8 characters\"\n variant={errors.password ? 'error' : 'default'}\n errorMessage={errors.password}\n />\n
\n\n
\n \n setFormData({ ...formData, confirmPassword: e.target.value })}\n placeholder=\"Confirm password\"\n variant={errors.confirmPassword ? 'error' : 'default'}\n errorMessage={errors.confirmPassword}\n />\n
\n
\n
\n\n {/* Legal Agreements */}\n
\n \n {errors.acceptTerms && (\n

{errors.acceptTerms}

\n )}\n\n \n {errors.acceptVat && (\n

{errors.acceptVat}

\n )}\n
\n\n {/* Actions */}\n
\n \n {submitting ? 'Creating Account...' : 'Create Sponsor Account'}\n \n setMode('landing')}\n disabled={submitting}\n >\n Cancel\n \n
\n
\n\n
\n

\n Already have an account?{' '}\n setMode('login')}\n className=\"text-primary-blue hover:underline\"\n >\n Sign in\n \n

\n
\n
\n
\n
\n );\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/teams/TeamsPageClient.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/teams/[id]/TeamDetailPageClient.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/teams/[id]/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/teams/leaderboard/TeamLeaderboardPageWrapper.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/teams/leaderboard/page.tsx","messages":[{"ruleId":"gridpilot-rules/rsc-no-unsafe-services","severity":2,"message":"Services import must be explicitly marked as server-safe - see apps/website/lib/contracts/view-models/ViewModel.ts","line":2,"column":1,"nodeType":"ImportDeclaration","messageId":"message","endLine":2,"endColumn":64},{"ruleId":"gridpilot-rules/rsc-no-view-models","severity":2,"message":"ViewModels or Presenters import forbidden in server code - see apps/website/lib/contracts/view-models/ViewModel.ts","line":7,"column":1,"nodeType":"ImportDeclaration","messageId":"message","endLine":7,"endColumn":79},{"ruleId":"gridpilot-rules/rsc-no-object-construction","severity":2,"message":"Object construction with new forbidden (use PageQueries) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":15,"column":19,"nodeType":"NewExpression","messageId":"message","endLine":15,"endColumn":36},{"ruleId":"gridpilot-rules/rsc-no-object-construction","severity":2,"message":"Object construction with new forbidden (use PageQueries) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":25,"column":37,"nodeType":"NewExpression","messageId":"message","endLine":25,"endColumn":64},{"ruleId":"gridpilot-rules/rsc-no-object-construction","severity":2,"message":"Object construction with new forbidden (use PageQueries) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":28,"column":13,"nodeType":"NewExpression","messageId":"message","endLine":28,"endColumn":43},{"ruleId":"gridpilot-rules/rsc-no-local-helpers","severity":2,"message":"Local helper functions forbidden (only assert*/invariant* allowed) - see apps/website/lib/contracts/view-models/ViewModel.ts","line":35,"column":9,"nodeType":"VariableDeclarator","messageId":"message","endLine":38,"endColumn":4}],"suppressedMessages":[],"errorCount":6,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { PageWrapper } from '@/components/shared/state/PageWrapper';\nimport { TeamService } from '@/lib/services/teams/TeamService';\nimport { Trophy } from 'lucide-react';\nimport { redirect } from 'next/navigation';\nimport { routes } from '@/lib/routing/RouteConfig';\nimport { TeamLeaderboardPageWrapper } from './TeamLeaderboardPageWrapper';\nimport { TeamSummaryViewModel } from '@/lib/view-models/TeamSummaryViewModel';\n\n// ============================================================================\n// MAIN PAGE COMPONENT\n// ============================================================================\n\nexport default async function TeamLeaderboardPage() {\n // Manual wiring: create dependencies\n const service = new TeamService();\n\n // Fetch data through service\n const result = await service.getAllTeams();\n\n // Handle result\n let data = null;\n let error = null;\n \n if (result.isOk()) {\n data = result.unwrap().map(t => new TeamSummaryViewModel(t));\n } else {\n const domainError = result.getError();\n error = new Error(domainError.message);\n }\n\n const hasData = (data?.length ?? 0) > 0;\n\n // Handle loading state (should be fast since we're using async/await)\n const isLoading = false;\n const retry = () => {\n // In server components, we can't retry without a reload\n redirect(routes.team.detail('leaderboard'));\n };\n\n return (\n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/app/teams/page.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/AppWrapper.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/TeamRankingsFilter.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/achievements/AchievementGrid.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/admin/UserFilters.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/admin/UserStatsSummary.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/auth/AuthWorkflowMockup.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/auth/UserRolesPreview.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/dashboard/DashboardHeroWrapper.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/dashboard/QuickActions.tsx","messages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Pure component in components/. Consider moving to ui/ for better reusability.","line":1,"column":1,"nodeType":null,"messageId":"pureComponentInComponents"}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\n\nimport { routes } from '@/lib/routing/RouteConfig';\nimport { Trophy, Users } from 'lucide-react';\nimport { Box } from '@/ui/Box';\nimport { Heading } from '@/ui/Heading';\nimport { QuickActionItem } from '@/ui/QuickActionItem';\n\nexport function QuickActions() {\n return (\n \n Quick Actions\n \n \n \n \n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/dev/DebugModeToggle.tsx","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":127,"column":19,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":127,"endColumn":22,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3912,3915],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3912,3915],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":176,"column":31,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":176,"endColumn":34,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[5414,5417],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[5414,5417],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":203,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":203,"endColumn":53},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":223,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":223,"endColumn":60},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":242,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":242,"endColumn":84},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":252,"column":65,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":252,"endColumn":93},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":256,"column":65,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":256,"endColumn":93},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":260,"column":65,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":260,"endColumn":93},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":310,"column":58,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":310,"endColumn":86},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":320,"column":55,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":320,"endColumn":83},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":353,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":353,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[12435,12438],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[12435,12438],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":355,"column":37,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":355,"endColumn":40,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[12563,12566],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[12563,12566],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":356,"column":18,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":356,"endColumn":21,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[12585,12588],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[12585,12588],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":359,"column":16,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":359,"endColumn":19,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[12647,12650],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[12647,12650],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":360,"column":16,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":360,"endColumn":19,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[12713,12716],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[12713,12716],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":15,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\n\nimport type { ApiRequestLogger } from '@/lib/infrastructure/ApiRequestLogger';\nimport { getGlobalApiLogger } from '@/lib/infrastructure/ApiRequestLogger';\nimport type { GlobalErrorHandler } from '@/lib/infrastructure/GlobalErrorHandler';\nimport { getGlobalErrorHandler } from '@/lib/infrastructure/GlobalErrorHandler';\nimport { Bug, Shield, X } from 'lucide-react';\nimport { useCallback, useEffect, useState } from 'react';\nimport { Box } from '@/ui/Box';\nimport { Button } from '@/ui/Button';\nimport { Icon } from '@/ui/Icon';\nimport { Stack } from '@/ui/Stack';\nimport { Text } from '@/ui/Text';\n\n// Extend Window interface for debug globals\ndeclare global {\n interface Window {\n __GRIDPILOT_FETCH_LOGGED__?: boolean;\n __GRIDPILOT_GLOBAL_HANDLER__?: GlobalErrorHandler;\n __GRIDPILOT_API_LOGGER__?: ApiRequestLogger;\n __GRIDPILOT_REACT_ERRORS__?: Array<{ error: unknown; componentStack?: string }>;\n }\n}\n\ninterface DebugModeToggleProps {\n /**\n * Whether to show the toggle (auto-detected from environment)\n */\n show?: boolean;\n}\n\n/**\n * Debug Mode Toggle Component\n * Provides a floating interface to control debug features and view real-time metrics\n */\nexport function DebugModeToggle({ show }: DebugModeToggleProps) {\n const [isOpen, setIsOpen] = useState(false);\n const [debugEnabled, setDebugEnabled] = useState(false);\n const [metrics, setMetrics] = useState({\n errors: 0,\n apiRequests: 0,\n apiFailures: 0,\n });\n\n const isDev = process.env.NODE_ENV === 'development';\n const shouldShow = show ?? isDev;\n\n const updateMetrics = useCallback(() => {\n if (!debugEnabled) return;\n\n const globalHandler = getGlobalErrorHandler();\n const apiLogger = getGlobalApiLogger();\n\n const errorStats = globalHandler.getStats();\n const apiStats = apiLogger.getStats();\n\n setMetrics({\n errors: errorStats.total,\n apiRequests: apiStats.total,\n apiFailures: apiStats.failed,\n });\n }, [debugEnabled]);\n\n const initializeDebugFeatures = useCallback(() => {\n const globalHandler = getGlobalErrorHandler();\n const apiLogger = getGlobalApiLogger();\n\n // Initialize global error handler\n globalHandler.initialize();\n\n // Override fetch with logging\n if (!window.__GRIDPILOT_FETCH_LOGGED__) {\n const loggedFetch = apiLogger.createLoggedFetch();\n window.fetch = loggedFetch as typeof fetch;\n window.__GRIDPILOT_FETCH_LOGGED__ = true;\n }\n\n // Expose to window for easy access\n window.__GRIDPILOT_GLOBAL_HANDLER__ = globalHandler;\n window.__GRIDPILOT_API_LOGGER__ = apiLogger;\n\n console.log('%c[DEBUG MODE] Enabled', 'color: #00ff88; font-weight: bold; font-size: 14px;');\n }, []);\n\n useEffect(() => {\n if (!shouldShow) return;\n\n // Load debug state from localStorage\n const saved = localStorage.getItem('gridpilot_debug_enabled');\n if (saved === 'true') {\n setDebugEnabled(true);\n initializeDebugFeatures();\n }\n\n // Update metrics every 2 seconds\n const interval = setInterval(updateMetrics, 2000);\n return () => clearInterval(interval);\n }, [shouldShow, initializeDebugFeatures, updateMetrics]);\n\n useEffect(() => {\n // Save debug state\n if (shouldShow) {\n localStorage.setItem('gridpilot_debug_enabled', debugEnabled.toString());\n }\n }, [debugEnabled, shouldShow]);\n\n const toggleDebug = () => {\n const newEnabled = !debugEnabled;\n setDebugEnabled(newEnabled);\n\n if (newEnabled) {\n initializeDebugFeatures();\n } else {\n // Disable debug features\n const globalHandler = getGlobalErrorHandler();\n globalHandler.destroy();\n\n console.log('%c[DEBUG MODE] Disabled', 'color: #ff4444; font-weight: bold; font-size: 14px;');\n }\n };\n\n const triggerTestError = () => {\n if (!debugEnabled) return;\n\n // Trigger a test API error\n const testError = new Error('This is a test error for debugging');\n (testError as any).type = 'TEST_ERROR';\n \n const globalHandler = getGlobalErrorHandler();\n globalHandler.report(testError, { test: true, timestamp: Date.now() });\n\n console.log('%c[TEST] Error triggered', 'color: #ffaa00; font-weight: bold;', testError);\n };\n\n const triggerTestApiCall = async () => {\n if (!debugEnabled) return;\n\n try {\n // This will fail and be logged\n await fetch('https://httpstat.us/500');\n } catch (error) {\n // Already logged by interceptor\n console.log('%c[TEST] API call completed', 'color: #00aaff; font-weight: bold;');\n }\n };\n\n const clearAllLogs = () => {\n const globalHandler = getGlobalErrorHandler();\n const apiLogger = getGlobalApiLogger();\n\n globalHandler.clearHistory();\n apiLogger.clearHistory();\n\n setMetrics({ errors: 0, apiRequests: 0, apiFailures: 0 });\n\n console.log('%c[DEBUG] All logs cleared', 'color: #00ff88; font-weight: bold;');\n };\n\n const copyDebugInfo = async () => {\n const globalHandler = getGlobalErrorHandler();\n const apiLogger = getGlobalApiLogger();\n\n const debugInfo = {\n timestamp: new Date().toISOString(),\n environment: {\n mode: process.env.NODE_ENV,\n version: process.env.NEXT_PUBLIC_APP_VERSION,\n },\n browser: {\n userAgent: navigator.userAgent,\n language: navigator.language,\n platform: navigator.platform,\n },\n errors: globalHandler.getStats(),\n api: apiLogger.getStats(),\n reactErrors: (window as any).__GRIDPILOT_REACT_ERRORS__ || [],\n };\n\n try {\n await navigator.clipboard.writeText(JSON.stringify(debugInfo, null, 2));\n console.log('%c[DEBUG] Debug info copied to clipboard', 'color: #00ff88; font-weight: bold;');\n } catch (err) {\n console.error('Failed to copy:', err);\n }\n };\n\n if (!shouldShow) {\n return null;\n }\n\n return (\n \n {/* Main Toggle Button */}\n {!isOpen && (\n setIsOpen(true)}\n p={3}\n rounded=\"full\"\n shadow=\"lg\"\n bg={debugEnabled ? 'bg-green-600' : 'bg-iron-gray'}\n color=\"text-white\"\n className=\"transition-all hover:scale-110\"\n title={debugEnabled ? 'Debug Mode Active' : 'Enable Debug Mode'}\n >\n \n \n )}\n\n {/* Debug Panel */}\n {isOpen && (\n \n {/* Header */}\n \n \n \n Debug Control\n \n setIsOpen(false)}\n p={1}\n className=\"hover:bg-charcoal-outline rounded\"\n >\n \n \n \n\n {/* Content */}\n \n \n {/* Debug Toggle */}\n \n \n \n Debug Mode\n \n \n {debugEnabled ? 'ON' : 'OFF'}\n \n \n\n {/* Metrics */}\n {debugEnabled && (\n \n \n Errors\n {metrics.errors}\n \n \n API\n {metrics.apiRequests}\n \n \n Failures\n {metrics.apiFailures}\n \n \n )}\n\n {/* Actions */}\n {debugEnabled && (\n \n Test Actions\n \n \n Test Error\n \n \n Test API\n \n \n\n Utilities\n \n \n Copy Info\n \n \n Clear Logs\n \n \n \n )}\n\n {/* Quick Links */}\n {debugEnabled && (\n \n Quick Access\n \n • window.__GRIDPILOT_GLOBAL_HANDLER__\n • window.__GRIDPILOT_API_LOGGER__\n • window.__GRIDPILOT_REACT_ERRORS__\n \n \n )}\n\n {/* Status */}\n \n \n {debugEnabled ? 'Debug features active' : 'Debug mode disabled'}\n {isDev && ' • Development Environment'}\n \n \n \n \n \n )}\n \n );\n}\n\n/**\n * Hook for programmatic debug control\n */\nexport function useDebugMode() {\n const [debugEnabled, setDebugEnabled] = useState(false);\n\n useEffect(() => {\n const saved = localStorage.getItem('gridpilot_debug_enabled');\n setDebugEnabled(saved === 'true');\n }, []);\n\n const enable = useCallback(() => {\n setDebugEnabled(true);\n localStorage.setItem('gridpilot_debug_enabled', 'true');\n \n // Initialize debug features\n const globalHandler = getGlobalErrorHandler();\n globalHandler.initialize();\n\n const apiLogger = getGlobalApiLogger();\n if (!(window as any).__GRIDPILOT_FETCH_LOGGED__) {\n const loggedFetch = apiLogger.createLoggedFetch();\n window.fetch = loggedFetch as any;\n (window as any).__GRIDPILOT_FETCH_LOGGED__ = true;\n }\n\n (window as any).__GRIDPILOT_GLOBAL_HANDLER__ = globalHandler;\n (window as any).__GRIDPILOT_API_LOGGER__ = apiLogger;\n }, []);\n\n const disable = useCallback(() => {\n setDebugEnabled(false);\n localStorage.setItem('gridpilot_debug_enabled', 'false');\n \n const globalHandler = getGlobalErrorHandler();\n globalHandler.destroy();\n }, []);\n\n const toggle = useCallback(() => {\n if (debugEnabled) {\n disable();\n } else {\n enable();\n }\n }, [debugEnabled, enable, disable]);\n\n return {\n enabled: debugEnabled,\n enable,\n disable,\n toggle,\n };\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/dev/DevToolbar.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/dev/sections/APIStatusSection.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/dev/sections/NotificationSendSection.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/dev/sections/NotificationTypeSection.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/dev/sections/ReplaySection.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/dev/sections/UrgencySection.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/dev/types.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/drivers/CreateDriverForm.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/drivers/DriverCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/drivers/DriverEntryRow.tsx","messages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":55,"column":9,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":55,"endColumn":61},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":89,"column":11,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":89,"endColumn":43}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\n\nimport { CountryFlagDisplay } from '@/lib/display-objects/CountryFlagDisplay';\nimport { Zap } from 'lucide-react';\nimport { Badge } from '@/ui/Badge';\nimport { Box } from '@/ui/Box';\nimport { Icon } from '@/ui/Icon';\nimport { Image } from '@/ui/Image';\nimport { Stack } from '@/ui/Stack';\nimport { Text } from '@/ui/Text';\n\ninterface DriverEntryRowProps {\n index: number;\n name: string;\n avatarUrl: string;\n country: string;\n rating?: number | null;\n isCurrentUser: boolean;\n onClick: () => void;\n}\n\nexport function DriverEntryRow({\n index,\n name,\n avatarUrl,\n country,\n rating,\n isCurrentUser,\n onClick,\n}: DriverEntryRowProps) {\n return (\n \n \n {index + 1}\n \n\n \n \n {name}\n \n \n {CountryFlagDisplay.fromCountryCode(country).toString()}\n \n \n\n \n \n \n {name}\n \n {isCurrentUser && You}\n \n {country}\n \n\n {rating != null && (\n \n \n {rating}\n \n )}\n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/drivers/DriverIdentity.tsx","messages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":38,"column":9,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":38,"endColumn":58},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":61,"column":38,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":61,"endColumn":95}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Link } from '@/ui/Link';\nimport { PlaceholderImage } from '@/ui/PlaceholderImage';\nimport { Box } from '@/ui/Box';\nimport { Text } from '@/ui/Text';\nimport { Badge } from '@/ui/Badge';\nimport { Image } from '@/ui/Image';\n\nexport interface DriverIdentityProps {\n driver: {\n id: string;\n name: string;\n avatarUrl: string | null;\n };\n href?: string;\n contextLabel?: React.ReactNode;\n meta?: React.ReactNode;\n size?: 'sm' | 'md';\n}\n\nexport function DriverIdentity(props: DriverIdentityProps) {\n const { driver, href, contextLabel, meta, size = 'md' } = props;\n\n const avatarSize = size === 'sm' ? 40 : 48;\n const nameSize = size === 'sm' ? 'sm' : 'base';\n\n const avatarUrl = driver.avatarUrl;\n\n const content = (\n \n \n {avatarUrl ? (\n \n ) : (\n \n )}\n \n\n \n \n \n {driver.name}\n \n {contextLabel && (\n \n {contextLabel}\n \n )}\n \n {meta && (\n \n {meta}\n \n )}\n \n \n );\n\n if (href) {\n return (\n \n {content}\n \n );\n }\n\n return {content};\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/drivers/DriverProfile.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/drivers/DriverRankings.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/drivers/DriverSummaryPillWrapper.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/drivers/FeaturedDriverCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/drivers/ProfileHeader.tsx","messages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":53,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":53,"endColumn":53}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\n\nimport type { DriverViewModel } from '@/lib/view-models/DriverViewModel';\nimport { Badge } from '@/ui/Badge';\nimport { Box } from '@/ui/Box';\nimport { Button } from '@/ui/Button';\nimport { CountryFlag } from '@/ui/CountryFlag';\nimport { DriverRatingPill } from '@/ui/DriverRatingPill';\nimport { Heading } from '@/ui/Heading';\nimport { Image } from '@/ui/Image';\nimport { PlaceholderImage } from '@/ui/PlaceholderImage';\nimport { Stack } from '@/ui/Stack';\nimport { Text } from '@/ui/Text';\n\ninterface ProfileHeaderProps {\n driver: DriverViewModel;\n rating?: number | null;\n rank?: number | null;\n isOwnProfile?: boolean;\n onEditClick?: () => void;\n teamName?: string | null;\n teamTag?: string | null;\n}\n\nexport function ProfileHeader({\n driver,\n rating,\n rank,\n isOwnProfile = false,\n onEditClick,\n teamName,\n teamTag,\n}: ProfileHeaderProps) {\n return (\n \n \n \n {driver.avatarUrl ? (\n \n ) : (\n \n )}\n \n \n \n \n {driver.name}\n {driver.country && }\n {teamTag && (\n \n {teamTag}\n \n )}\n \n \n \n iRacing ID: {driver.iracingId}\n {teamName && (\n \n \n \n {teamTag ? `[${teamTag}] ${teamName}` : teamName}\n \n \n )}\n \n\n {(typeof rating === 'number' || typeof rank === 'number') && (\n \n \n \n )}\n \n \n\n {isOwnProfile && (\n \n )}\n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/drivers/ProfileHero.tsx","messages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":58,"column":63,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":58,"endColumn":200},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":61,"column":14,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":61,"endColumn":46},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":62,"column":16,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":62,"endColumn":220},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":63,"column":18,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":63,"endColumn":132},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":69,"column":17,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":69,"endColumn":78},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":76,"column":14,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":76,"endColumn":46},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":88,"column":67,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":88,"endColumn":215},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":90,"column":27,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":90,"endColumn":86},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":95,"column":67,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":95,"endColumn":215},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":97,"column":29,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":97,"endColumn":88},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":98,"column":53,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":98,"endColumn":81},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":107,"column":62,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":107,"endColumn":112},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":109,"column":22,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":109,"endColumn":63},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":113,"column":25,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":113,"endColumn":66},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":123,"column":22,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":123,"endColumn":63},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":135,"column":29,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":135,"endColumn":70},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":144,"column":28,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":144,"endColumn":84},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":146,"column":51,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":146,"endColumn":84},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":157,"column":71,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":157,"endColumn":273},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":158,"column":29,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":158,"endColumn":70},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":160,"column":37,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":160,"endColumn":98}],"suppressedMessages":[],"errorCount":21,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\n\nimport { mediaConfig } from '@/lib/config/mediaConfig';\nimport { CountryFlagDisplay } from '@/lib/display-objects/CountryFlagDisplay';\nimport { Box } from '@/ui/Box';\nimport { Button } from '@/ui/Button';\nimport { Heading } from '@/ui/Heading';\nimport { Image } from '@/ui/Image';\nimport { Link } from '@/ui/Link';\nimport { Stack } from '@/ui/Stack';\nimport { Surface } from '@/ui/Surface';\nimport { Text } from '@/ui/Text';\nimport { Calendar, Clock, ExternalLink, Globe, Star, Trophy, UserPlus } from 'lucide-react';\n\ninterface ProfileHeroProps {\n driver: {\n name: string;\n avatarUrl?: string;\n country: string;\n iracingId: number;\n joinedAt: string | Date;\n };\n stats: {\n rating: number;\n } | null;\n globalRank: number;\n timezone: string;\n socialHandles: {\n platform: string;\n handle: string;\n url: string;\n }[];\n onAddFriend: () => void;\n friendRequestSent: boolean;\n}\n\nfunction getSocialIcon(platform: string) {\n const { Twitter, Youtube, Twitch, MessageCircle } = require('lucide-react');\n switch (platform) {\n case 'twitter': return Twitter;\n case 'youtube': return Youtube;\n case 'twitch': return Twitch;\n case 'discord': return MessageCircle;\n default: return Globe;\n }\n}\n\nexport function ProfileHero({\n driver,\n stats,\n globalRank,\n timezone,\n socialHandles,\n onAddFriend,\n friendRequestSent,\n}: ProfileHeroProps) {\n return (\n \n \n {/* Avatar */}\n \n \n \n \n \n \n \n\n {/* Driver Info */}\n \n \n {driver.name}\n \n {CountryFlagDisplay.fromCountryCode(driver.country).toString()}\n \n \n\n {/* Rating and Rank */}\n \n {stats && (\n <>\n \n \n \n {stats.rating}\n Rating\n \n \n \n \n \n #{globalRank}\n Global\n \n \n \n )}\n \n\n {/* Meta info */}\n \n \n \n iRacing: {driver.iracingId}\n \n \n \n \n Joined{' '}\n {new Date(driver.joinedAt).toLocaleDateString('en-US', {\n month: 'short',\n year: 'numeric',\n })}\n \n \n \n \n {timezone}\n \n \n \n\n {/* Action Buttons */}\n \n }\n >\n {friendRequestSent ? 'Request Sent' : 'Add Friend'}\n \n \n \n\n {/* Social Handles */}\n {socialHandles.length > 0 && (\n \n \n Connect:\n {socialHandles.map((social) => {\n const Icon = getSocialIcon(social.platform);\n return (\n \n \n \n \n {social.handle}\n \n \n \n \n );\n })}\n \n \n )}\n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/drivers/ProfileRaceHistory.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/drivers/ProfileSettings.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/drivers/ProfileStats.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/errors/ApiErrorBoundary.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/errors/DevErrorPanel.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/errors/EnhancedErrorBoundary.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/errors/EnhancedFormError.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/errors/ErrorAnalyticsDashboard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/errors/ErrorDisplay.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/errors/NotificationIntegration.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/feed/ActivityFeed.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/feed/ActivityFeedItem.tsx","messages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":26,"column":7,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":26,"endColumn":55},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":27,"column":7,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":27,"endColumn":32},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":40,"column":12,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":40,"endColumn":44}],"suppressedMessages":[],"errorCount":3,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\n\nimport { ReactNode } from 'react';\nimport { Box } from '@/ui/Box';\nimport { Surface } from '@/ui/Surface';\nimport { Text } from '@/ui/Text';\n\ninterface ActivityFeedItemProps {\n icon: ReactNode;\n content: ReactNode;\n timestamp: string;\n}\n\nexport function ActivityFeedItem({\n icon,\n content,\n timestamp,\n}: ActivityFeedItemProps) {\n return (\n \n \n {icon}\n \n \n \n {content}\n \n \n {timestamp}\n \n \n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/feed/ActivityFeedList.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/feed/FeedItemCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/feed/FeedLayout.tsx","messages":[{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":44,"column":5,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":64,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":44,"column":5,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":44,"endColumn":56},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":44,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":44,"endColumn":55},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":45,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":63,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":45,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":45,"endColumn":67},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":45,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":45,"endColumn":66},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":46,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":58,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":46,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":46,"endColumn":50},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":46,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":46,"endColumn":49},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":47,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":54,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":47,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":47,"endColumn":70},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":47,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":47,"endColumn":69},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":48,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":48,"endColumn":18},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":49,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":49,"endColumn":78},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":49,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":49,"endColumn":65},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":49,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":49,"endColumn":64},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":50,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":52,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":50,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":50,"endColumn":52},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":50,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":50,"endColumn":51},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":55,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":55,"endColumn":44},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":59,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":62,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":59,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":59,"endColumn":38},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":59,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":59,"endColumn":37}],"suppressedMessages":[],"errorCount":23,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Card } from '@/ui/Card';\nimport { FeedList } from '@/components/feed/FeedList';\nimport { UpcomingRacesSidebar } from '@/components/races/UpcomingRacesSidebar';\nimport { LatestResultsSidebar } from '@/components/races/LatestResultsSidebar';\n\ninterface FeedItemData {\n id: string;\n type: string;\n headline: string;\n body?: string;\n timestamp: string;\n formattedTime: string;\n ctaHref?: string;\n ctaLabel?: string;\n}\n\ntype FeedUpcomingRace = {\n id: string;\n track: string;\n car: string;\n scheduledAt: string | Date;\n};\n\ntype FeedLatestResult = {\n raceId: string;\n track: string;\n car: string;\n winnerName: string;\n scheduledAt: string | Date;\n};\n\ninterface FeedLayoutProps {\n feedItems: FeedItemData[];\n upcomingRaces: FeedUpcomingRace[];\n latestResults: FeedLatestResult[];\n}\n\nexport function FeedLayout({\n feedItems,\n upcomingRaces,\n latestResults\n}: FeedLayoutProps) {\n return (\n
\n
\n
\n
\n
\n

Activity

\n

\n See what your friends and leagues are doing right now.\n

\n
\n
\n \n \n \n
\n \n
\n
\n );\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/feed/FeedList.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/feed/RecentActivity.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/landing/AlternatingSection.tsx","messages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":98,"column":107,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":98,"endColumn":357}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\n\nimport { useParallax } from \"@/hooks/useScrollProgress\";\nimport { Box } from '@/ui/Box';\nimport { Container } from '@/ui/Container';\nimport { Heading } from '@/ui/Heading';\nimport { Text } from '@/ui/Text';\nimport { useRef } from 'react';\n\ninterface AlternatingSectionProps {\n heading: string;\n description: string | React.ReactNode;\n mockup: React.ReactNode;\n layout: 'text-left' | 'text-right';\n backgroundImage?: string;\n backgroundVideo?: string;\n}\n\nexport function AlternatingSection({\n heading,\n description,\n mockup,\n layout,\n backgroundImage,\n backgroundVideo\n}: AlternatingSectionProps) {\n const sectionRef = useRef(null);\n \n const bgParallax = useParallax(sectionRef, 0.2);\n\n return (\n \n {backgroundVideo && (\n <>\n \n \n \n {/* Racing red accent for sections with background videos */}\n \n \n )}\n {backgroundImage && !backgroundVideo && (\n <>\n \n {/* Racing red accent for sections with background images */}\n \n \n )}\n \n {/* Carbon fiber texture on sections without images or videos */}\n {!backgroundImage && !backgroundVideo && (\n \n )}\n \n {/* Checkered pattern accent */}\n \n \n \n \n {/* Text Content - Always first on mobile, respects layout on desktop */}\n \n \n {heading}\n \n \n \n {description}\n \n \n \n\n {/* Mockup - Always second on mobile, respects layout on desktop */}\n \n \n {mockup}\n \n \n \n \n \n );\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/landing/BenefitCard.tsx","messages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":47,"column":7,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":47,"endColumn":173},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":48,"column":7,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":48,"endColumn":135},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":62,"column":36,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":62,"endColumn":99},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":67,"column":51,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":67,"endColumn":80},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":87,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":87,"endColumn":149}],"suppressedMessages":[],"errorCount":5,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\n\nimport { motion, useReducedMotion } from 'framer-motion';\nimport { LucideIcon } from 'lucide-react';\nimport { useEffect, useState } from 'react';\nimport { Box } from '@/ui/Box';\nimport { Heading } from '@/ui/Heading';\nimport { Icon } from '@/ui/Icon';\nimport { Surface } from '@/ui/Surface';\nimport { Text } from '@/ui/Text';\n\ninterface BenefitCardProps {\n icon: LucideIcon;\n title: string;\n description: string;\n stats?: {\n value: string;\n label: string;\n };\n variant?: 'default' | 'highlight';\n delay?: number;\n}\n\nexport function BenefitCard({\n icon,\n title,\n description,\n stats,\n variant = 'default',\n delay = 0,\n}: BenefitCardProps) {\n const shouldReduceMotion = useReducedMotion();\n const [isMounted, setIsMounted] = useState(false);\n\n useEffect(() => {\n setIsMounted(true);\n }, []);\n\n const isHighlight = variant === 'highlight';\n\n const cardContent = (\n \n {/* Icon */}\n \n \n \n\n {/* Content */}\n {title}\n {description}\n\n {/* Stats */}\n {stats && (\n \n \n \n {stats.value}\n \n {stats.label}\n \n \n )}\n\n {/* Highlight Glow Effect */}\n {isHighlight && (\n \n )}\n \n );\n\n if (!isMounted || shouldReduceMotion) {\n return {cardContent};\n }\n\n return (\n \n {cardContent}\n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/landing/FAQ.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/landing/FeatureGrid.tsx","messages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":68,"column":46,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":68,"endColumn":296},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":86,"column":50,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":86,"endColumn":298}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\n\nimport { Section } from '@/ui/Section';\nimport { Container } from '@/ui/Container';\nimport { Heading } from '@/ui/Heading';\nimport { MockupStack } from '@/components/mockups/MockupStack';\nimport { Box } from '@/ui/Box';\nimport { Text } from '@/ui/Text';\nimport { Stack } from '@/ui/Stack';\nimport { LeagueHomeMockup } from '@/components/mockups/LeagueHomeMockup';\nimport { StandingsTableMockup } from '@/components/mockups/StandingsTableMockup';\nimport { TeamCompetitionMockup } from '@/components/mockups/TeamCompetitionMockup';\nimport { ProtestWorkflowMockup } from '@/components/mockups/ProtestWorkflowMockup';\nimport { LeagueDiscoveryMockup } from '@/components/mockups/LeagueDiscoveryMockup';\nimport { DriverProfileMockup } from '@/components/mockups/DriverProfileMockup';\n\nconst features = [\n {\n title: \"A Real Home for Your League\",\n description: \"Stop juggling Discord, spreadsheets, and iRacing admin panels. GridPilot brings everything into one dedicated platform built specifically for league racing.\",\n MockupComponent: LeagueHomeMockup\n },\n {\n title: \"Automatic Results & Standings\",\n description: \"Race happens. Results appear. Standings update. No manual data entry, no spreadsheet formulas, no waiting for someone to publish.\",\n MockupComponent: StandingsTableMockup\n },\n {\n title: \"Real Team Racing\",\n description: \"Constructors' championships that actually matter. Driver lineups. Team strategies. Multi-class racing done right.\",\n MockupComponent: TeamCompetitionMockup\n },\n {\n title: \"Clean Protests & Penalties\",\n description: \"Structured incident reporting with video clip references. Steward review workflows. Transparent penalty application. Professional race control.\",\n MockupComponent: ProtestWorkflowMockup\n },\n {\n title: \"Find Your Perfect League\",\n description: \"Search and discover leagues by game, region, and skill level. Browse featured competitions, check driver counts, and join communities that match your racing style.\",\n MockupComponent: LeagueDiscoveryMockup\n },\n {\n title: \"Your Racing Identity\",\n description: \"Cross-league driver profiles with career stats, achievements, and racing history. Build your reputation across multiple championships and showcase your progression.\",\n MockupComponent: DriverProfileMockup\n }\n];\n\nfunction FeatureCard({ feature, index }: { feature: typeof features[0], index: number }) {\n return (\n \n \n \n \n \n \n \n \n \n \n \n \n {feature.title}\n \n \n \n {feature.description}\n \n \n \n );\n}\n\nexport function FeatureGrid() {\n return (\n
\n \n \n \n \n Building for League Racing\n \n \n These features are in development. Join the community to help shape what gets built first\n \n \n \n \n {features.map((feature, index) => (\n \n ))}\n \n \n
\n );\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/landing/FeatureItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/landing/LandingHero.tsx","messages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":56,"column":134,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":56,"endColumn":165},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":56,"column":166,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":56,"endColumn":198},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":57,"column":134,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":57,"endColumn":165},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":57,"column":166,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":57,"endColumn":200},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":58,"column":135,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":58,"endColumn":166},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":58,"column":167,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":58,"endColumn":201},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":72,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":79,"endColumn":15},{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`'` can be escaped with `'`, `‘`, `'`, `’`.","line":81,"column":46,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"'"},"fix":{"range":[3644,3736],"text":"\n League racing is incredible. What's missing is everything around it.\n "},"desc":"Replace with `'`."},{"messageId":"replaceWithAlt","data":{"alt":"‘"},"fix":{"range":[3644,3736],"text":"\n League racing is incredible. What‘s missing is everything around it.\n "},"desc":"Replace with `‘`."},{"messageId":"replaceWithAlt","data":{"alt":"'"},"fix":{"range":[3644,3736],"text":"\n League racing is incredible. What's missing is everything around it.\n "},"desc":"Replace with `'`."},{"messageId":"replaceWithAlt","data":{"alt":"’"},"fix":{"range":[3644,3736],"text":"\n League racing is incredible. What’s missing is everything around it.\n "},"desc":"Replace with `’`."}]},{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`'` can be escaped with `'`, `‘`, `'`, `’`.","line":89,"column":21,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"'"},"fix":{"range":[4000,4079],"text":"\n If you've been in any league, you know the feeling:\n "},"desc":"Replace with `'`."},{"messageId":"replaceWithAlt","data":{"alt":"‘"},"fix":{"range":[4000,4079],"text":"\n If you‘ve been in any league, you know the feeling:\n "},"desc":"Replace with `‘`."},{"messageId":"replaceWithAlt","data":{"alt":"'"},"fix":{"range":[4000,4079],"text":"\n If you've been in any league, you know the feeling:\n "},"desc":"Replace with `'`."},{"messageId":"replaceWithAlt","data":{"alt":"’"},"fix":{"range":[4000,4079],"text":"\n If you’ve been in any league, you know the feeling:\n "},"desc":"Replace with `’`."}]},{"ruleId":"react/no-unescaped-entities","severity":2,"message":"`'` can be escaped with `'`, `‘`, `'`, `’`.","line":120,"column":32,"nodeType":"JSXText","messageId":"unescapedEntityAlts","suggestions":[{"messageId":"replaceWithAlt","data":{"alt":"'"},"fix":{"range":[5520,5583],"text":"\n The ecosystem isn't built for this.\n "},"desc":"Replace with `'`."},{"messageId":"replaceWithAlt","data":{"alt":"‘"},"fix":{"range":[5520,5583],"text":"\n The ecosystem isn‘t built for this.\n "},"desc":"Replace with `‘`."},{"messageId":"replaceWithAlt","data":{"alt":"'"},"fix":{"range":[5520,5583],"text":"\n The ecosystem isn't built for this.\n "},"desc":"Replace with `'`."},{"messageId":"replaceWithAlt","data":{"alt":"’"},"fix":{"range":[5520,5583],"text":"\n The ecosystem isn’t built for this.\n "},"desc":"Replace with `’`."}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":152,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":152,"endColumn":43},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":153,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":156,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":158,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":158,"endColumn":23},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":159,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":159,"endColumn":40},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":160,"column":21,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":160,"endColumn":64}],"suppressedMessages":[],"errorCount":15,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\nimport { useRef } from 'react';\nimport { useParallax } from '@/hooks/useScrollProgress';\nimport { Box } from '@/ui/Box';\nimport { Button } from '@/ui/Button';\nimport { Container } from '@/ui/Container';\nimport { Heading } from '@/ui/Heading';\nimport { Stack } from '@/ui/Stack';\nimport { Text } from '@/ui/Text';\n\nconst discordUrl = process.env.NEXT_PUBLIC_DISCORD_URL || '#';\n\nif (!process.env.NEXT_PUBLIC_DISCORD_URL) {\n console.warn('NEXT_PUBLIC_DISCORD_URL is not set. Discord button will use \"#\" as fallback.');\n}\n\nexport function LandingHero() {\n const sectionRef = useRef(null);\n \n const bgParallax = useParallax(sectionRef, 0.3);\n\n return (\n \n {/* Background image layer with parallax */}\n \n \n {/* Racing red accent gradient */}\n \n \n {/* Racing stripes background */}\n \n \n {/* Checkered pattern overlay */}\n \n \n {/* Speed lines - left side */}\n \n \n \n \n {/* Carbon fiber accent - bottom */}\n \n \n {/* Radial gradient overlay with racing red accent */}\n \n \n \n \n \n League racing is incredible. What's missing is everything around it.\n \n \n \n If you've been in any league, you know the feeling:\n \n {/* Problem badges - mobile optimized */}\n \n {[\n 'Results scattered across Discord',\n 'No long-term identity',\n 'No career progression',\n 'Forgotten after each season'\n ].map((text) => (\n \n ×\n {text}\n \n ))}\n \n \n The ecosystem isn't built for this.\n \n \n GridPilot gives your league racing a real home.\n \n \n \n \n {/* Discord Logo SVG */}\n \n \n \n \n \n \n \n \n \n \n Join us on Discord\n \n \n \n \n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/landing/LandingItems.tsx","messages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Pure component in components/. Consider moving to ui/ for better reusability.","line":1,"column":1,"nodeType":null,"messageId":"pureComponentInComponents"},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'Box' is defined but never used.","line":5,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":5,"endColumn":13}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\n\nimport React from 'react';\nimport { Check } from 'lucide-react';\nimport { Box } from '@/ui/Box';\nimport { Stack } from '@/ui/Stack';\nimport { Text } from '@/ui/Text';\nimport { Surface } from '@/ui/Surface';\nimport { Icon } from '@/ui/Icon';\n\nexport function FeatureItem({ text }: { text: string }) {\n return (\n \n \n \n \n \n \n {text}\n \n \n \n );\n}\n\nexport function ResultItem({ text, color }: { text: string, color: string }) {\n return (\n \n \n \n \n \n \n {text}\n \n \n \n );\n}\n\nexport function StepItem({ step, text }: { step: number, text: string }) {\n return (\n \n \n \n {step}\n \n \n {text}\n \n \n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/layout/HeaderContent.tsx","messages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Pure component in components/. Consider moving to ui/ for better reusability.","line":1,"column":1,"nodeType":null,"messageId":"pureComponentInComponents"},{"ruleId":"gridpilot-rules/no-nextjs-imports-in-ui","severity":2,"message":"Next.js imports are forbidden in components/. Pass navigation/routing from app/ or use callbacks.","line":2,"column":1,"nodeType":"ImportDeclaration","messageId":"noNextImports","endLine":2,"endColumn":32},{"ruleId":"gridpilot-rules/no-nextjs-imports-in-ui","severity":2,"message":"Next.js imports are forbidden in components/. Pass navigation/routing from app/ or use callbacks.","line":2,"column":1,"nodeType":"ImportDeclaration","messageId":"noNextImports","endLine":2,"endColumn":32},{"ruleId":"gridpilot-rules/no-nextjs-imports-in-ui","severity":2,"message":"Next.js imports are forbidden in components/. Pass navigation/routing from app/ or use callbacks.","line":3,"column":1,"nodeType":"ImportDeclaration","messageId":"noNextImports","endLine":3,"endColumn":30},{"ruleId":"gridpilot-rules/no-nextjs-imports-in-ui","severity":2,"message":"Next.js imports are forbidden in components/. Pass navigation/routing from app/ or use callbacks.","line":3,"column":1,"nodeType":"ImportDeclaration","messageId":"noNextImports","endLine":3,"endColumn":30},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":8,"column":5,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":24,"endColumn":11},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":8,"column":5,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":8,"endColumn":56},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":8,"column":10,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":8,"endColumn":55},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":9,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":23,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":9,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":9,"endColumn":52},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":9,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":9,"endColumn":51},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":10,"column":24,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":10,"endColumn":60},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":16,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":16,"endColumn":42},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":20,"column":47,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":20,"endColumn":85}],"suppressedMessages":[],"errorCount":14,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import React from 'react';\nimport Image from 'next/image';\nimport Link from 'next/link';\nimport { Text } from '@/ui/Text';\n\nexport function HeaderContent() {\n return (\n
\n
\n \n \n \n \n Making league racing less chaotic\n \n
\n
\n );\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leaderboards/DriverLeaderboardPreview.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":59,"column":9,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":59,"endColumn":56,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":90,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":90,"endColumn":115,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":108,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":108,"endColumn":78,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":120,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":120,"endColumn":49,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":131,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":131,"endColumn":49,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leaderboards/LeaderboardItem.tsx","messages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":66,"column":7,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":66,"endColumn":64},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":76,"column":9,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":76,"endColumn":91},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":78,"column":33,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":78,"endColumn":56},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":88,"column":65,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":88,"endColumn":124},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":92,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":92,"endColumn":50},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":95,"column":29,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":95,"endColumn":54},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":98,"column":29,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":98,"endColumn":56},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":107,"column":55,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":107,"endColumn":83},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":111,"column":55,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":111,"endColumn":83}],"suppressedMessages":[],"errorCount":9,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import React from 'react';\nimport { Crown, Flag } from 'lucide-react';\nimport { Box } from '@/ui/Box';\nimport { Text } from '@/ui/Text';\nimport { Stack } from '@/ui/Stack';\nimport { Image } from '@/ui/Image';\nimport { mediaConfig } from '@/lib/config/mediaConfig';\n\ninterface LeaderboardItemProps {\n position: number;\n name: string;\n avatarUrl?: string;\n nationality: string;\n rating: number;\n wins: number;\n skillLevelLabel?: string;\n skillLevelColor?: string;\n categoryLabel?: string;\n categoryColor?: string;\n onClick: () => void;\n}\n\nexport function LeaderboardItem({\n position,\n name,\n avatarUrl,\n nationality,\n rating,\n wins,\n skillLevelLabel,\n skillLevelColor,\n categoryLabel,\n categoryColor,\n onClick,\n}: LeaderboardItemProps) {\n const getMedalColor = (pos: number) => {\n switch (pos) {\n case 1: return 'text-yellow-400';\n case 2: return 'text-gray-300';\n case 3: return 'text-amber-600';\n default: return 'text-gray-500';\n }\n };\n\n const getMedalBg = (pos: number) => {\n switch (pos) {\n case 1: return 'bg-yellow-400/10 border-yellow-400/30';\n case 2: return 'bg-gray-300/10 border-gray-300/30';\n case 3: return 'bg-amber-600/10 border-amber-600/30';\n default: return 'bg-iron-gray/50 border-charcoal-outline';\n }\n };\n\n return (\n \n {/* Position */}\n \n {position <= 3 ? : position}\n \n\n {/* Avatar */}\n \n {name}\n \n\n {/* Info */}\n \n \n {name}\n \n \n \n {nationality}\n {categoryLabel && (\n {categoryLabel}\n )}\n {skillLevelLabel && (\n {skillLevelLabel}\n )}\n \n \n\n {/* Stats */}\n \n \n {rating.toLocaleString()}\n Rating\n \n \n {wins}\n Wins\n \n \n
\n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leaderboards/LeaderboardPreview.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leaderboards/LeaderboardsHero.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leaderboards/RankingList.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leaderboards/RankingListItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leaderboards/TeamLeaderboardPreview.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":58,"column":9,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":58,"endColumn":56,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":89,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":89,"endColumn":115,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":123,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":123,"endColumn":80,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":135,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":135,"endColumn":49,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":146,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":146,"endColumn":49,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/ChampionshipStandings.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/ChampionshipStandingsList.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/EmptyState.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/EndRaceModal.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/JoinLeagueButton.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/LeagueActivityFeed.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/LeagueBasicsSection.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/LeagueCardWrapper.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/LeagueChampionshipStats.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/LeagueDecalPlacementEditor.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":192,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":192,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":214,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":214,"endColumn":129,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":216,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":216,"endColumn":81,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":230,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":230,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":237,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":237,"endColumn":35,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":261,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":265,"endColumn":22,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":267,"column":19,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":273,"endColumn":21,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":278,"column":23,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":278,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":281,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":281,"endColumn":59,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":301,"column":19,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":304,"endColumn":21,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":342,"column":27,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":342,"endColumn":55,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":351,"column":27,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":351,"endColumn":55,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":389,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":389,"endColumn":85,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":406,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":406,"endColumn":85,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":423,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":423,"endColumn":39,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":434,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":434,"endColumn":39,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":458,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":458,"endColumn":83,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":481,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":481,"endColumn":31,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/LeagueDropSection.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":97,"column":7,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":97,"endColumn":95,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":195,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":195,"endColumn":57,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":199,"column":15,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":199,"endColumn":42,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":207,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":207,"endColumn":58,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":222,"column":11,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":222,"endColumn":39,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":229,"column":11,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":229,"endColumn":39,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":395,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":395,"endColumn":40,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":399,"column":15,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":399,"endColumn":43,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":409,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":409,"endColumn":40,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":412,"column":15,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":412,"endColumn":43,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":422,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":422,"endColumn":49,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":428,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":428,"endColumn":48,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":439,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":439,"endColumn":49,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":445,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":445,"endColumn":48,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":456,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":456,"endColumn":49,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":462,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":462,"endColumn":48,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":477,"column":19,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":477,"endColumn":47,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":516,"column":17,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":516,"endColumn":101,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":566,"column":17,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":566,"endColumn":114,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":570,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":570,"endColumn":72,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":587,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":587,"endColumn":48,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":591,"column":23,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":591,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":611,"column":27,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":611,"endColumn":55,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/LeagueHeader.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/LeagueMemberRow.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'driverId' is defined but never used.","line":27,"column":3,"nodeType":"Identifier","messageId":"unusedVar","endLine":27,"endColumn":11}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import React, { ReactNode } from 'react';\nimport { TableRow, TableCell } from '@/ui/Table';\nimport { Box } from '@/ui/Box';\nimport { Text } from '@/ui/Text';\nimport { Badge } from '@/ui/Badge';\nimport { DriverIdentity } from '@/components/drivers/DriverIdentity';\nimport { DriverViewModel } from '@/lib/view-models/DriverViewModel';\n\ninterface LeagueMemberRowProps {\n driver?: DriverViewModel;\n driverId: string;\n isCurrentUser: boolean;\n isTopPerformer: boolean;\n role: string;\n roleVariant: 'default' | 'primary' | 'success' | 'warning' | 'danger' | 'info';\n joinedAt: string | Date;\n rating?: number | string;\n rank?: number | string;\n wins?: number;\n actions?: ReactNode;\n href: string;\n meta?: string | null;\n}\n\nexport function LeagueMemberRow({\n driver,\n driverId,\n isCurrentUser,\n isTopPerformer,\n role,\n roleVariant,\n joinedAt,\n rating,\n rank,\n wins,\n actions,\n href,\n meta,\n}: LeagueMemberRowProps) {\n const roleLabel = role.charAt(0).toUpperCase() + role.slice(1);\n\n return (\n \n \n \n {driver ? (\n \n ) : (\n Unknown Driver\n )}\n {isCurrentUser && (\n (You)\n )}\n {isTopPerformer && (\n \n )}\n \n \n \n \n {rating || '—'}\n \n \n \n \n #{rank || '—'}\n \n \n \n \n {wins || 0}\n \n \n \n \n {roleLabel}\n \n \n \n \n {new Date(joinedAt).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n })}\n \n \n {actions && (\n \n {actions}\n \n )}\n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/LeagueMembers.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-no-data-manipulation","severity":2,"message":"Components must not manipulate data - see apps/website/lib/contracts/view-data/ViewData.ts","line":87,"column":25,"nodeType":"CallExpression","messageId":"message","endLine":110,"endColumn":5,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":206,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":206,"endColumn":54,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/LeagueMembershipFeesSection.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/LeagueOwnershipTransfer.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/LeagueReviewSummary.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":78,"column":7,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":78,"endColumn":32,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":86,"column":9,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":86,"endColumn":31,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":193,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":193,"endColumn":33,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":197,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":197,"endColumn":33,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":230,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":230,"endColumn":49,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":342,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":342,"endColumn":49,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/LeagueSchedule.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-no-data-manipulation","severity":2,"message":"Components must not manipulate data - see apps/website/lib/contracts/view-data/ViewData.ts","line":91,"column":22,"nodeType":"CallExpression","messageId":"message","endLine":91,"endColumn":46,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-no-data-manipulation","severity":2,"message":"Components must not manipulate data - see apps/website/lib/contracts/view-data/ViewData.ts","line":94,"column":44,"nodeType":"CallExpression","messageId":"message","endLine":94,"endColumn":68,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":225,"column":35,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":225,"endColumn":64,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":237,"column":35,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":237,"endColumn":64,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/LeagueScoringSection.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":111,"column":7,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":111,"endColumn":74,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":113,"column":7,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":113,"endColumn":57,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":126,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":126,"endColumn":34,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":148,"column":7,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":148,"endColumn":106,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":174,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":174,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":178,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":178,"endColumn":38,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":184,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":184,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":188,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":188,"endColumn":38,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":204,"column":17,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":204,"endColumn":60,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":215,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":215,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":222,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":222,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":251,"column":19,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":251,"endColumn":47,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":286,"column":17,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":286,"endColumn":45,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":299,"column":17,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":299,"endColumn":45,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":312,"column":11,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":312,"endColumn":39,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":432,"column":7,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":432,"endColumn":63,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":604,"column":17,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":604,"endColumn":45,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":608,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":608,"endColumn":42,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":620,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":620,"endColumn":35,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":624,"column":17,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":624,"endColumn":45,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":638,"column":9,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":638,"endColumn":44,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":657,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":663,"endColumn":23,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":688,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":688,"endColumn":42,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":698,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":698,"endColumn":149,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":751,"column":29,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":751,"endColumn":57,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":755,"column":29,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":755,"endColumn":54,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":762,"column":27,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":762,"endColumn":50,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":768,"column":33,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":768,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":781,"column":31,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":781,"endColumn":49,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":785,"column":31,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":785,"endColumn":59,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":804,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":804,"endColumn":30,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":811,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":817,"endColumn":15,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":836,"column":17,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":836,"endColumn":45,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":848,"column":19,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":848,"endColumn":47,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":894,"column":25,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":894,"endColumn":53,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":898,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":898,"endColumn":50,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":910,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":910,"endColumn":43,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":914,"column":25,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":914,"endColumn":53,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":931,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":931,"endColumn":120,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":951,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":951,"endColumn":44,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":961,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":961,"endColumn":44,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":973,"column":23,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":973,"endColumn":50,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":986,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":986,"endColumn":75,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":993,"column":27,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":993,"endColumn":55,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":1006,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":1006,"endColumn":75,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":1026,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":1026,"endColumn":49,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":1038,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":1038,"endColumn":61,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":1051,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":1051,"endColumn":61,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":1206,"column":17,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":1206,"endColumn":45,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":1210,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":1210,"endColumn":42,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":1222,"column":17,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":1222,"endColumn":45,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":1226,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":1226,"endColumn":42,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":1244,"column":25,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":1244,"endColumn":53,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":1253,"column":25,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":1253,"endColumn":52,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":1281,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":1289,"endColumn":19,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":1310,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":1310,"endColumn":39,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":1316,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":1316,"endColumn":38,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":1320,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":1320,"endColumn":109,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":1328,"column":23,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":1328,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":1385,"column":27,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":1385,"endColumn":55,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":1389,"column":27,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":1389,"endColumn":52,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":1396,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":1396,"endColumn":48,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":1402,"column":31,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":1402,"endColumn":49,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":1413,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":1413,"endColumn":79,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":1418,"column":29,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":1418,"endColumn":47,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":1422,"column":29,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":1422,"endColumn":57,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/LeagueSponsorshipsSection.tsx","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":55,"column":41,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":55,"endColumn":44,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1931,1934],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1931,1934],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":224,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":224,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\n\nimport { Award, DollarSign, Star, X } from 'lucide-react';\nimport { useState } from 'react';\nimport { PendingSponsorshipRequests } from '../sponsors/PendingSponsorshipRequests';\nimport { Button } from '@/ui/Button';\nimport { Input } from '@/ui/Input';\nimport { Box } from '@/ui/Box';\nimport { Text } from '@/ui/Text';\nimport { Heading } from '@/ui/Heading';\nimport { Stack } from '@/ui/Stack';\nimport { Icon } from '@/ui/Icon';\nimport { Badge } from '@/ui/Badge';\nimport { StatBox } from '@/ui/StatBox';\n\nimport { useEffectiveDriverId } from \"@/hooks/useEffectiveDriverId\";\nimport { useLeagueSeasons } from \"@/hooks/league/useLeagueSeasons\";\nimport { useSponsorshipRequests } from \"@/hooks/league/useSponsorshipRequests\";\nimport { useInject } from '@/lib/di/hooks/useInject';\nimport { SPONSOR_SERVICE_TOKEN } from '@/lib/di/tokens';\n\ninterface SponsorshipSlot {\n tier: 'main' | 'secondary';\n sponsorName?: string;\n logoUrl?: string;\n price: number;\n isOccupied: boolean;\n}\n\ninterface LeagueSponsorshipsSectionProps {\n leagueId: string;\n seasonId?: string;\n readOnly?: boolean;\n}\n\nexport function LeagueSponsorshipsSection({\n leagueId,\n seasonId: propSeasonId,\n readOnly = false\n}: LeagueSponsorshipsSectionProps) {\n const currentDriverId = useEffectiveDriverId();\n const sponsorshipService = useInject(SPONSOR_SERVICE_TOKEN);\n \n const [slots, setSlots] = useState([\n { tier: 'main', price: 500, isOccupied: false },\n { tier: 'secondary', price: 200, isOccupied: false },\n { tier: 'secondary', price: 200, isOccupied: false },\n ]);\n const [editingIndex, setEditingIndex] = useState(null);\n const [tempPrice, setTempPrice] = useState('');\n\n // Load season ID if not provided\n const { data: seasonsResult } = useLeagueSeasons(leagueId);\n const seasons = seasonsResult?.isOk() ? seasonsResult.unwrap() : [];\n const activeSeason = seasons.find((s: any) => s.status === 'active') ?? seasons[0];\n const seasonId = propSeasonId || activeSeason?.seasonId;\n\n // Load pending sponsorship requests\n const { data: pendingRequestsData, isLoading: requestsLoading, refetch: refetchRequests } = useSponsorshipRequests('season', seasonId || '');\n const pendingRequests = pendingRequestsData?.requests || [];\n\n const handleAcceptRequest = async (requestId: string) => {\n if (!currentDriverId) return;\n \n try {\n await sponsorshipService.acceptSponsorshipRequest(requestId, currentDriverId);\n await refetchRequests();\n } catch (err) {\n console.error('Failed to accept request:', err);\n alert(err instanceof Error ? err.message : 'Failed to accept request');\n }\n };\n\n const handleRejectRequest = async (requestId: string, reason?: string) => {\n if (!currentDriverId) return;\n \n try {\n await sponsorshipService.rejectSponsorshipRequest(requestId, currentDriverId, reason);\n await refetchRequests();\n } catch (err) {\n console.error('Failed to reject request:', err);\n alert(err instanceof Error ? err.message : 'Failed to reject request');\n }\n };\n\n const handleEditPrice = (index: number) => {\n const slot = slots[index];\n if (!slot) return;\n setEditingIndex(index);\n setTempPrice(slot.price.toString());\n };\n\n const handleSavePrice = (index: number) => {\n const price = parseFloat(tempPrice);\n if (!isNaN(price) && price > 0) {\n const updated = [...slots];\n const slot = updated[index];\n if (slot) {\n slot.price = price;\n setSlots(updated);\n }\n }\n setEditingIndex(null);\n setTempPrice('');\n };\n\n const handleCancelEdit = () => {\n setEditingIndex(null);\n setTempPrice('');\n };\n\n const totalRevenue = slots.reduce((sum, slot) => \n slot.isOccupied ? sum + slot.price : sum, 0\n );\n const platformFee = totalRevenue * 0.10;\n const netRevenue = totalRevenue - platformFee;\n\n const availableSlots = slots.filter(s => !s.isOccupied).length;\n\n return (\n \n {/* Header */}\n \n \n Sponsorships\n \n Define pricing for sponsor slots in this league. Sponsors pay per season.\n \n \n These sponsors are attached to seasons in this league, so you can change partners from season to season.\n \n \n {!readOnly && (\n \n \n \n {availableSlots} slot{availableSlots !== 1 ? 's' : ''} available\n \n \n )}\n \n\n {/* Revenue Summary */}\n {totalRevenue > 0 && (\n \n \n \n \n \n )}\n\n {/* Sponsorship Slots */}\n \n {slots.map((slot, index) => {\n const isEditing = editingIndex === index;\n const IconComp = slot.tier === 'main' ? Star : Award;\n \n return (\n \n \n \n \n \n \n \n \n \n \n {slot.tier === 'main' ? 'Main Sponsor' : 'Secondary Sponsor'}\n \n {slot.isOccupied && (\n \n Occupied\n \n )}\n \n \n {slot.tier === 'main' \n ? 'Big livery slot • League page logo • Name in league title'\n : 'Small livery slot • League page logo'}\n \n \n \n\n \n {isEditing ? (\n \n ) => setTempPrice(e.target.value)}\n placeholder=\"Price\"\n // eslint-disable-next-line gridpilot-rules/component-classification\n className=\"w-32\"\n min=\"0\"\n step=\"0.01\"\n />\n handleSavePrice(index)}\n size=\"sm\"\n >\n Save\n \n \n \n \n \n ) : (\n <>\n \n \n ${slot.price.toFixed(2)}\n \n per season\n \n {!readOnly && !slot.isOccupied && (\n handleEditPrice(index)}\n size=\"sm\"\n >\n Edit Price\n \n )}\n \n )}\n \n \n
\n );\n })}\n \n\n {/* Pending Sponsorship Requests */}\n {!readOnly && (pendingRequests.length > 0 || requestsLoading) && (\n \n \n \n )}\n\n {/* Alpha Notice */}\n \n \n Alpha Note: Sponsorship management is demonstration-only.\n In production, sponsors can browse leagues, select slots, and complete payment integration.\n \n \n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/LeagueStewardingSection.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/LeagueStructureSection.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":99,"column":7,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":99,"endColumn":95,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'maxTeams' is assigned a value but never used.","line":195,"column":15,"nodeType":"Identifier","messageId":"unusedVar","endLine":195,"endColumn":23,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'driversPerTeam' is assigned a value but never used.","line":195,"column":25,"nodeType":"Identifier","messageId":"unusedVar","endLine":195,"endColumn":39,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":424,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":424,"endColumn":42,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":576,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":576,"endColumn":42,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":647,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":647,"endColumn":35,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/LeagueSummaryCardWrapper.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/LeagueTabs.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":32,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":32,"endColumn":46,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/LeagueTimingsSection.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":156,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":156,"endColumn":107,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":163,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":163,"endColumn":48,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":189,"column":19,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":189,"endColumn":47,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":205,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":205,"endColumn":121,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":220,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":220,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":230,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":230,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":240,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":240,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":253,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":253,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":260,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":260,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":267,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":267,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-no-data-manipulation","severity":2,"message":"Components must not manipulate data - see apps/website/lib/contracts/view-data/ViewData.ts","line":360,"column":11,"nodeType":"CallExpression","messageId":"message","endLine":360,"endColumn":54,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-no-data-manipulation","severity":2,"message":"Components must not manipulate data - see apps/website/lib/contracts/view-data/ViewData.ts","line":374,"column":11,"nodeType":"CallExpression","messageId":"message","endLine":374,"endColumn":29,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-no-data-manipulation","severity":2,"message":"Components must not manipulate data - see apps/website/lib/contracts/view-data/ViewData.ts","line":379,"column":9,"nodeType":"CallExpression","messageId":"message","endLine":379,"endColumn":39,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-no-data-manipulation","severity":2,"message":"Components must not manipulate data - see apps/website/lib/contracts/view-data/ViewData.ts","line":417,"column":11,"nodeType":"CallExpression","messageId":"message","endLine":417,"endColumn":44,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-no-data-manipulation","severity":2,"message":"Components must not manipulate data - see apps/website/lib/contracts/view-data/ViewData.ts","line":485,"column":11,"nodeType":"CallExpression","messageId":"message","endLine":491,"endColumn":13,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-no-data-manipulation","severity":2,"message":"Components must not manipulate data - see apps/website/lib/contracts/view-data/ViewData.ts","line":495,"column":9,"nodeType":"CallExpression","messageId":"message","endLine":500,"endColumn":11,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-no-data-manipulation","severity":2,"message":"Components must not manipulate data - see apps/website/lib/contracts/view-data/ViewData.ts","line":533,"column":9,"nodeType":"CallExpression","messageId":"message","endLine":540,"endColumn":11,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-no-data-manipulation","severity":2,"message":"Components must not manipulate data - see apps/website/lib/contracts/view-data/ViewData.ts","line":544,"column":7,"nodeType":"CallExpression","messageId":"message","endLine":549,"endColumn":9,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":575,"column":11,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":575,"endColumn":39,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":602,"column":19,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":602,"endColumn":47,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":611,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":611,"endColumn":48,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":641,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":645,"endColumn":23,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":666,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":666,"endColumn":40,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":679,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":679,"endColumn":40,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":696,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":696,"endColumn":40,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":710,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":710,"endColumn":54,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":714,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":714,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":724,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":724,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":734,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":734,"endColumn":52,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":738,"column":15,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":738,"endColumn":43,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":749,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":749,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":824,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":824,"endColumn":106,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":828,"column":17,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":828,"endColumn":44,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":838,"column":15,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":838,"endColumn":43,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":851,"column":15,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":851,"endColumn":43,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":861,"column":15,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":861,"endColumn":43,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":876,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":876,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":887,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":887,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":898,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":898,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":909,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":909,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":969,"column":7,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":969,"endColumn":101,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":991,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":991,"endColumn":44,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":1009,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":1009,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":1014,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":1014,"endColumn":85,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":1022,"column":11,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":1022,"endColumn":39,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":1117,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":1117,"endColumn":49,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":1125,"column":9,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":1127,"endColumn":12,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":1285,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":1285,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":1336,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":1336,"endColumn":66,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":1352,"column":19,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":1352,"endColumn":47,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":1380,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":1380,"endColumn":66,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":1402,"column":19,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":1402,"endColumn":47,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":1417,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":1417,"endColumn":46,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":1423,"column":19,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":1423,"endColumn":47,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":1438,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":1438,"endColumn":46,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":1448,"column":19,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":1448,"endColumn":47,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":1459,"column":17,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":1459,"endColumn":45,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":1470,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":1470,"endColumn":44,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":1478,"column":17,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":1478,"endColumn":45,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":1516,"column":29,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":1516,"endColumn":56,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":1544,"column":19,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":1544,"endColumn":47,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":1587,"column":17,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":1587,"endColumn":45,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":1604,"column":11,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":1604,"endColumn":54,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":1608,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":1608,"endColumn":77,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":1639,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":1639,"endColumn":66,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":1644,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":1644,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":1656,"column":15,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":1656,"endColumn":45,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":1719,"column":15,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":1719,"endColumn":43,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/LeagueVisibilitySection.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":101,"column":7,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":101,"endColumn":95,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":340,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":340,"endColumn":42,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":362,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":362,"endColumn":42,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":519,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":519,"endColumn":42,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":543,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":543,"endColumn":42,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/MembershipStatus.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/PenaltyHistoryList.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/PendingProtestsList.tsx","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'leagueId' is defined but never used.","line":25,"column":3,"nodeType":"Identifier","messageId":"unusedVar","endLine":25,"endColumn":11},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":35,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":35,"endColumn":63}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\n\nimport { DriverViewModel } from \"@/lib/view-models/DriverViewModel\";\nimport { ProtestViewModel } from \"@/lib/view-models/ProtestViewModel\";\nimport { RaceViewModel } from \"@/lib/view-models/RaceViewModel\";\nimport { Box } from \"@/ui/Box\";\nimport { Card } from \"@/ui/Card\";\nimport { ProtestListItem } from \"./ProtestListItem\";\nimport { Stack } from \"@/ui/Stack\";\nimport { Text } from \"@/ui/Text\";\nimport { Flag } from \"lucide-react\";\n\ninterface PendingProtestsListProps {\n protests: ProtestViewModel[];\n races: Record;\n drivers: Record;\n leagueId: string;\n onReviewProtest: (protest: ProtestViewModel) => void;\n onProtestReviewed: () => void;\n}\n\nexport function PendingProtestsList({\n protests,\n drivers,\n leagueId,\n onReviewProtest,\n}: PendingProtestsListProps) {\n\n if (protests.length === 0) {\n return (\n \n \n \n \n \n \n \n All Clear! 🏁\n No pending protests to review\n \n \n \n \n );\n }\n\n return (\n \n {protests.map((protest) => {\n const filedAt = protest.filedAt || protest.submittedAt;\n const daysSinceFiled = Math.floor((Date.now() - new Date(filedAt).getTime()) / (1000 * 60 * 60 * 24));\n const isUrgent = daysSinceFiled > 2;\n \n const protester = drivers[protest.protestingDriverId];\n const accused = drivers[protest.accusedDriverId];\n \n return (\n onReviewProtest(protest)}\n />\n );\n })}\n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/ProtestCardWrapper.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/ProtestListItem.tsx","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":46,"column":41,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":46,"endColumn":44,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[989,992],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[989,992],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":61,"column":7,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":61,"endColumn":64}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\n\nimport { AlertCircle, AlertTriangle, Video } from 'lucide-react';\nimport { Badge } from '@/ui/Badge';\nimport { Box } from '@/ui/Box';\nimport { Button } from '@/ui/Button';\nimport { Card } from '@/ui/Card';\nimport { Icon } from '@/ui/Icon';\nimport { Link } from '@/ui/Link';\nimport { Stack } from '@/ui/Stack';\nimport { Text } from '@/ui/Text';\n\ninterface ProtestListItemProps {\n protesterName: string;\n protesterHref: string;\n accusedName: string;\n accusedHref: string;\n status: string;\n isUrgent: boolean;\n daysOld: number;\n lap: number;\n filedAtLabel: string;\n description: string;\n proofVideoUrl?: string;\n decisionNotes?: string;\n isAdmin: boolean;\n onReview?: () => void;\n}\n\nexport function ProtestListItem({\n protesterName,\n protesterHref,\n accusedName,\n accusedHref,\n status,\n isUrgent,\n daysOld,\n lap,\n filedAtLabel,\n description,\n proofVideoUrl,\n decisionNotes,\n isAdmin,\n onReview,\n}: ProtestListItemProps) {\n const getStatusVariant = (s: string): any => {\n switch (s) {\n case 'pending':\n case 'under_review': return 'warning';\n case 'upheld': return 'danger';\n case 'dismissed': return 'default';\n case 'withdrawn': return 'primary';\n default: return 'warning';\n }\n };\n\n return (\n \n \n \n \n \n \n {protesterName}\n \n vs\n \n {accusedName}\n \n \n {status.replace('_', ' ')}\n \n {isUrgent && (\n \n {daysOld}d old\n \n )}\n \n \n Lap {lap}\n \n Filed {filedAtLabel}\n {proofVideoUrl && (\n <>\n \n \n \n Video Evidence\n \n \n )}\n \n {description}\n \n {decisionNotes && (\n \n Steward Decision\n {decisionNotes}\n \n )}\n \n {isAdmin && status === 'pending' && onReview && (\n \n Review\n \n )}\n \n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/QuickPenaltyModal.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":83,"column":7,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":83,"endColumn":35,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/ReadonlyLeagueInfo.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/ReviewProtestModal.tsx","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":65,"column":27,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":65,"endColumn":30,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2063,2066],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2063,2066],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":78,"column":36,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":78,"endColumn":39,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2587,2590],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2587,2590],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}],"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":411,"column":29,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":411,"endColumn":69,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/ScheduleRaceCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/SponsorshipRequestCard.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":50,"column":7,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":53,"endColumn":9,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":57,"column":14,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":57,"endColumn":46,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/SponsorshipSlotCard.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":37,"column":7,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":40,"endColumn":9,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":61,"column":23,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":61,"endColumn":65,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/StandingsTable.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/StewardingStats.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/leagues/TransactionRow.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/mockups/CareerProgressionMockup.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":50,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":50,"endColumn":49,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":101,"column":19,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":101,"endColumn":47,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":109,"column":19,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":109,"endColumn":47,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":200,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":200,"endColumn":39,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/mockups/CompanionAutomationMockup.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":138,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":138,"endColumn":48,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":243,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":243,"endColumn":43,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":304,"column":15,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":304,"endColumn":43,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/mockups/DriverProfileMockup.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":55,"column":17,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":55,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":95,"column":19,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":95,"endColumn":50,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":141,"column":17,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":141,"endColumn":45,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/mockups/LeagueDiscoveryMockup.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":115,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":115,"endColumn":47,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":119,"column":23,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":119,"endColumn":380,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":210,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":210,"endColumn":43,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":223,"column":27,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":223,"endColumn":55,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":232,"column":27,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":232,"endColumn":55,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":241,"column":27,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":241,"endColumn":55,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":257,"column":23,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":257,"endColumn":359,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":261,"column":23,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":261,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":270,"column":23,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":270,"endColumn":140,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":274,"column":23,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":274,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":293,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":293,"endColumn":47,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":301,"column":23,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":301,"endColumn":380,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":306,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":306,"endColumn":49,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":329,"column":23,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":329,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":348,"column":23,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":348,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/mockups/LeagueHomeMockup.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":44,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":44,"endColumn":40,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":100,"column":19,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":100,"endColumn":46,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":109,"column":15,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":109,"endColumn":42,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":123,"column":15,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":123,"endColumn":42,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":177,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":177,"endColumn":48,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":190,"column":15,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":190,"endColumn":42,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/mockups/MockupStack.tsx","messages":[{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":31,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":68,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":31,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":31,"endColumn":160},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":31,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":31,"endColumn":125},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":31,"column":126,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":31,"endColumn":159},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":32,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":44,"endColumn":11},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":32,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":44,"endColumn":11},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":33,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":33,"endColumn":89},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":34,"column":11,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":43,"endColumn":13},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":46,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":58,"endColumn":11},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":46,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":58,"endColumn":11},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":47,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":47,"endColumn":89},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":48,"column":11,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":57,"endColumn":13},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":60,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":67,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":60,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":65,"endColumn":10},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":61,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":61,"endColumn":77},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":62,"column":11,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":64,"endColumn":13},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":74,"column":5,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":144,"endColumn":11},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":74,"column":5,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":74,"endColumn":158},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":74,"column":10,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":74,"endColumn":123},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":74,"column":124,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":74,"endColumn":157},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":75,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":89,"endColumn":9},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":76,"column":9,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":76,"endColumn":87},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":77,"column":9,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":85,"endColumn":11},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":91,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":105,"endColumn":9},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":92,"column":9,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":92,"endColumn":87},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":93,"column":9,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":101,"endColumn":11},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":107,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":130,"endColumn":8},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":108,"column":9,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":108,"endColumn":75},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":109,"column":9,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":111,"endColumn":11},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":131,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":141,"endColumn":11},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":132,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":132,"endColumn":70}],"suppressedMessages":[],"errorCount":31,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\n\nimport { motion, useReducedMotion } from 'framer-motion';\nimport { ReactNode, useEffect, useState } from 'react';\n\ninterface MockupStackProps {\n children: ReactNode;\n index?: number;\n}\n\nexport function MockupStack({ children, index = 0 }: MockupStackProps) {\n const shouldReduceMotion = useReducedMotion();\n const [isMounted, setIsMounted] = useState(false);\n const [isMobile, setIsMobile] = useState(true); // Default to mobile (no animations)\n\n useEffect(() => {\n setIsMounted(true);\n const checkMobile = () => setIsMobile(window.innerWidth < 768);\n checkMobile();\n window.addEventListener('resize', checkMobile);\n return () => window.removeEventListener('resize', checkMobile);\n }, []);\n\n const seed = index * 1337;\n const rotation1 = ((seed * 17) % 80 - 40) / 20;\n const rotation2 = ((seed * 23) % 80 - 40) / 20;\n\n // On mobile or before mount, render without animations\n if (!isMounted || isMobile) {\n return (\n
\n \n \n \n\n \n {children}\n
\n
\n );\n }\n\n // Desktop: render with animations\n return (\n
\n \n \n \n\n \n \n {children}\n \n
\n );\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/mockups/ProtestWorkflowMockup.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":68,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":68,"endColumn":58,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":72,"column":21,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":72,"endColumn":104,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":80,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":80,"endColumn":130,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":95,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":95,"endColumn":77,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":145,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":145,"endColumn":60,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":159,"column":23,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":159,"endColumn":106,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":180,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":180,"endColumn":48,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":208,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":208,"endColumn":48,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":214,"column":23,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":214,"endColumn":134,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/mockups/RaceHistoryMockup.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":67,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":67,"endColumn":49,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":124,"column":23,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":124,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":132,"column":23,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":132,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":140,"column":23,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":140,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":148,"column":23,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":148,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":156,"column":23,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":156,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":184,"column":17,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":184,"endColumn":45,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":206,"column":23,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":206,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":217,"column":23,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":217,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":226,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":226,"endColumn":48,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":240,"column":23,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":240,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":252,"column":23,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":252,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":261,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":261,"endColumn":48,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":275,"column":23,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":275,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":287,"column":23,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":287,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":296,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":296,"endColumn":48,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":310,"column":23,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":310,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":322,"column":23,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":322,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":331,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":331,"endColumn":48,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/mockups/SimPlatformMockup.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":28,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":28,"endColumn":42,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":60,"column":15,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":60,"endColumn":43,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":73,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":73,"endColumn":44,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":84,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":84,"endColumn":49,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":94,"column":17,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":94,"endColumn":45,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":113,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":113,"endColumn":49,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":123,"column":17,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":123,"endColumn":45,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":142,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":142,"endColumn":49,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":152,"column":17,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":152,"endColumn":45,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":171,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":171,"endColumn":49,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":181,"column":17,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":181,"endColumn":45,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":194,"column":15,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":194,"endColumn":43,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/mockups/StandingsTableMockup.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":25,"column":15,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":25,"endColumn":43,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":34,"column":15,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":34,"endColumn":43,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":66,"column":17,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":66,"endColumn":45,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":77,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":77,"endColumn":49,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":91,"column":19,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":91,"endColumn":62,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":125,"column":11,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":125,"endColumn":39,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":136,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":136,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":144,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":144,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":153,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":153,"endColumn":41,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":157,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":157,"endColumn":40,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":164,"column":15,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":164,"endColumn":43,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":172,"column":15,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":172,"endColumn":42,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":217,"column":15,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":217,"endColumn":43,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":236,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":236,"endColumn":42,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":289,"column":11,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":289,"endColumn":39,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/mockups/TeamCompetitionMockup.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":49,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":49,"endColumn":65,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":60,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":65,"endColumn":23,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":71,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":71,"endColumn":140,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":80,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":80,"endColumn":49,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":89,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":89,"endColumn":94,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":116,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":116,"endColumn":65,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":128,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":132,"endColumn":23,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":145,"column":25,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":145,"endColumn":100,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":211,"column":15,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":211,"endColumn":43,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":252,"column":19,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":252,"endColumn":63,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":265,"column":19,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":269,"endColumn":21,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":275,"column":19,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":275,"endColumn":138,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":284,"column":19,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":284,"endColumn":47,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":295,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":297,"endColumn":23,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":307,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":307,"endColumn":109,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":320,"column":15,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":320,"endColumn":43,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":361,"column":19,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":361,"endColumn":63,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":373,"column":19,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":377,"endColumn":21,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":391,"column":23,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":391,"endColumn":67,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":402,"column":23,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":402,"endColumn":51,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":417,"column":21,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":419,"endColumn":23,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/mockups/WorkflowMockup.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/notifications/ModalNotification.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":182,"column":7,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":182,"endColumn":54,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":192,"column":9,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":192,"endColumn":57,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":204,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":204,"endColumn":39,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":214,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":214,"endColumn":119,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":234,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":234,"endColumn":46,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":264,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":264,"endColumn":102,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":327,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":327,"endColumn":185,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/notifications/NotificationCenter.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":125,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":125,"endColumn":61,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":193,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":193,"endColumn":64,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":215,"column":27,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":215,"endColumn":49,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":234,"column":31,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":234,"endColumn":59,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":243,"column":35,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":243,"endColumn":63,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":264,"column":17,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":264,"endColumn":45,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/notifications/NotificationProvider.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/notifications/ToastNotification.tsx","messages":[],"suppressedMessages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":118,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":118,"endColumn":47,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":120,"column":13,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":120,"endColumn":67,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/notifications/notificationTypes.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/onboarding/AvatarStep.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/onboarding/OnboardingWizard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/onboarding/PersonalInfoStep.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/profile/UserPill.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/races/FileProtestModal.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/races/ImportResultsForm.tsx","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":34,"column":46,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":34,"endColumn":49,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1172,1175],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1172,1175],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}],"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/races/LatestResultsSidebar.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/races/LiveRacesBanner.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/races/NextRaceCardWrapper.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/races/RaceCardWrapper.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/races/RaceEntryList.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/races/RaceFilterBar.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/races/RaceList.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/races/RaceListItem.tsx","messages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":70,"column":11,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":70,"endColumn":105},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":78,"column":57,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":78,"endColumn":95}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\n\nimport { ArrowRight, Car, ChevronRight, LucideIcon, Trophy, Zap } from 'lucide-react';\nimport { Badge } from '@/ui/Badge';\nimport { Box } from '@/ui/Box';\nimport { Heading } from '@/ui/Heading';\nimport { Icon } from '@/ui/Icon';\nimport { Link } from '@/ui/Link';\nimport { Stack } from '@/ui/Stack';\nimport { Text } from '@/ui/Text';\n\ninterface RaceListItemProps {\n track: string;\n car: string;\n timeLabel?: string;\n relativeTimeLabel?: string;\n dateLabel?: string;\n dayLabel?: string;\n status: string;\n leagueName?: string | null;\n leagueHref?: string;\n strengthOfField?: number | null;\n onClick: () => void;\n statusConfig: {\n icon: LucideIcon;\n variant: 'default' | 'primary' | 'success' | 'warning' | 'danger' | 'info';\n label: string;\n };\n}\n\nexport function RaceListItem({\n track,\n car,\n timeLabel,\n relativeTimeLabel,\n dateLabel,\n dayLabel,\n status,\n leagueName,\n leagueHref,\n strengthOfField,\n onClick,\n statusConfig,\n}: RaceListItemProps) {\n const StatusIcon = statusConfig.icon;\n\n return (\n \n {/* Live indicator */}\n {status === 'running' && (\n \n )}\n\n \n {/* Time/Date Column */}\n \n {dateLabel && (\n \n {dateLabel}\n \n )}\n \n {dayLabel || timeLabel}\n \n \n {status === 'running' ? 'LIVE' : relativeTimeLabel || timeLabel}\n \n \n\n {/* Divider */}\n \n\n {/* Main Content */}\n \n \n \n \n {track}\n \n \n \n \n {car}\n \n {strengthOfField && (\n \n \n SOF {strengthOfField}\n \n )}\n \n \n\n {/* Status Badge */}\n \n \n {statusConfig.label}\n \n \n\n {/* League Link */}\n {leagueName && leagueHref && (\n \n e.stopPropagation()}\n variant=\"primary\"\n size=\"sm\"\n >\n \n {leagueName}\n \n \n \n )}\n \n\n {/* Arrow */}\n \n \n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/races/RaceListItemWrapper.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/races/RaceResultCardWrapper.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/races/RaceResultRow.tsx","messages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":48,"column":7,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":48,"endColumn":64},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":49,"column":7,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":49,"endColumn":142},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":59,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":59,"endColumn":59},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":66,"column":132,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":66,"endColumn":175},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":69,"column":143,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":69,"endColumn":175},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":94,"column":32,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":94,"endColumn":61},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":100,"column":129,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":100,"endColumn":159}],"suppressedMessages":[],"errorCount":7,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\n\nimport { CountryFlagDisplay } from '@/lib/display-objects/CountryFlagDisplay';\nimport { Box } from '@/ui/Box';\nimport { Image } from '@/ui/Image';\nimport { Stack } from '@/ui/Stack';\nimport { Surface } from '@/ui/Surface';\nimport { Text } from '@/ui/Text';\n\ninterface ResultEntry {\n position: number;\n driverId: string;\n driverName: string;\n driverAvatar: string;\n country: string;\n car: string;\n laps: number;\n time: string;\n fastestLap: string;\n points: number;\n incidents: number;\n isCurrentUser: boolean;\n}\n\ninterface RaceResultRowProps {\n result: ResultEntry;\n points: number;\n}\n\nexport function RaceResultRow({ result, points }: RaceResultRowProps) {\n const { isCurrentUser, position, driverAvatar, driverName, country, car, laps, incidents, time, fastestLap } = result;\n\n const getPositionColor = (pos: number) => {\n if (pos === 1) return { bg: 'bg-yellow-500/20', color: 'text-yellow-400' };\n if (pos === 2) return { bg: 'bg-gray-400/20', color: 'text-gray-300' };\n if (pos === 3) return { bg: 'bg-amber-600/20', color: 'text-amber-600' };\n return { bg: 'bg-iron-gray/50', color: 'text-gray-500' };\n };\n\n const posConfig = getPositionColor(position);\n\n return (\n \n \n {/* Position */}\n \n {position}\n \n\n {/* Avatar */}\n \n \n {driverName}\n \n \n {CountryFlagDisplay.fromCountryCode(country).toString()}\n \n \n\n {/* Driver Info */}\n \n \n {driverName}\n {isCurrentUser && (\n \n YOU\n \n )}\n \n \n {car}\n \n Laps: {laps}\n \n Incidents: {incidents}\n \n \n\n {/* Times */}\n \n {time}\n FL: {fastestLap}\n \n\n {/* Points */}\n \n PTS\n {points}\n \n \n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/races/RaceSidebar.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/races/UpcomingRaces.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/races/UpcomingRacesList.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/races/UpcomingRacesSidebar.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/shared/CapabilityGate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/shared/CountrySelect.tsx","messages":[{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":109,"column":5,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":189,"endColumn":11},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":109,"column":5,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":109,"endColumn":50},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":109,"column":29,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":109,"endColumn":49},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":111,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":133,"endColumn":16},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":111,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":120,"endColumn":8},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":115,"column":9,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":119,"endColumn":97},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":121,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":131,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":121,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":121,"endColumn":50},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":121,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":121,"endColumn":49},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":122,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":122,"endColumn":51},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":124,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":127,"endColumn":20},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":124,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":124,"endColumn":55},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":124,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":124,"endColumn":54},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":126,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":126,"endColumn":21},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":129,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":129,"endColumn":65},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":129,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":129,"endColumn":45},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":129,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":129,"endColumn":44},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":132,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":132,"endColumn":108},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":137,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":182,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":137,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":137,"endColumn":142},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":137,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":137,"endColumn":141},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":139,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":151,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":139,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":139,"endColumn":65},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":139,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":139,"endColumn":64},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":140,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":150,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":140,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":140,"endColumn":39},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":140,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":140,"endColumn":38},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":141,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":141,"endColumn":97},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":142,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":149,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":142,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":149,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":148,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":148,"endColumn":188},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":154,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":181,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":154,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":154,"endColumn":53},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":154,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":154,"endColumn":52},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":157,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":174,"endColumn":26},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":157,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":166,"endColumn":18},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":161,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":165,"endColumn":22},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":167,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":170,"endColumn":26},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":167,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":167,"endColumn":61},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":167,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":167,"endColumn":60},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":169,"column":21,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":169,"endColumn":27},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":172,"column":28,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":172,"endColumn":65},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":177,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":179,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":177,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":177,"endColumn":76},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":177,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":177,"endColumn":75},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":187,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":187,"endColumn":74},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":187,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":187,"endColumn":56},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":187,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":187,"endColumn":55}],"suppressedMessages":[],"errorCount":48,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\n\nimport { Check, ChevronDown, Globe, Search } from 'lucide-react';\nimport { useEffect, useRef, useState } from 'react';\nimport { CountryFlag } from '@/ui/CountryFlag';\n\nexport interface Country {\n code: string;\n name: string;\n}\n\nexport const COUNTRIES: Country[] = [\n { code: 'US', name: 'United States' },\n { code: 'GB', name: 'United Kingdom' },\n { code: 'DE', name: 'Germany' },\n { code: 'NL', name: 'Netherlands' },\n { code: 'FR', name: 'France' },\n { code: 'IT', name: 'Italy' },\n { code: 'ES', name: 'Spain' },\n { code: 'AU', name: 'Australia' },\n { code: 'CA', name: 'Canada' },\n { code: 'BR', name: 'Brazil' },\n { code: 'JP', name: 'Japan' },\n { code: 'BE', name: 'Belgium' },\n { code: 'AT', name: 'Austria' },\n { code: 'CH', name: 'Switzerland' },\n { code: 'SE', name: 'Sweden' },\n { code: 'NO', name: 'Norway' },\n { code: 'DK', name: 'Denmark' },\n { code: 'FI', name: 'Finland' },\n { code: 'PL', name: 'Poland' },\n { code: 'PT', name: 'Portugal' },\n { code: 'CZ', name: 'Czech Republic' },\n { code: 'HU', name: 'Hungary' },\n { code: 'RU', name: 'Russia' },\n { code: 'MX', name: 'Mexico' },\n { code: 'AR', name: 'Argentina' },\n { code: 'CL', name: 'Chile' },\n { code: 'NZ', name: 'New Zealand' },\n { code: 'ZA', name: 'South Africa' },\n { code: 'IN', name: 'India' },\n { code: 'KR', name: 'South Korea' },\n { code: 'SG', name: 'Singapore' },\n { code: 'MY', name: 'Malaysia' },\n { code: 'TH', name: 'Thailand' },\n { code: 'AE', name: 'United Arab Emirates' },\n { code: 'SA', name: 'Saudi Arabia' },\n { code: 'IE', name: 'Ireland' },\n { code: 'GR', name: 'Greece' },\n { code: 'TR', name: 'Turkey' },\n { code: 'RO', name: 'Romania' },\n { code: 'UA', name: 'Ukraine' },\n];\n\ninterface CountrySelectProps {\n value: string;\n onChange: (value: string) => void;\n error?: boolean;\n errorMessage?: string;\n disabled?: boolean;\n placeholder?: string;\n}\n\nexport function CountrySelect({\n value,\n onChange,\n error,\n errorMessage,\n disabled,\n placeholder = 'Select country',\n}: CountrySelectProps) {\n const [isOpen, setIsOpen] = useState(false);\n const [search, setSearch] = useState('');\n const containerRef = useRef(null);\n const inputRef = useRef(null);\n\n const selectedCountry = COUNTRIES.find(c => c.code === value);\n\n const filteredCountries = COUNTRIES.filter(country =>\n country.name.toLowerCase().includes(search.toLowerCase()) ||\n country.code.toLowerCase().includes(search.toLowerCase())\n );\n\n useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (containerRef.current && !containerRef.current.contains(event.target as Node)) {\n setIsOpen(false);\n setSearch('');\n }\n }\n\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, []);\n\n useEffect(() => {\n if (isOpen && inputRef.current) {\n inputRef.current.focus();\n }\n }, [isOpen]);\n\n const handleSelect = (code: string) => {\n onChange(code);\n setIsOpen(false);\n setSearch('');\n };\n\n return (\n
\n {/* Trigger Button */}\n !disabled && setIsOpen(!isOpen)}\n disabled={disabled}\n className={`flex items-center justify-between w-full rounded-md border-0 px-4 py-3 bg-iron-gray text-white shadow-sm ring-1 ring-inset transition-all duration-150 sm:text-sm ${\n error\n ? 'ring-warning-amber focus:ring-warning-amber'\n : 'ring-charcoal-outline focus:ring-primary-blue'\n } ${disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer hover:ring-gray-500'}`}\n >\n
\n \n {selectedCountry ? (\n \n \n {selectedCountry.name}\n \n ) : (\n {placeholder}\n )}\n
\n \n \n\n {/* Dropdown */}\n {isOpen && (\n
\n {/* Search Input */}\n
\n
\n \n setSearch(e.target.value)}\n placeholder=\"Search countries...\"\n className=\"w-full rounded-md border-0 px-4 py-2 pl-9 bg-deep-graphite text-white text-sm placeholder:text-gray-500 focus:outline-none focus:ring-1 focus:ring-primary-blue\"\n />\n
\n
\n\n {/* Country List */}\n
\n {filteredCountries.length > 0 ? (\n filteredCountries.map((country) => (\n handleSelect(country.code)}\n className={`flex items-center justify-between w-full px-4 py-2.5 text-left text-sm transition-colors ${\n value === country.code\n ? 'bg-primary-blue/20 text-white'\n : 'text-gray-300 hover:bg-deep-graphite'\n }`}\n >\n \n \n {country.name}\n \n {value === country.code && (\n \n )}\n \n ))\n ) : (\n
\n No countries found\n
\n )}\n
\n
\n )}\n\n {/* Error Message */}\n {error && errorMessage && (\n

{errorMessage}

\n )}\n
\n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/shared/ModeGuard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/shared/RangeField.tsx","messages":[{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":126,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":162,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":126,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":126,"endColumn":36},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":126,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":126,"endColumn":35},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":127,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":160,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":127,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":127,"endColumn":66},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":127,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":127,"endColumn":65},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":128,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":128,"endColumn":88},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":128,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":128,"endColumn":73},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":128,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":128,"endColumn":72},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":129,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":159,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":129,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":129,"endColumn":73},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":129,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":129,"endColumn":72},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":130,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":154,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":130,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":136,"endColumn":14},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":132,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":132,"endColumn":125},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":138,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":138,"endColumn":122},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":138,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":138,"endColumn":122},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":138,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":138,"endColumn":119},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":140,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":143,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":140,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":143,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":141,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":141,"endColumn":131},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":142,"column":17,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":142,"endColumn":54},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":145,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":153,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":145,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":153,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":146,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":151,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":152,"column":17,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":152,"endColumn":53},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":155,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":158,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":155,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":155,"endColumn":63},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":155,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":155,"endColumn":62},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":156,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":156,"endColumn":102},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":156,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":156,"endColumn":81},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":156,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":156,"endColumn":80},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":157,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":157,"endColumn":77},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":157,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":157,"endColumn":59},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":157,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":157,"endColumn":58},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":161,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":161,"endColumn":76},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":161,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":161,"endColumn":65},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":161,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":161,"endColumn":64},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":167,"column":5,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":269,"endColumn":11},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":167,"column":5,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":167,"endColumn":32},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":167,"column":10,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":167,"endColumn":31},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":168,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":171,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":168,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":168,"endColumn":66},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":168,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":168,"endColumn":65},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":169,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":169,"endColumn":83},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":169,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":169,"endColumn":68},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":169,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":169,"endColumn":67},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":170,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":170,"endColumn":80},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":170,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":170,"endColumn":53},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":170,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":170,"endColumn":52},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":174,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":177,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":174,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":174,"endColumn":52},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":174,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":174,"endColumn":51},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":175,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":175,"endColumn":93},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":175,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":175,"endColumn":72},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":175,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":175,"endColumn":71},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":176,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":176,"endColumn":69},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":176,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":176,"endColumn":51},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":176,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":176,"endColumn":50},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":181,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":220,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":181,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":187,"endColumn":8},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":183,"column":9,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":183,"endColumn":124},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":189,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":189,"endColumn":117},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":189,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":189,"endColumn":117},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":189,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":189,"endColumn":114},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":192,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":195,"endColumn":11},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":192,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":195,"endColumn":11},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":193,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":193,"endColumn":155},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":194,"column":11,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":194,"endColumn":48},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":198,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":207,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":198,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":198,"endColumn":101},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":198,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":198,"endColumn":100},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":200,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":205,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":200,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":205,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":202,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":204,"endColumn":18},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":210,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":219,"endColumn":11},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":210,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":219,"endColumn":11},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":211,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":217,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":218,"column":11,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":218,"endColumn":47},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":223,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":265,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":223,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":223,"endColumn":64},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":223,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":223,"endColumn":63},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":224,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":245,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":224,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":224,"endColumn":50},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":224,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":224,"endColumn":49},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":225,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":243,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":225,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":243,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":235,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":242,"endColumn":15},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":244,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":244,"endColumn":69},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":244,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":244,"endColumn":51},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":244,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":244,"endColumn":50},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":248,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":263,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":248,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":248,"endColumn":39},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":248,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":248,"endColumn":38},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":250,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":261,"endColumn":24},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":250,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":259,"endColumn":16},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":258,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":258,"endColumn":156},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":267,"column":22,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":267,"endColumn":75},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":267,"column":22,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":267,"endColumn":59},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":267,"column":25,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":267,"endColumn":58},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":268,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":268,"endColumn":70},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":268,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":268,"endColumn":59},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":268,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":268,"endColumn":58}],"suppressedMessages":[],"errorCount":103,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\n\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\n\ninterface RangeFieldProps {\n label: string;\n value: number;\n min: number;\n max: number;\n step?: number;\n onChange: (value: number) => void;\n helperText?: string;\n error?: string | undefined;\n disabled?: boolean;\n unitLabel?: string;\n rangeHint?: string;\n /** Show large value display above slider */\n showLargeValue?: boolean;\n /** Compact mode - single line */\n compact?: boolean;\n}\n\nexport function RangeField({\n label,\n value,\n min,\n max,\n step = 1,\n onChange,\n helperText,\n error,\n disabled,\n unitLabel = 'min',\n rangeHint,\n showLargeValue = false,\n compact = false,\n}: RangeFieldProps) {\n const [localValue, setLocalValue] = useState(value);\n const [isDragging, setIsDragging] = useState(false);\n const sliderRef = useRef(null);\n const inputRef = useRef(null);\n\n // Sync local value with prop when not dragging\n useEffect(() => {\n if (!isDragging) {\n setLocalValue(value);\n }\n }, [value, isDragging]);\n\n const clampedValue = Number.isFinite(localValue)\n ? Math.min(Math.max(localValue, min), max)\n : min;\n\n const rangePercent = ((clampedValue - min) / Math.max(max - min, 1)) * 100;\n\n const effectiveRangeHint =\n rangeHint ?? (min === 0 ? `Up to ${max} ${unitLabel}` : `${min}–${max} ${unitLabel}`);\n\n const calculateValueFromPosition = useCallback(\n (clientX: number) => {\n if (!sliderRef.current) return clampedValue;\n const rect = sliderRef.current.getBoundingClientRect();\n const percent = Math.min(Math.max((clientX - rect.left) / rect.width, 0), 1);\n const rawValue = min + percent * (max - min);\n const steppedValue = Math.round(rawValue / step) * step;\n return Math.min(Math.max(steppedValue, min), max);\n },\n [min, max, step, clampedValue]\n );\n\n const handlePointerDown = useCallback(\n (e: React.PointerEvent) => {\n if (disabled) return;\n e.preventDefault();\n setIsDragging(true);\n const newValue = calculateValueFromPosition(e.clientX);\n setLocalValue(newValue);\n onChange(newValue);\n (e.target as HTMLElement).setPointerCapture(e.pointerId);\n },\n [disabled, calculateValueFromPosition, onChange]\n );\n\n const handlePointerMove = useCallback(\n (e: React.PointerEvent) => {\n if (!isDragging || disabled) return;\n const newValue = calculateValueFromPosition(e.clientX);\n setLocalValue(newValue);\n onChange(newValue);\n },\n [isDragging, disabled, calculateValueFromPosition, onChange]\n );\n\n const handlePointerUp = useCallback(() => {\n setIsDragging(false);\n }, []);\n\n const handleInputChange = (e: React.ChangeEvent) => {\n const raw = e.target.value;\n if (raw === '') {\n setLocalValue(min);\n return;\n }\n const parsed = parseInt(raw, 10);\n if (!Number.isNaN(parsed)) {\n const clamped = Math.min(Math.max(parsed, min), max);\n setLocalValue(clamped);\n onChange(clamped);\n }\n };\n\n const handleInputBlur = () => {\n // Ensure value is synced on blur\n onChange(clampedValue);\n };\n\n // Quick preset buttons for common values\n const quickPresets = [\n Math.round(min + (max - min) * 0.25),\n Math.round(min + (max - min) * 0.5),\n Math.round(min + (max - min) * 0.75),\n ].filter((v, i, arr) => arr.indexOf(v) === i && v !== clampedValue);\n\n if (compact) {\n return (\n
\n
\n \n
\n \n {/* Track background */}\n
\n {/* Track fill */}\n \n {/* Thumb */}\n \n
\n
\n {clampedValue}\n {unitLabel}\n
\n
\n
\n {error &&

{error}

}\n
\n );\n }\n\n return (\n
\n
\n \n {effectiveRangeHint}\n
\n\n {showLargeValue && (\n
\n {clampedValue}\n {unitLabel}\n
\n )}\n\n {/* Custom slider */}\n \n {/* Track background */}\n
\n \n {/* Track fill with gradient */}\n \n\n {/* Tick marks */}\n
\n {[0, 25, 50, 75, 100].map((tick) => (\n = tick ? 'bg-white/40' : 'bg-charcoal-outline'\n }`}\n />\n ))}\n
\n\n {/* Thumb */}\n \n
\n\n {/* Value input and quick presets */}\n
\n
\n \n {unitLabel}\n
\n\n {quickPresets.length > 0 && (\n
\n {quickPresets.slice(0, 3).map((preset) => (\n {\n setLocalValue(preset);\n onChange(preset);\n }}\n disabled={disabled}\n className=\"px-2 py-1 text-[10px] rounded bg-charcoal-outline/50 text-gray-400 hover:bg-charcoal-outline hover:text-white transition-colors\"\n >\n {preset}\n \n ))}\n
\n )}\n
\n\n {helperText &&

{helperText}

}\n {error &&

{error}

}\n
\n );\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/shared/state/EmptyState.tsx","messages":[{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":9,"column":5,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":15,"endColumn":11},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":9,"column":5,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":9,"endColumn":101},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":9,"column":10,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":9,"endColumn":31},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":10,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":10,"endColumn":96},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":11,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":11,"endColumn":96},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":12,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":12,"endColumn":58},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":13,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":13,"endColumn":58},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":14,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":14,"endColumn":113},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":18,"column":5,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":23,"endColumn":11},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":18,"column":5,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":18,"endColumn":101},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":18,"column":10,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":18,"endColumn":31},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":19,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":19,"endColumn":73},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":20,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":20,"endColumn":89},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":21,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":21,"endColumn":99},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":22,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":22,"endColumn":99},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":26,"column":5,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":31,"endColumn":11},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":26,"column":5,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":26,"endColumn":101},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":26,"column":10,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":26,"endColumn":31},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":27,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":27,"endColumn":72},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":28,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":28,"endColumn":72},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":29,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":29,"endColumn":73},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":30,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":30,"endColumn":120},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":34,"column":5,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":38,"endColumn":11},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":34,"column":5,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":34,"endColumn":101},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":34,"column":10,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":34,"endColumn":31},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":35,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":35,"endColumn":92},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":36,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":36,"endColumn":122},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":37,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":37,"endColumn":98},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":41,"column":5,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":47,"endColumn":11},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":41,"column":5,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":41,"endColumn":101},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":41,"column":10,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":41,"endColumn":31},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":42,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":42,"endColumn":72},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":43,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":43,"endColumn":82},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":44,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":44,"endColumn":106},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":45,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":45,"endColumn":58},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":46,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":46,"endColumn":58},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":78,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":88,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":78,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":78,"endColumn":49},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":78,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":78,"endColumn":48},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":80,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":82,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":80,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":80,"endColumn":42},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":80,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":80,"endColumn":41},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":84,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":86,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":84,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":84,"endColumn":133},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":84,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":84,"endColumn":132},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":85,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":85,"endColumn":52},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":91,"column":7,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":93,"endColumn":12},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":91,"column":7,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":91,"endColumn":73},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":91,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":91,"endColumn":72},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":97,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":99,"endColumn":13},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":97,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":97,"endColumn":71},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":97,"column":12,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":97,"endColumn":70},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":104,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":115,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":104,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":104,"endColumn":46},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":104,"column":14,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":104,"endColumn":45},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":108,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":108,"endColumn":38},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":111,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":111,"endColumn":55},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":111,"column":28,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":111,"endColumn":52},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":124,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":133,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":124,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":129,"endColumn":10},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":125,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":125,"endColumn":55},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":130,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":132,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":130,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":130,"endColumn":45},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":130,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":130,"endColumn":44},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":138,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":169,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":138,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":143,"endColumn":10},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":139,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":139,"endColumn":54},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":144,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":168,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":144,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":144,"endColumn":55},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":144,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":144,"endColumn":54},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":147,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":149,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":147,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":147,"endColumn":52},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":147,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":147,"endColumn":51},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":148,"column":23,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":148,"endColumn":58},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":151,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":153,"endColumn":18},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":151,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":151,"endColumn":63},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":151,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":151,"endColumn":62},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":155,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":157,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":155,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":155,"endColumn":52},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":155,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":155,"endColumn":51},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":160,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":166,"endColumn":24},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":160,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":163,"endColumn":16},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":162,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":162,"endColumn":122},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":165,"column":33,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":165,"endColumn":68},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":165,"column":46,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":165,"endColumn":65},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":174,"column":9,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":231,"endColumn":15},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":174,"column":9,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":179,"endColumn":10},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":175,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":175,"endColumn":105},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":180,"column":11,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":230,"endColumn":17},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":180,"column":11,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":180,"endColumn":56},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":180,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":180,"endColumn":55},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":181,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":193,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":181,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":181,"endColumn":35},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":181,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":181,"endColumn":34},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":183,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":185,"endColumn":23},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":183,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":183,"endColumn":68},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":183,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":183,"endColumn":67},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":187,"column":17,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":191,"endColumn":23},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":187,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":187,"endColumn":54},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":187,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":187,"endColumn":53},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":188,"column":19,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":190,"endColumn":25},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":188,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":188,"endColumn":141},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":188,"column":24,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":188,"endColumn":140},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":189,"column":27,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":189,"endColumn":62},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":195,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":197,"endColumn":18},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":195,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":195,"endColumn":64},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":195,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":195,"endColumn":63},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":200,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":202,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":200,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":200,"endColumn":73},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":200,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":200,"endColumn":72},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":206,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":217,"endColumn":21},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":206,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":206,"endColumn":79},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":206,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":206,"endColumn":78},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":210,"column":19,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":210,"endColumn":44},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":213,"column":21,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":213,"endColumn":61},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":213,"column":34,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":213,"endColumn":58},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":221,"column":13,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":229,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":221,"column":13,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":221,"endColumn":57},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":221,"column":18,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":221,"endColumn":56},{"ruleId":"gridpilot-rules/no-raw-html-in-app","severity":2,"message":"Raw HTML in components/ should use ui/ elements instead.","line":223,"column":15,"nodeType":"JSXElement","messageId":"noRawHtmlInComponents","endLine":228,"endColumn":19},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":223,"column":15,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":226,"endColumn":16},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":225,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":225,"endColumn":62},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":250,"column":7,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":250,"endColumn":28},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":267,"column":7,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":267,"endColumn":28},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":283,"column":7,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":283,"endColumn":28}],"suppressedMessages":[],"errorCount":125,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\n\nimport { Button } from '@/ui/Button';\nimport { EmptyStateProps } from '@/ui/state-types';\n\n// Illustration components (simple SVG representations)\nconst Illustrations = {\n racing: () => (\n \n \n \n \n \n \n \n ),\n league: () => (\n \n \n \n \n \n \n ),\n team: () => (\n \n \n \n \n \n \n ),\n sponsor: () => (\n \n \n \n \n \n ),\n driver: () => (\n \n \n \n \n \n \n \n ),\n} as const;\n\n/**\n * EmptyState Component\n * \n * Provides consistent empty/placeholder states with 3 variants:\n * - default: Standard empty state with icon, title, description, and action\n * - minimal: Simple version without extra styling\n * - full-page: Full page empty state with centered layout\n * \n * Supports both icons and illustrations for visual appeal.\n */\nexport function EmptyState({\n icon: Icon,\n title,\n description,\n action,\n variant = 'default',\n className = '',\n illustration,\n ariaLabel = 'Empty state',\n}: EmptyStateProps) {\n // Render illustration if provided\n const IllustrationComponent = illustration ? Illustrations[illustration] : null;\n\n // Common content\n const Content = () => (\n <>\n {/* Visual - Icon or Illustration */}\n
\n {IllustrationComponent ? (\n
\n \n
\n ) : Icon ? (\n
\n \n
\n ) : null}\n
\n\n {/* Title */}\n

\n {title}\n

\n\n {/* Description */}\n {description && (\n

\n {description}\n

\n )}\n\n {/* Action Button */}\n {action && (\n
\n \n {action.icon && (\n \n )}\n {action.label}\n \n
\n )}\n \n );\n\n // Render different variants\n switch (variant) {\n case 'default':\n return (\n \n
\n \n
\n
\n );\n\n case 'minimal':\n return (\n \n
\n {/* Minimal icon */}\n {Icon && (\n
\n \n
\n )}\n

\n {title}\n

\n {description && (\n

\n {description}\n

\n )}\n {action && (\n \n {action.label}\n {action.icon && }\n \n )}\n
\n
\n );\n\n case 'full-page':\n return (\n \n
\n
\n {IllustrationComponent ? (\n
\n \n
\n ) : Icon ? (\n
\n
\n \n
\n
\n ) : null}\n
\n \n

\n {title}\n

\n \n {description && (\n

\n {description}\n

\n )}\n\n {action && (\n
\n \n {action.icon && (\n \n )}\n {action.label}\n \n
\n )}\n\n {/* Additional helper text for full-page variant */}\n
\n Need help? Contact us at{' '}\n \n support@gridpilot.com\n \n
\n
\n
\n );\n\n default:\n return null;\n }\n}\n\n/**\n * Convenience component for default empty state\n */\nexport function DefaultEmptyState({ icon, title, description, action, className, illustration }: EmptyStateProps) {\n return (\n \n );\n}\n\n/**\n * Convenience component for minimal empty state\n */\nexport function MinimalEmptyState({ icon, title, description, action, className }: Omit) {\n return (\n \n );\n}\n\n/**\n * Convenience component for full-page empty state\n */\nexport function FullPageEmptyState({ icon, title, description, action, className, illustration }: EmptyStateProps) {\n return (\n \n );\n}\n\n/**\n * Pre-configured empty states for common scenarios\n */\n\nimport { Activity, Lock, Search } from 'lucide-react';\n\nexport function NoDataEmptyState({ onRetry }: { onRetry?: () => void }) {\n return (\n \n );\n}\n\nexport function NoResultsEmptyState({ onRetry }: { onRetry?: () => void }) {\n return (\n \n );\n}\n\nexport function NoAccessEmptyState({ onBack }: { onBack?: () => void }) {\n return (\n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/shared/state/ErrorDisplay.tsx","messages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":59,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":59,"endColumn":32},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":84,"column":64,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":84,"endColumn":93},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":105,"column":21,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":105,"endColumn":42},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":115,"column":17,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":115,"endColumn":53},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":115,"column":26,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":115,"endColumn":52},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"Raw HTML tags are forbidden in components and pages. Use UI components from ui/ instead.","line":116,"column":19,"nodeType":"JSXOpeningElement","messageId":"noRawHtml","endLine":116,"endColumn":82},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":116,"column":28,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":116,"endColumn":81},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":119,"column":98,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":119,"endColumn":148},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":137,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":137,"endColumn":32},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":189,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":189,"endColumn":32},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":200,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":200,"endColumn":92}],"suppressedMessages":[],"errorCount":11,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\n\nimport { ApiError } from '@/lib/api/base/ApiError';\nimport { AlertCircle, ArrowLeft, Home, RefreshCw } from 'lucide-react';\nimport { Box } from '@/ui/Box';\nimport { Button } from '@/ui/Button';\nimport { Heading } from '@/ui/Heading';\nimport { Icon } from '@/ui/Icon';\nimport { Stack } from '@/ui/Stack';\nimport { ErrorDisplayAction, ErrorDisplayProps } from '@/ui/state-types';\nimport { Surface } from '@/ui/Surface';\nimport { Text } from '@/ui/Text';\n\nexport function ErrorDisplay({\n error,\n onRetry,\n variant = 'full-screen',\n actions = [],\n showRetry = true,\n showNavigation = true,\n hideTechnicalDetails = false,\n className = '',\n}: ErrorDisplayProps) {\n const getErrorInfo = () => {\n const isApiError = error instanceof ApiError;\n \n return {\n title: isApiError ? 'API Error' : 'Unexpected Error',\n message: error.message || 'Something went wrong',\n statusCode: isApiError ? error.context.statusCode : undefined,\n details: isApiError ? error.context.responseText : undefined,\n isApiError,\n };\n };\n\n const errorInfo = getErrorInfo();\n\n const defaultActions: ErrorDisplayAction[] = [\n ...(showRetry && onRetry ? [{ label: 'Retry', onClick: onRetry, variant: 'primary' as const, icon: RefreshCw }] : []),\n ...(showNavigation ? [\n { label: 'Go Back', onClick: () => window.history.back(), variant: 'secondary' as const, icon: ArrowLeft },\n { label: 'Home', onClick: () => window.location.href = '/', variant: 'secondary' as const, icon: Home },\n ] : []),\n ...actions,\n ];\n\n switch (variant) {\n case 'full-screen':\n return (\n \n \n \n \n \n \n \n\n \n {errorInfo.title}\n \n\n \n {errorInfo.message}\n \n\n {errorInfo.isApiError && errorInfo.statusCode && (\n \n HTTP {errorInfo.statusCode}\n {errorInfo.details && !hideTechnicalDetails && (\n - {errorInfo.details}\n )}\n \n )}\n\n {defaultActions.length > 0 && (\n \n {defaultActions.map((action, index) => (\n }\n className=\"px-6 py-3\"\n >\n {action.label}\n \n ))}\n \n )}\n\n {!hideTechnicalDetails && process.env.NODE_ENV === 'development' && error.stack && (\n \n
\n \n Technical Details\n \n \n {error.stack}\n \n
\n
\n )}\n
\n \n );\n\n case 'card':\n return (\n \n \n \n \n \n {errorInfo.title}\n \n \n {errorInfo.message}\n \n\n {errorInfo.isApiError && errorInfo.statusCode && (\n \n HTTP {errorInfo.statusCode}\n {errorInfo.details && !hideTechnicalDetails && ` - ${errorInfo.details}`}\n \n )}\n\n {defaultActions.length > 0 && (\n \n {defaultActions.map((action, index) => (\n \n {action.label}\n \n ))}\n \n )}\n \n \n \n );\n\n case 'inline':\n return (\n \n \n {errorInfo.message}\n {onRetry && showRetry && (\n \n Retry\n \n )}\n \n );\n\n default:\n return null;\n }\n}\n\nexport function ApiErrorDisplay({\n error,\n onRetry,\n variant = 'full-screen',\n hideTechnicalDetails = false,\n}: {\n error: ApiError;\n onRetry?: () => void;\n variant?: 'full-screen' | 'card' | 'inline';\n hideTechnicalDetails?: boolean;\n}) {\n return (\n \n );\n}\n\nexport function NetworkErrorDisplay({\n onRetry,\n variant = 'full-screen',\n}: {\n onRetry?: () => void;\n variant?: 'full-screen' | 'card' | 'inline';\n}) {\n return (\n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/shared/state/LoadingWrapper.tsx","messages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":61,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":61,"endColumn":32},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":68,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":68,"endColumn":110},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":79,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":79,"endColumn":32},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":91,"column":15,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":91,"endColumn":45},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":109,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":109,"endColumn":32},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":116,"column":20,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":116,"endColumn":117},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":130,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":130,"endColumn":32},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":135,"column":16,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":135,"endColumn":111},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":148,"column":11,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":148,"endColumn":32},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":161,"column":15,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":161,"endColumn":40},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":162,"column":15,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":162,"endColumn":45},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":165,"column":22,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":165,"endColumn":117},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":185,"column":7,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":185,"endColumn":28},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":199,"column":7,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":199,"endColumn":28},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":212,"column":7,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":212,"endColumn":28},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":225,"column":7,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":225,"endColumn":28}],"suppressedMessages":[],"errorCount":16,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\n\nimport { Box } from '@/ui/Box';\nimport { Stack } from '@/ui/Stack';\nimport { LoadingWrapperProps } from '@/ui/state-types';\nimport { Text } from '@/ui/Text';\n\n/**\n * LoadingWrapper Component\n * \n * Provides consistent loading states with multiple variants:\n * - spinner: Traditional loading spinner (default)\n * - skeleton: Skeleton screens for better UX\n * - full-screen: Centered in viewport\n * - inline: Compact inline loading\n * - card: Loading card placeholders\n * \n * All variants are fully accessible with ARIA labels and keyboard support.\n */\nexport function LoadingWrapper({\n variant = 'spinner',\n message = 'Loading...',\n className = '',\n size = 'md',\n skeletonCount = 3,\n cardConfig,\n ariaLabel = 'Loading content',\n}: LoadingWrapperProps) {\n // Size mappings for different variants\n const sizeClasses = {\n sm: {\n spinner: 'w-4 h-4 border-2',\n inline: 'xs' as const,\n card: 'h-24',\n },\n md: {\n spinner: 'w-10 h-10 border-2',\n inline: 'sm' as const,\n card: 'h-32',\n },\n lg: {\n spinner: 'w-16 h-16 border-4',\n inline: 'base' as const,\n card: 'h-40',\n },\n };\n\n const spinnerSize = sizeClasses[size].spinner;\n const inlineSize = sizeClasses[size].inline;\n const cardHeight = cardConfig?.height || sizeClasses[size].card;\n\n // Render different variants\n switch (variant) {\n case 'spinner':\n return (\n \n \n \n {message}\n \n \n );\n\n case 'skeleton':\n return (\n \n {Array.from({ length: skeletonCount }).map((_, index) => (\n \n ))}\n \n );\n\n case 'full-screen':\n return (\n \n \n \n \n {message}\n This may take a moment...\n \n \n \n );\n\n case 'inline':\n return (\n \n \n {message}\n \n );\n\n case 'card':\n const cardCount = cardConfig?.count || 3;\n const cardClassName = cardConfig?.className || '';\n \n return (\n \n {Array.from({ length: cardCount }).map((_, index) => (\n \n \n \n \n \n ))}\n \n );\n\n default:\n return null;\n }\n}\n\n/**\n * Convenience component for full-screen loading\n */\nexport function FullScreenLoading({ message = 'Loading...', className = '' }: Pick) {\n return (\n \n );\n}\n\n/**\n * Convenience component for inline loading\n */\nexport function InlineLoading({ message = 'Loading...', size = 'sm', className = '' }: Pick) {\n return (\n \n );\n}\n\n/**\n * Convenience component for skeleton loading\n */\nexport function SkeletonLoading({ skeletonCount = 3, className = '' }: Pick) {\n return (\n \n );\n}\n\n/**\n * Convenience component for card loading\n */\nexport function CardLoading({ cardConfig, className = '' }: Pick) {\n return (\n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/shared/state/PageWrapper.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/shared/state/StateContainer.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/shared/state/StatefulPageWrapper.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/social/FriendsPreview.tsx","messages":[{"ruleId":"gridpilot-rules/no-hardcoded-routes","severity":2,"message":"Hardcoded link href \"/drivers/\". Use routes from RouteConfig.ts","line":42,"column":21,"nodeType":"TemplateElement","messageId":"hardcodedLink","endLine":42,"endColumn":33},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":45,"column":72,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":45,"endColumn":202},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":46,"column":22,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":46,"endColumn":173},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":52,"column":20,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":52,"endColumn":81}],"suppressedMessages":[],"errorCount":4,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\n\nimport { mediaConfig } from '@/lib/config/mediaConfig';\nimport { CountryFlagDisplay } from '@/lib/display-objects/CountryFlagDisplay';\nimport { Box } from '@/ui/Box';\nimport { Card } from '@/ui/Card';\nimport { Heading } from '@/ui/Heading';\nimport { Icon } from '@/ui/Icon';\nimport { Image } from '@/ui/Image';\nimport { Link } from '@/ui/Link';\nimport { Stack } from '@/ui/Stack';\nimport { Surface } from '@/ui/Surface';\nimport { Text } from '@/ui/Text';\nimport { Users } from 'lucide-react';\n\ninterface Friend {\n id: string;\n name: string;\n avatarUrl?: string;\n country: string;\n}\n\ninterface FriendsPreviewProps {\n friends: Friend[];\n}\n\nexport function FriendsPreview({ friends }: FriendsPreviewProps) {\n return (\n \n \n \n }>\n Friends\n \n ({friends.length})\n \n \n \n {friends.slice(0, 8).map((friend) => (\n \n \n \n \n \n \n {friend.name}\n {CountryFlagDisplay.fromCountryCode(friend.country).toString()}\n \n \n \n ))}\n {friends.length > 8 && (\n \n +{friends.length - 8} more\n \n )}\n \n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/social/FriendsSidebar.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/sponsors/ActivityItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/sponsors/AvailableLeagueCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/sponsors/MetricBuilders.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/sponsors/MetricCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/sponsors/PendingSponsorshipRequests.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/sponsors/RenewalAlert.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/sponsors/SlotTemplates.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/sponsors/SponsorBenefitCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/sponsors/SponsorHero.tsx","messages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":65,"column":11,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":65,"endColumn":28},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":75,"column":39,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":75,"endColumn":65},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":109,"column":9,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":109,"endColumn":26},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":143,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":143,"endColumn":98},{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":151,"column":13,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":151,"endColumn":81}],"suppressedMessages":[],"errorCount":5,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\n\nimport { motion, useReducedMotion } from 'framer-motion';\nimport { Building2 } from 'lucide-react';\nimport { useEffect, useState } from 'react';\nimport { Box } from '@/ui/Box';\nimport { Heading } from '@/ui/Heading';\nimport { Icon } from '@/ui/Icon';\nimport { Text } from '@/ui/Text';\n\ninterface SponsorHeroProps {\n title: string;\n subtitle: string;\n children?: React.ReactNode;\n}\n\nexport function SponsorHero({ title, subtitle, children }: SponsorHeroProps) {\n const shouldReduceMotion = useReducedMotion();\n const [isMounted, setIsMounted] = useState(false);\n\n useEffect(() => {\n setIsMounted(true);\n }, []);\n\n const containerVariants = {\n hidden: { opacity: 0 },\n visible: {\n opacity: 1,\n transition: {\n staggerChildren: 0.1,\n delayChildren: 0.1,\n },\n },\n };\n\n const itemVariants = {\n hidden: { opacity: 0, y: 20 },\n visible: {\n opacity: 1,\n y: 0,\n transition: { duration: 0.4, ease: 'easeOut' as const },\n },\n };\n\n const gridStyle = {\n backgroundImage: `\n linear-gradient(to right, #198CFF 1px, transparent 1px),\n linear-gradient(to bottom, #198CFF 1px, transparent 1px)\n `,\n backgroundSize: '40px 40px',\n };\n\n if (!isMounted || shouldReduceMotion) {\n return (\n \n {/* Background Pattern */}\n \n \n \n {/* Grid Pattern */}\n \n\n \n \n \n \n Sponsor Portal\n \n \n \n {title}\n \n \n \n {subtitle}\n \n\n {children}\n \n \n \n );\n }\n\n return (\n \n {/* Background Pattern */}\n \n \n \n {/* Animated Grid Pattern */}\n \n\n \n \n \n \n Sponsor Portal\n \n \n \n {title}\n \n \n \n {subtitle}\n \n\n \n {children}\n \n \n \n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/sponsors/SponsorInsightsCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/sponsors/SponsorInsightsCardHelpers.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/sponsors/SponsorInsightsCardTypes.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/sponsors/SponsorTierCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/sponsors/SponsorWorkflowMockup.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/sponsors/SponsorshipCategoryCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/teams/CreateTeamForm.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/teams/FeaturedRecruiting.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/teams/JoinTeamButton.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/teams/SkillLevelSection.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/teams/TeamAdmin.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/teams/TeamHero.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/teams/TeamHeroSection.tsx","messages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The style property is forbidden in components and pages. Use proper component props for styling.","line":34,"column":9,"nodeType":"JSXAttribute","messageId":"noStyle","endLine":37,"endColumn":11}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"\n\nimport { Users } from 'lucide-react';\nimport { ReactNode } from 'react';\nimport { Badge } from '@/ui/Badge';\nimport { Box } from '@/ui/Box';\nimport { Heading } from '@/ui/Heading';\nimport { Stack } from '@/ui/Stack';\nimport { Text } from '@/ui/Text';\n\ninterface TeamHeroSectionProps {\n title: ReactNode;\n description: string;\n statsContent: ReactNode;\n actionsContent: ReactNode;\n sideContent: ReactNode;\n}\n\nexport function TeamHeroSection({\n title,\n description,\n statsContent,\n actionsContent,\n sideContent,\n}: TeamHeroSectionProps) {\n return (\n \n {/* Main Hero Card */}\n \n {/* Background decorations */}\n \n \n \n\n \n \n \n {/* Badge */}\n \n \n Team Racing\n \n \n\n \n {title}\n \n\n \n {description}\n \n\n {/* Quick Stats */}\n \n {statsContent}\n \n\n {/* CTA Buttons */}\n \n {actionsContent}\n \n \n\n {/* Side Content */}\n \n {sideContent}\n \n \n \n \n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/teams/TeamHeroSectionWrapper.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/teams/TeamHeroStats.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/teams/TeamIdentity.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/teams/TeamLeaderboardPreviewWrapper.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/teams/TeamMembershipCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/teams/TeamPodium.tsx","messages":[{"ruleId":"gridpilot-rules/component-classification","severity":2,"message":"The className property is forbidden in components and pages. Use proper component props for styling.","line":76,"column":17,"nodeType":"JSXAttribute","messageId":"noClassName","endLine":76,"endColumn":43}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import React from 'react';\nimport { Trophy, Crown, Users } from 'lucide-react';\nimport type { TeamSummaryViewModel } from '@/lib/view-models/TeamSummaryViewModel';\nimport { getMediaUrl } from '@/lib/utilities/media';\nimport { Box } from '@/ui/Box';\nimport { Stack } from '@/ui/Stack';\nimport { Text } from '@/ui/Text';\nimport { Icon } from '@/ui/Icon';\nimport { Button } from '@/ui/Button';\nimport { Image } from '@/ui/Image';\nimport { Podium, PodiumItem } from '@/ui/Podium';\n\ninterface TeamPodiumProps {\n teams: TeamSummaryViewModel[];\n onClick: (id: string) => void;\n}\n\nexport function TeamPodium({ teams, onClick }: TeamPodiumProps) {\n const top3 = teams.slice(0, 3) as [TeamSummaryViewModel, TeamSummaryViewModel, TeamSummaryViewModel];\n if (teams.length < 3) return null;\n\n // Display order: 2nd, 1st, 3rd\n const podiumOrder: [TeamSummaryViewModel, TeamSummaryViewModel, TeamSummaryViewModel] = [\n top3[1],\n top3[0],\n top3[2],\n ];\n const podiumHeights = ['28', '36', '20'];\n const podiumPositions = [2, 1, 3];\n\n const getPositionColor = (position: number) => {\n switch (position) {\n case 1:\n return 'text-yellow-400';\n case 2:\n return 'text-gray-300';\n case 3:\n return 'text-amber-600';\n default:\n return 'text-gray-500';\n }\n };\n\n const getBgColor = (position: number) => {\n switch (position) {\n case 1:\n return 'bg-gradient-to-br from-primary-blue/20 via-iron-gray/80 to-deep-graphite';\n case 2:\n return 'bg-iron-gray';\n case 3:\n return 'bg-gradient-to-br from-purple-600/20 via-iron-gray/80 to-deep-graphite';\n default:\n return 'bg-iron-gray/50';\n }\n };\n\n return (\n \n {podiumOrder.map((team, index) => {\n const position = podiumPositions[index] ?? 0;\n\n return (\n onClick(team.id)}\n h=\"auto\"\n mb={4}\n p={0}\n className=\"transition-all\"\n >\n \n {/* Crown for 1st place */}\n {position === 1 && (\n \n \n \n \n \n \n \n \n )}\n\n {/* Team logo */}\n \n \n \n\n {/* Team name */}\n \n {team.name}\n \n\n {/* Category */}\n {team.category && (\n \n {team.category}\n \n )}\n\n {/* Rating placeholder */}\n \n —\n \n\n {/* Stats row */}\n \n \n \n {team.totalWins}\n \n \n \n {team.memberCount}\n \n \n \n \n }\n />\n );\n })}\n \n );\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/teams/TeamRankingsTable.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/teams/TeamRoster.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/teams/TeamRosterItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/teams/TeamStandings.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/teams/TopThreePodium.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/components/teams/WhyJoinTeamSection.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/env.d.ts","messages":[{"ruleId":"import/no-default-export","severity":2,"message":"Prefer named exports.","line":40,"column":10,"nodeType":"ExportDefaultDeclaration","endLine":40,"endColumn":17}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/// \n/// \n\ndeclare module 'framer-motion' {\n import type { ComponentType } from 'react';\n\n // Minimal shim to satisfy strict typing for usage in JSX\n export type MotionComponent = ComponentType>;\n\n export const motion: {\n div: MotionComponent;\n span: MotionComponent;\n button: MotionComponent;\n svg: MotionComponent;\n p: MotionComponent;\n [element: string]: MotionComponent;\n };\n\n export const AnimatePresence: ComponentType>;\n\n export function useReducedMotion(): boolean;\n\n // Shim motion values with a minimal interface exposing .set()\n export interface MotionValue {\n get(): T;\n set(v: T): void;\n }\n\n export function useMotionValue(initial: number): MotionValue;\n export function useSpring(value: MotionValue | number, config?: Record): MotionValue;\n export function useTransform(\n value: MotionValue,\n transformer: (input: TInput) => TOutput,\n ): MotionValue;\n}\n\ndeclare module '@next/third-party-devtools' {\n import type { ComponentType } from 'react';\n const Devtools: ComponentType>;\n export default Devtools;\n}\n\ndeclare module 'react/compiler-runtime' {\n export {};\n}\n\ndeclare global {\n namespace NodeJS {\n interface ProcessEnv {\n NODE_ENV?: 'development' | 'production' | 'test';\n\n // Website (public, exposed to browser)\n NEXT_PUBLIC_SITE_URL?: string;\n NEXT_PUBLIC_API_BASE_URL?: string;\n NEXT_PUBLIC_SITE_NAME?: string;\n NEXT_PUBLIC_SUPPORT_EMAIL?: string;\n NEXT_PUBLIC_SPONSOR_EMAIL?: string;\n NEXT_PUBLIC_LEGAL_COMPANY_NAME?: string;\n NEXT_PUBLIC_LEGAL_VAT_ID?: string;\n NEXT_PUBLIC_LEGAL_REGISTERED_COUNTRY?: string;\n NEXT_PUBLIC_LEGAL_REGISTERED_ADDRESS?: string;\n NEXT_PUBLIC_DISCORD_URL?: string;\n NEXT_PUBLIC_X_URL?: string;\n NEXT_TELEMETRY_DISABLED?: string;\n\n // Website (server-only)\n API_BASE_URL?: string;\n FEATURE_FLAGS?: string;\n\n // Vercel KV (server-only)\n KV_REST_API_URL?: string;\n KV_REST_API_TOKEN?: string;\n\n // Build/CI toggles (server-only)\n CI?: string;\n DOCKER?: string;\n }\n }\n}\n\nexport {};","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/auth/index.ts","messages":[{"ruleId":"gridpilot-rules/no-index-files","severity":2,"message":"Index files are banned. Use explicit imports and barrel exports. Example: Instead of \"import { foo } from \"./\", use \"import { foo } from \"./foo\" and export from \"./foo\" explicitly.","line":1,"column":1,"nodeType":null,"messageId":"indexFile"}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"export { useCurrentSession } from './useCurrentSession';\nexport { useLogin } from './useLogin';\nexport { useLogout } from './useLogout';\nexport { useSignup } from './useSignup';\nexport { useForgotPassword } from './useForgotPassword';\nexport { useResetPassword } from './useResetPassword';","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/auth/useCurrentSession.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/auth/useForgotPassword.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/auth/useLogin.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/auth/useLogout.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/auth/useResetPassword.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/auth/useSignup.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/driver/index.ts","messages":[{"ruleId":"gridpilot-rules/no-index-files","severity":2,"message":"Index files are banned. Use explicit imports and barrel exports. Example: Instead of \"import { foo } from \"./\", use \"import { foo } from \"./foo\" and export from \"./foo\" explicitly.","line":1,"column":1,"nodeType":null,"messageId":"indexFile"}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"export { useCurrentDriver } from './useCurrentDriver';\nexport { useDriverLeaderboard } from '@/hooks/useDriverLeaderboard';\nexport { useDriverProfile } from './useDriverProfile';\nexport { useUpdateDriverProfile } from './useUpdateDriverProfile';\nexport { useCreateDriver } from './useCreateDriver';\nexport { useFindDriverById } from './useFindDriverById';","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/driver/useCreateDriver.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/driver/useCurrentDriver.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":7,"column":19,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":7,"endColumn":22,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[327,330],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[327,330],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { useQuery, UseQueryOptions } from '@tanstack/react-query';\nimport { useInject } from '@/lib/di/hooks/useInject';\nimport { DRIVER_SERVICE_TOKEN } from '@/lib/di/tokens';\nimport { enhanceQueryResult } from '@/lib/di/hooks/useReactQueryWithApiError';\nimport { ApiError } from '@/lib/api/base/ApiError';\n\ntype DriverData = any; // Replace with actual type\n\nexport function useCurrentDriver(\n options?: Omit, 'queryKey' | 'queryFn'>\n) {\n const driverService = useInject(DRIVER_SERVICE_TOKEN);\n\n const queryResult = useQuery({\n queryKey: ['currentDriver'],\n queryFn: () => driverService.getCurrentDriver(),\n ...options,\n });\n\n return enhanceQueryResult(queryResult);\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/driver/useDriverProfile.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":22,"column":60,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":22,"endColumn":63,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1008,1011],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1008,1011],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { useQuery, UseQueryOptions } from '@tanstack/react-query';\nimport { useInject } from '@/lib/di/hooks/useInject';\nimport { DRIVER_SERVICE_TOKEN } from '@/lib/di/tokens';\nimport { enhanceQueryResult } from '@/lib/di/hooks/useReactQueryWithApiError';\nimport { ApiError } from '@/lib/api/base/ApiError';\nimport { DriverProfileViewModel } from '@/lib/view-models/DriverProfileViewModel';\n\nexport function useDriverProfile(\n driverId: string,\n options?: Omit, 'queryKey' | 'queryFn'>\n) {\n const driverService = useInject(DRIVER_SERVICE_TOKEN);\n\n const queryResult = useQuery({\n queryKey: ['driverProfile', driverId],\n queryFn: async () => {\n const result = await driverService.getDriverProfile(driverId);\n if (result.isErr()) {\n const error = result.getError();\n throw new ApiError(error.message, 'SERVER_ERROR', { timestamp: new Date().toISOString() });\n }\n return new DriverProfileViewModel(result.unwrap() as any);\n },\n enabled: !!driverId,\n ...options,\n });\n\n return enhanceQueryResult(queryResult);\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/driver/useDriverProfilePageData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/driver/useFindDriverById.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/driver/useUpdateDriverProfile.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/league/useAllLeagues.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/league/useCreateLeague.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/league/useCreateLeagueWithBlockers.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/league/useLeagueAdminStatus.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/league/useLeagueDetail.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/league/useLeagueMembershipMutation.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/league/useLeagueMemberships.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/league/useLeagueRaces.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/league/useLeagueRosterAdmin.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/league/useLeagueSchedule.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/league/useLeagueScheduleAdminPageData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/league/useLeagueSeasons.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/league/useLeagueSettings.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/league/useLeagueSponsorshipsPageData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/league/useLeagueStewardingData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/league/useLeagueStewardingMutations.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'variables' is defined but never used.","line":5,"column":12,"nodeType":"Identifier","messageId":"unusedVar","endLine":5,"endColumn":166},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'variables' is defined but never used.","line":31,"column":12,"nodeType":"Identifier","messageId":"unusedVar","endLine":31,"endColumn":66}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { usePageMutation } from '@/lib/page/usePageData';\n\nexport function useLeagueStewardingMutations(onRefetch: () => void) {\n const acceptProtestMutation = usePageMutation(\n async (variables: { protestId: string; penaltyType: string; penaltyValue: number; stewardNotes: string; raceId: string; accusedDriverId: string; reason: string }) => {\n // TODO: Implement protest review and penalty application\n // await leagueStewardingService.reviewProtest({\n // protestId: variables.protestId,\n // stewardId: currentDriverId,\n // decision: 'uphold',\n // decisionNotes: variables.stewardNotes,\n // });\n \n // await leagueStewardingService.applyPenalty({\n // raceId: variables.raceId,\n // driverId: variables.accusedDriverId,\n // stewardId: currentDriverId,\n // type: variables.penaltyType,\n // value: variables.penaltyValue,\n // reason: variables.reason,\n // protestId: variables.protestId,\n // notes: variables.stewardNotes,\n // });\n },\n {\n onSuccess: () => onRefetch(),\n }\n );\n\n const rejectProtestMutation = usePageMutation(\n async (variables: { protestId: string; stewardNotes: string }) => {\n // TODO: Implement protest rejection\n // await leagueStewardingService.reviewProtest({\n // protestId: variables.protestId,\n // stewardId: currentDriverId,\n // decision: 'dismiss',\n // decisionNotes: variables.stewardNotes,\n // });\n },\n {\n onSuccess: () => onRefetch(),\n }\n );\n\n return { acceptProtestMutation, rejectProtestMutation };\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/league/useLeagueWalletPageData.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":51,"column":67,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":51,"endColumn":70,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1850,1853],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1850,1853],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\n\nimport { usePageData } from '@/lib/page/usePageData';\nimport { useInject } from '@/lib/di/hooks/useInject';\nimport { LEAGUE_WALLET_SERVICE_TOKEN } from '@/lib/di/tokens';\nimport { LeagueWalletViewModel } from '@/lib/view-models/LeagueWalletViewModel';\nimport { WalletTransactionViewModel } from '@/lib/view-models/WalletTransactionViewModel';\nimport { useLeagueWalletWithdrawalWithBlockers } from './useLeagueWalletWithdrawalWithBlockers';\n\nexport function useLeagueWalletPageData(leagueId: string) {\n const leagueWalletService = useInject(LEAGUE_WALLET_SERVICE_TOKEN);\n\n const queryResult = usePageData({\n queryKey: ['leagueWallet', leagueId],\n queryFn: async () => {\n const dto = await leagueWalletService.getWalletForLeague(leagueId);\n // Transform DTO to ViewModel at client boundary\n const transactions = dto.transactions.map(t => new WalletTransactionViewModel({\n id: t.id,\n type: t.type,\n description: t.description,\n amount: t.amount,\n fee: t.fee,\n netAmount: t.netAmount,\n date: new Date(t.date),\n status: t.status,\n reference: t.reference,\n }));\n return new LeagueWalletViewModel({\n balance: dto.balance,\n currency: dto.currency,\n totalRevenue: dto.totalRevenue,\n totalFees: dto.totalFees,\n totalWithdrawals: dto.totalWithdrawals,\n pendingPayouts: dto.pendingPayouts,\n transactions,\n canWithdraw: dto.canWithdraw,\n withdrawalBlockReason: dto.withdrawalBlockReason,\n });\n },\n enabled: !!leagueId,\n });\n\n return queryResult;\n}\n\n/**\n * @deprecated Use useLeagueWalletWithdrawalWithBlockers instead\n * This wrapper maintains backward compatibility while using the new blocker-aware hook\n */\nexport function useLeagueWalletWithdrawal(leagueId: string, data: any, refetch: () => void) {\n return useLeagueWalletWithdrawalWithBlockers(leagueId, data, refetch);\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/league/useLeagueWalletWithdrawalWithBlockers.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":12,"column":79,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":12,"endColumn":82,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[484,487],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[484,487],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\n\nimport { usePageMutation } from '@/lib/page/usePageData';\nimport { useInject } from '@/lib/di/hooks/useInject';\nimport { LEAGUE_WALLET_SERVICE_TOKEN } from '@/lib/di/tokens';\nimport { SubmitBlocker, ThrottleBlocker } from '@/lib/blockers';\n\n/**\n * Hook for wallet withdrawals with client-side blockers\n * Handles UX prevention mechanisms (rate limiting, duplicate submission prevention)\n */\nexport function useLeagueWalletWithdrawalWithBlockers(leagueId: string, data: any, refetch: () => void) {\n const leagueWalletService = useInject(LEAGUE_WALLET_SERVICE_TOKEN);\n \n // Client-side blockers for UX improvement\n const submitBlocker = new SubmitBlocker();\n const throttle = new ThrottleBlocker(500);\n\n const withdrawMutation = usePageMutation(\n async ({ amount }: { amount: number }) => {\n if (!data) throw new Error('Wallet data not available');\n \n // Client-side blockers (UX only, not security)\n if (!submitBlocker.canExecute() || !throttle.canExecute()) {\n throw new Error('Request blocked due to rate limiting');\n }\n\n submitBlocker.block();\n throttle.block();\n \n try {\n const result = await leagueWalletService.withdraw(\n leagueId,\n amount,\n data.currency,\n 'season-2', // Current active season\n 'bank-account-***1234'\n );\n\n if (!result.success) {\n throw new Error(result.message || 'Withdrawal failed');\n }\n\n return result;\n } finally {\n submitBlocker.release();\n }\n },\n {\n onSuccess: () => {\n // Refetch wallet data after successful withdrawal\n refetch();\n },\n }\n );\n\n return withdrawMutation;\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/league/usePenaltyMutation.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":10,"column":27,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":10,"endColumn":30,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[391,394],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[391,394],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { useMutation, useQueryClient } from '@tanstack/react-query';\nimport { useInject } from '@/lib/di/hooks/useInject';\nimport { PENALTY_SERVICE_TOKEN } from '@/lib/di/tokens';\n\nexport function usePenaltyMutation() {\n const penaltyService = useInject(PENALTY_SERVICE_TOKEN);\n const queryClient = useQueryClient();\n\n const applyPenaltyMutation = useMutation({\n mutationFn: (command: any) => penaltyService.applyPenalty(command),\n onSuccess: () => {\n // Invalidate relevant queries to refresh data\n queryClient.invalidateQueries({ queryKey: ['leagueStewardingData'] });\n queryClient.invalidateQueries({ queryKey: ['penalties'] });\n },\n });\n\n return applyPenaltyMutation;\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/league/useProtestDetail.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/league/useSponsorshipRequests.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/onboarding/useCompleteOnboarding.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/onboarding/useGenerateAvatars.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'params' is defined but never used.","line":24,"column":24,"nodeType":"Identifier","messageId":"unusedVar","endLine":24,"endColumn":30},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'service' is assigned a value but never used.","line":25,"column":13,"nodeType":"Identifier","messageId":"unusedVar","endLine":25,"endColumn":20}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\n\nimport { useMutation, UseMutationOptions } from '@tanstack/react-query';\nimport { OnboardingService } from '@/lib/services/onboarding/OnboardingService';\nimport { Result } from '@/lib/contracts/Result';\nimport { DomainError } from '@/lib/contracts/services/Service';\n\ninterface GenerateAvatarsParams {\n userId: string;\n facePhotoData: string;\n suitColor: string;\n}\n\ninterface GenerateAvatarsResult {\n success: boolean;\n avatarUrls?: string[];\n errorMessage?: string;\n}\n\nexport function useGenerateAvatars(\n options?: Omit, Error, GenerateAvatarsParams>, 'mutationFn'>\n) {\n return useMutation, Error, GenerateAvatarsParams>({\n mutationFn: async (params) => {\n const service = new OnboardingService();\n // This method doesn't exist in the service yet, but the hook is now created\n // The service will need to implement this or we need to adjust the architecture\n return Result.ok({ success: false, errorMessage: 'Not implemented' });\n },\n ...options,\n });\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/race/useAllRacesPageData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/race/useFileProtest.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/race/useRaceResultsPageData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/race/useRegisterForRace.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/race/useWithdrawFromRace.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/sponsor/index.ts","messages":[{"ruleId":"gridpilot-rules/no-index-files","severity":2,"message":"Index files are banned. Use explicit imports and barrel exports. Example: Instead of \"import { foo } from \"./\", use \"import { foo } from \"./foo\" and export from \"./foo\" explicitly.","line":1,"column":1,"nodeType":null,"messageId":"indexFile"}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"export { useAvailableLeagues } from './useAvailableLeagues';\nexport { useSponsorDashboard } from './useSponsorDashboard';\nexport { useSponsorSponsorships } from './useSponsorSponsorships';\nexport { useSponsorBilling } from './useSponsorBilling';\nexport { useSponsorLeagueDetail } from './useSponsorLeagueDetail';","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/sponsor/useAvailableLeagues.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/sponsor/useSponsorBilling.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/sponsor/useSponsorDashboard.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/sponsor/useSponsorLeagueDetail.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/sponsor/useSponsorMode.ts","messages":[{"ruleId":"import/no-named-as-default-member","severity":2,"message":"Caution: `React` also has a named export `useState`. Check if you meant to write `import {useState} from 'react'` instead.","line":6,"column":37,"nodeType":"MemberExpression","endLine":6,"endColumn":51},{"ruleId":"import/no-named-as-default-member","severity":2,"message":"Caution: `React` also has a named export `useEffect`. Check if you meant to write `import {useEffect} from 'react'` instead.","line":8,"column":3,"nodeType":"MemberExpression","endLine":8,"endColumn":18}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { useAuth } from '@/lib/auth/AuthContext';\nimport React from 'react';\n\nexport function useSponsorMode(): boolean {\n const { session } = useAuth();\n const [isSponsor, setIsSponsor] = React.useState(false);\n \n React.useEffect(() => {\n if (!session) {\n setIsSponsor(false);\n return;\n }\n\n // Check session.role for sponsor\n const role = session.role;\n if (role === 'sponsor') {\n setIsSponsor(true);\n return;\n }\n\n // Fallback: check email patterns\n const email = session.email?.toLowerCase() || '';\n const displayName = session.displayName?.toLowerCase() || '';\n \n setIsSponsor(email.includes('sponsor') || displayName.includes('sponsor'));\n }, [session]);\n \n return isSponsor;\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/sponsor/useSponsorSponsorships.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/team/index.ts","messages":[{"ruleId":"gridpilot-rules/no-index-files","severity":2,"message":"Index files are banned. Use explicit imports and barrel exports. Example: Instead of \"import { foo } from \"./\", use \"import { foo } from \"./foo\" and export from \"./foo\" explicitly.","line":1,"column":1,"nodeType":null,"messageId":"indexFile"}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"export { useAllTeams } from './useAllTeams';\nexport { useTeamDetails } from './useTeamDetails';\nexport { useTeamMembers } from './useTeamMembers';\nexport { useTeamJoinRequests } from './useTeamJoinRequests';\nexport { useCreateTeam } from './useCreateTeam';\nexport { useUpdateTeam } from './useUpdateTeam';\nexport { useTeamMembership } from './useTeamMembership';\nexport { useApproveJoinRequest } from './useApproveJoinRequest';\nexport { useRejectJoinRequest } from './useRejectJoinRequest';\nexport { useTeamStandings } from './useTeamStandings';\nexport { useJoinTeam } from './useJoinTeam';\nexport { useLeaveTeam } from './useLeaveTeam';\nexport { useTeamRoster } from './useTeamRoster';","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/team/useAllTeams.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/team/useApproveJoinRequest.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/team/useCreateTeam.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/team/useJoinTeam.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'teamService' is assigned a value but never used.","line":13,"column":9,"nodeType":"Identifier","messageId":"unusedVar","endLine":13,"endColumn":20}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { useMutation, UseMutationOptions } from '@tanstack/react-query';\nimport { useInject } from '@/lib/di/hooks/useInject';\nimport { TEAM_SERVICE_TOKEN } from '@/lib/di/tokens';\nimport { ApiError } from '@/lib/api/base/ApiError';\n\ninterface JoinTeamParams {\n teamId: string;\n driverId: string;\n requiresApproval?: boolean;\n}\n\nexport function useJoinTeam(options?: Omit, 'mutationFn'>) {\n const teamService = useInject(TEAM_SERVICE_TOKEN);\n\n return useMutation({\n mutationFn: async (params) => {\n // Note: Team join functionality would need to be added to teamService\n // For now, we'll use a placeholder\n console.log('Joining team:', params);\n if (params.requiresApproval) {\n alert('Join request sent! Wait for team approval.');\n } else {\n alert('Successfully joined team!');\n }\n },\n ...options,\n });\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/team/useLeaveTeam.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'teamService' is assigned a value but never used.","line":12,"column":9,"nodeType":"Identifier","messageId":"unusedVar","endLine":12,"endColumn":20}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { useMutation, UseMutationOptions } from '@tanstack/react-query';\nimport { useInject } from '@/lib/di/hooks/useInject';\nimport { TEAM_SERVICE_TOKEN } from '@/lib/di/tokens';\nimport { ApiError } from '@/lib/api/base/ApiError';\n\ninterface LeaveTeamParams {\n teamId: string;\n driverId: string;\n}\n\nexport function useLeaveTeam(options?: Omit, 'mutationFn'>) {\n const teamService = useInject(TEAM_SERVICE_TOKEN);\n\n return useMutation({\n mutationFn: async (params) => {\n // Note: Leave team functionality would need to be added to teamService\n // For now, we'll use a placeholder\n console.log('Leaving team:', params);\n alert('Successfully left team');\n },\n ...options,\n });\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/team/useRejectJoinRequest.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/team/useTeamDetails.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/team/useTeamJoinRequests.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/team/useTeamMembers.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/team/useTeamMembership.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'GetTeamMembershipOutputDTO' is defined but never used.","line":5,"column":15,"nodeType":"Identifier","messageId":"unusedVar","endLine":5,"endColumn":41}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { useQuery } from '@tanstack/react-query';\nimport { useInject } from '@/lib/di/hooks/useInject';\nimport { TEAM_SERVICE_TOKEN } from '@/lib/di/tokens';\nimport { enhanceQueryResult } from '@/lib/di/hooks/useReactQueryWithApiError';\nimport type { GetTeamMembershipOutputDTO } from '@/lib/types/generated/GetTeamMembershipOutputDTO';\n\nexport function useTeamMembership(teamId: string, driverId: string) {\n const teamService = useInject(TEAM_SERVICE_TOKEN);\n\n const queryResult = useQuery({\n queryKey: ['teamMembership', teamId, driverId],\n queryFn: async () => {\n const result = await teamService.getMembership(teamId, driverId);\n if (result.isErr()) {\n throw result.getError();\n }\n return result.unwrap();\n },\n enabled: !!teamId && !!driverId,\n });\n\n return enhanceQueryResult(queryResult);\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/team/useTeamRoster.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":9,"column":11,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":9,"endColumn":14,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[354,357],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[354,357],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'teamService' is assigned a value but never used.","line":21,"column":9,"nodeType":"Identifier","messageId":"unusedVar","endLine":21,"endColumn":20}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { useQuery } from '@tanstack/react-query';\nimport { useInject } from '@/lib/di/hooks/useInject';\nimport { TEAM_SERVICE_TOKEN, DRIVER_SERVICE_TOKEN } from '@/lib/di/tokens';\nimport { enhanceQueryResult } from '@/lib/di/hooks/useReactQueryWithApiError';\n\ntype TeamMemberRole = 'owner' | 'manager' | 'member';\n\ninterface TeamRosterMember {\n driver: any;\n role: TeamMemberRole;\n joinedAt: string;\n rating: number | null;\n overallRank: number | null;\n}\n\nexport function useTeamRoster(memberships: Array<{\n driverId: string;\n role: string;\n joinedAt: string;\n}>) {\n const teamService = useInject(TEAM_SERVICE_TOKEN);\n const driverService = useInject(DRIVER_SERVICE_TOKEN);\n\n const queryResult = useQuery({\n queryKey: ['teamRoster', memberships],\n queryFn: async () => {\n // Get driver details for each membership\n const membersWithDetails = await Promise.all(\n memberships.map(async (m) => {\n const driver = await driverService.findById(m.driverId);\n // Convert role to TeamMemberRole\n const role: TeamMemberRole = m.role === 'owner' ? 'owner' : \n m.role === 'manager' ? 'manager' : 'member';\n return {\n driver: driver || { id: m.driverId, name: 'Unknown Driver', country: 'Unknown', position: 'N/A', races: '0', impressions: '0', team: 'None' },\n role,\n joinedAt: m.joinedAt,\n rating: null, // DriverDTO doesn't include rating\n overallRank: null, // DriverDTO doesn't include overallRank\n };\n })\n );\n return membersWithDetails;\n },\n enabled: memberships.length > 0,\n });\n\n return enhanceQueryResult(queryResult);\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/team/useTeamStandings.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'leagueService' is assigned a value but never used.","line":7,"column":9,"nodeType":"Identifier","messageId":"unusedVar","endLine":7,"endColumn":22}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { useQuery } from '@tanstack/react-query';\nimport { useInject } from '@/lib/di/hooks/useInject';\nimport { LEAGUE_SERVICE_TOKEN } from '@/lib/di/tokens';\nimport { enhanceQueryResult } from '@/lib/di/hooks/useReactQueryWithApiError';\n\nexport function useTeamStandings(teamId: string, leagues: string[]) {\n const leagueService = useInject(LEAGUE_SERVICE_TOKEN);\n\n const queryResult = useQuery({\n queryKey: ['teamStandings', teamId, leagues],\n queryFn: async () => {\n // For demo purposes, create mock standings\n return leagues.map(leagueId => ({\n leagueId,\n leagueName: `League ${leagueId}`,\n position: Math.floor(Math.random() * 10) + 1,\n points: Math.floor(Math.random() * 100),\n wins: Math.floor(Math.random() * 5),\n racesCompleted: Math.floor(Math.random() * 10),\n }));\n },\n enabled: leagues.length > 0,\n });\n\n return enhanceQueryResult(queryResult);\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/team/useUpdateTeam.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/useCapability.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/useDriverLeaderboard.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/useDriverSearch.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/useEffectiveDriverId.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/useEnhancedForm.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'createErrorContext' is defined but never used.","line":9,"column":77,"nodeType":"Identifier","messageId":"unusedVar","endLine":9,"endColumn":95},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'ApiError' is defined but never used.","line":10,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":10,"endColumn":18},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":19,"column":53,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":19,"endColumn":56,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[659,662],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[659,662],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":27,"column":55,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":27,"endColumn":58,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[863,866],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[863,866],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":36,"column":65,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":36,"endColumn":68,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1192,1195],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1192,1195],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":52,"column":58,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":52,"endColumn":61,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1900,1903],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1900,1903],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"react-hooks/exhaustive-deps","severity":2,"message":"React Hook useEffect has a missing dependency: 'getValues'. Either include it or remove the dependency array.","line":94,"column":6,"nodeType":"ArrayExpression","endLine":94,"endColumn":65,"suggestions":[{"desc":"Update the dependencies array to be: [formState.fields, formState.submitCount, getValues, options.validate]","fix":{"range":[3178,3237],"text":"[formState.fields, formState.submitCount, getValues, options.validate]"}}]},{"ruleId":"react-hooks/exhaustive-deps","severity":2,"message":"React Hook useCallback has a missing dependency: 'options'. Either include it or remove the dependency array.","line":213,"column":6,"nodeType":"ArrayExpression","endLine":213,"endColumn":35,"suggestions":[{"desc":"Update the dependencies array to be: [options, getValues]","fix":{"range":[6056,6085],"text":"[options, getValues]"}}]}],"suppressedMessages":[],"errorCount":8,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Enhanced Form Hook with Advanced Error Handling\n * \n * Provides comprehensive form state management, validation, and error handling\n * with both user-friendly and developer-friendly error messages.\n */\n\nimport { useState, useCallback, useEffect, FormEvent, ChangeEvent, Dispatch, SetStateAction } from 'react';\nimport { parseApiError, formatValidationErrorsForForm, logErrorWithContext, createErrorContext } from '@/lib/utils/errorUtils';\nimport { ApiError } from '@/lib/api/base/ApiError';\n\nexport interface FormField {\n value: T;\n error?: string;\n touched: boolean;\n validating: boolean;\n}\n\nexport interface FormState> {\n fields: { [K in keyof T]: FormField };\n isValid: boolean;\n isSubmitting: boolean;\n submitError?: string;\n submitCount: number;\n}\n\nexport interface FormOptions> {\n initialValues: T;\n validate?: (values: T) => Record | Promise>;\n onSubmit: (values: T) => Promise;\n onError?: (error: unknown, values: T) => void;\n onSuccess?: (values: T) => void;\n component?: string;\n}\n\nexport interface UseEnhancedFormReturn> {\n formState: FormState;\n setFormState: Dispatch>>;\n handleChange: (e: ChangeEvent) => void;\n setFieldValue: (field: K, value: T[K]) => void;\n setFieldError: (field: K, error: string) => void;\n handleSubmit: (e: FormEvent) => Promise;\n reset: () => void;\n setFormError: (error: string) => void;\n clearFieldError: (field: K) => void;\n validateField: (field: K) => Promise;\n}\n\n/**\n * Enhanced form hook with comprehensive error handling\n */\nexport function useEnhancedForm>(\n options: FormOptions\n): UseEnhancedFormReturn {\n const [formState, setFormState] = useState>(() => ({\n fields: Object.keys(options.initialValues).reduce((acc, key) => ({\n ...acc,\n [key]: {\n value: options.initialValues[key as keyof T],\n error: undefined,\n touched: false,\n validating: false,\n }\n }), {} as { [K in keyof T]: FormField }),\n isValid: true,\n isSubmitting: false,\n submitError: undefined,\n submitCount: 0,\n }));\n\n // Validate form on change\n useEffect(() => {\n if (options.validate && formState.submitCount > 0) {\n const validateAsync = async () => {\n try {\n const errors = await options.validate!(getValues());\n setFormState(prev => ({\n ...prev,\n isValid: Object.keys(errors).length === 0,\n fields: Object.keys(prev.fields).reduce((acc, key) => ({\n ...acc,\n [key]: {\n ...prev.fields[key as keyof T],\n error: errors[key],\n }\n }), {} as { [K in keyof T]: FormField }),\n }));\n } catch (error) {\n console.error('Validation error:', error);\n }\n };\n validateAsync();\n }\n }, [formState.fields, formState.submitCount, options.validate]);\n\n const getValues = useCallback((): T => {\n return Object.keys(formState.fields).reduce((acc, key) => ({\n ...acc,\n [key]: formState.fields[key as keyof T].value,\n }), {} as T);\n }, [formState.fields]);\n\n const handleChange = useCallback((e: ChangeEvent) => {\n const { name, value, type } = e.target;\n const checked = 'checked' in e.target ? e.target.checked : false;\n const fieldValue = type === 'checkbox' ? checked : value;\n \n setFormState(prev => ({\n ...prev,\n fields: {\n ...prev.fields,\n [name]: {\n ...prev.fields[name as keyof T],\n value: fieldValue as T[keyof T],\n touched: true,\n error: undefined, // Clear error on change\n },\n },\n }));\n }, []);\n\n const setFieldValue = useCallback((field: K, value: T[K]) => {\n setFormState(prev => ({\n ...prev,\n fields: {\n ...prev.fields,\n [field]: {\n ...prev.fields[field],\n value,\n touched: true,\n error: undefined,\n },\n },\n }));\n }, []);\n\n const setFieldError = useCallback((field: K, error: string) => {\n setFormState(prev => ({\n ...prev,\n fields: {\n ...prev.fields,\n [field]: {\n ...prev.fields[field],\n error,\n touched: true,\n },\n },\n isValid: false,\n }));\n }, []);\n\n const clearFieldError = useCallback((field: K) => {\n setFormState(prev => ({\n ...prev,\n fields: {\n ...prev.fields,\n [field]: {\n ...prev.fields[field],\n error: undefined,\n },\n },\n }));\n }, []);\n\n const setFormError = useCallback((error: string) => {\n setFormState(prev => ({\n ...prev,\n submitError: error,\n }));\n }, []);\n\n const validateField = useCallback(async (field: K) => {\n if (!options.validate) return;\n \n setFormState(prev => ({\n ...prev,\n fields: {\n ...prev.fields,\n [field]: {\n ...prev.fields[field],\n validating: true,\n },\n },\n }));\n\n try {\n const values = getValues();\n const errors = await options.validate(values);\n \n setFormState(prev => ({\n ...prev,\n fields: {\n ...prev.fields,\n [field]: {\n ...prev.fields[field],\n error: errors[field as string],\n validating: false,\n },\n },\n }));\n } catch (error) {\n setFormState(prev => ({\n ...prev,\n fields: {\n ...prev.fields,\n [field]: {\n ...prev.fields[field],\n validating: false,\n },\n },\n }));\n }\n }, [options.validate, getValues]);\n\n const reset = useCallback(() => {\n setFormState({\n fields: Object.keys(options.initialValues).reduce((acc, key) => ({\n ...acc,\n [key]: {\n value: options.initialValues[key as keyof T],\n error: undefined,\n touched: false,\n validating: false,\n }\n }), {} as { [K in keyof T]: FormField }),\n isValid: true,\n isSubmitting: false,\n submitError: undefined,\n submitCount: 0,\n });\n }, [options.initialValues]);\n\n const handleSubmit = useCallback(async (e: FormEvent) => {\n e.preventDefault();\n \n const values = getValues();\n \n // Increment submit count to trigger validation\n setFormState(prev => ({\n ...prev,\n submitCount: prev.submitCount + 1,\n isSubmitting: true,\n submitError: undefined,\n }));\n\n // Run validation if provided\n if (options.validate) {\n try {\n const errors = await options.validate(values);\n const hasErrors = Object.keys(errors).length > 0;\n \n if (hasErrors) {\n setFormState(prev => ({\n ...prev,\n isSubmitting: false,\n isValid: false,\n fields: Object.keys(prev.fields).reduce((acc, key) => ({\n ...acc,\n [key]: {\n ...prev.fields[key as keyof T],\n error: errors[key],\n touched: true,\n }\n }), {} as { [K in keyof T]: FormField }),\n }));\n return;\n }\n } catch (validationError) {\n logErrorWithContext(validationError, {\n timestamp: new Date().toISOString(),\n component: options.component || 'useEnhancedForm',\n action: 'validate',\n formData: values,\n });\n \n setFormState(prev => ({\n ...prev,\n isSubmitting: false,\n submitError: 'Validation failed. Please check your input.',\n }));\n return;\n }\n }\n\n // Submit the form\n try {\n await options.onSubmit(values);\n \n setFormState(prev => ({\n ...prev,\n isSubmitting: false,\n submitError: undefined,\n }));\n \n options.onSuccess?.(values);\n } catch (error) {\n const parsed = parseApiError(error);\n \n // Log for developers\n logErrorWithContext(error, {\n timestamp: new Date().toISOString(),\n component: options.component || 'useEnhancedForm',\n action: 'submit',\n formData: values,\n });\n\n // Handle validation errors from API\n if (parsed.isValidationError && parsed.validationErrors.length > 0) {\n const fieldErrors = formatValidationErrorsForForm(parsed.validationErrors);\n \n setFormState(prev => ({\n ...prev,\n isSubmitting: false,\n isValid: false,\n fields: Object.keys(prev.fields).reduce((acc, key) => ({\n ...acc,\n [key]: {\n ...prev.fields[key as keyof T],\n error: fieldErrors[key],\n touched: true,\n }\n }), {} as { [K in keyof T]: FormField }),\n }));\n } else {\n // General submit error\n setFormState(prev => ({\n ...prev,\n isSubmitting: false,\n submitError: parsed.userMessage,\n }));\n }\n \n options.onError?.(error, values);\n }\n }, [getValues, options]);\n\n return {\n formState,\n setFormState,\n handleChange,\n setFieldValue,\n setFieldError,\n handleSubmit,\n reset,\n setFormError,\n clearFieldError,\n validateField,\n };\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/useLeagueScoringPresets.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/useLeagueWizardService.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/usePenaltyTypesReference.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/hooks/useScrollProgress.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/adapters/MediaAdapter.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/api/admin/AdminApiClient.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/api/analytics/AnalyticsApiClient.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/api/auth/AuthApiClient.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/api/base/ApiConnectionMonitor.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'ApiError' is defined but never used.","line":6,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":6,"endColumn":18},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'CircuitBreakerRegistry' is defined but never used.","line":7,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":7,"endColumn":32}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * API Connection Status Monitor and Health Checks\n */\n\nimport { EventEmitter } from 'events';\nimport { ApiError } from './ApiError';\nimport { CircuitBreakerRegistry } from './RetryHandler';\n\nexport type ConnectionStatus = 'connected' | 'disconnected' | 'degraded' | 'checking';\n\nexport interface ConnectionHealth {\n status: ConnectionStatus;\n lastCheck: Date | null;\n lastSuccess: Date | null;\n lastFailure: Date | null;\n consecutiveFailures: number;\n totalRequests: number;\n successfulRequests: number;\n failedRequests: number;\n averageResponseTime: number;\n}\n\nexport interface HealthCheckResult {\n healthy: boolean;\n responseTime: number;\n error?: string;\n timestamp: Date;\n}\n\nexport class ApiConnectionMonitor extends EventEmitter {\n private static instance: ApiConnectionMonitor;\n private health: ConnectionHealth;\n private isChecking = false;\n private checkInterval: NodeJS.Timeout | null = null;\n private healthCheckEndpoint: string;\n private readonly CHECK_INTERVAL = 30000; // 30 seconds\n private readonly DEGRADATION_THRESHOLD = 0.7; // 70% failure rate\n\n private constructor(healthCheckEndpoint: string = '/health') {\n super();\n this.healthCheckEndpoint = healthCheckEndpoint;\n this.health = {\n status: 'disconnected',\n lastCheck: null,\n lastSuccess: null,\n lastFailure: null,\n consecutiveFailures: 0,\n totalRequests: 0,\n successfulRequests: 0,\n failedRequests: 0,\n averageResponseTime: 0,\n };\n }\n\n static getInstance(healthCheckEndpoint?: string): ApiConnectionMonitor {\n if (!ApiConnectionMonitor.instance) {\n ApiConnectionMonitor.instance = new ApiConnectionMonitor(healthCheckEndpoint);\n }\n return ApiConnectionMonitor.instance;\n }\n\n /**\n * Start automatic health monitoring\n */\n startMonitoring(intervalMs?: number): void {\n if (this.checkInterval) {\n clearInterval(this.checkInterval);\n }\n\n const interval = intervalMs || this.CHECK_INTERVAL;\n this.checkInterval = setInterval(() => {\n this.performHealthCheck();\n }, interval);\n\n // Initial check\n this.performHealthCheck();\n }\n\n /**\n * Stop automatic health monitoring\n */\n stopMonitoring(): void {\n if (this.checkInterval) {\n clearInterval(this.checkInterval);\n this.checkInterval = null;\n }\n }\n\n /**\n * Perform a manual health check\n */\n async performHealthCheck(): Promise {\n if (this.isChecking) {\n return {\n healthy: false,\n responseTime: 0,\n error: 'Check already in progress',\n timestamp: new Date(),\n };\n }\n\n this.isChecking = true;\n const startTime = Date.now();\n\n try {\n // Try multiple endpoints to determine actual connectivity\n const baseUrl = this.getBaseUrl();\n const endpointsToTry = [\n `${baseUrl}${this.healthCheckEndpoint}`,\n `${baseUrl}/api/health`,\n `${baseUrl}/status`,\n baseUrl, // Root endpoint\n ];\n\n let lastError: Error | null = null;\n let successfulResponse: Response | null = null;\n\n for (const endpoint of endpointsToTry) {\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 3000);\n\n const response = await fetch(endpoint, {\n method: 'GET',\n signal: controller.signal,\n cache: 'no-store',\n // Add credentials to handle auth\n credentials: 'include',\n });\n\n clearTimeout(timeoutId);\n\n // Consider any response (even 404) as connectivity success\n if (response.ok || response.status === 404 || response.status === 401) {\n successfulResponse = response;\n break;\n }\n } catch (endpointError) {\n lastError = endpointError as Error;\n // Try next endpoint\n continue;\n }\n }\n\n const responseTime = Date.now() - startTime;\n\n if (successfulResponse) {\n this.recordSuccess(responseTime);\n this.isChecking = false;\n\n return {\n healthy: true,\n responseTime,\n timestamp: new Date(),\n };\n } else {\n // If we got here, all endpoints failed\n const errorMessage = lastError?.message || 'All endpoints failed to respond';\n this.recordFailure(errorMessage);\n this.isChecking = false;\n\n return {\n healthy: false,\n responseTime,\n error: errorMessage,\n timestamp: new Date(),\n };\n }\n } catch (error) {\n const responseTime = Date.now() - startTime;\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n \n this.recordFailure(errorMessage);\n this.isChecking = false;\n\n return {\n healthy: false,\n responseTime,\n error: errorMessage,\n timestamp: new Date(),\n };\n }\n }\n\n /**\n * Record a successful API request\n */\n recordSuccess(responseTime: number = 0): void {\n this.health.totalRequests++;\n this.health.successfulRequests++;\n this.health.consecutiveFailures = 0;\n this.health.lastSuccess = new Date();\n this.health.lastCheck = new Date();\n\n // Update average response time\n const total = this.health.successfulRequests;\n this.health.averageResponseTime = \n ((this.health.averageResponseTime * (total - 1)) + responseTime) / total;\n\n this.updateStatus();\n this.emit('success', { responseTime });\n }\n\n /**\n * Record a failed API request\n */\n recordFailure(error: string | Error): void {\n this.health.totalRequests++;\n this.health.failedRequests++;\n this.health.consecutiveFailures++;\n this.health.lastFailure = new Date();\n this.health.lastCheck = new Date();\n\n this.updateStatus();\n this.emit('failure', { \n error: typeof error === 'string' ? error : error.message,\n consecutiveFailures: this.health.consecutiveFailures \n });\n }\n\n /**\n * Get current connection health\n */\n getHealth(): ConnectionHealth {\n return { ...this.health };\n }\n\n /**\n * Get current connection status\n */\n getStatus(): ConnectionStatus {\n return this.health.status;\n }\n\n /**\n * Check if API is currently available\n */\n isAvailable(): boolean {\n return this.health.status === 'connected' || this.health.status === 'degraded';\n }\n\n /**\n * Get reliability percentage\n */\n getReliability(): number {\n if (this.health.totalRequests === 0) return 0;\n return (this.health.successfulRequests / this.health.totalRequests) * 100;\n }\n\n /**\n * Reset all statistics\n */\n reset(): void {\n this.health = {\n status: 'disconnected',\n lastCheck: null,\n lastSuccess: null,\n lastFailure: null,\n consecutiveFailures: 0,\n totalRequests: 0,\n successfulRequests: 0,\n failedRequests: 0,\n averageResponseTime: 0,\n };\n this.emit('reset');\n }\n\n /**\n * Get detailed status report for development\n */\n getDebugReport(): string {\n const reliability = this.getReliability().toFixed(2);\n const avgTime = this.health.averageResponseTime.toFixed(2);\n \n return `API Connection Status:\n Status: ${this.health.status}\n Reliability: ${reliability}%\n Total Requests: ${this.health.totalRequests}\n Successful: ${this.health.successfulRequests}\n Failed: ${this.health.failedRequests}\n Consecutive Failures: ${this.health.consecutiveFailures}\n Avg Response Time: ${avgTime}ms\n Last Check: ${this.health.lastCheck?.toISOString() || 'never'}\n Last Success: ${this.health.lastSuccess?.toISOString() || 'never'}\n Last Failure: ${this.health.lastFailure?.toISOString() || 'never'}`;\n }\n\n private updateStatus(): void {\n const reliability = this.health.totalRequests > 0\n ? this.health.successfulRequests / this.health.totalRequests\n : 0;\n\n // More nuanced status determination\n if (this.health.totalRequests === 0) {\n // No requests yet - don't assume disconnected\n this.health.status = 'checking';\n } else if (this.health.consecutiveFailures >= 3) {\n // Multiple consecutive failures indicates real connectivity issue\n this.health.status = 'disconnected';\n } else if (reliability < this.DEGRADATION_THRESHOLD && this.health.totalRequests >= 5) {\n // Only degrade if we have enough samples and reliability is low\n this.health.status = 'degraded';\n } else if (reliability >= this.DEGRADATION_THRESHOLD || this.health.successfulRequests > 0) {\n // If we have any successes, we're connected\n this.health.status = 'connected';\n } else {\n // Default to checking if uncertain\n this.health.status = 'checking';\n }\n\n // Emit status change events (only on actual changes)\n if (this.health.status === 'disconnected') {\n this.emit('disconnected');\n } else if (this.health.status === 'degraded') {\n this.emit('degraded');\n } else if (this.health.status === 'connected') {\n this.emit('connected');\n } else if (this.health.status === 'checking') {\n this.emit('checking');\n }\n }\n\n private getBaseUrl(): string {\n // Try to get base URL from environment or fallback\n if (typeof window !== 'undefined') {\n return process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:3001';\n }\n return process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:3001';\n }\n}\n\n/**\n * Global connection status utility\n */\nexport const connectionMonitor = ApiConnectionMonitor.getInstance();\n\n/**\n * Hook for React components to monitor connection status\n */\nexport function useConnectionStatus() {\n const monitor = ApiConnectionMonitor.getInstance();\n \n return {\n status: monitor.getStatus(),\n health: monitor.getHealth(),\n isAvailable: monitor.isAvailable(),\n reliability: monitor.getReliability(),\n checkHealth: () => monitor.performHealthCheck(),\n getDebugReport: () => monitor.getDebugReport(),\n };\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/api/base/ApiError.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/api/base/BaseApiClient.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'path' is defined but never used.","line":170,"column":42,"nodeType":"Identifier","messageId":"unusedVar","endLine":170,"endColumn":54},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'method' is defined but never used.","line":170,"column":56,"nodeType":"Identifier","messageId":"unusedVar","endLine":170,"endColumn":70},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'path' is defined but never used.","line":186,"column":51,"nodeType":"Identifier","messageId":"unusedVar","endLine":186,"endColumn":63}],"suppressedMessages":[],"errorCount":3,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Base API Client for HTTP operations\n *\n * Provides generic HTTP methods with common request/response handling,\n * error handling, authentication, retry logic, and circuit breaker.\n */\n\nimport { Logger } from '../../interfaces/Logger';\nimport { ErrorReporter } from '../../interfaces/ErrorReporter';\nimport { ApiError, ApiErrorType } from './ApiError';\nimport { RetryHandler, CircuitBreakerRegistry, DEFAULT_RETRY_CONFIG } from './RetryHandler';\nimport { ApiConnectionMonitor } from './ApiConnectionMonitor';\nimport { getGlobalApiLogger } from '@/lib/infrastructure/ApiRequestLogger';\n\nexport interface BaseApiClientOptions {\n timeout?: number;\n retry?: boolean;\n retryConfig?: typeof DEFAULT_RETRY_CONFIG;\n}\n\nexport class BaseApiClient {\n protected baseUrl: string;\n private errorReporter: ErrorReporter;\n private logger: Logger;\n private retryHandler: RetryHandler;\n private circuitBreakerRegistry: CircuitBreakerRegistry;\n private connectionMonitor: ApiConnectionMonitor;\n private defaultOptions: BaseApiClientOptions;\n\n constructor(\n baseUrl: string,\n errorReporter: ErrorReporter,\n logger: Logger,\n options: BaseApiClientOptions = {}\n ) {\n this.baseUrl = baseUrl;\n this.errorReporter = errorReporter;\n this.logger = logger;\n this.retryHandler = new RetryHandler(options.retryConfig || DEFAULT_RETRY_CONFIG);\n this.circuitBreakerRegistry = CircuitBreakerRegistry.getInstance();\n this.connectionMonitor = ApiConnectionMonitor.getInstance();\n this.defaultOptions = {\n timeout: options.timeout || 30000,\n retry: options.retry !== false,\n retryConfig: options.retryConfig || DEFAULT_RETRY_CONFIG,\n };\n\n // Start monitoring connection health\n this.connectionMonitor.startMonitoring();\n }\n\n /**\n * Classify HTTP status code into error type\n */\n private classifyError(status: number): ApiErrorType {\n if (status >= 500) return 'SERVER_ERROR';\n if (status === 429) return 'RATE_LIMIT_ERROR';\n if (status === 401 || status === 403) return 'AUTH_ERROR';\n if (status === 400) return 'VALIDATION_ERROR';\n if (status === 404) return 'NOT_FOUND';\n return 'UNKNOWN_ERROR';\n }\n\n /**\n * Create an ApiError from fetch response\n */\n private async createApiError(\n response: Response,\n method: string,\n path: string,\n retryCount: number = 0\n ): Promise {\n const status = response.status;\n const errorType = this.classifyError(status);\n \n let message = response.statusText;\n let responseText = '';\n\n try {\n responseText = await response.text();\n if (responseText) {\n const errorData = JSON.parse(responseText);\n if (errorData.message) {\n message = errorData.message;\n }\n }\n } catch {\n // Keep default message\n }\n\n return new ApiError(\n message,\n errorType,\n {\n endpoint: path,\n method,\n statusCode: status,\n responseText,\n timestamp: new Date().toISOString(),\n retryCount,\n }\n );\n }\n\n /**\n * Create an ApiError from network/timeout errors\n */\n private createNetworkError(\n error: Error,\n method: string,\n path: string,\n retryCount: number = 0\n ): ApiError {\n let errorType: ApiErrorType = 'NETWORK_ERROR';\n let message = error.message;\n\n // More specific error classification\n if (error.name === 'AbortError') {\n errorType = 'CANCELED_ERROR';\n message = 'Request was canceled';\n } else if (error.name === 'TypeError' && error.message.includes('fetch')) {\n errorType = 'NETWORK_ERROR';\n // Check for CORS specifically\n if (error.message.includes('Failed to fetch') || error.message.includes('fetch failed')) {\n message = 'Unable to connect to server. Possible CORS or network issue.';\n }\n } else if (error.message.includes('timeout') || error.message.includes('timed out')) {\n errorType = 'TIMEOUT_ERROR';\n message = 'Request timed out after 30 seconds';\n } else if (error.message.includes('Failed to fetch') || error.message.includes('NetworkError')) {\n errorType = 'NETWORK_ERROR';\n // This could be CORS, network down, or server not responding\n message = 'Network error: Unable to reach the API server';\n }\n\n return new ApiError(\n message,\n errorType,\n {\n endpoint: path,\n method,\n timestamp: new Date().toISOString(),\n retryCount,\n // Add helpful context for developers\n troubleshooting: this.getTroubleshootingContext(error, path),\n isRetryable: this.isRetryableError(errorType),\n isConnectivity: errorType === 'NETWORK_ERROR' || errorType === 'TIMEOUT_ERROR',\n developerHint: this.getDeveloperHint(error, path, method),\n },\n error\n );\n }\n\n /**\n * Check if error type is retryable\n */\n private isRetryableError(errorType: ApiErrorType): boolean {\n const retryableTypes: ApiErrorType[] = [\n 'NETWORK_ERROR',\n 'SERVER_ERROR',\n 'RATE_LIMIT_ERROR',\n 'TIMEOUT_ERROR',\n ];\n return retryableTypes.includes(errorType);\n }\n\n /**\n * Get developer-friendly hint for troubleshooting\n */\n private getDeveloperHint(error: Error, path: string, method: string): string {\n if (error.message.includes('fetch failed') || error.message.includes('Failed to fetch')) {\n return 'Check if API server is running and CORS is configured correctly';\n }\n if (error.message.includes('timeout')) {\n return 'Request timed out - consider increasing timeout or checking network';\n }\n if (error.message.includes('ECONNREFUSED')) {\n return 'Connection refused - verify API server address and port';\n }\n return 'Review network connection and API endpoint configuration';\n }\n\n /**\n * Get troubleshooting context for network errors\n */\n private getTroubleshootingContext(error: Error, path: string): string {\n if (typeof window !== 'undefined') {\n const baseUrl = this.baseUrl;\n const currentOrigin = window.location.origin;\n \n // Check if it's likely a CORS issue\n if (baseUrl && !baseUrl.includes(currentOrigin) && error.message.includes('Failed to fetch')) {\n return 'CORS issue likely. Check API server CORS configuration.';\n }\n \n // Check if API server is same origin\n if (baseUrl.includes(currentOrigin) || baseUrl.startsWith('/')) {\n return 'Same-origin request. Check if API server is running.';\n }\n }\n \n return 'Check network connection and API server status.';\n }\n\n protected async request(\n method: string,\n path: string,\n data?: object | FormData,\n options: BaseApiClientOptions & { allowUnauthenticated?: boolean } = {},\n ): Promise {\n const finalOptions = { ...this.defaultOptions, ...options };\n const endpoint = `${this.baseUrl}${path}`;\n\n // Check circuit breaker\n const circuitBreaker = this.circuitBreakerRegistry.getBreaker(path);\n if (!circuitBreaker.canExecute()) {\n const error = new ApiError(\n 'Circuit breaker is open - service temporarily unavailable',\n 'SERVER_ERROR',\n {\n endpoint: path,\n method,\n timestamp: new Date().toISOString(),\n }\n );\n this.handleError(error);\n throw error;\n }\n\n const executeRequest = async (signal: AbortSignal): Promise => {\n const isFormData = typeof FormData !== 'undefined' && data instanceof FormData;\n const headers: HeadersInit = isFormData\n ? {}\n : {\n 'Content-Type': 'application/json',\n };\n\n const config: RequestInit = {\n method,\n headers,\n credentials: 'include',\n signal,\n };\n\n if (data) {\n config.body = isFormData ? data : JSON.stringify(data);\n }\n\n const startTime = Date.now();\n let requestId: string | undefined;\n\n // Log request start (only in development for maximum transparency)\n if (process.env.NODE_ENV === 'development') {\n try {\n const apiLogger = getGlobalApiLogger();\n const headerObj: Record = {};\n if (typeof headers === 'object') {\n Object.entries(headers).forEach(([key, value]) => {\n headerObj[key] = value;\n });\n }\n requestId = apiLogger.logRequest(\n endpoint,\n method,\n headerObj,\n data\n );\n } catch (e) {\n // Silent fail - logger might not be initialized\n }\n }\n\n try {\n const response = await fetch(endpoint, config);\n const responseTime = Date.now() - startTime;\n\n // Record success for monitoring\n this.connectionMonitor.recordSuccess(responseTime);\n\n if (!response.ok) {\n if (\n finalOptions.allowUnauthenticated &&\n (response.status === 401 || response.status === 403)\n ) {\n // For auth probe endpoints, 401/403 is expected\n return null as T;\n }\n\n const error = await this.createApiError(response, method, path);\n circuitBreaker.recordFailure();\n this.connectionMonitor.recordFailure(error);\n this.handleError(error);\n\n // Log error\n if (process.env.NODE_ENV === 'development' && requestId) {\n try {\n const apiLogger = getGlobalApiLogger();\n apiLogger.logError(requestId, error, responseTime);\n } catch (e) {\n // Silent fail\n }\n }\n\n throw error;\n }\n\n // Record successful circuit breaker call\n circuitBreaker.recordSuccess();\n\n const text = await response.text();\n if (!text) {\n // Log empty response\n if (process.env.NODE_ENV === 'development' && requestId) {\n try {\n const apiLogger = getGlobalApiLogger();\n apiLogger.logResponse(requestId, response, null, responseTime);\n } catch (e) {\n // Silent fail\n }\n }\n return null as T;\n }\n\n const parsedData = JSON.parse(text) as T;\n\n // Log successful response\n if (process.env.NODE_ENV === 'development' && requestId) {\n try {\n const apiLogger = getGlobalApiLogger();\n apiLogger.logResponse(requestId, response, parsedData, responseTime);\n } catch (e) {\n // Silent fail\n }\n }\n\n return parsedData;\n\n } catch (error) {\n const responseTime = Date.now() - startTime;\n\n if (error instanceof ApiError) {\n throw error;\n }\n\n // Convert to ApiError\n const apiError = this.createNetworkError(error as Error, method, path);\n \n circuitBreaker.recordFailure();\n this.connectionMonitor.recordFailure(apiError);\n this.handleError(apiError);\n\n // Log network error\n if (process.env.NODE_ENV === 'development' && requestId) {\n try {\n const apiLogger = getGlobalApiLogger();\n apiLogger.logError(requestId, apiError, responseTime);\n } catch (e) {\n // Silent fail\n }\n }\n \n throw apiError;\n }\n };\n\n // Wrap with retry logic if enabled\n if (finalOptions.retry) {\n try {\n return await this.retryHandler.execute(executeRequest);\n } catch (error) {\n // If retry exhausted, throw the final error\n throw error;\n }\n } else {\n // No retry, just execute with timeout\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), finalOptions.timeout);\n\n try {\n return await executeRequest(controller.signal);\n } finally {\n clearTimeout(timeoutId);\n }\n }\n }\n\n /**\n * Handle errors - log and report\n */\n private handleError(error: ApiError): void {\n const severity = error.getSeverity();\n const message = error.getDeveloperMessage();\n\n // Enhanced context for better debugging\n const enhancedContext = {\n ...error.context,\n severity,\n isRetryable: error.isRetryable(),\n isConnectivity: error.isConnectivityIssue(),\n };\n\n // Use appropriate log level\n if (severity === 'error') {\n this.logger.error(message, error, enhancedContext);\n } else if (severity === 'warn') {\n this.logger.warn(message, enhancedContext);\n } else {\n this.logger.info(message, enhancedContext);\n }\n\n // Report to error tracking\n this.errorReporter.report(error, enhancedContext);\n }\n\n protected get(path: string, options?: BaseApiClientOptions): Promise {\n return this.request('GET', path, undefined, options);\n }\n\n protected post(path: string, data: object, options?: BaseApiClientOptions): Promise {\n return this.request('POST', path, data, options);\n }\n\n protected put(path: string, data: object, options?: BaseApiClientOptions): Promise {\n return this.request('PUT', path, data, options);\n }\n\n protected delete(path: string, options?: BaseApiClientOptions): Promise {\n return this.request('DELETE', path, undefined, options);\n }\n\n protected patch(path: string, data: object, options?: BaseApiClientOptions): Promise {\n return this.request('PATCH', path, data, options);\n }\n\n /**\n * Get current connection health status\n */\n getConnectionStatus() {\n return {\n status: this.connectionMonitor.getStatus(),\n health: this.connectionMonitor.getHealth(),\n isAvailable: this.connectionMonitor.isAvailable(),\n reliability: this.connectionMonitor.getReliability(),\n };\n }\n\n /**\n * Force a health check\n */\n async checkHealth() {\n return this.connectionMonitor.performHealthCheck();\n }\n\n /**\n * Get circuit breaker status for debugging\n */\n getCircuitBreakerStatus() {\n return this.circuitBreakerRegistry.getStatus();\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/api/base/GracefulDegradation.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":40,"column":46,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":40,"endColumn":49,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[748,751],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[748,751],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Graceful degradation utilities for when API is unavailable\n */\n\nimport { ApiConnectionMonitor } from './ApiConnectionMonitor';\nimport { ApiError } from './ApiError';\n\nexport interface DegradationOptions {\n /**\n * Fallback data to return when API is unavailable\n */\n fallback?: T;\n \n /**\n * Whether to throw error or return fallback\n */\n throwOnError?: boolean;\n \n /**\n * Maximum time to wait for API response\n */\n timeout?: number;\n \n /**\n * Whether to use cached data if available\n */\n useCache?: boolean;\n}\n\nexport interface CacheEntry {\n data: T;\n timestamp: Date;\n expiry: Date;\n}\n\n/**\n * Simple in-memory cache for API responses\n */\nclass ResponseCache {\n private cache = new Map>();\n\n /**\n * Get cached data if not expired\n */\n get(key: string): T | null {\n const entry = this.cache.get(key);\n if (!entry) return null;\n\n if (new Date() > entry.expiry) {\n this.cache.delete(key);\n return null;\n }\n\n return entry.data;\n }\n\n /**\n * Set cached data with expiry\n */\n set(key: string, data: T, ttlMs: number = 300000): void {\n const now = new Date();\n const expiry = new Date(now.getTime() + ttlMs);\n \n this.cache.set(key, {\n data,\n timestamp: now,\n expiry,\n });\n }\n\n /**\n * Clear all cached data\n */\n clear(): void {\n this.cache.clear();\n }\n\n /**\n * Get cache statistics\n */\n getStats() {\n return {\n size: this.cache.size,\n entries: Array.from(this.cache.entries()).map(([key, entry]) => ({\n key,\n timestamp: entry.timestamp,\n expiry: entry.expiry,\n })),\n };\n }\n}\n\n/**\n * Global cache instance\n */\nexport const responseCache = new ResponseCache();\n\n/**\n * Execute a function with graceful degradation\n */\nexport async function withGracefulDegradation(\n fn: () => Promise,\n options: DegradationOptions = {}\n): Promise {\n const {\n fallback,\n throwOnError = false,\n timeout = 10000,\n useCache = true,\n } = options;\n\n const monitor = ApiConnectionMonitor.getInstance();\n\n // Check if API is available\n if (!monitor.isAvailable()) {\n // Try cache first\n if (useCache && options.fallback) {\n const cacheKey = `graceful:${fn.toString()}`;\n const cached = responseCache.get(cacheKey);\n if (cached) {\n return cached;\n }\n }\n\n // Return fallback\n if (fallback !== undefined) {\n return fallback;\n }\n\n // Throw error if no fallback\n if (throwOnError) {\n throw new ApiError(\n 'API unavailable and no fallback provided',\n 'NETWORK_ERROR',\n {\n timestamp: new Date().toISOString(),\n }\n );\n }\n\n // Return undefined (caller must handle)\n return undefined;\n }\n\n // API is available, try to execute\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n const result = await Promise.race([\n fn(),\n new Promise((_, reject) => {\n controller.signal.addEventListener('abort', () => {\n reject(new Error('Request timeout'));\n });\n }),\n ]);\n\n clearTimeout(timeoutId);\n\n // Cache the result if enabled\n if (useCache && result !== null && result !== undefined) {\n const cacheKey = `graceful:${fn.toString()}`;\n responseCache.set(cacheKey, result);\n }\n\n return result;\n\n } catch (error) {\n // Record failure in monitor\n if (error instanceof ApiError) {\n monitor.recordFailure(error);\n } else {\n monitor.recordFailure(error as Error);\n }\n\n // Try cache as fallback\n if (useCache && options.fallback) {\n const cacheKey = `graceful:${fn.toString()}`;\n const cached = responseCache.get(cacheKey);\n if (cached) {\n return cached;\n }\n }\n\n // Return fallback if provided\n if (fallback !== undefined) {\n return fallback;\n }\n\n // Re-throw or return undefined\n if (throwOnError) {\n throw error;\n }\n\n return undefined;\n }\n}\n\n/**\n * Service wrapper for graceful degradation\n */\nexport class GracefulService {\n private monitor: ApiConnectionMonitor;\n private cacheKey: string;\n\n constructor(\n private serviceName: string,\n private getData: () => Promise,\n private defaultFallback: T\n ) {\n this.monitor = ApiConnectionMonitor.getInstance();\n this.cacheKey = `service:${serviceName}`;\n }\n\n /**\n * Get data with graceful degradation\n */\n async get(options: Partial> = {}): Promise {\n const result = await withGracefulDegradation(this.getData, {\n fallback: this.defaultFallback,\n throwOnError: false,\n useCache: true,\n ...options,\n });\n\n return result ?? this.defaultFallback;\n }\n\n /**\n * Force refresh data\n */\n async refresh(): Promise {\n responseCache.clear(); // Clear cache for this service\n return this.get({ useCache: false });\n }\n\n /**\n * Get service health status\n */\n getStatus() {\n const health = this.monitor.getHealth();\n const isAvailable = this.monitor.isAvailable();\n \n return {\n serviceName: this.serviceName,\n available: isAvailable,\n reliability: health.totalRequests > 0 \n ? (health.successfulRequests / health.totalRequests) * 100 \n : 100,\n lastCheck: health.lastCheck,\n };\n }\n}\n\n/**\n * Offline mode detection\n */\nexport class OfflineDetector {\n private static instance: OfflineDetector;\n private isOffline = false;\n private listeners: Array<(isOffline: boolean) => void> = [];\n\n private constructor() {\n if (typeof window !== 'undefined') {\n window.addEventListener('online', () => this.setOffline(false));\n window.addEventListener('offline', () => this.setOffline(true));\n \n // Initial check\n this.isOffline = !navigator.onLine;\n }\n }\n\n static getInstance(): OfflineDetector {\n if (!OfflineDetector.instance) {\n OfflineDetector.instance = new OfflineDetector();\n }\n return OfflineDetector.instance;\n }\n\n private setOffline(offline: boolean): void {\n if (this.isOffline !== offline) {\n this.isOffline = offline;\n this.listeners.forEach(listener => listener(offline));\n }\n }\n\n /**\n * Check if browser is offline\n */\n isBrowserOffline(): boolean {\n return this.isOffline;\n }\n\n /**\n * Add listener for offline status changes\n */\n onStatusChange(callback: (isOffline: boolean) => void): void {\n this.listeners.push(callback);\n }\n\n /**\n * Remove listener\n */\n removeListener(callback: (isOffline: boolean) => void): void {\n this.listeners = this.listeners.filter(cb => cb !== callback);\n }\n}\n\n/**\n * Hook for offline detection\n */\nexport function useOfflineStatus() {\n if (typeof window === 'undefined') {\n return false; // Server-side\n }\n\n // This would need to be used in a React component context\n // For now, provide a simple check function\n return OfflineDetector.getInstance().isBrowserOffline();\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/api/base/RetryHandler.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'ApiErrorType' is defined but never used.","line":5,"column":20,"nodeType":"Identifier","messageId":"unusedVar","endLine":5,"endColumn":32}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Retry logic and circuit breaker for API requests\n */\n\nimport { ApiError, ApiErrorType } from './ApiError';\n\nexport interface RetryConfig {\n maxRetries: number;\n baseDelay: number; // milliseconds\n maxDelay: number; // milliseconds\n backoffMultiplier: number;\n timeout: number; // milliseconds\n}\n\nexport const DEFAULT_RETRY_CONFIG: RetryConfig = {\n maxRetries: 3,\n baseDelay: 1000,\n maxDelay: 10000,\n backoffMultiplier: 2,\n timeout: 30000,\n};\n\nexport interface CircuitBreakerConfig {\n failureThreshold: number;\n successThreshold: number;\n timeout: number; // milliseconds before trying again\n}\n\nexport const DEFAULT_CIRCUIT_BREAKER_CONFIG: CircuitBreakerConfig = {\n failureThreshold: 5,\n successThreshold: 3,\n timeout: 60000, // 1 minute\n};\n\nexport class CircuitBreaker {\n private failures = 0;\n private successes = 0;\n private state: 'CLOSED' | 'OPEN' | 'HALF_OPEN' = 'CLOSED';\n private lastFailureTime: number | null = null;\n private readonly config: CircuitBreakerConfig;\n\n constructor(config: CircuitBreakerConfig = DEFAULT_CIRCUIT_BREAKER_CONFIG) {\n this.config = config;\n }\n\n /**\n * Check if request should proceed\n */\n canExecute(): boolean {\n if (this.state === 'CLOSED') {\n return true;\n }\n\n if (this.state === 'OPEN') {\n const now = Date.now();\n if (this.lastFailureTime && now - this.lastFailureTime > this.config.timeout) {\n this.state = 'HALF_OPEN';\n return true;\n }\n return false;\n }\n\n // HALF_OPEN - allow one request to test if service recovered\n return true;\n }\n\n /**\n * Record a successful request\n */\n recordSuccess(): void {\n if (this.state === 'HALF_OPEN') {\n this.successes++;\n if (this.successes >= this.config.successThreshold) {\n this.reset();\n }\n } else if (this.state === 'CLOSED') {\n // Keep failures in check\n this.failures = Math.max(0, this.failures - 1);\n }\n }\n\n /**\n * Record a failed request\n */\n recordFailure(): void {\n this.failures++;\n this.lastFailureTime = Date.now();\n\n if (this.state === 'HALF_OPEN') {\n this.state = 'OPEN';\n this.successes = 0;\n } else if (this.state === 'CLOSED' && this.failures >= this.config.failureThreshold) {\n this.state = 'OPEN';\n }\n }\n\n /**\n * Get current state\n */\n getState(): string {\n return this.state;\n }\n\n /**\n * Get failure count\n */\n getFailures(): number {\n return this.failures;\n }\n\n /**\n * Reset the circuit breaker\n */\n reset(): void {\n this.failures = 0;\n this.successes = 0;\n this.state = 'CLOSED';\n this.lastFailureTime = null;\n }\n}\n\nexport class RetryHandler {\n private config: RetryConfig;\n private abortController: AbortController | null = null;\n\n constructor(config: RetryConfig = DEFAULT_RETRY_CONFIG) {\n this.config = config;\n }\n\n /**\n * Execute a function with retry logic\n */\n async execute(\n fn: (signal: AbortSignal) => Promise,\n isRetryable?: (error: ApiError) => boolean\n ): Promise {\n this.abortController = new AbortController();\n const signal = this.abortController.signal;\n\n let lastError: Error | null = null;\n \n for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {\n try {\n // Check if already aborted\n if (signal.aborted) {\n throw new Error('Request aborted');\n }\n\n const result = await fn(signal);\n return result;\n } catch (error) {\n lastError = error as Error;\n\n // Check if we should abort\n if (signal.aborted) {\n throw error;\n }\n\n // Check if this is the last attempt\n if (attempt === this.config.maxRetries) {\n break;\n }\n\n // Check if error is retryable\n if (error instanceof ApiError) {\n if (!error.isRetryable()) {\n throw error;\n }\n if (isRetryable && !isRetryable(error)) {\n throw error;\n }\n }\n\n // Calculate delay with exponential backoff\n const delay = this.calculateDelay(attempt);\n \n // Wait before retrying\n await this.sleep(delay, signal);\n }\n }\n\n // All retries exhausted\n throw lastError;\n }\n\n /**\n * Cancel the current request\n */\n abort(): void {\n if (this.abortController) {\n this.abortController.abort();\n }\n }\n\n /**\n * Calculate delay for retry attempt\n */\n private calculateDelay(attempt: number): number {\n const delay = Math.min(\n this.config.baseDelay * Math.pow(this.config.backoffMultiplier, attempt),\n this.config.maxDelay\n );\n // Add jitter to prevent thundering herd\n const jitter = Math.random() * 0.3 * delay;\n return delay + jitter;\n }\n\n /**\n * Sleep with abort support\n */\n private sleep(ms: number, signal: AbortSignal): Promise {\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n signal.removeEventListener('abort', abortHandler);\n resolve();\n }, ms);\n\n const abortHandler = () => {\n clearTimeout(timeout);\n signal.removeEventListener('abort', abortHandler);\n reject(new Error('Request aborted during retry delay'));\n };\n\n signal.addEventListener('abort', abortHandler, { once: true });\n });\n }\n}\n\n/**\n * Global circuit breaker registry for different API endpoints\n */\nexport class CircuitBreakerRegistry {\n private static instance: CircuitBreakerRegistry;\n private breakers: Map = new Map();\n\n private constructor() {}\n\n static getInstance(): CircuitBreakerRegistry {\n if (!CircuitBreakerRegistry.instance) {\n CircuitBreakerRegistry.instance = new CircuitBreakerRegistry();\n }\n return CircuitBreakerRegistry.instance;\n }\n\n /**\n * Get or create circuit breaker for a specific endpoint\n */\n getBreaker(endpoint: string, config?: CircuitBreakerConfig): CircuitBreaker {\n if (!this.breakers.has(endpoint)) {\n this.breakers.set(endpoint, new CircuitBreaker(config));\n }\n return this.breakers.get(endpoint)!;\n }\n\n /**\n * Reset all circuit breakers\n */\n resetAll(): void {\n this.breakers.forEach(breaker => breaker.reset());\n }\n\n /**\n * Get status of all circuit breakers\n */\n getStatus(): Record {\n const status: Record = {};\n this.breakers.forEach((breaker, endpoint) => {\n status[endpoint] = {\n state: breaker.getState(),\n failures: breaker.getFailures(),\n };\n });\n return status;\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/api/dashboard/DashboardApiClient.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/api/drivers/DriversApiClient.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/api/index.ts","messages":[{"ruleId":"gridpilot-rules/no-index-files","severity":2,"message":"Index files are banned. Use explicit imports and barrel exports. Example: Instead of \"import { foo } from \"./\", use \"import { foo } from \"./foo\" and export from \"./foo\" explicitly.","line":1,"column":1,"nodeType":null,"messageId":"indexFile"}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { LeaguesApiClient } from './leagues/LeaguesApiClient';\nimport { RacesApiClient } from './races/RacesApiClient';\nimport { DriversApiClient } from './drivers/DriversApiClient';\nimport { TeamsApiClient } from './teams/TeamsApiClient';\nimport { SponsorsApiClient } from './sponsors/SponsorsApiClient';\nimport { MediaApiClient } from './media/MediaApiClient';\nimport { AnalyticsApiClient } from './analytics/AnalyticsApiClient';\nimport { AuthApiClient } from './auth/AuthApiClient';\nimport { PaymentsApiClient } from './payments/PaymentsApiClient';\nimport { DashboardApiClient } from './dashboard/DashboardApiClient';\nimport { PenaltiesApiClient } from './penalties/PenaltiesApiClient';\nimport { ProtestsApiClient } from './protests/ProtestsApiClient';\nimport { AdminApiClient } from './admin/AdminApiClient';\nimport { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';\nimport { EnhancedErrorReporter } from '@/lib/infrastructure/EnhancedErrorReporter';\n\n/**\n * Main API Client\n *\n * Orchestrates all domain-specific API clients with consistent configuration.\n */\nexport class ApiClient {\n public readonly leagues: LeaguesApiClient;\n public readonly races: RacesApiClient;\n public readonly drivers: DriversApiClient;\n public readonly teams: TeamsApiClient;\n public readonly sponsors: SponsorsApiClient;\n public readonly media: MediaApiClient;\n public readonly analytics: AnalyticsApiClient;\n public readonly auth: AuthApiClient;\n public readonly payments: PaymentsApiClient;\n public readonly dashboard: DashboardApiClient;\n public readonly penalties: PenaltiesApiClient;\n public readonly protests: ProtestsApiClient;\n public readonly admin: AdminApiClient;\n\n constructor(baseUrl: string) {\n const logger = new ConsoleLogger();\n const errorReporter = new EnhancedErrorReporter(logger, {\n showUserNotifications: true,\n logToConsole: true,\n reportToExternal: process.env.NODE_ENV === 'production',\n });\n\n this.leagues = new LeaguesApiClient(baseUrl, errorReporter, logger);\n this.races = new RacesApiClient(baseUrl, errorReporter, logger);\n this.drivers = new DriversApiClient(baseUrl, errorReporter, logger);\n this.teams = new TeamsApiClient(baseUrl, errorReporter, logger);\n this.sponsors = new SponsorsApiClient(baseUrl, errorReporter, logger);\n this.media = new MediaApiClient(baseUrl, errorReporter, logger);\n this.analytics = new AnalyticsApiClient(baseUrl, errorReporter, logger);\n this.auth = new AuthApiClient(baseUrl, errorReporter, logger);\n this.payments = new PaymentsApiClient(baseUrl, errorReporter, logger);\n this.dashboard = new DashboardApiClient(baseUrl, errorReporter, logger);\n this.penalties = new PenaltiesApiClient(baseUrl, errorReporter, logger);\n this.protests = new ProtestsApiClient(baseUrl, errorReporter, logger);\n this.admin = new AdminApiClient(baseUrl, errorReporter, logger);\n }\n}\n\n// ============================================================================\n// Singleton Instance\n// ============================================================================\n\nconst API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:3001';\n\nexport const api = new ApiClient(API_BASE_URL);","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/api/leagues/LeaguesApiClient.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_example' is assigned a value but never used.","line":137,"column":22,"nodeType":"Identifier","messageId":"unusedVar","endLine":137,"endColumn":30},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_example' is assigned a value but never used.","line":148,"column":22,"nodeType":"Identifier","messageId":"unusedVar","endLine":148,"endColumn":30}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { BaseApiClient } from '../base/BaseApiClient';\nimport type { AllLeaguesWithCapacityDTO } from '../../types/generated/AllLeaguesWithCapacityDTO';\nimport type { TotalLeaguesDTO } from '../../types/generated/TotalLeaguesDTO';\nimport type { LeagueStandingsDTO } from '../../types/generated/LeagueStandingsDTO';\nimport type { LeagueScheduleDTO } from '../../types/generated/LeagueScheduleDTO';\nimport type { LeagueMembershipsDTO } from '../../types/generated/LeagueMembershipsDTO';\nimport type { CreateLeagueInputDTO } from '../../types/generated/CreateLeagueInputDTO';\nimport type { CreateLeagueOutputDTO } from '../../types/generated/CreateLeagueOutputDTO';\nimport type { SponsorshipDetailDTO } from '../../types/generated/SponsorshipDetailDTO';\nimport type { RaceDTO } from '../../types/generated/RaceDTO';\nimport type { GetLeagueAdminConfigOutputDTO } from '../../types/generated/GetLeagueAdminConfigOutputDTO';\nimport type { LeagueScoringPresetDTO } from '../../types/generated/LeagueScoringPresetDTO';\nimport type { LeagueSeasonSummaryDTO } from '../../types/generated/LeagueSeasonSummaryDTO';\nimport type { CreateLeagueScheduleRaceInputDTO } from '../../types/generated/CreateLeagueScheduleRaceInputDTO';\nimport type { CreateLeagueScheduleRaceOutputDTO } from '../../types/generated/CreateLeagueScheduleRaceOutputDTO';\nimport type { UpdateLeagueScheduleRaceInputDTO } from '../../types/generated/UpdateLeagueScheduleRaceInputDTO';\nimport type { LeagueScheduleRaceMutationSuccessDTO } from '../../types/generated/LeagueScheduleRaceMutationSuccessDTO';\nimport type { LeagueSeasonSchedulePublishOutputDTO } from '../../types/generated/LeagueSeasonSchedulePublishOutputDTO';\nimport type { LeagueRosterMemberDTO } from '../../types/generated/LeagueRosterMemberDTO';\nimport type { LeagueRosterJoinRequestDTO } from '../../types/generated/LeagueRosterJoinRequestDTO';\nimport type { ApproveJoinRequestOutputDTO } from '../../types/generated/ApproveJoinRequestOutputDTO';\nimport type { RejectJoinRequestOutputDTO } from '../../types/generated/RejectJoinRequestOutputDTO';\nimport type { UpdateLeagueMemberRoleOutputDTO } from '../../types/generated/UpdateLeagueMemberRoleOutputDTO';\nimport type { RemoveLeagueMemberOutputDTO } from '../../types/generated/RemoveLeagueMemberOutputDTO';\nimport type { AllLeaguesWithCapacityAndScoringDTO } from '../../types/AllLeaguesWithCapacityAndScoringDTO';\n\nfunction isRecord(value: unknown): value is Record {\n return typeof value === 'object' && value !== null;\n}\n\nfunction isRaceDTO(value: unknown): value is RaceDTO {\n if (!isRecord(value)) return false;\n return typeof value.id === 'string' && typeof value.name === 'string' && typeof value.date === 'string';\n}\n\nfunction parseRaceDTOArray(value: unknown): RaceDTO[] {\n if (!Array.isArray(value)) return [];\n return value.filter(isRaceDTO);\n}\n\n/**\n * Leagues API Client\n *\n * Handles all league-related API operations.\n */\nexport class LeaguesApiClient extends BaseApiClient {\n /** Get all leagues with capacity information */\n getAllWithCapacity(): Promise {\n return this.get('/leagues/all-with-capacity');\n }\n\n /** Get all leagues with capacity + scoring summary (for leagues page filters) */\n getAllWithCapacityAndScoring(): Promise {\n return this.get('/leagues/all-with-capacity-and-scoring');\n }\n\n /** Get total number of leagues */\n getTotal(): Promise {\n return this.get('/leagues/total-leagues');\n }\n\n /** Get league standings */\n getStandings(leagueId: string): Promise {\n return this.get(`/leagues/${leagueId}/standings`);\n }\n\n /** Get league schedule */\n getSchedule(leagueId: string, seasonId?: string): Promise {\n const qs = seasonId ? `?seasonId=${encodeURIComponent(seasonId)}` : '';\n return this.get(`/leagues/${leagueId}/schedule${qs}`);\n }\n\n /** Get league memberships */\n getMemberships(leagueId: string): Promise {\n return this.get(`/leagues/${leagueId}/memberships`);\n }\n\n /** Create a new league */\n create(input: CreateLeagueInputDTO): Promise {\n return this.post('/leagues', input);\n }\n\n /** Remove a member from league */\n removeMember(leagueId: string, performerDriverId: string, targetDriverId: string): Promise<{ success: boolean }> {\n return this.patch<{ success: boolean }>(`/leagues/${leagueId}/members/${targetDriverId}/remove`, { performerDriverId });\n }\n\n /** Update a member's role in league */\n updateMemberRole(leagueId: string, performerDriverId: string, targetDriverId: string, newRole: string): Promise<{ success: boolean }> {\n return this.patch<{ success: boolean }>(`/leagues/${leagueId}/members/${targetDriverId}/role`, { performerDriverId, newRole });\n }\n\n /** Get league seasons */\n getSeasons(leagueId: string): Promise {\n return this.get(`/leagues/${leagueId}/seasons`);\n }\n\n /** Get season sponsorships */\n getSeasonSponsorships(seasonId: string): Promise<{ sponsorships: SponsorshipDetailDTO[] }> {\n return this.get<{ sponsorships: SponsorshipDetailDTO[] }>(`/leagues/seasons/${seasonId}/sponsorships`);\n }\n\n /** Get league config */\n getLeagueConfig(leagueId: string): Promise {\n return this.get(`/leagues/${leagueId}/config`);\n }\n\n /** Get league scoring presets */\n getScoringPresets(): Promise<{ presets: LeagueScoringPresetDTO[] }> {\n return this.get<{ presets: LeagueScoringPresetDTO[] }>(`/leagues/scoring-presets`);\n }\n\n /** Transfer league ownership */\n transferOwnership(leagueId: string, currentOwnerId: string, newOwnerId: string): Promise<{ success: boolean }> {\n return this.post<{ success: boolean }>(`/leagues/${leagueId}/transfer-ownership`, {\n currentOwnerId,\n newOwnerId,\n });\n }\n\n /** Publish a league season schedule (admin/owner only; actor derived from session) */\n publishSeasonSchedule(leagueId: string, seasonId: string): Promise {\n return this.post(`/leagues/${leagueId}/seasons/${seasonId}/schedule/publish`, {});\n }\n\n /** Unpublish a league season schedule (admin/owner only; actor derived from session) */\n unpublishSeasonSchedule(leagueId: string, seasonId: string): Promise {\n return this.post(`/leagues/${leagueId}/seasons/${seasonId}/schedule/unpublish`, {});\n }\n\n /** Create a schedule race for a league season (admin/owner only; actor derived from session) */\n createSeasonScheduleRace(\n leagueId: string,\n seasonId: string,\n input: CreateLeagueScheduleRaceInputDTO,\n ): Promise {\n const { example: _example, ...payload } = input;\n return this.post(`/leagues/${leagueId}/seasons/${seasonId}/schedule/races`, payload);\n }\n\n /** Update a schedule race for a league season (admin/owner only; actor derived from session) */\n updateSeasonScheduleRace(\n leagueId: string,\n seasonId: string,\n raceId: string,\n input: UpdateLeagueScheduleRaceInputDTO,\n ): Promise {\n const { example: _example, ...payload } = input;\n return this.patch(`/leagues/${leagueId}/seasons/${seasonId}/schedule/races/${raceId}`, payload);\n }\n\n /** Delete a schedule race for a league season (admin/owner only; actor derived from session) */\n deleteSeasonScheduleRace(\n leagueId: string,\n seasonId: string,\n raceId: string,\n ): Promise {\n return this.delete(`/leagues/${leagueId}/seasons/${seasonId}/schedule/races/${raceId}`);\n }\n\n /** Get races for a league */\n async getRaces(leagueId: string): Promise<{ races: RaceDTO[] }> {\n const response = await this.get<{ races?: unknown }>(`/leagues/${leagueId}/races`);\n return { races: parseRaceDTOArray(response?.races) };\n }\n\n /** Admin roster: list current members (admin/owner only; actor derived from session) */\n getAdminRosterMembers(leagueId: string): Promise {\n return this.get(`/leagues/${leagueId}/admin/roster/members`);\n }\n\n /** Admin roster: list pending join requests (admin/owner only; actor derived from session) */\n getAdminRosterJoinRequests(leagueId: string): Promise {\n return this.get(`/leagues/${leagueId}/admin/roster/join-requests`);\n }\n\n /** Admin roster: approve a join request (admin/owner only; actor derived from session) */\n approveRosterJoinRequest(leagueId: string, joinRequestId: string): Promise {\n return this.post(`/leagues/${leagueId}/admin/roster/join-requests/${joinRequestId}/approve`, {});\n }\n\n /** Admin roster: reject a join request (admin/owner only; actor derived from session) */\n rejectRosterJoinRequest(leagueId: string, joinRequestId: string): Promise {\n return this.post(`/leagues/${leagueId}/admin/roster/join-requests/${joinRequestId}/reject`, {});\n }\n\n /** Admin roster: update member role (admin/owner only; actor derived from session) */\n updateRosterMemberRole(leagueId: string, targetDriverId: string, newRole: string): Promise {\n return this.patch(`/leagues/${leagueId}/admin/roster/members/${targetDriverId}/role`, { newRole });\n }\n\n /** Admin roster: remove member (admin/owner only; actor derived from session) */\n removeRosterMember(leagueId: string, targetDriverId: string): Promise {\n return this.patch(`/leagues/${leagueId}/admin/roster/members/${targetDriverId}/remove`, {});\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/api/media/MediaApiClient.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/api/payments/PaymentsApiClient.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'GetWalletTransactionsOutputDto' is defined but never used.","line":49,"column":6,"nodeType":"Identifier","messageId":"unusedVar","endLine":49,"endColumn":36},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'DeletePrizeInputDto' is defined but never used.","line":73,"column":6,"nodeType":"Identifier","messageId":"unusedVar","endLine":73,"endColumn":25}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { BaseApiClient } from '../base/BaseApiClient';\nimport type { MembershipFeeDTO } from '../../types/generated/MembershipFeeDTO';\nimport type { MemberPaymentDTO } from '../../types/generated/MemberPaymentDTO';\nimport type { PaymentDTO } from '../../types/generated/PaymentDTO';\nimport type { PrizeDTO } from '../../types/generated/PrizeDTO';\nimport type { TransactionDTO } from '../../types/generated/TransactionDTO';\nimport type { UpdatePaymentStatusInputDTO } from '../../types/generated/UpdatePaymentStatusInputDTO';\nimport type { WalletDTO } from '../../types/generated/WalletDTO';\n\n// Define missing types that are not fully generated\ntype GetPaymentsOutputDto = { payments: PaymentDTO[] };\ntype CreatePaymentInputDto = {\n type: 'sponsorship' | 'membership_fee';\n amount: number;\n payerId: string;\n payerType: 'sponsor' | 'driver';\n leagueId: string;\n seasonId?: string;\n};\ntype CreatePaymentOutputDto = { payment: PaymentDTO };\ntype GetMembershipFeesOutputDto = {\n fee: MembershipFeeDTO | null;\n payments: MemberPaymentDTO[]\n};\ntype GetPrizesOutputDto = { prizes: PrizeDTO[] };\ntype GetWalletOutputDto = {\n wallet: WalletDTO;\n transactions: TransactionDTO[]\n};\ntype ProcessWalletTransactionInputDto = {\n leagueId: string;\n type: 'deposit' | 'withdrawal' | 'platform_fee';\n amount: number;\n description: string;\n referenceId?: string;\n referenceType?: 'sponsorship' | 'membership_fee' | 'prize';\n};\ntype ProcessWalletTransactionOutputDto = {\n wallet: WalletDTO;\n transaction: TransactionDTO\n};\ntype UpdateMemberPaymentInputDto = {\n feeId: string;\n driverId: string;\n status?: 'pending' | 'paid' | 'overdue';\n paidAt?: Date | string;\n};\ntype UpdateMemberPaymentOutputDto = { payment: MemberPaymentDTO };\ntype GetWalletTransactionsOutputDto = { transactions: TransactionDTO[] };\ntype UpdatePaymentStatusOutputDto = { payment: PaymentDTO };\ntype UpsertMembershipFeeInputDto = {\n leagueId: string;\n seasonId?: string;\n type: 'season' | 'monthly' | 'per_race';\n amount: number;\n};\ntype UpsertMembershipFeeOutputDto = { fee: MembershipFeeDTO };\ntype CreatePrizeInputDto = {\n leagueId: string;\n seasonId: string;\n position: number;\n name: string;\n amount: number;\n type: 'cash' | 'merchandise' | 'other';\n description?: string;\n};\ntype CreatePrizeOutputDto = { prize: PrizeDTO };\ntype AwardPrizeInputDto = {\n prizeId: string;\n driverId: string;\n};\ntype AwardPrizeOutputDto = { prize: PrizeDTO };\ntype DeletePrizeInputDto = { prizeId: string };\ntype DeletePrizeOutputDto = { success: boolean };\n\n/**\n * Payments API Client\n *\n * Handles all payment-related API operations.\n */\nexport class PaymentsApiClient extends BaseApiClient {\n /** Get payments */\n getPayments(query?: { leagueId?: string; payerId?: string; type?: 'sponsorship' | 'membership_fee'; status?: 'pending' | 'completed' | 'failed' | 'refunded' }): Promise {\n const params = new URLSearchParams();\n if (query?.leagueId) params.append('leagueId', query.leagueId);\n if (query?.payerId) params.append('payerId', query.payerId);\n if (query?.type) params.append('type', query.type);\n if (query?.status) params.append('status', query.status);\n const queryString = params.toString();\n return this.get(`/payments${queryString ? `?${queryString}` : ''}`);\n }\n\n /** Create a payment */\n createPayment(input: CreatePaymentInputDto): Promise {\n return this.post('/payments', input);\n }\n\n /** Get membership fees */\n getMembershipFees(query: { leagueId: string; driverId?: string }): Promise {\n const params = new URLSearchParams();\n params.append('leagueId', query.leagueId);\n if (query.driverId) params.append('driverId', query.driverId);\n const queryString = params.toString();\n return this.get(`/payments/membership-fees?${queryString}`);\n }\n\n /** Get prizes */\n getPrizes(query?: { leagueId?: string; seasonId?: string }): Promise {\n const params = new URLSearchParams();\n if (query?.leagueId) params.append('leagueId', query.leagueId);\n if (query?.seasonId) params.append('seasonId', query.seasonId);\n const queryString = params.toString();\n return this.get(`/payments/prizes${queryString ? `?${queryString}` : ''}`);\n }\n\n /** Get wallet */\n getWallet(query?: { leagueId?: string }): Promise {\n const params = new URLSearchParams();\n if (query?.leagueId) params.append('leagueId', query.leagueId);\n const queryString = params.toString();\n return this.get(`/payments/wallets${queryString ? `?${queryString}` : ''}`);\n }\n\n /** Update payment status */\n updatePaymentStatus(input: UpdatePaymentStatusInputDTO): Promise {\n return this.patch('/payments/status', input);\n }\n\n /** Upsert membership fee */\n upsertMembershipFee(input: UpsertMembershipFeeInputDto): Promise {\n return this.post('/payments/membership-fees', input);\n }\n\n /** Update member payment */\n updateMemberPayment(input: UpdateMemberPaymentInputDto): Promise {\n return this.patch('/payments/membership-fees/member-payment', input);\n }\n\n /** Create prize */\n createPrize(input: CreatePrizeInputDto): Promise {\n return this.post('/payments/prizes', input);\n }\n\n /** Award prize */\n awardPrize(input: AwardPrizeInputDto): Promise {\n return this.patch('/payments/prizes/award', input);\n }\n\n /** Delete prize */\n deletePrize(prizeId: string): Promise {\n return this.delete(`/payments/prizes?prizeId=${prizeId}`);\n }\n\n /** Process wallet transaction */\n processWalletTransaction(input: ProcessWalletTransactionInputDto): Promise {\n return this.post('/payments/wallets/transactions', input);\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/api/penalties/PenaltiesApiClient.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/api/policy/PolicyApiClient.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/api/protests/ProtestsApiClient.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/api/races/RacesApiClient.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'AllRacesPageDTO' is defined but never used.","line":15,"column":15,"nodeType":"Identifier","messageId":"unusedVar","endLine":15,"endColumn":30},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'FilteredRacesPageDataDTO' is defined but never used.","line":16,"column":15,"nodeType":"Identifier","messageId":"unusedVar","endLine":16,"endColumn":39}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { BaseApiClient } from '../base/BaseApiClient';\nimport type { RaceStatsDTO } from '../../types/generated/RaceStatsDTO';\nimport type { RacesPageDataRaceDTO } from '../../types/generated/RacesPageDataRaceDTO';\nimport type { RaceResultsDetailDTO } from '../../types/generated/RaceResultsDetailDTO';\nimport type { RaceWithSOFDTO } from '../../types/generated/RaceWithSOFDTO';\nimport type { RegisterForRaceParamsDTO } from '../../types/generated/RegisterForRaceParamsDTO';\nimport type { ImportRaceResultsDTO } from '../../types/generated/ImportRaceResultsDTO';\nimport type { WithdrawFromRaceParamsDTO } from '../../types/generated/WithdrawFromRaceParamsDTO';\nimport type { RaceDetailRaceDTO } from '../../types/generated/RaceDetailRaceDTO';\nimport type { RaceDetailLeagueDTO } from '../../types/generated/RaceDetailLeagueDTO';\nimport type { RaceDetailEntryDTO } from '../../types/generated/RaceDetailEntryDTO';\nimport type { RaceDetailRegistrationDTO } from '../../types/generated/RaceDetailRegistrationDTO';\nimport type { RaceDetailUserResultDTO } from '../../types/generated/RaceDetailUserResultDTO';\nimport type { FileProtestCommandDTO } from '../../types/generated/FileProtestCommandDTO';\nimport type { AllRacesPageDTO } from '../../types/generated/AllRacesPageDTO';\nimport type { FilteredRacesPageDataDTO } from '../../types/tbd/FilteredRacesPageDataDTO';\n\n// Define missing types\nexport type RacesPageDataDTO = { races: RacesPageDataRaceDTO[] };\nexport type RaceDetailDTO = {\n race: RaceDetailRaceDTO | null;\n league: RaceDetailLeagueDTO | null;\n entryList: RaceDetailEntryDTO[];\n registration: RaceDetailRegistrationDTO;\n userResult: RaceDetailUserResultDTO | null;\n error?: string;\n};\nexport type ImportRaceResultsSummaryDTO = {\n success: boolean;\n raceId: string;\n driversProcessed: number;\n resultsRecorded: number;\n errors?: string[];\n};\n\n/**\n * Races API Client\n *\n * Handles all race-related API operations.\n */\nexport class RacesApiClient extends BaseApiClient {\n /** Get total number of races */\n getTotal(): Promise {\n return this.get('/races/total-races');\n }\n\n /** Get races page data */\n getPageData(leagueId?: string): Promise {\n const query = leagueId ? `?leagueId=${encodeURIComponent(leagueId)}` : '';\n return this.get(`/races/page-data${query}`);\n }\n\n /** Get race detail */\n getDetail(raceId: string, driverId: string): Promise {\n return this.get(`/races/${raceId}?driverId=${driverId}`);\n }\n\n /** Get race results detail */\n getResultsDetail(raceId: string): Promise {\n return this.get(`/races/${raceId}/results`);\n }\n\n /** Get race with strength of field */\n getWithSOF(raceId: string): Promise {\n return this.get(`/races/${raceId}/sof`);\n }\n\n /** Register for race */\n register(raceId: string, input: RegisterForRaceParamsDTO): Promise {\n return this.post(`/races/${raceId}/register`, input);\n }\n\n /** Import race results */\n importResults(raceId: string, input: ImportRaceResultsDTO): Promise {\n return this.post(`/races/${raceId}/import-results`, input);\n }\n\n /** Withdraw from race */\n withdraw(raceId: string, input: WithdrawFromRaceParamsDTO): Promise {\n return this.post(`/races/${raceId}/withdraw`, input);\n }\n\n /** Cancel race */\n cancel(raceId: string): Promise {\n return this.post(`/races/${raceId}/cancel`, {});\n }\n\n /** Complete race */\n complete(raceId: string): Promise {\n return this.post(`/races/${raceId}/complete`, {});\n }\n\n /** Re-open race */\n reopen(raceId: string): Promise {\n return this.post(`/races/${raceId}/reopen`, {});\n }\n\n /** File a protest */\n fileProtest(input: FileProtestCommandDTO): Promise {\n return this.post('/races/protests/file', input);\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/api/sponsors/SponsorsApiClient.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":69,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":69,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3185,3188],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3185,3188],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":70,"column":15,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":70,"endColumn":18,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3206,3209],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3206,3209],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":71,"column":12,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":71,"endColumn":15,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3224,3227],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3224,3227],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":77,"column":34,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":77,"endColumn":37,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3376,3379],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3376,3379],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":83,"column":13,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":83,"endColumn":16,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3542,3545],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3542,3545],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":84,"column":14,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":84,"endColumn":17,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3560,3563],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3560,3563],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":85,"column":12,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":85,"endColumn":15,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3578,3581],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3578,3581],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":92,"column":14,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":92,"endColumn":17,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3745,3748],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3745,3748],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":93,"column":20,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":93,"endColumn":23,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3769,3772],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3769,3772],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":94,"column":14,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":94,"endColumn":17,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3787,3790],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3787,3790],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":100,"column":44,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":100,"endColumn":47,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3936,3939],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3936,3939],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":11,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { BaseApiClient } from '../base/BaseApiClient';\nimport type { CreateSponsorInputDTO } from '../../types/generated/CreateSponsorInputDTO';\nimport type { SponsorDashboardDTO } from '../../types/generated/SponsorDashboardDTO';\nimport type { SponsorSponsorshipsDTO } from '../../types/generated/SponsorSponsorshipsDTO';\nimport type { GetPendingSponsorshipRequestsOutputDTO } from '../../types/generated/GetPendingSponsorshipRequestsOutputDTO';\nimport type { AcceptSponsorshipRequestInputDTO } from '../../types/generated/AcceptSponsorshipRequestInputDTO';\nimport type { RejectSponsorshipRequestInputDTO } from '../../types/generated/RejectSponsorshipRequestInputDTO';\nimport type { GetSponsorOutputDTO } from '../../types/generated/GetSponsorOutputDTO';\nimport type { SponsorDTO } from '../../types/generated/SponsorDTO';\n\n// Types that are not yet generated\nexport type CreateSponsorOutputDto = { id: string; name: string };\nexport type GetEntitySponsorshipPricingResultDto = { pricing: Array<{ entityType: string; price: number }> };\nexport type GetSponsorsOutputDto = { sponsors: SponsorDTO[] };\n\n/**\n * Sponsors API Client\n *\n * Handles all sponsor-related API operations.\n */\nexport class SponsorsApiClient extends BaseApiClient {\n /** Get sponsorship pricing */\n getPricing(): Promise {\n return this.get('/sponsors/pricing');\n }\n\n /** Get all sponsors */\n getAll(): Promise {\n return this.get('/sponsors');\n }\n\n /** Create a new sponsor */\n create(input: CreateSponsorInputDTO): Promise {\n return this.post('/sponsors', input);\n }\n\n /** Get sponsor dashboard */\n getDashboard(sponsorId: string): Promise {\n return this.get(`/sponsors/dashboard/${sponsorId}`);\n }\n\n /** Get sponsor sponsorships */\n getSponsorships(sponsorId: string): Promise {\n return this.get(`/sponsors/${sponsorId}/sponsorships`);\n }\n\n /** Get sponsor by ID */\n getSponsor(sponsorId: string): Promise {\n return this.get(`/sponsors/${sponsorId}`);\n }\n\n /** Get pending sponsorship requests for an entity */\n getPendingSponsorshipRequests(params: { entityType: string; entityId: string }): Promise {\n return this.get(`/sponsors/requests?entityType=${params.entityType}&entityId=${params.entityId}`);\n }\n\n /** Accept a sponsorship request */\n acceptSponsorshipRequest(requestId: string, input: AcceptSponsorshipRequestInputDTO): Promise {\n return this.post(`/sponsors/requests/${requestId}/accept`, input);\n }\n\n /** Reject a sponsorship request */\n rejectSponsorshipRequest(requestId: string, input: RejectSponsorshipRequestInputDTO): Promise {\n return this.post(`/sponsors/requests/${requestId}/reject`, input);\n }\n\n /** Get sponsor billing information */\n getBilling(sponsorId: string): Promise<{\n paymentMethods: any[];\n invoices: any[];\n stats: any;\n }> {\n return this.get(`/sponsors/billing/${sponsorId}`);\n }\n\n /** Get available leagues for sponsorship */\n getAvailableLeagues(): Promise {\n return this.get('/sponsors/leagues/available');\n }\n\n /** Get detailed league information */\n getLeagueDetail(leagueId: string): Promise<{\n league: any;\n drivers: any[];\n races: any[];\n }> {\n return this.get(`/sponsors/leagues/${leagueId}/detail`);\n }\n\n /** Get sponsor settings */\n getSettings(sponsorId: string): Promise<{\n profile: any;\n notifications: any;\n privacy: any;\n }> {\n return this.get(`/sponsors/settings/${sponsorId}`);\n }\n\n /** Update sponsor settings */\n updateSettings(sponsorId: string, input: any): Promise {\n return this.put(`/sponsors/settings/${sponsorId}`, input);\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/api/teams/TeamsApiClient.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'LeagueMemberDTO' is defined but never used.","line":1,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":1,"endColumn":25}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { LeagueMemberDTO } from '@/lib/types/generated/LeagueMemberDTO';\nimport type { GetAllTeamsOutputDTO } from '@/lib/types/generated/GetAllTeamsOutputDTO';\nimport type { GetTeamDetailsOutputDTO } from '@/lib/types/generated/GetTeamDetailsOutputDTO';\nimport type { GetTeamMembersOutputDTO } from '@/lib/types/generated/GetTeamMembersOutputDTO';\nimport type { GetTeamJoinRequestsOutputDTO } from '@/lib/types/generated/GetTeamJoinRequestsOutputDTO';\nimport type { CreateTeamInputDTO } from '@/lib/types/generated/CreateTeamInputDTO';\nimport type { CreateTeamOutputDTO } from '@/lib/types/generated/CreateTeamOutputDTO';\nimport type { UpdateTeamInputDTO } from '@/lib/types/generated/UpdateTeamInputDTO';\nimport type { UpdateTeamOutputDTO } from '@/lib/types/generated/UpdateTeamOutputDTO';\nimport type { GetDriverTeamOutputDTO } from '@/lib/types/generated/GetDriverTeamOutputDTO';\nimport type { GetTeamMembershipOutputDTO } from '@/lib/types/generated/GetTeamMembershipOutputDTO';\nimport { BaseApiClient } from '../base/BaseApiClient';\n\n/**\n * Teams API Client\n *\n * Handles all team-related API operations.\n */\nexport class TeamsApiClient extends BaseApiClient {\n /** Get all teams */\n getAll(): Promise {\n return this.get('/teams/all');\n }\n\n /** Get team details */\n getDetails(teamId: string): Promise {\n return this.get(`/teams/${teamId}`);\n }\n\n /** Get team members */\n getMembers(teamId: string): Promise {\n return this.get(`/teams/${teamId}/members`);\n }\n\n /** Get team join requests */\n getJoinRequests(teamId: string): Promise {\n return this.get(`/teams/${teamId}/join-requests`);\n }\n\n /** Create a new team */\n create(input: CreateTeamInputDTO): Promise {\n return this.post('/teams', input);\n }\n\n /** Update team */\n update(teamId: string, input: UpdateTeamInputDTO): Promise {\n return this.patch(`/teams/${teamId}`, input);\n }\n\n /** Get driver's team */\n getDriverTeam(driverId: string): Promise {\n return this.get(`/teams/driver/${driverId}`);\n }\n\n /** Get membership for a driver in a team */\n getMembership(teamId: string, driverId: string): Promise {\n return this.get(`/teams/${teamId}/members/${driverId}`);\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/api/wallets/WalletsApiClient.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/apiClient.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/auth/AuthContext.tsx","messages":[{"ruleId":"gridpilot-rules/lib-no-next-imports","severity":2,"message":"Next.js imports are forbidden in lib/ directory. Found: useRouter from \"next/navigation\"","line":10,"column":10,"nodeType":"ImportSpecifier","messageId":"noNextImports","endLine":10,"endColumn":19}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\n\nimport {\n createContext,\n useCallback,\n useContext,\n useMemo,\n type ReactNode,\n} from 'react';\nimport { useRouter } from 'next/navigation';\n\nimport type { SessionViewModel } from '@/lib/view-models/SessionViewModel';\nimport { useCurrentSession } from \"@/hooks/auth/useCurrentSession\";\nimport { useLogout } from \"@/hooks/auth/useLogout\";\n\nexport type AuthContextValue = {\n session: SessionViewModel | null;\n loading: boolean;\n login: (returnTo?: string) => void;\n logout: () => Promise;\n refreshSession: () => Promise;\n};\n\nconst AuthContext = createContext(undefined);\n\ninterface AuthProviderProps {\n initialSession?: SessionViewModel | null;\n children: ReactNode;\n}\n\nexport function AuthProvider({ initialSession = null, children }: AuthProviderProps) {\n const router = useRouter();\n \n // Use React-Query hooks for session management\n const { data: session, isLoading, refetch: refreshSession } = useCurrentSession({\n initialData: initialSession,\n });\n\n // Use mutation hooks for logout\n const logoutMutation = useLogout();\n\n const login = useCallback(\n (returnTo?: string) => {\n const search = new URLSearchParams();\n if (returnTo) {\n search.set('returnTo', returnTo);\n }\n\n const target = search.toString()\n ? `/auth/login?${search.toString()}`\n : '/auth/login';\n\n router.push(target);\n },\n [router],\n );\n\n const logout = useCallback(async () => {\n try {\n await logoutMutation.mutateAsync();\n router.push('/');\n router.refresh();\n } catch (error) {\n console.error('Logout failed:', error);\n router.push('/');\n }\n }, [logoutMutation, router]);\n\n const handleRefreshSession = useCallback(async () => {\n await refreshSession();\n }, [refreshSession]);\n\n const value = useMemo(\n () => ({\n session: session ?? null,\n loading: isLoading,\n login,\n logout,\n refreshSession: handleRefreshSession,\n }),\n [session, isLoading, login, logout, handleRefreshSession],\n );\n\n return {children};\n}\n\nexport function useAuth(): AuthContextValue {\n const ctx = useContext(AuthContext);\n if (!ctx) {\n throw new Error('useAuth must be used within an AuthProvider');\n }\n return ctx;\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/auth/AuthFlowRouter.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/auth/AuthRedirectBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/auth/LoginFlowController.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/auth/PathnameInterpreter.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/auth/ReturnToSanitizer.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/auth/RouteAccessPolicy.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/auth/RouteCatalog.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":117,"column":16,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":117,"endColumn":19,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2832,2835],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2832,2835],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":153,"column":28,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":153,"endColumn":31,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3819,3822],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3819,3822],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { routes, routeMatchers } from '../routing/RouteConfig';\n\n/**\n * RouteCatalog exposes route IDs and patterns for matching\n * \n * Route IDs follow the pattern: 'category.routeName'\n * Examples:\n * - 'auth.login' → '/auth/login'\n * - 'protected.dashboard' → '/dashboard'\n * - 'league.detail' → '/leagues/[id]' (pattern)\n */\nexport class RouteCatalog {\n /**\n * List all public route IDs\n * Public routes are accessible without authentication\n */\n listPublicRoutes(): string[] {\n return [\n 'public.home',\n 'public.leagues',\n 'public.drivers',\n 'public.teams',\n 'public.leaderboards',\n 'public.races',\n 'public.sponsorSignup',\n 'auth.login',\n 'auth.signup',\n 'auth.forgotPassword',\n 'auth.resetPassword',\n 'auth.iRacingStart',\n 'auth.iRacingCallback',\n 'error.notFound',\n 'error.serverError',\n // Parameterized public routes\n 'league.detail',\n 'league.rulebook',\n 'league.schedule',\n 'league.standings',\n 'driver.detail',\n 'team.detail',\n 'race.detail',\n 'race.results',\n 'race.all',\n ];\n }\n\n /**\n * List all protected route IDs\n * Protected routes require authentication\n */\n listProtectedRoutes(): string[] {\n return [\n 'protected.dashboard',\n 'protected.onboarding',\n 'protected.profile',\n 'protected.profileSettings',\n 'protected.profileLeagues',\n 'protected.profileLiveries',\n 'protected.profileLiveryUpload',\n 'protected.profileSponsorshipRequests',\n 'sponsor.root',\n 'sponsor.dashboard',\n 'sponsor.billing',\n 'sponsor.campaigns',\n 'sponsor.leagues',\n 'sponsor.settings',\n 'admin.root',\n 'admin.users',\n 'league.create',\n 'race.root',\n 'team.root',\n 'team.leaderboard',\n ];\n }\n\n /**\n * List all admin route IDs\n * Admin routes require admin-level permissions\n */\n listAdminRoutes(): string[] {\n return [\n 'admin.root',\n 'admin.users',\n 'league.rosterAdmin',\n 'league.scheduleAdmin',\n 'league.stewarding',\n 'league.settings',\n 'league.sponsorships',\n 'league.wallet',\n 'race.stewarding',\n ];\n }\n\n /**\n * List all sponsor route IDs\n * Sponsor routes require sponsor role\n */\n listSponsorRoutes(): string[] {\n return [\n 'sponsor.root',\n 'sponsor.dashboard',\n 'sponsor.billing',\n 'sponsor.campaigns',\n 'sponsor.leagues',\n 'sponsor.settings',\n ];\n }\n\n /**\n * Get the path pattern for a route ID\n * @param routeId - Route ID in format 'category.routeName'\n * @returns Path pattern (e.g., '/auth/login' or '/leagues/[id]')\n * @throws Error if route ID is unknown\n */\n getPattern(routeId: string): string {\n const parts = routeId.split('.');\n let route: any = routes;\n\n for (const part of parts) {\n route = route[part];\n if (!route) {\n throw new Error(`Unknown route ID: ${routeId}`);\n }\n }\n\n // Handle parameterized routes\n if (typeof route === 'function') {\n // Return pattern with placeholder\n const paramPattern = route('placeholder');\n return paramPattern.replace('/placeholder', '/[id]');\n }\n\n return route as string;\n }\n\n /**\n * Check if a path is an auth page\n * @param logicalPath - Path to check\n * @returns True if path is an auth page\n */\n isAuthPage(logicalPath: string): boolean {\n return routeMatchers.isInGroup(logicalPath, 'auth');\n }\n\n /**\n * Get all route patterns with their IDs\n * @returns Array of route patterns with IDs\n */\n getAllPatterns(): Array<{ routeId: string; pattern: string }> {\n const patterns: Array<{ routeId: string; pattern: string }> = [];\n\n // Helper to traverse routes and build patterns\n const traverse = (obj: any, prefix: string) => {\n for (const [key, value] of Object.entries(obj)) {\n const routeId = prefix ? `${prefix}.${key}` : key;\n\n if (typeof value === 'function') {\n // Parameterized route\n const pattern = value('placeholder').replace('/placeholder', '/[id]');\n patterns.push({ routeId, pattern });\n } else if (typeof value === 'object' && value !== null) {\n // Nested category\n traverse(value, routeId);\n } else if (typeof value === 'string') {\n // Simple route\n patterns.push({ routeId, pattern: value });\n }\n }\n };\n\n traverse(routes, '');\n return patterns;\n }\n\n /**\n * Get route ID by path\n * @param path - Path to find\n * @returns Route ID or null if not found\n * \n * Note: This method prioritizes exact matches over parameterized matches.\n * For example, '/leagues/create' will match 'league.create' before 'league.detail'.\n */\n getRouteIdByPath(path: string): string | null {\n const allPatterns = this.getAllPatterns();\n \n // First, try exact matches\n for (const { routeId, pattern } of allPatterns) {\n if (pattern === path) {\n return routeId;\n }\n }\n \n // Then, try parameterized matches\n for (const { routeId, pattern } of allPatterns) {\n if (pattern.includes('[')) {\n const paramPattern = pattern.replace(/\\[([^\\]]+)\\]/g, '([^/]+)');\n const regex = new RegExp(`^${paramPattern}$`);\n if (regex.test(path)) {\n return routeId;\n }\n }\n }\n\n return null;\n }\n\n /**\n * Check if a path requires specific role-based access\n * @param logicalPath - Path to check\n * @returns Array of required roles or null\n */\n getRequiredRoles(logicalPath: string): string[] | null {\n // Check admin routes\n if (routeMatchers.isInGroup(logicalPath, 'admin')) {\n return ['system-owner', 'super-admin', 'league-admin'];\n }\n \n // Check sponsor routes\n if (routeMatchers.isInGroup(logicalPath, 'sponsor')) {\n return ['sponsor'];\n }\n \n // Check league admin routes (specific patterns)\n if (logicalPath.match(/\\/leagues\\/[^/]+\\/(roster\\/admin|schedule\\/admin|stewarding|settings|sponsorships|wallet)/)) {\n return ['system-owner', 'super-admin', 'league-admin'];\n }\n \n // Check race stewarding routes\n if (logicalPath.match(/\\/races\\/[^/]+\\/stewarding/)) {\n return ['system-owner', 'super-admin', 'league-steward'];\n }\n \n // Public or auth-only routes (no specific role)\n return null;\n }\n\n /**\n * Get the home path for a specific role\n * @param role - The role name\n * @returns The logical path for that role's home page\n */\n getRoleHome(role: string): string {\n const roleHomeMap: Record = {\n 'driver': '/dashboard',\n 'sponsor': '/sponsor/dashboard',\n 'league-admin': '/admin',\n 'league-steward': '/admin',\n 'league-owner': '/admin',\n 'system-owner': '/admin',\n 'super-admin': '/admin',\n };\n\n return roleHomeMap[role] || '/dashboard';\n }\n\n /**\n * Get the route ID for a specific role's home page\n * @param role - The role name\n * @returns The route ID for that role's home page\n */\n getRoleHomeRouteId(role: string): string {\n const roleHomeRouteMap: Record = {\n 'driver': 'protected.dashboard',\n 'sponsor': 'sponsor.dashboard',\n 'league-admin': 'admin',\n 'league-steward': 'admin',\n 'league-owner': 'admin',\n 'system-owner': 'admin',\n 'super-admin': 'admin',\n };\n\n return roleHomeRouteMap[role] || 'protected.dashboard';\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/auth/RouteGuard.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/auth/RoutePathBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/auth/createRouteGuard.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/blockers/Blocker.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/blockers/SubmitBlocker.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/blockers/ThrottleBlocker.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/blockers/index.ts","messages":[{"ruleId":"gridpilot-rules/no-index-files","severity":2,"message":"Index files are banned. Use explicit imports and barrel exports. Example: Instead of \"import { foo } from \"./\", use \"import { foo } from \"./foo\" and export from \"./foo\" explicitly.","line":1,"column":1,"nodeType":null,"messageId":"indexFile"}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * @file index.ts\n * Blockers exports\n */\n\nexport { Blocker } from './Blocker';\nexport { SubmitBlocker } from './SubmitBlocker';\nexport { ThrottleBlocker } from './ThrottleBlocker';","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/AdminDashboardViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/AdminUsersViewDataBuilder.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":21,"column":91,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":21,"endColumn":94,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[720,723],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[720,723],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":22,"column":91,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":22,"endColumn":94,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[830,833],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[830,833],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":23,"column":119,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":23,"endColumn":122,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[968,971],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[968,971],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":3,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import type { UserListResponse } from '@/lib/types/admin';\nimport { AdminUsersViewData } from '@/lib/view-data/AdminUsersViewData';\n\n/**\n * AdminUsersViewDataBuilder\n * \n * Server-side builder that transforms API DTO\n * into ViewData for the AdminUsersTemplate.\n * \n * Deterministic, side-effect free.\n */\nexport class AdminUsersViewDataBuilder {\n static build(apiDto: UserListResponse): AdminUsersViewData {\n const users = apiDto.users.map(user => ({\n id: user.id,\n email: user.email,\n displayName: user.displayName,\n roles: user.roles,\n status: user.status,\n isSystemAdmin: user.isSystemAdmin,\n createdAt: typeof user.createdAt === 'string' ? user.createdAt : (user.createdAt as any).toISOString(),\n updatedAt: typeof user.updatedAt === 'string' ? user.updatedAt : (user.updatedAt as any).toISOString(),\n lastLoginAt: user.lastLoginAt ? (typeof user.lastLoginAt === 'string' ? user.lastLoginAt : (user.lastLoginAt as any).toISOString()) : undefined,\n primaryDriverId: user.primaryDriverId,\n }));\n\n return {\n users,\n total: apiDto.total,\n page: apiDto.page,\n limit: apiDto.limit,\n totalPages: apiDto.totalPages,\n // Pre-computed derived values for template\n activeUserCount: users.filter(u => u.status === 'active').length,\n adminCount: users.filter(u => u.isSystemAdmin).length,\n };\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/AvatarViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/CategoryIconViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/CompleteOnboardingViewData.ts","messages":[{"ruleId":"gridpilot-rules/view-data-builder-contract","severity":2,"message":"View Data Builders must have a static build() method","line":1,"column":1,"nodeType":"Program","messageId":"missingBuildMethod","endLine":5,"endColumn":2}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"export interface CompleteOnboardingViewData {\n success: boolean;\n driverId?: string;\n errorMessage?: string;\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/CompleteOnboardingViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/DashboardViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/DriverProfileViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/DriverRankingsViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/DriversViewDataBuilder.ts","messages":[{"ruleId":"gridpilot-rules/view-data-builder-contract","severity":2,"message":"Parameter must be named \"apiDto\", not \"pageDto\" or other names","line":1,"column":1,"nodeType":"Program","messageId":"wrongParameterName","endLine":26,"endColumn":2}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import type { DriversLeaderboardDTO } from '@/lib/types/generated/DriversLeaderboardDTO';\nimport type { DriversViewData } from '@/lib/types/view-data/DriversViewData';\n\nexport class DriversViewDataBuilder {\n static build(dto: DriversLeaderboardDTO): DriversViewData {\n return {\n drivers: dto.drivers.map(driver => ({\n id: driver.id,\n name: driver.name,\n rating: driver.rating,\n skillLevel: driver.skillLevel,\n category: driver.category,\n nationality: driver.nationality,\n racesCompleted: driver.racesCompleted,\n wins: driver.wins,\n podiums: driver.podiums,\n isActive: driver.isActive,\n rank: driver.rank,\n avatarUrl: driver.avatarUrl,\n })),\n totalRaces: dto.totalRaces,\n totalWins: dto.totalWins,\n activeCount: dto.activeCount,\n };\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/ForgotPasswordViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/GenerateAvatarsViewData.ts","messages":[{"ruleId":"gridpilot-rules/view-data-builder-contract","severity":2,"message":"View Data Builders must have a static build() method","line":1,"column":1,"nodeType":"Program","messageId":"missingBuildMethod","endLine":5,"endColumn":2}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"export interface GenerateAvatarsViewData {\n success: boolean;\n avatarUrls: string[];\n errorMessage?: string;\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/GenerateAvatarsViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/LeaderboardsViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/LeagueCoverViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/LeagueDetailViewDataBuilder.ts","messages":[{"ruleId":"gridpilot-rules/view-data-builder-contract","severity":2,"message":"Parameter must be named \"apiDto\", not \"pageDto\" or other names","line":1,"column":1,"nodeType":"Program","messageId":"wrongParameterName","endLine":92,"endColumn":2},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":21,"column":15,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":21,"endColumn":18,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1025,1028],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1025,1028],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'r' is defined but never used.","line":40,"column":39,"nodeType":"Identifier","messageId":"unusedVar","endLine":40,"endColumn":40}],"suppressedMessages":[],"errorCount":3,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import type { LeagueWithCapacityAndScoringDTO } from '@/lib/types/generated/LeagueWithCapacityAndScoringDTO';\nimport type { LeagueMembershipsDTO } from '@/lib/types/generated/LeagueMembershipsDTO';\nimport type { RaceDTO } from '@/lib/types/generated/RaceDTO';\nimport type { GetDriverOutputDTO } from '@/lib/types/generated/GetDriverOutputDTO';\nimport type { LeagueScoringConfigDTO } from '@/lib/types/generated/LeagueScoringConfigDTO';\nimport type { LeagueDetailViewData, LeagueInfoData, LiveRaceData, DriverSummaryData, SponsorInfo } from '@/lib/view-data/LeagueDetailViewData';\n\n/**\n * LeagueDetailViewDataBuilder\n *\n * Transforms API DTOs into LeagueDetailViewData for server-side rendering.\n * Deterministic; side-effect free; no HTTP calls.\n */\nexport class LeagueDetailViewDataBuilder {\n static build(input: {\n league: LeagueWithCapacityAndScoringDTO;\n owner: GetDriverOutputDTO | null;\n scoringConfig: LeagueScoringConfigDTO | null;\n memberships: LeagueMembershipsDTO;\n races: RaceDTO[];\n sponsors: any[];\n }): LeagueDetailViewData {\n const { league, owner, scoringConfig, memberships, races, sponsors } = input;\n \n // Calculate running races - using available fields from RaceDTO\n const runningRaces: LiveRaceData[] = races\n .filter(r => r.name.includes('Running')) // Placeholder filter\n .map(r => ({\n id: r.id,\n name: r.name,\n date: r.date,\n registeredCount: 0,\n strengthOfField: 0,\n }));\n \n // Calculate info data\n const membersCount = Array.isArray(memberships.members) ? memberships.members.length : 0;\n const completedRacesCount = races.filter(r => r.name.includes('Completed')).length; // Placeholder\n const avgSOF = races.length > 0\n ? Math.round(races.reduce((sum, r) => sum + 0, 0) / races.length)\n : null;\n \n const info: LeagueInfoData = {\n name: league.name,\n description: league.description || '',\n membersCount,\n racesCount: completedRacesCount,\n avgSOF,\n structure: `Solo • ${league.settings?.maxDrivers ?? 32} max`,\n scoring: scoringConfig?.scoringPresetId || 'Standard',\n createdAt: league.createdAt,\n discordUrl: league.socialLinks?.discordUrl,\n youtubeUrl: league.socialLinks?.youtubeUrl,\n websiteUrl: league.socialLinks?.websiteUrl,\n };\n \n // Convert owner to driver summary\n const ownerSummary: DriverSummaryData | null = owner ? {\n driverId: owner.id,\n driverName: owner.name,\n avatarUrl: owner.avatarUrl || null,\n rating: null,\n rank: null,\n roleBadgeText: 'Owner',\n roleBadgeClasses: 'bg-yellow-500/10 text-yellow-500 border-yellow-500/30',\n profileUrl: `/drivers/${owner.id}`,\n } : null;\n \n // Convert sponsors\n const sponsorInfo: SponsorInfo[] = sponsors.map(s => ({\n id: s.id,\n name: s.name,\n tier: s.tier,\n logoUrl: s.logoUrl,\n websiteUrl: s.websiteUrl,\n tagline: s.tagline,\n }));\n \n return {\n leagueId: league.id,\n name: league.name,\n description: league.description || '',\n info,\n runningRaces,\n sponsors: sponsorInfo,\n ownerSummary,\n adminSummaries: [], // Would need additional data\n stewardSummaries: [], // Would need additional data\n sponsorInsights: null, // Only for sponsor mode\n };\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/LeagueLogoViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/LeagueRosterAdminViewDataBuilder.ts","messages":[{"ruleId":"gridpilot-rules/view-data-builder-contract","severity":2,"message":"Parameter must be named \"apiDto\", not \"pageDto\" or other names","line":1,"column":1,"nodeType":"Program","messageId":"wrongParameterName","endLine":47,"endColumn":2}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import type { LeagueRosterMemberDTO } from '@/lib/types/generated/LeagueRosterMemberDTO';\nimport type { LeagueRosterJoinRequestDTO } from '@/lib/types/generated/LeagueRosterJoinRequestDTO';\nimport type { LeagueRosterAdminViewData, RosterMemberData, JoinRequestData } from '@/lib/view-data/LeagueRosterAdminViewData';\n\n/**\n * LeagueRosterAdminViewDataBuilder\n *\n * Transforms API DTOs into LeagueRosterAdminViewData for server-side rendering.\n * Deterministic; side-effect free; no HTTP calls.\n */\nexport class LeagueRosterAdminViewDataBuilder {\n static build(input: {\n leagueId: string;\n members: LeagueRosterMemberDTO[];\n joinRequests: LeagueRosterJoinRequestDTO[];\n }): LeagueRosterAdminViewData {\n const { leagueId, members, joinRequests } = input;\n \n // Transform members\n const rosterMembers: RosterMemberData[] = members.map(member => ({\n driverId: member.driverId,\n driver: {\n id: member.driverId,\n name: member.driver?.name || 'Unknown Driver',\n },\n role: member.role,\n joinedAt: member.joinedAt,\n }));\n \n // Transform join requests\n const requests: JoinRequestData[] = joinRequests.map(req => ({\n id: req.id,\n driver: {\n id: req.driverId,\n name: 'Unknown Driver', // driver field is unknown type\n },\n requestedAt: req.requestedAt,\n message: req.message,\n }));\n \n return {\n leagueId,\n members: rosterMembers,\n joinRequests: requests,\n };\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/LeagueScheduleViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/LeagueSettingsViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/LeagueSponsorshipsViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/LeagueStandingsViewDataBuilder.ts","messages":[{"ruleId":"gridpilot-rules/view-data-builder-contract","severity":2,"message":"Parameter must be named \"apiDto\", not \"pageDto\" or other names","line":1,"column":1,"nodeType":"Program","messageId":"wrongParameterName","endLine":75,"endColumn":2}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import type { LeagueStandingsViewData, StandingEntryData, DriverData, LeagueMembershipData } from '@/lib/view-data/LeagueStandingsViewData';\nimport type { LeagueStandingDTO } from '@/lib/types/generated/LeagueStandingDTO';\nimport type { LeagueMemberDTO } from '@/lib/types/generated/LeagueMemberDTO';\n\ninterface LeagueStandingsApiDto {\n standings: LeagueStandingDTO[];\n}\n\ninterface LeagueMembershipsApiDto {\n members: LeagueMemberDTO[];\n}\n\n/**\n * LeagueStandingsViewDataBuilder\n *\n * Transforms API DTOs into LeagueStandingsViewData for server-side rendering.\n * Deterministic; side-effect free; no HTTP calls.\n */\nexport class LeagueStandingsViewDataBuilder {\n static build(\n standingsDto: LeagueStandingsApiDto,\n membershipsDto: LeagueMembershipsApiDto,\n leagueId: string\n ): LeagueStandingsViewData {\n const standings = standingsDto.standings || [];\n const members = membershipsDto.members || [];\n\n // Convert LeagueStandingDTO to StandingEntryData\n const standingData: StandingEntryData[] = standings.map(standing => ({\n driverId: standing.driverId,\n position: standing.position,\n totalPoints: standing.points,\n racesFinished: standing.races,\n racesStarted: standing.races,\n avgFinish: null, // Not in DTO\n penaltyPoints: 0, // Not in DTO\n bonusPoints: 0, // Not in DTO\n }));\n\n // Extract unique drivers from standings\n const driverMap = new Map();\n standings.forEach(standing => {\n if (standing.driver && !driverMap.has(standing.driver.id)) {\n const driver = standing.driver;\n driverMap.set(driver.id, {\n id: driver.id,\n name: driver.name,\n avatarUrl: null, // DTO may not have this\n iracingId: driver.iracingId,\n rating: undefined,\n country: driver.country,\n });\n }\n });\n const driverData: DriverData[] = Array.from(driverMap.values());\n\n // Convert LeagueMemberDTO to LeagueMembershipData\n const membershipData: LeagueMembershipData[] = members.map(member => ({\n driverId: member.driverId,\n leagueId: leagueId,\n role: (member.role as LeagueMembershipData['role']) || 'member',\n joinedAt: member.joinedAt,\n status: 'active' as const,\n }));\n\n return {\n standings: standingData,\n drivers: driverData,\n memberships: membershipData,\n leagueId,\n currentDriverId: null, // Would need to get from auth\n isAdmin: false, // Would need to check permissions\n };\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/LeagueWalletViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/LeaguesViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/LoginViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/OnboardingPageViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/OnboardingViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/ProfileLeaguesViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/ProfileViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/ProtestDetailViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/RaceDetailViewDataBuilder.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":10,"column":24,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":10,"endColumn":27,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[388,391],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[388,391],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":49,"column":71,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":49,"endColumn":74,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1557,1560],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1557,1560],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { RaceDetailViewData, RaceDetailRace, RaceDetailLeague, RaceDetailEntry, RaceDetailRegistration, RaceDetailUserResult } from '@/lib/view-data/races/RaceDetailViewData';\n\n/**\n * Race Detail View Data Builder\n * \n * Transforms API DTO into ViewData for the race detail template.\n * Deterministic, side-effect free.\n */\nexport class RaceDetailViewDataBuilder {\n static build(apiDto: any): RaceDetailViewData {\n if (!apiDto || !apiDto.race) {\n return {\n race: {\n id: '',\n track: '',\n car: '',\n scheduledAt: '',\n status: 'scheduled',\n sessionType: 'race',\n },\n entryList: [],\n registration: {\n isUserRegistered: false,\n canRegister: false,\n },\n canReopenRace: false,\n };\n }\n\n const race: RaceDetailRace = {\n id: apiDto.race.id,\n track: apiDto.race.track,\n car: apiDto.race.car,\n scheduledAt: apiDto.race.scheduledAt,\n status: apiDto.race.status as 'scheduled' | 'running' | 'completed' | 'cancelled',\n sessionType: apiDto.race.sessionType,\n };\n\n const league: RaceDetailLeague | undefined = apiDto.league ? {\n id: apiDto.league.id,\n name: apiDto.league.name,\n description: apiDto.league.description || undefined,\n settings: {\n maxDrivers: apiDto.league.settings?.maxDrivers || 32,\n qualifyingFormat: apiDto.league.settings?.qualifyingFormat || 'Open',\n },\n } : undefined;\n\n const entryList: RaceDetailEntry[] = apiDto.entryList.map((entry: any) => ({\n id: entry.id,\n name: entry.name,\n avatarUrl: entry.avatarUrl,\n country: entry.country,\n rating: entry.rating,\n isCurrentUser: entry.isCurrentUser,\n }));\n\n const registration: RaceDetailRegistration = {\n isUserRegistered: apiDto.registration.isUserRegistered,\n canRegister: apiDto.registration.canRegister,\n };\n\n const userResult: RaceDetailUserResult | undefined = apiDto.userResult ? {\n position: apiDto.userResult.position,\n startPosition: apiDto.userResult.startPosition,\n positionChange: apiDto.userResult.positionChange,\n incidents: apiDto.userResult.incidents,\n isClean: apiDto.userResult.isClean,\n isPodium: apiDto.userResult.isPodium,\n ratingChange: apiDto.userResult.ratingChange,\n } : undefined;\n\n return {\n race,\n league,\n entryList,\n registration,\n userResult,\n canReopenRace: apiDto.canReopenRace || false,\n };\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/RaceResultsViewDataBuilder.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":10,"column":24,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":10,"endColumn":27,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[335,338],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[335,338],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":22,"column":78,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":22,"endColumn":81,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[635,638],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[635,638],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":38,"column":84,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":38,"endColumn":87,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1235,1238],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1235,1238],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":3,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { RaceResultsViewData, RaceResultsResult, RaceResultsPenalty } from '@/lib/view-data/races/RaceResultsViewData';\n\n/**\n * Race Results View Data Builder\n * \n * Transforms API DTO into ViewData for the race results template.\n * Deterministic, side-effect free.\n */\nexport class RaceResultsViewDataBuilder {\n static build(apiDto: any): RaceResultsViewData {\n if (!apiDto) {\n return {\n raceSOF: null,\n results: [],\n penalties: [],\n pointsSystem: {},\n fastestLapTime: 0,\n };\n }\n\n // Transform results\n const results: RaceResultsResult[] = (apiDto.results || []).map((result: any) => ({\n position: result.position,\n driverId: result.driverId,\n driverName: result.driverName,\n driverAvatar: result.avatarUrl,\n country: result.country || 'US',\n car: result.car || 'Unknown',\n laps: result.laps || 0,\n time: result.time || '0:00.00',\n fastestLap: result.fastestLap?.toString() || '0.00',\n points: result.points || 0,\n incidents: result.incidents || 0,\n isCurrentUser: result.isCurrentUser || false,\n }));\n\n // Transform penalties\n const penalties: RaceResultsPenalty[] = (apiDto.penalties || []).map((penalty: any) => ({\n driverId: penalty.driverId,\n driverName: penalty.driverName || 'Unknown',\n type: penalty.type as 'time_penalty' | 'grid_penalty' | 'points_deduction' | 'disqualification' | 'warning' | 'license_points',\n value: penalty.value || 0,\n reason: penalty.reason || 'Penalty applied',\n notes: penalty.notes,\n }));\n\n return {\n raceTrack: apiDto.race?.track,\n raceScheduledAt: apiDto.race?.scheduledAt,\n totalDrivers: apiDto.stats?.totalDrivers,\n leagueName: apiDto.league?.name,\n raceSOF: apiDto.strengthOfField || null,\n results,\n penalties,\n pointsSystem: apiDto.pointsSystem || {},\n fastestLapTime: apiDto.fastestLapTime || 0,\n };\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/RaceStewardingViewDataBuilder.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":10,"column":24,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":10,"endColumn":27,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[337,340],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[337,340],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":35,"column":79,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":35,"endColumn":82,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[951,954],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[951,954],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":49,"column":81,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":49,"endColumn":84,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1398,1401],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1398,1401],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":63,"column":67,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":63,"endColumn":70,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1831,1834],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1831,1834],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":4,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { RaceStewardingViewData, Protest, Penalty, Driver } from '@/lib/view-data/races/RaceStewardingViewData';\n\n/**\n * Race Stewarding View Data Builder\n * \n * Transforms API DTO into ViewData for the race stewarding template.\n * Deterministic, side-effect free.\n */\nexport class RaceStewardingViewDataBuilder {\n static build(apiDto: any): RaceStewardingViewData {\n if (!apiDto) {\n return {\n race: null,\n league: null,\n pendingProtests: [],\n resolvedProtests: [],\n penalties: [],\n driverMap: {},\n pendingCount: 0,\n resolvedCount: 0,\n penaltiesCount: 0,\n };\n }\n\n const race = apiDto.race ? {\n id: apiDto.race.id,\n track: apiDto.race.track,\n scheduledAt: apiDto.race.scheduledAt,\n } : null;\n\n const league = apiDto.league ? {\n id: apiDto.league.id,\n } : null;\n\n const pendingProtests: Protest[] = (apiDto.pendingProtests || []).map((p: any) => ({\n id: p.id,\n protestingDriverId: p.protestingDriverId,\n accusedDriverId: p.accusedDriverId,\n incident: {\n lap: p.incident?.lap || 0,\n description: p.incident?.description || '',\n },\n filedAt: p.filedAt,\n status: p.status,\n proofVideoUrl: p.proofVideoUrl,\n decisionNotes: p.decisionNotes,\n }));\n\n const resolvedProtests: Protest[] = (apiDto.resolvedProtests || []).map((p: any) => ({\n id: p.id,\n protestingDriverId: p.protestingDriverId,\n accusedDriverId: p.accusedDriverId,\n incident: {\n lap: p.incident?.lap || 0,\n description: p.incident?.description || '',\n },\n filedAt: p.filedAt,\n status: p.status,\n proofVideoUrl: p.proofVideoUrl,\n decisionNotes: p.decisionNotes,\n }));\n\n const penalties: Penalty[] = (apiDto.penalties || []).map((p: any) => ({\n id: p.id,\n driverId: p.driverId,\n type: p.type,\n value: p.value || 0,\n reason: p.reason || '',\n notes: p.notes,\n }));\n\n const driverMap: Record = apiDto.driverMap || {};\n\n return {\n race,\n league,\n pendingProtests,\n resolvedProtests,\n penalties,\n driverMap,\n pendingCount: apiDto.pendingCount || pendingProtests.length,\n resolvedCount: apiDto.resolvedCount || resolvedProtests.length,\n penaltiesCount: apiDto.penaltiesCount || penalties.length,\n };\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/RacesAllViewDataBuilder.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'RacesAllRace' is defined but never used.","line":1,"column":28,"nodeType":"Identifier","messageId":"unusedVar","endLine":1,"endColumn":40},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":10,"column":24,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":10,"endColumn":27,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[295,298],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[295,298],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":11,"column":43,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":11,"endColumn":46,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[362,365],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[362,365],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":3,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { RacesAllViewData, RacesAllRace } from '@/lib/view-data/races/RacesAllViewData';\n\n/**\n * Races All View Data Builder\n * \n * Transforms API DTO into ViewData for the all races template.\n * Deterministic, side-effect free.\n */\nexport class RacesAllViewDataBuilder {\n static build(apiDto: any): RacesAllViewData {\n const races = apiDto.races.map((race: any) => ({\n id: race.id,\n track: race.track,\n car: race.car,\n scheduledAt: race.scheduledAt,\n status: race.status as 'scheduled' | 'running' | 'completed' | 'cancelled',\n sessionType: 'race',\n leagueId: race.leagueId,\n leagueName: race.leagueName,\n strengthOfField: race.strengthOfField ?? undefined,\n }));\n\n return {\n races,\n };\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/RacesViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/ResetPasswordViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/RulebookViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/SignupViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/SponsorDashboardViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/SponsorLogoViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/SponsorshipRequestsPageViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/SponsorshipRequestsViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/StewardingViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/TeamDetailViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/TeamLogoViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/TeamsViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/TrackImageViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/types/ForgotPasswordViewData.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":12,"column":14,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":12,"endColumn":17,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[236,239],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[236,239],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Forgot Password View Data\n * \n * ViewData for the forgot password template.\n */\n\nexport interface ForgotPasswordViewData {\n returnTo: string;\n showSuccess: boolean;\n successMessage?: string;\n magicLink?: string;\n formState: any; // Will be managed by client component\n isSubmitting: boolean;\n submitError?: string;\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/types/FormFieldState.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/types/FormState.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/types/LoginViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/types/ResetPasswordViewData.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":12,"column":14,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":12,"endColumn":17,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[228,231],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[228,231],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Reset Password View Data\n * \n * ViewData for the reset password template.\n */\n\nexport interface ResetPasswordViewData {\n token: string;\n returnTo: string;\n showSuccess: boolean;\n successMessage?: string;\n formState: any; // Will be managed by client component\n isSubmitting: boolean;\n submitError?: string;\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-data/types/SignupViewData.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":9,"column":14,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":9,"endColumn":17,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[137,140],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[137,140],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Signup View Data\n * \n * ViewData for the signup template.\n */\n\nexport interface SignupViewData {\n returnTo: string;\n formState: any; // Will be managed by client component\n isSubmitting: boolean;\n submitError?: string;\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-models/DriverProfileViewModelBuilder.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":114,"column":33,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":114,"endColumn":36,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[4521,4524],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[4521,4524],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":122,"column":25,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":122,"endColumn":28,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[4778,4781],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[4778,4781],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":123,"column":29,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":123,"endColumn":32,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[4851,4854],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[4851,4854],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":3,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import type { GetDriverProfileOutputDTO } from '@/lib/types/generated/GetDriverProfileOutputDTO';\nimport type { DriverProfileDriverSummaryDTO } from '@/lib/types/generated/DriverProfileDriverSummaryDTO';\nimport type { DriverProfileStatsDTO } from '@/lib/types/generated/DriverProfileStatsDTO';\nimport type { DriverProfileFinishDistributionDTO } from '@/lib/types/generated/DriverProfileFinishDistributionDTO';\nimport type { DriverProfileTeamMembershipDTO } from '@/lib/types/generated/DriverProfileTeamMembershipDTO';\nimport type { DriverProfileSocialSummaryDTO } from '@/lib/types/generated/DriverProfileSocialSummaryDTO';\nimport type { DriverProfileExtendedProfileDTO } from '@/lib/types/generated/DriverProfileExtendedProfileDTO';\nimport { DriverProfileViewModel } from '@/lib/view-models/DriverProfileViewModel';\nimport type {\n DriverProfileDriverSummaryViewModel,\n DriverProfileStatsViewModel,\n DriverProfileFinishDistributionViewModel,\n DriverProfileTeamMembershipViewModel,\n DriverProfileSocialSummaryViewModel,\n DriverProfileExtendedProfileViewModel,\n} from '@/lib/view-models/DriverProfileViewModel';\n\n/**\n * DriverProfileViewModelBuilder\n *\n * Transforms GetDriverProfileOutputDTO into DriverProfileViewModel.\n * Deterministic, side-effect free, no HTTP calls.\n */\nexport class DriverProfileViewModelBuilder {\n /**\n * Build ViewModel from API DTO\n * \n * @param apiDto - The API transport DTO\n * @returns ViewModel ready for template\n */\n static build(apiDto: GetDriverProfileOutputDTO): DriverProfileViewModel {\n return new DriverProfileViewModel({\n currentDriver: apiDto.currentDriver ? this.transformCurrentDriver(apiDto.currentDriver) : null,\n stats: apiDto.stats ? this.transformStats(apiDto.stats) : null,\n finishDistribution: apiDto.finishDistribution ? this.transformFinishDistribution(apiDto.finishDistribution) : null,\n teamMemberships: apiDto.teamMemberships.map(m => this.transformTeamMembership(m)),\n socialSummary: this.transformSocialSummary(apiDto.socialSummary),\n extendedProfile: apiDto.extendedProfile ? this.transformExtendedProfile(apiDto.extendedProfile) : null,\n });\n }\n\n private static transformCurrentDriver(dto: DriverProfileDriverSummaryDTO): DriverProfileDriverSummaryViewModel {\n return {\n id: dto.id,\n name: dto.name,\n country: dto.country,\n avatarUrl: dto.avatarUrl || '', // Handle undefined\n iracingId: dto.iracingId || null,\n joinedAt: dto.joinedAt,\n rating: dto.rating ?? null,\n globalRank: dto.globalRank ?? null,\n consistency: dto.consistency ?? null,\n bio: dto.bio || null,\n totalDrivers: dto.totalDrivers ?? null,\n };\n }\n\n private static transformStats(dto: DriverProfileStatsDTO): DriverProfileStatsViewModel {\n return {\n totalRaces: dto.totalRaces,\n wins: dto.wins,\n podiums: dto.podiums,\n dnfs: dto.dnfs,\n avgFinish: dto.avgFinish ?? null,\n bestFinish: dto.bestFinish ?? null,\n worstFinish: dto.worstFinish ?? null,\n finishRate: dto.finishRate ?? null,\n winRate: dto.winRate ?? null,\n podiumRate: dto.podiumRate ?? null,\n percentile: dto.percentile ?? null,\n rating: dto.rating ?? null,\n consistency: dto.consistency ?? null,\n overallRank: dto.overallRank ?? null,\n };\n }\n\n private static transformFinishDistribution(dto: DriverProfileFinishDistributionDTO): DriverProfileFinishDistributionViewModel {\n return {\n totalRaces: dto.totalRaces,\n wins: dto.wins,\n podiums: dto.podiums,\n topTen: dto.topTen,\n dnfs: dto.dnfs,\n other: dto.other,\n };\n }\n\n private static transformTeamMembership(dto: DriverProfileTeamMembershipDTO): DriverProfileTeamMembershipViewModel {\n return {\n teamId: dto.teamId,\n teamName: dto.teamName,\n teamTag: dto.teamTag || null,\n role: dto.role,\n joinedAt: dto.joinedAt,\n isCurrent: dto.isCurrent,\n };\n }\n\n private static transformSocialSummary(dto: DriverProfileSocialSummaryDTO): DriverProfileSocialSummaryViewModel {\n return {\n friendsCount: dto.friendsCount,\n friends: dto.friends.map(f => ({\n id: f.id,\n name: f.name,\n country: f.country,\n avatarUrl: f.avatarUrl || '', // Handle undefined\n })),\n };\n }\n\n private static transformExtendedProfile(dto: DriverProfileExtendedProfileDTO): DriverProfileExtendedProfileViewModel {\n return {\n socialHandles: dto.socialHandles.map(h => ({\n platform: h.platform as any, // Type assertion - assuming valid platform\n handle: h.handle,\n url: h.url,\n })),\n achievements: dto.achievements.map(a => ({\n id: a.id,\n title: a.title,\n description: a.description,\n icon: a.icon as any, // Type assertion - assuming valid icon\n rarity: a.rarity as any, // Type assertion - assuming valid rarity\n earnedAt: a.earnedAt,\n })),\n racingStyle: dto.racingStyle,\n favoriteTrack: dto.favoriteTrack,\n favoriteCar: dto.favoriteCar,\n timezone: dto.timezone,\n availableHours: dto.availableHours,\n lookingForTeam: dto.lookingForTeam,\n openToRequests: dto.openToRequests,\n };\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-models/DriversViewModelBuilder.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'DriverLeaderboardItemDTO' is defined but never used.","line":2,"column":15,"nodeType":"Identifier","messageId":"unusedVar","endLine":2,"endColumn":39}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import type { DriversLeaderboardDTO } from '@/lib/types/generated/DriversLeaderboardDTO';\nimport type { DriverLeaderboardItemDTO } from '@/lib/types/generated/DriverLeaderboardItemDTO';\nimport { DriverLeaderboardViewModel } from '@/lib/view-models/DriverLeaderboardViewModel';\n\n/**\n * DriversViewModelBuilder\n * \n * Transforms DriversLeaderboardDTO into DriverLeaderboardViewModel.\n * Deterministic, side-effect free, no HTTP calls.\n */\nexport class DriversViewModelBuilder {\n static build(apiDto: DriversLeaderboardDTO): DriverLeaderboardViewModel {\n return new DriverLeaderboardViewModel({\n drivers: apiDto.drivers,\n });\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-models/ForgotPasswordViewModelBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-models/LoginViewModelBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-models/OnboardingViewModelBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-models/ResetPasswordViewModelBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/builders/view-models/SignupViewModelBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/command-models/auth/LoginCommandModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/command-models/auth/SignupCommandModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/command-models/leagues/LeagueWizardCommandModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/command-models/protests/ProtestDecisionCommandModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/config/apiBaseUrl.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/config/env.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/config/mediaConfig.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/contracts/Result.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":21,"column":26,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":21,"endColumn":29,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[471,474],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[471,474],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":21,"column":32,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":21,"endColumn":35,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[477,480],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[477,480],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":23,"column":22,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":23,"endColumn":25,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[520,523],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[520,523],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_defaultValue' is defined but never used.","line":32,"column":12,"nodeType":"Identifier","messageId":"unusedVar","endLine":32,"endColumn":28},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":49,"column":26,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":49,"endColumn":29,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1239,1242],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1239,1242],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":49,"column":32,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":49,"endColumn":35,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1245,1248],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1245,1248],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_fn' is defined but never used.","line":51,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":51,"endColumn":32},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":51,"column":23,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":51,"endColumn":26,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1335,1338],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1335,1338],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":52,"column":20,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":52,"endColumn":23,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1383,1386],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1383,1386],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":9,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Result type for operations that can fail\n * \n * Inspired by Rust's Result type, this provides a type-safe way to handle\n * success and error cases without exceptions.\n */\n\nexport interface ResultOk {\n isOk(): true;\n isErr(): false;\n unwrap(): T;\n unwrapOr(defaultValue: T): T;\n getError(): never;\n map(fn: (value: T) => U): ResultOk;\n}\n\nexport interface ResultError {\n isOk(): false;\n isErr(): true;\n unwrap(): never;\n unwrapOr(defaultValue: any): any;\n getError(): E;\n map(fn: (value: any) => U): ResultError;\n}\n\nexport class Ok implements ResultOk {\n constructor(private readonly value: T) {}\n\n isOk(): true { return true; }\n isErr(): false { return false; }\n unwrap(): T { return this.value; }\n unwrapOr(_defaultValue: T): T { return this.value; }\n getError(): never {\n throw new Error('Cannot get error from Ok result');\n }\n map(fn: (value: T) => U): ResultOk {\n return new Ok(fn(this.value));\n }\n}\n\nexport class Err implements ResultError {\n constructor(private readonly error: E) {}\n\n isOk(): false { return false; }\n isErr(): true { return true; }\n unwrap(): never {\n throw new Error(`Called unwrap on error: ${this.error}`);\n }\n unwrapOr(defaultValue: any): any { return defaultValue; }\n getError(): E { return this.error; }\n map(_fn: (value: any) => U): ResultError {\n return this as any;\n }\n}\n\n/**\n * Result type alias\n */\nexport type Result = ResultOk | ResultError;\n\n/**\n * Result class with static factory methods\n * \n * Usage:\n * - Result.ok(value) creates a successful Result\n * - Result.err(error) creates an error Result\n */\nexport const Result = {\n ok(value: T): Result {\n return new Ok(value);\n },\n \n err(error: E): Result {\n return new Err(error);\n },\n};\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/contracts/api/ApiClient.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/contracts/builders/ViewDataBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/contracts/builders/ViewModelBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/contracts/display-objects/DisplayObject.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/contracts/mutations/Mutation.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/contracts/mutations/MutationError.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":21,"column":49,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":21,"endColumn":52,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[774,777],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[774,777],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Mutation Error Type\n * \n * Errors that can be handled by the client after a mutation.\n * These are mapped from DomainErrors by Mutations.\n */\n\nexport type MutationError =\n | 'userNotFound' // User doesn't exist\n | 'noPermission' // Insufficient permissions\n | 'invalidData' // Validation failed\n | 'updateFailed' // Update operation failed\n | 'deleteFailed' // Delete operation failed\n | 'createFailed' // Create operation failed\n | 'networkError' // Network/communication error\n | 'serverError' // Generic server error\n | 'notImplemented' // Feature not implemented\n | 'unknown'; // Unknown error\n\n// Helper to map DomainError to MutationError\nexport function mapToMutationError(domainError: any): MutationError {\n const errorType = domainError?.type || domainError?.name || 'unknown';\n \n switch (errorType) {\n case 'notFound':\n case 'NotFoundError':\n case 'userNotFound':\n return 'userNotFound';\n case 'unauthorized':\n case 'UnauthorizedError':\n case 'ForbiddenError':\n return 'noPermission';\n case 'validationError':\n case 'ValidationError':\n return 'invalidData';\n case 'serverError':\n case 'ServerError':\n case 'HttpServerError':\n return 'serverError';\n case 'networkError':\n case 'NetworkError':\n return 'networkError';\n case 'notImplemented':\n case 'NotImplementedError':\n return 'notImplemented';\n default:\n return 'unknown';\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/contracts/page-queries/PageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/contracts/page-queries/PageQueryResult.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/contracts/page-queries/PresentationError.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":18,"column":53,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":18,"endColumn":56,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[698,701],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[698,701],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Presentation Error Type\n * \n * Errors that can be handled by the presentation layer (RSC pages, templates).\n * These are mapped from DomainErrors by PageQueries.\n */\n\nexport type PresentationError = \n | 'notFound' // Resource not found - show 404 page\n | 'redirect' // Redirect to another page (e.g., login)\n | 'unauthorized' // Not authorized - show access denied\n | 'serverError' // Generic server error\n | 'networkError' // Network/communication error\n | 'validationError' // Invalid input data\n | 'unknown'; // Unknown error\n\n// Helper to map DomainError to PresentationError\nexport function mapToPresentationError(domainError: any): PresentationError {\n const errorType = domainError?.type || domainError?.name || 'unknown';\n \n switch (errorType) {\n case 'notFound':\n case 'NotFoundError':\n return 'notFound';\n case 'unauthorized':\n case 'UnauthorizedError':\n case 'ForbiddenError':\n return 'unauthorized';\n case 'serverError':\n case 'ServerError':\n case 'HttpServerError':\n return 'serverError';\n case 'networkError':\n case 'NetworkError':\n return 'networkError';\n case 'validationError':\n case 'ValidationError':\n return 'validationError';\n default:\n return 'unknown';\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/contracts/presenters/Presenter.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/contracts/services/Service.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/contracts/types/primitives.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/contracts/view-data/ViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/contracts/view-models/ViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/di/container.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":43,"column":60,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":43,"endColumn":63,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1186,1189],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1186,1189],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'promises' is assigned a value but never used.","line":47,"column":9,"nodeType":"Identifier","messageId":"unusedVar","endLine":47,"endColumn":17}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Container } from 'inversify';\n\n// Module imports\nimport { ApiModule } from './modules/api.module';\nimport { AuthModule } from './modules/auth.module';\nimport { CoreModule } from './modules/core.module';\nimport { DriverModule } from './modules/driver.module';\nimport { LeagueModule } from './modules/league.module';\nimport { TeamModule } from './modules/team.module';\nimport { RaceModule } from './modules/race.module';\nimport { LandingModule } from './modules/landing.module';\nimport { PolicyModule } from './modules/policy.module';\nimport { SponsorModule } from './modules/sponsor.module';\nimport { AnalyticsModule } from './modules/analytics.module';\n\n/**\n * Creates and configures the root DI container\n */\nexport function createContainer(): Container {\n const container = new Container();\n\n // Load all modules\n container.load(\n CoreModule,\n ApiModule,\n AuthModule,\n LeagueModule,\n DriverModule,\n TeamModule,\n RaceModule,\n LandingModule,\n PolicyModule,\n SponsorModule,\n AnalyticsModule\n );\n\n return container;\n}\n\n/**\n * Creates a container for testing with mock overrides\n */\nexport function createTestContainer(overrides: Map = new Map()): Container {\n const container = createContainer();\n \n // Apply mock overrides using rebind\n const promises = Array.from(overrides.entries()).map(([token, mockInstance]) => {\n return container.rebind(token).then(bind => bind.toConstantValue(mockInstance));\n });\n \n // Return container immediately, mocks will be available after promises resolve\n // For synchronous testing, users can bind directly before loading modules\n return container;\n}\n\n/**\n * Container lifecycle management\n */\nexport class ContainerManager {\n private static instance: ContainerManager | null = null;\n private container: Container | null = null;\n\n private constructor() {}\n\n static getInstance(): ContainerManager {\n if (!ContainerManager.instance) {\n ContainerManager.instance = new ContainerManager();\n }\n return ContainerManager.instance;\n }\n\n getContainer(): Container {\n if (!this.container) {\n this.container = createContainer();\n }\n return this.container;\n }\n\n createScopedContainer(): Container {\n // In this version, we create a new container\n return new Container();\n }\n\n dispose(): void {\n if (this.container) {\n this.container.unbindAll();\n this.container = null;\n }\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/di/hooks/useInject.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":38,"column":41,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":38,"endColumn":44,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1000,1003],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1000,1003],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\n\nimport { useContext, useMemo } from 'react';\nimport { ContainerContext } from '../providers/ContainerProvider';\n\n/**\n * Primary injection hook - gets a service by token\n *\n * @example\n * const leagueService = useInject(LEAGUE_SERVICE_TOKEN);\n */\nexport function useInject(token: T): T extends { type: infer U } ? U : unknown {\n const container = useContext(ContainerContext);\n \n if (!container) {\n throw new Error('useInject must be used within ContainerProvider');\n }\n\n return useMemo(() => {\n try {\n return container.get(token) as T extends { type: infer U } ? U : unknown;\n } catch (error) {\n console.error(`Failed to resolve token ${token.toString()}:`, error);\n throw error;\n }\n }, [container, token]);\n}\n\n/**\n * Hook to get multiple services at once\n * \n * @example\n * const [leagueService, driverService] = useInjectMany([\n * LEAGUE_SERVICE_TOKEN,\n * DRIVER_SERVICE_TOKEN\n * ]);\n */\nexport function useInjectMany(tokens: symbol[]): T {\n const container = useContext(ContainerContext);\n \n if (!container) {\n throw new Error('useInjectMany must be used within ContainerProvider');\n }\n\n return useMemo(() => {\n return tokens.map(token => container.get(token)) as T;\n }, [container, tokens]);\n}\n\n/**\n * Hook to get all services of a given type (tag-based resolution)\n * \n * @example\n * const allServices = useInjectAll('Service');\n */\nexport function useInjectAll(serviceIdentifier: string | symbol): T[] {\n const container = useContext(ContainerContext);\n \n if (!container) {\n throw new Error('useInjectAll must be used within ContainerProvider');\n }\n\n return useMemo(() => {\n return container.getAll(serviceIdentifier);\n }, [container, serviceIdentifier]);\n}\n\n/**\n * Hook for optional service injection (returns null if not found)\n * \n * @example\n * const optionalService = useInjectOptional(MAYBE_SERVICE_TOKEN);\n */\nexport function useInjectOptional(token: symbol): T | null {\n const container = useContext(ContainerContext);\n \n return useMemo(() => {\n if (!container) {\n return null;\n }\n try {\n return container.get(token);\n } catch {\n return null;\n }\n }, [container, token]);\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/di/hooks/useReactQueryWithApiError.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":8,"column":42,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":8,"endColumn":45,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[308,311],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[308,311],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":27,"column":52,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":27,"endColumn":55,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[820,823],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[820,823],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { UseQueryResult } from '@tanstack/react-query';\nimport { ApiError } from '@/lib/api/base/ApiError';\n\n/**\n * Converts React-Query error to ApiError for StateContainer compatibility\n * This eliminates the need to repeat error conversion logic in every hook\n */\nexport function convertToApiError(error: any): ApiError | null {\n if (!error) return null;\n \n if (error instanceof ApiError) {\n return error;\n }\n \n return new ApiError(\n error.message || 'An unexpected error occurred',\n 'UNKNOWN_ERROR',\n { timestamp: new Date().toISOString() },\n error instanceof Error ? error : undefined\n );\n}\n\n/**\n * Helper function to enhance React-Query result with ApiError conversion\n * Returns the same structure as before but with DRY error handling\n */\nexport function enhanceQueryResult(\n queryResult: UseQueryResult\n) {\n const apiError = convertToApiError(queryResult.error);\n \n return {\n ...queryResult,\n error: apiError, // Directly return ApiError for StateContainer compatibility\n retry: async () => {\n await queryResult.refetch();\n },\n };\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/di/index.ts","messages":[{"ruleId":"gridpilot-rules/no-index-files","severity":2,"message":"Index files are banned. Use explicit imports and barrel exports. Example: Instead of \"import { foo } from \"./\", use \"import { foo } from \"./foo\" and export from \"./foo\" explicitly.","line":1,"column":1,"nodeType":null,"messageId":"indexFile"}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"// Must be first import - enables decorator metadata\nimport 'reflect-metadata';\n\n// Core exports\nexport * from './container';\nexport * from './tokens';\n\n// React integration\nexport * from './hooks/useInject';\nexport * from './hooks/useReactQueryWithApiError';\nexport * from './providers/ContainerProvider';\n\n// Modules\nexport * from './modules/api.module';\nexport * from './modules/auth.module';\nexport * from './modules/core.module';\nexport * from './modules/driver.module';\nexport * from './modules/league.module';\nexport * from './modules/race.module';\nexport * from './modules/team.module';\nexport * from './modules/landing.module';\nexport * from './modules/policy.module';\nexport * from './modules/sponsor.module';","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/di/modules/analytics.module.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/di/modules/api.module.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":42,"column":18,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":42,"endColumn":21,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1702,1705],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1702,1705],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":43,"column":14,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":43,"endColumn":17,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1720,1723],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1720,1723],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { ContainerModule } from 'inversify';\nimport { RacesApiClient } from '../../api/races/RacesApiClient';\nimport { DriversApiClient } from '../../api/drivers/DriversApiClient';\nimport { TeamsApiClient } from '../../api/teams/TeamsApiClient';\nimport { LeaguesApiClient } from '../../api/leagues/LeaguesApiClient';\nimport { SponsorsApiClient } from '../../api/sponsors/SponsorsApiClient';\nimport { PaymentsApiClient } from '../../api/payments/PaymentsApiClient';\nimport { WalletsApiClient } from '../../api/wallets/WalletsApiClient';\nimport { AuthApiClient } from '../../api/auth/AuthApiClient';\nimport { AnalyticsApiClient } from '../../api/analytics/AnalyticsApiClient';\nimport { MediaApiClient } from '../../api/media/MediaApiClient';\nimport { DashboardApiClient } from '../../api/dashboard/DashboardApiClient';\nimport { PolicyApiClient } from '../../api/policy/PolicyApiClient';\nimport { ProtestsApiClient } from '../../api/protests/ProtestsApiClient';\nimport { PenaltiesApiClient } from '../../api/penalties/PenaltiesApiClient';\n\nimport { \n LOGGER_TOKEN,\n ERROR_REPORTER_TOKEN,\n CONFIG_TOKEN,\n LEAGUE_API_CLIENT_TOKEN,\n DRIVER_API_CLIENT_TOKEN,\n TEAM_API_CLIENT_TOKEN,\n RACE_API_CLIENT_TOKEN,\n SPONSOR_API_CLIENT_TOKEN,\n PAYMENT_API_CLIENT_TOKEN,\n WALLET_API_CLIENT_TOKEN,\n AUTH_API_CLIENT_TOKEN,\n ANALYTICS_API_CLIENT_TOKEN,\n MEDIA_API_CLIENT_TOKEN,\n DASHBOARD_API_CLIENT_TOKEN,\n POLICY_API_CLIENT_TOKEN,\n PROTEST_API_CLIENT_TOKEN,\n PENALTY_API_CLIENT_TOKEN\n} from '../tokens';\n\nexport const ApiModule = new ContainerModule((options) => {\n const bind = options.bind;\n\n // Factory for creating API clients with shared dependencies\n const createApiClient = (\n ClientClass: any,\n context: any\n ) => {\n const getConfig = context.get(CONFIG_TOKEN);\n const baseUrl = getConfig(); // Call function to get fresh config\n const errorReporter = context.get(ERROR_REPORTER_TOKEN);\n const logger = context.get(LOGGER_TOKEN);\n \n return new ClientClass(baseUrl, errorReporter, logger);\n };\n\n // Register all API clients\n bind(LEAGUE_API_CLIENT_TOKEN)\n .toDynamicValue(ctx => createApiClient(LeaguesApiClient, ctx))\n .inSingletonScope();\n\n bind(DRIVER_API_CLIENT_TOKEN)\n .toDynamicValue(ctx => createApiClient(DriversApiClient, ctx))\n .inSingletonScope();\n\n bind(TEAM_API_CLIENT_TOKEN)\n .toDynamicValue(ctx => createApiClient(TeamsApiClient, ctx))\n .inSingletonScope();\n\n bind(RACE_API_CLIENT_TOKEN)\n .toDynamicValue(ctx => createApiClient(RacesApiClient, ctx))\n .inSingletonScope();\n\n bind(SPONSOR_API_CLIENT_TOKEN)\n .toDynamicValue(ctx => createApiClient(SponsorsApiClient, ctx))\n .inSingletonScope();\n\n bind(PAYMENT_API_CLIENT_TOKEN)\n .toDynamicValue(ctx => createApiClient(PaymentsApiClient, ctx))\n .inSingletonScope();\n\n bind(WALLET_API_CLIENT_TOKEN)\n .toDynamicValue(ctx => createApiClient(WalletsApiClient, ctx))\n .inSingletonScope();\n\n bind(AUTH_API_CLIENT_TOKEN)\n .toDynamicValue(ctx => createApiClient(AuthApiClient, ctx))\n .inSingletonScope();\n\n bind(ANALYTICS_API_CLIENT_TOKEN)\n .toDynamicValue(ctx => createApiClient(AnalyticsApiClient, ctx))\n .inSingletonScope();\n\n bind(MEDIA_API_CLIENT_TOKEN)\n .toDynamicValue(ctx => createApiClient(MediaApiClient, ctx))\n .inSingletonScope();\n\n bind(DASHBOARD_API_CLIENT_TOKEN)\n .toDynamicValue(ctx => createApiClient(DashboardApiClient, ctx))\n .inSingletonScope();\n\n bind(POLICY_API_CLIENT_TOKEN)\n .toDynamicValue(ctx => createApiClient(PolicyApiClient, ctx))\n .inSingletonScope();\n\n bind(PROTEST_API_CLIENT_TOKEN)\n .toDynamicValue(ctx => createApiClient(ProtestsApiClient, ctx))\n .inSingletonScope();\n\n bind(PENALTY_API_CLIENT_TOKEN)\n .toDynamicValue(ctx => createApiClient(PenaltiesApiClient, ctx))\n .inSingletonScope();\n});","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/di/modules/auth.module.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'AuthApiClient' is defined but never used.","line":4,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":4,"endColumn":23},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'AUTH_API_CLIENT_TOKEN' is defined but never used.","line":9,"column":3,"nodeType":"Identifier","messageId":"unusedVar","endLine":9,"endColumn":24}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { ContainerModule } from 'inversify';\nimport { AuthService } from '../../services/auth/AuthService';\nimport { SessionService } from '../../services/auth/SessionService';\nimport { AuthApiClient } from '../../api/auth/AuthApiClient';\n\nimport {\n AUTH_SERVICE_TOKEN,\n SESSION_SERVICE_TOKEN,\n AUTH_API_CLIENT_TOKEN\n} from '../tokens';\n\nexport const AuthModule = new ContainerModule((options) => {\n const bind = options.bind;\n\n // Session Service\n bind(SESSION_SERVICE_TOKEN)\n .to(SessionService)\n .inSingletonScope();\n\n // Auth Service - now creates its own dependencies\n bind(AUTH_SERVICE_TOKEN)\n .to(AuthService)\n .inSingletonScope();\n});\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/di/modules/core.module.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/di/modules/driver.module.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'DRIVER_API_CLIENT_TOKEN' is defined but never used.","line":2,"column":32,"nodeType":"Identifier","messageId":"unusedVar","endLine":2,"endColumn":55},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'DriversApiClient' is defined but never used.","line":5,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":5,"endColumn":26}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { ContainerModule } from 'inversify';\nimport { DRIVER_SERVICE_TOKEN, DRIVER_API_CLIENT_TOKEN, ONBOARDING_SERVICE_TOKEN } from '../tokens';\nimport { DriverService } from '@/lib/services/drivers/DriverService';\nimport { OnboardingService } from '@/lib/services/onboarding/OnboardingService';\nimport { DriversApiClient } from '@/lib/api/drivers/DriversApiClient';\n\nexport const DriverModule = new ContainerModule((options) => {\n const bind = options.bind;\n\n bind(DRIVER_SERVICE_TOKEN)\n .to(DriverService)\n .inSingletonScope();\n\n bind(ONBOARDING_SERVICE_TOKEN)\n .toDynamicValue(() => {\n return new OnboardingService();\n })\n .inSingletonScope();\n});","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/di/modules/landing.module.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'RACE_API_CLIENT_TOKEN' is defined but never used.","line":2,"column":33,"nodeType":"Identifier","messageId":"unusedVar","endLine":2,"endColumn":54},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'LEAGUE_API_CLIENT_TOKEN' is defined but never used.","line":2,"column":56,"nodeType":"Identifier","messageId":"unusedVar","endLine":2,"endColumn":79},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'TEAM_API_CLIENT_TOKEN' is defined but never used.","line":2,"column":81,"nodeType":"Identifier","messageId":"unusedVar","endLine":2,"endColumn":102},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'AUTH_API_CLIENT_TOKEN' is defined but never used.","line":2,"column":104,"nodeType":"Identifier","messageId":"unusedVar","endLine":2,"endColumn":125},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'RacesApiClient' is defined but never used.","line":4,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":4,"endColumn":24},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'LeaguesApiClient' is defined but never used.","line":5,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":5,"endColumn":26},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'TeamsApiClient' is defined but never used.","line":6,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":6,"endColumn":24},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'AuthApiClient' is defined but never used.","line":7,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":7,"endColumn":23}],"suppressedMessages":[],"errorCount":8,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { ContainerModule } from 'inversify';\nimport { LANDING_SERVICE_TOKEN, RACE_API_CLIENT_TOKEN, LEAGUE_API_CLIENT_TOKEN, TEAM_API_CLIENT_TOKEN, AUTH_API_CLIENT_TOKEN } from '../tokens';\nimport { LandingService } from '@/lib/services/landing/LandingService';\nimport { RacesApiClient } from '@/lib/api/races/RacesApiClient';\nimport { LeaguesApiClient } from '@/lib/api/leagues/LeaguesApiClient';\nimport { TeamsApiClient } from '@/lib/api/teams/TeamsApiClient';\nimport { AuthApiClient } from '@/lib/api/auth/AuthApiClient';\n\nexport const LandingModule = new ContainerModule((options) => {\n const bind = options.bind;\n\n // Landing Service\n bind(LANDING_SERVICE_TOKEN)\n .to(LandingService)\n .inSingletonScope();\n});","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/di/modules/league.module.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/di/modules/policy.module.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'POLICY_API_CLIENT_TOKEN' is defined but never used.","line":2,"column":32,"nodeType":"Identifier","messageId":"unusedVar","endLine":2,"endColumn":55},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'PolicyApiClient' is defined but never used.","line":4,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":4,"endColumn":25}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { ContainerModule } from 'inversify';\nimport { POLICY_SERVICE_TOKEN, POLICY_API_CLIENT_TOKEN } from '../tokens';\nimport { PolicyService } from '@/lib/services/policy/PolicyService';\nimport { PolicyApiClient } from '@/lib/api/policy/PolicyApiClient';\n\nexport const PolicyModule = new ContainerModule((options) => {\n const bind = options.bind;\n\n // Policy Service\n bind(POLICY_SERVICE_TOKEN)\n .to(PolicyService)\n .inSingletonScope();\n});","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/di/modules/race.module.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'RacesApiClient' is defined but never used.","line":6,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":6,"endColumn":24},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'ProtestsApiClient' is defined but never used.","line":7,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":7,"endColumn":27},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'PenaltiesApiClient' is defined but never used.","line":8,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":8,"endColumn":28},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'RACE_API_CLIENT_TOKEN' is defined but never used.","line":14,"column":3,"nodeType":"Identifier","messageId":"unusedVar","endLine":14,"endColumn":24},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'PROTEST_API_CLIENT_TOKEN' is defined but never used.","line":15,"column":3,"nodeType":"Identifier","messageId":"unusedVar","endLine":15,"endColumn":27},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'PENALTY_API_CLIENT_TOKEN' is defined but never used.","line":16,"column":3,"nodeType":"Identifier","messageId":"unusedVar","endLine":16,"endColumn":27}],"suppressedMessages":[],"errorCount":6,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { ContainerModule } from 'inversify';\nimport { RaceService } from '@/lib/services/races/RaceService';\nimport { RaceResultsService } from '@/lib/services/races/RaceResultsService';\nimport { RaceStewardingService } from '@/lib/services/races/RaceStewardingService';\n\nimport { RacesApiClient } from '@/lib/api/races/RacesApiClient';\nimport { ProtestsApiClient } from '@/lib/api/protests/ProtestsApiClient';\nimport { PenaltiesApiClient } from '@/lib/api/penalties/PenaltiesApiClient';\n\nimport {\n RACE_SERVICE_TOKEN,\n RACE_RESULTS_SERVICE_TOKEN,\n RACE_STEWARDING_SERVICE_TOKEN,\n RACE_API_CLIENT_TOKEN,\n PROTEST_API_CLIENT_TOKEN,\n PENALTY_API_CLIENT_TOKEN,\n} from '../tokens';\n\nexport const RaceModule = new ContainerModule((options) => {\n const bind = options.bind;\n\n // Race Service - creates its own dependencies per contract\n bind(RACE_SERVICE_TOKEN)\n .to(RaceService)\n .inSingletonScope();\n\n // Race Results Service - creates its own dependencies per contract\n bind(RACE_RESULTS_SERVICE_TOKEN)\n .to(RaceResultsService)\n .inSingletonScope();\n\n // Race Stewarding Service - creates its own dependencies per contract\n bind(RACE_STEWARDING_SERVICE_TOKEN)\n .to(RaceStewardingService)\n .inSingletonScope();\n});","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/di/modules/sponsor.module.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/di/modules/team.module.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/di/providers/ContainerProvider.tsx","messages":[{"ruleId":"react-hooks/exhaustive-deps","severity":2,"message":"React Hook useMemo has an unnecessary dependency: 'scoped'. Either exclude it or remove the dependency array.","line":34,"column":6,"nodeType":"ArrayExpression","endLine":34,"endColumn":33,"suggestions":[{"desc":"Update the dependencies array to be: [providedContainer]","fix":{"range":[907,934],"text":"[providedContainer]"}}]},{"ruleId":"react-hooks/exhaustive-deps","severity":2,"message":"React Hook useMemo has an unnecessary dependency: 'rootContainer'. Either exclude it or remove the dependency array.","line":63,"column":6,"nodeType":"ArrayExpression","endLine":63,"endColumn":21,"suggestions":[{"desc":"Update the dependencies array to be: []","fix":{"range":[1621,1636],"text":"[]"}}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\n\nimport { createContext, ReactNode, useContext, useMemo } from 'react';\nimport { Container } from 'inversify';\nimport { createContainer } from '../container';\n\nexport const ContainerContext = createContext(null);\n\ninterface ContainerProviderProps {\n children: ReactNode;\n /**\n * Optional container instance (for testing or custom configuration)\n */\n container?: Container;\n /**\n * Create scoped container for request/session isolation\n */\n scoped?: boolean;\n}\n\nexport function ContainerProvider({ \n children, \n container: providedContainer,\n scoped = false \n}: ContainerProviderProps) {\n const container = useMemo(() => {\n if (providedContainer) {\n return providedContainer;\n }\n \n const rootContainer = createContainer();\n // Note: This version doesn't support child containers, so scoped just returns root\n return rootContainer;\n }, [providedContainer, scoped]);\n\n return (\n \n {children}\n \n );\n}\n\n/**\n * Hook to access the container directly\n */\nexport function useContainer(): Container {\n const container = useContext(ContainerContext);\n if (!container) {\n throw new Error('useContainer must be used within ContainerProvider');\n }\n return container;\n}\n\n/**\n * Hook to get a scoped container for request isolation\n * (In this version, returns root container)\n */\nexport function useScopedContainer(): Container {\n const rootContainer = useContainer();\n return useMemo(() => {\n // Return new container for isolation\n return new Container();\n }, [rootContainer]);\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/di/tokens.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/display-objects/AchievementDisplay.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/display-objects/CountryFlagDisplay.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/display-objects/DashboardConsistencyDisplay.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/display-objects/DashboardCountDisplay.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/display-objects/DashboardDateDisplay.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/display-objects/DashboardLeaguePositionDisplay.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/display-objects/DashboardRankDisplay.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/display-objects/LeagueRoleDisplay.ts","messages":[{"ruleId":"gridpilot-rules/display-no-business-logic","severity":2,"message":"Display Objects must be class-based and export only classes - see apps/website/lib/contracts/display-objects/DisplayObject.ts","line":8,"column":1,"nodeType":"ExportNamedDeclaration","messageId":"message","endLine":25,"endColumn":12}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"export type LeagueRole = 'owner' | 'admin' | 'steward' | 'member';\n\nexport interface LeagueRoleDisplayData {\n text: string;\n badgeClasses: string;\n}\n\nexport const leagueRoleDisplay: Record = {\n owner: {\n text: 'Owner',\n badgeClasses: 'bg-yellow-500/10 text-yellow-500 border-yellow-500/30',\n },\n admin: {\n text: 'Admin',\n badgeClasses: 'bg-purple-500/10 text-purple-400 border-purple-500/30',\n },\n steward: {\n text: 'Steward',\n badgeClasses: 'bg-blue-500/10 text-blue-400 border-blue-500/30',\n },\n member: {\n text: 'Member',\n badgeClasses: 'bg-primary-blue/10 text-primary-blue border-primary-blue/30',\n },\n} as const;\n\n// For backward compatibility, also export the class with static method\nexport class LeagueRoleDisplay {\n static getLeagueRoleDisplay(role: LeagueRole) {\n return leagueRoleDisplay[role];\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/display-objects/LeagueWizardValidationMessages.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/display-objects/MedalDisplay.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/display-objects/ProfileDisplay.ts","messages":[{"ruleId":"gridpilot-rules/display-no-business-logic","severity":2,"message":"Display Objects must be class-based and export only classes - see apps/website/lib/contracts/display-objects/DisplayObject.ts","line":17,"column":1,"nodeType":"ExportNamedDeclaration","messageId":"message","endLine":31,"endColumn":12},{"ruleId":"gridpilot-rules/display-no-business-logic","severity":2,"message":"Display Objects must be class-based and export only classes - see apps/website/lib/contracts/display-objects/DisplayObject.ts","line":33,"column":1,"nodeType":"ExportNamedDeclaration","messageId":"message","endLine":36,"endColumn":2},{"ruleId":"gridpilot-rules/display-no-business-logic","severity":2,"message":"Display Objects must be class-based and export only classes - see apps/website/lib/contracts/display-objects/DisplayObject.ts","line":48,"column":1,"nodeType":"ExportNamedDeclaration","messageId":"message","endLine":69,"endColumn":12},{"ruleId":"gridpilot-rules/display-no-business-logic","severity":2,"message":"Display Objects must be class-based and export only classes - see apps/website/lib/contracts/display-objects/DisplayObject.ts","line":71,"column":1,"nodeType":"ExportNamedDeclaration","messageId":"message","endLine":73,"endColumn":2},{"ruleId":"gridpilot-rules/display-no-business-logic","severity":2,"message":"Display Objects must be class-based and export only classes - see apps/website/lib/contracts/display-objects/DisplayObject.ts","line":86,"column":1,"nodeType":"ExportNamedDeclaration","messageId":"message","endLine":93,"endColumn":12},{"ruleId":"gridpilot-rules/display-no-business-logic","severity":2,"message":"Display Objects must be class-based and export only classes - see apps/website/lib/contracts/display-objects/DisplayObject.ts","line":95,"column":1,"nodeType":"ExportNamedDeclaration","messageId":"message","endLine":97,"endColumn":2},{"ruleId":"gridpilot-rules/display-no-business-logic","severity":2,"message":"Display Objects must be class-based and export only classes - see apps/website/lib/contracts/display-objects/DisplayObject.ts","line":108,"column":1,"nodeType":"ExportNamedDeclaration","messageId":"message","endLine":125,"endColumn":12},{"ruleId":"gridpilot-rules/display-no-business-logic","severity":2,"message":"Display Objects must be class-based and export only classes - see apps/website/lib/contracts/display-objects/DisplayObject.ts","line":127,"column":1,"nodeType":"ExportNamedDeclaration","messageId":"message","endLine":129,"endColumn":2},{"ruleId":"gridpilot-rules/display-no-business-logic","severity":2,"message":"Display Objects must be class-based and export only classes - see apps/website/lib/contracts/display-objects/DisplayObject.ts","line":140,"column":1,"nodeType":"ExportNamedDeclaration","messageId":"message","endLine":146,"endColumn":2},{"ruleId":"gridpilot-rules/display-no-business-logic","severity":2,"message":"Display Objects must be class-based and export only classes - see apps/website/lib/contracts/display-objects/DisplayObject.ts","line":153,"column":1,"nodeType":"ExportNamedDeclaration","messageId":"message","endLine":160,"endColumn":2},{"ruleId":"gridpilot-rules/display-no-business-logic","severity":2,"message":"Display Objects must be class-based and export only classes - see apps/website/lib/contracts/display-objects/DisplayObject.ts","line":176,"column":1,"nodeType":"ExportNamedDeclaration","messageId":"message","endLine":179,"endColumn":2},{"ruleId":"gridpilot-rules/display-no-business-logic","severity":2,"message":"Display Objects must be class-based and export only classes - see apps/website/lib/contracts/display-objects/DisplayObject.ts","line":186,"column":1,"nodeType":"ExportNamedDeclaration","messageId":"message","endLine":189,"endColumn":2},{"ruleId":"gridpilot-rules/display-no-business-logic","severity":2,"message":"Display Objects must be class-based and export only classes - see apps/website/lib/contracts/display-objects/DisplayObject.ts","line":196,"column":1,"nodeType":"ExportNamedDeclaration","messageId":"message","endLine":199,"endColumn":2},{"ruleId":"gridpilot-rules/display-no-business-logic","severity":2,"message":"Display Objects must be class-based and export only classes - see apps/website/lib/contracts/display-objects/DisplayObject.ts","line":206,"column":1,"nodeType":"ExportNamedDeclaration","messageId":"message","endLine":209,"endColumn":2},{"ruleId":"gridpilot-rules/display-no-business-logic","severity":2,"message":"Display Objects must be class-based and export only classes - see apps/website/lib/contracts/display-objects/DisplayObject.ts","line":216,"column":1,"nodeType":"ExportNamedDeclaration","messageId":"message","endLine":219,"endColumn":2},{"ruleId":"gridpilot-rules/display-no-business-logic","severity":2,"message":"Display Objects must be class-based and export only classes - see apps/website/lib/contracts/display-objects/DisplayObject.ts","line":226,"column":1,"nodeType":"ExportNamedDeclaration","messageId":"message","endLine":229,"endColumn":2},{"ruleId":"gridpilot-rules/display-no-business-logic","severity":2,"message":"Display Objects must be class-based and export only classes - see apps/website/lib/contracts/display-objects/DisplayObject.ts","line":240,"column":1,"nodeType":"ExportNamedDeclaration","messageId":"message","endLine":257,"endColumn":12},{"ruleId":"gridpilot-rules/display-no-business-logic","severity":2,"message":"Display Objects must be class-based and export only classes - see apps/website/lib/contracts/display-objects/DisplayObject.ts","line":259,"column":1,"nodeType":"ExportNamedDeclaration","messageId":"message","endLine":261,"endColumn":2}],"suppressedMessages":[],"errorCount":18,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Profile Display Objects\n * \n * Deterministic formatting for profile data.\n * NO Intl.*, NO Date.toLocale*, NO dynamic formatting.\n */\n\n// ============================================================================\n// COUNTRY FLAG DISPLAY\n// ============================================================================\n\nexport interface CountryFlagDisplayData {\n flag: string;\n label: string;\n}\n\nexport const countryFlagDisplay: Record = {\n // Common country codes - add as needed\n US: { flag: '🇺🇸', label: 'United States' },\n GB: { flag: '🇬🇧', label: 'United Kingdom' },\n DE: { flag: '🇩🇪', label: 'Germany' },\n FR: { flag: '🇫🇷', label: 'France' },\n IT: { flag: '🇮🇹', label: 'Italy' },\n ES: { flag: '🇪🇸', label: 'Spain' },\n JP: { flag: '🇯🇵', label: 'Japan' },\n AU: { flag: '🇦🇺', label: 'Australia' },\n CA: { flag: '🇨🇦', label: 'Canada' },\n BR: { flag: '🇧🇷', label: 'Brazil' },\n // Fallback for unknown codes\n DEFAULT: { flag: '🏁', label: 'Unknown' },\n} as const;\n\nexport function getCountryFlagDisplay(countryCode: string): CountryFlagDisplayData {\n const code = countryCode.toUpperCase();\n return countryFlagDisplay[code] || countryFlagDisplay.DEFAULT;\n}\n\n// ============================================================================\n// ACHIEVEMENT RARITY DISPLAY\n// ============================================================================\n\nexport interface AchievementRarityDisplayData {\n text: string;\n badgeClasses: string;\n borderClasses: string;\n}\n\nexport const achievementRarityDisplay: Record = {\n common: {\n text: 'Common',\n badgeClasses: 'bg-gray-400/10 text-gray-400',\n borderClasses: 'border-gray-400/30',\n },\n rare: {\n text: 'Rare',\n badgeClasses: 'bg-primary-blue/10 text-primary-blue',\n borderClasses: 'border-primary-blue/30',\n },\n epic: {\n text: 'Epic',\n badgeClasses: 'bg-purple-400/10 text-purple-400',\n borderClasses: 'border-purple-400/30',\n },\n legendary: {\n text: 'Legendary',\n badgeClasses: 'bg-yellow-400/10 text-yellow-400',\n borderClasses: 'border-yellow-400/30',\n },\n} as const;\n\nexport function getAchievementRarityDisplay(rarity: string): AchievementRarityDisplayData {\n return achievementRarityDisplay[rarity] || achievementRarityDisplay.common;\n}\n\n// ============================================================================\n// ACHIEVEMENT ICON DISPLAY\n// ============================================================================\n\nexport type AchievementIconType = 'trophy' | 'medal' | 'star' | 'crown' | 'target' | 'zap';\n\nexport interface AchievementIconDisplayData {\n name: string;\n // Icon component will be resolved in UI layer\n}\n\nexport const achievementIconDisplay: Record = {\n trophy: { name: 'Trophy' },\n medal: { name: 'Medal' },\n star: { name: 'Star' },\n crown: { name: 'Crown' },\n target: { name: 'Target' },\n zap: { name: 'Zap' },\n} as const;\n\nexport function getAchievementIconDisplay(icon: string): AchievementIconDisplayData {\n return achievementIconDisplay[icon as AchievementIconType] || achievementIconDisplay.trophy;\n}\n\n// ============================================================================\n// SOCIAL PLATFORM DISPLAY\n// ============================================================================\n\nexport interface SocialPlatformDisplayData {\n name: string;\n hoverClasses: string;\n}\n\nexport const socialPlatformDisplay: Record = {\n twitter: {\n name: 'Twitter',\n hoverClasses: 'hover:text-sky-400 hover:bg-sky-400/10',\n },\n youtube: {\n name: 'YouTube',\n hoverClasses: 'hover:text-red-500 hover:bg-red-500/10',\n },\n twitch: {\n name: 'Twitch',\n hoverClasses: 'hover:text-purple-400 hover:bg-purple-400/10',\n },\n discord: {\n name: 'Discord',\n hoverClasses: 'hover:text-indigo-400 hover:bg-indigo-400/10',\n },\n} as const;\n\nexport function getSocialPlatformDisplay(platform: string): SocialPlatformDisplayData {\n return socialPlatformDisplay[platform] || socialPlatformDisplay.discord;\n}\n\n// ============================================================================\n// DATE FORMATTING (DETERMINISTIC)\n// ============================================================================\n\n/**\n * Format date string to \"Month Year\" format\n * Input: ISO date string (e.g., \"2024-01-15T10:30:00Z\")\n * Output: \"Jan 2024\"\n */\nexport function formatMonthYear(dateString: string): string {\n const date = new Date(dateString);\n const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\n const month = months[date.getUTCMonth()];\n const year = date.getUTCFullYear();\n return `${month} ${year}`;\n}\n\n/**\n * Format date string to \"Month Day, Year\" format\n * Input: ISO date string\n * Output: \"Jan 15, 2024\"\n */\nexport function formatMonthDayYear(dateString: string): string {\n const date = new Date(dateString);\n const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\n const month = months[date.getUTCMonth()];\n const day = date.getUTCDate();\n const year = date.getUTCFullYear();\n return `${month} ${day}, ${year}`;\n}\n\n// ============================================================================\n// STATISTICS FORMATTING\n// ============================================================================\n\nexport interface StatDisplayData {\n value: string;\n label: string;\n}\n\n/**\n * Format percentage with 1 decimal place\n * Input: 0.1234\n * Output: \"12.3%\"\n */\nexport function formatPercentage(value: number | null): string {\n if (value === null || value === undefined) return '0.0%';\n return `${(value * 100).toFixed(1)}%`;\n}\n\n/**\n * Format finish position\n * Input: 1\n * Output: \"P1\"\n */\nexport function formatFinishPosition(position: number | null): string {\n if (position === null || position === undefined) return 'P-';\n return `P${position}`;\n}\n\n/**\n * Format average finish with 1 decimal place\n * Input: 3.456\n * Output: \"P3.5\"\n */\nexport function formatAvgFinish(avg: number | null): string {\n if (avg === null || avg === undefined) return 'P-';\n return `P${avg.toFixed(1)}`;\n}\n\n/**\n * Format rating (whole number)\n * Input: 1234.56\n * Output: \"1235\"\n */\nexport function formatRating(rating: number | null): string {\n if (rating === null || rating === undefined) return '0';\n return Math.round(rating).toString();\n}\n\n/**\n * Format consistency percentage\n * Input: 87.5\n * Output: \"88%\"\n */\nexport function formatConsistency(consistency: number | null): string {\n if (consistency === null || consistency === undefined) return '0%';\n return `${Math.round(consistency)}%`;\n}\n\n/**\n * Format percentile\n * Input: 15.5\n * Output: \"Top 16%\"\n */\nexport function formatPercentile(percentile: number | null): string {\n if (percentile === null || percentile === undefined) return 'Top -%';\n return `Top ${Math.round(percentile)}%`;\n}\n\n// ============================================================================\n// TEAM ROLE DISPLAY\n// ============================================================================\n\nexport interface TeamRoleDisplayData {\n text: string;\n badgeClasses: string;\n}\n\nexport const teamRoleDisplay: Record = {\n owner: {\n text: 'Owner',\n badgeClasses: 'bg-yellow-500/10 text-yellow-500 border-yellow-500/30',\n },\n admin: {\n text: 'Admin',\n badgeClasses: 'bg-purple-500/10 text-purple-400 border-purple-500/30',\n },\n steward: {\n text: 'Steward',\n badgeClasses: 'bg-blue-500/10 text-blue-400 border-blue-500/30',\n },\n member: {\n text: 'Member',\n badgeClasses: 'bg-primary-blue/10 text-primary-blue border-primary-blue/30',\n },\n} as const;\n\nexport function getTeamRoleDisplay(role: string): TeamRoleDisplayData {\n return teamRoleDisplay[role] || teamRoleDisplay.member;\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/display-objects/RatingDisplay.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/display-objects/SkillLevelDisplay.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/display-objects/WinRateDisplay.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/feature/FeatureFlagProvider.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/feature/FeatureFlagService.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/gateways/SessionGateway.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/infrastructure/ApiRequestLogger.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/infrastructure/ConsoleErrorReporter.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/infrastructure/EnhancedErrorReporter.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'notificationSystem' is assigned a value but never used.","line":11,"column":5,"nodeType":"Identifier","messageId":"unusedVar","endLine":11,"endColumn":28},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":11,"column":25,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":11,"endColumn":28,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[404,407],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[404,407],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Enhanced Error Reporter with user notifications and environment-specific handling\n */\n\nimport { ErrorReporter } from '../interfaces/ErrorReporter';\nimport { Logger } from '../interfaces/Logger';\nimport { ApiError } from '../api/base/ApiError';\nimport { connectionMonitor } from '../api/base/ApiConnectionMonitor';\n\n// Import notification system (will be used if available)\nlet notificationSystem: any = null;\ntry {\n // Dynamically import to avoid circular dependencies\n import('@/components/notifications/NotificationProvider').then(module => {\n notificationSystem = module;\n }).catch(() => {\n // Notification system not available yet\n });\n} catch {\n // Silent fail - notification system may not be initialized\n}\n\nexport interface EnhancedErrorReporterOptions {\n /**\n * Whether to show user-facing notifications\n */\n showUserNotifications?: boolean;\n \n /**\n * Whether to log to console (always true in dev)\n */\n logToConsole?: boolean;\n \n /**\n * Whether to report to external service (e.g., Sentry)\n */\n reportToExternal?: boolean;\n \n /**\n * Custom error handler for specific error types\n */\n customHandlers?: Record void>;\n}\n\nexport class EnhancedErrorReporter implements ErrorReporter {\n private options: EnhancedErrorReporterOptions;\n private logger: Logger;\n private errorBuffer: Array<{ error: ApiError; context: unknown }> = [];\n private readonly MAX_BUFFER_SIZE = 50;\n\n constructor(logger: Logger, options: EnhancedErrorReporterOptions = {}) {\n this.logger = logger;\n this.options = {\n showUserNotifications: options.showUserNotifications ?? true,\n logToConsole: options.logToConsole ?? true,\n reportToExternal: options.reportToExternal ?? false,\n customHandlers: options.customHandlers || {},\n };\n }\n\n /**\n * Main error reporting method\n */\n report(error: Error, context?: unknown): void {\n // Only handle ApiError instances for enhanced reporting\n if (!(error instanceof ApiError)) {\n // For non-API errors, use basic logging\n if (this.options.logToConsole) {\n console.error('Non-API Error:', error, context);\n }\n return;\n }\n\n // Add to buffer for potential batch reporting\n this.addToBuffer(error, context);\n\n // Log based on environment and severity\n this.logError(error, context);\n\n // Handle custom error types\n this.handleCustomHandlers(error);\n\n // Show user notifications if enabled\n if (this.options.showUserNotifications) {\n this.showUserNotification(error);\n }\n\n // Report to external services if configured\n if (this.options.reportToExternal) {\n this.reportToExternal(error, context);\n }\n\n // Update connection monitor\n if (error.isConnectivityIssue()) {\n connectionMonitor.recordFailure(error);\n }\n }\n\n /**\n * Log error with appropriate severity\n */\n private logError(error: ApiError, context: unknown): void {\n if (!this.options.logToConsole) return;\n\n const isDev = process.env.NODE_ENV === 'development';\n const severity = error.getSeverity();\n\n const message = isDev ? error.getDeveloperMessage() : error.getUserMessage();\n const contextObj = typeof context === 'object' && context !== null ? context : {};\n const errorContextObj = typeof error.context === 'object' && error.context !== null ? error.context : {};\n \n const logContext = {\n ...errorContextObj,\n ...contextObj,\n type: error.type,\n isRetryable: error.isRetryable(),\n isConnectivity: error.isConnectivityIssue(),\n };\n\n if (severity === 'error') {\n this.logger.error(message, error, logContext);\n if (isDev) {\n console.error(`[API-ERROR] ${message}`, { error, context: logContext });\n }\n } else if (severity === 'warn') {\n this.logger.warn(message, logContext);\n if (isDev) {\n console.warn(`[API-WARN] ${message}`, { context: logContext });\n }\n } else {\n this.logger.info(message, logContext);\n if (isDev) {\n console.log(`[API-INFO] ${message}`, { context: logContext });\n }\n }\n }\n\n /**\n * Show user-facing notification\n */\n private showUserNotification(error: ApiError): void {\n const isDev = process.env.NODE_ENV === 'development';\n\n // In development, we might want to show more details\n if (isDev) {\n // Use console notification in dev\n console.log(`%c[USER-NOTIFICATION] ${error.getUserMessage()}`, \n 'background: #222; color: #bada55; padding: 4px 8px; border-radius: 4px;'\n );\n return;\n }\n\n // In production, use the notification system if available\n // This is a deferred import to avoid circular dependencies\n if (typeof window !== 'undefined') {\n setTimeout(() => {\n try {\n // Try to access notification context if available\n const notificationEvent = new CustomEvent('gridpilot-notification', {\n detail: {\n type: 'error',\n title: this.getNotificationTitle(error),\n message: error.getUserMessage(),\n variant: error.isConnectivityIssue() ? 'modal' : 'toast',\n autoDismiss: !error.isConnectivityIssue(),\n }\n });\n window.dispatchEvent(notificationEvent);\n } catch (e) {\n // Fallback to browser alert if notification system unavailable\n if (error.isConnectivityIssue()) {\n console.warn('API Error:', error.getUserMessage());\n }\n }\n }, 100);\n }\n }\n\n /**\n * Get appropriate notification title\n */\n private getNotificationTitle(error: ApiError): string {\n switch (error.type) {\n case 'NETWORK_ERROR':\n return 'Connection Lost';\n case 'TIMEOUT_ERROR':\n return 'Request Timed Out';\n case 'AUTH_ERROR':\n return 'Authentication Required';\n case 'SERVER_ERROR':\n return 'Server Error';\n case 'RATE_LIMIT_ERROR':\n return 'Rate Limit Reached';\n default:\n return 'Something Went Wrong';\n }\n }\n\n /**\n * Handle custom error type handlers\n */\n private handleCustomHandlers(error: ApiError): void {\n if (this.options.customHandlers && this.options.customHandlers[error.type]) {\n try {\n this.options.customHandlers[error.type]!(error);\n } catch (handlerError) {\n console.error('Custom error handler failed:', handlerError);\n }\n }\n }\n\n /**\n * Report to external services (placeholder for future integration)\n */\n private reportToExternal(error: ApiError, context: unknown): void {\n // Placeholder for external error reporting (e.g., Sentry, LogRocket)\n // In a real implementation, this would send to your error tracking service\n \n if (process.env.NODE_ENV === 'development') {\n const contextObj = typeof context === 'object' && context !== null ? context : {};\n console.log('[EXTERNAL-REPORT] Would report:', {\n type: error.type,\n message: error.message,\n context: { ...error.context, ...contextObj },\n timestamp: new Date().toISOString(),\n });\n }\n }\n\n /**\n * Add error to buffer for potential batch reporting\n */\n private addToBuffer(error: ApiError, context: unknown): void {\n this.errorBuffer.push({ error, context });\n \n // Keep buffer size in check\n if (this.errorBuffer.length > this.MAX_BUFFER_SIZE) {\n this.errorBuffer.shift();\n }\n }\n\n /**\n * Get buffered errors\n */\n getBufferedErrors(): Array<{ error: ApiError; context: unknown }> {\n return [...this.errorBuffer];\n }\n\n /**\n * Clear error buffer\n */\n clearBuffer(): void {\n this.errorBuffer = [];\n }\n\n /**\n * Batch report buffered errors\n */\n flush(): void {\n if (this.errorBuffer.length === 0) return;\n\n if (this.options.logToConsole) {\n console.groupCollapsed(`[API-REPORT] Flushing ${this.errorBuffer.length} buffered errors`);\n this.errorBuffer.forEach(({ error, context }) => {\n console.log(`${error.type}: ${error.message}`, { error, context });\n });\n console.groupEnd();\n }\n\n // In production, this would batch send to external service\n if (this.options.reportToExternal) {\n const batch = this.errorBuffer.map(({ error, context }) => {\n const contextObj = typeof context === 'object' && context !== null ? context : {};\n return {\n type: error.type,\n message: error.message,\n context: { ...error.context, ...contextObj },\n timestamp: new Date().toISOString(),\n };\n });\n \n console.log('[EXTERNAL-REPORT] Batch:', batch);\n }\n\n this.clearBuffer();\n }\n\n /**\n * Update options dynamically\n */\n updateOptions(newOptions: Partial): void {\n this.options = { ...this.options, ...newOptions };\n }\n}\n\n/**\n * Global error reporter instance\n */\nlet globalReporter: EnhancedErrorReporter | null = null;\n\nexport function getGlobalErrorReporter(): EnhancedErrorReporter {\n if (!globalReporter) {\n // Import the console logger\n const { ConsoleLogger } = require('./logging/ConsoleLogger');\n globalReporter = new EnhancedErrorReporter(new ConsoleLogger(), {\n showUserNotifications: true,\n logToConsole: true,\n reportToExternal: process.env.NODE_ENV === 'production',\n });\n }\n return globalReporter;\n}\n\n/**\n * Helper function to report API errors easily\n */\nexport function reportApiError(\n error: ApiError,\n context?: unknown,\n reporter?: EnhancedErrorReporter\n): void {\n const rep = reporter || getGlobalErrorReporter();\n rep.report(error, context);\n}\n\n/**\n * React hook for error reporting\n */\nexport function useErrorReporter() {\n const reporter = getGlobalErrorReporter();\n \n return {\n report: (error: Error, context?: unknown) => reporter.report(error, context),\n flush: () => reporter.flush(),\n getBuffered: () => reporter.getBufferedErrors(),\n updateOptions: (opts: Partial) => reporter.updateOptions(opts),\n };\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/infrastructure/ErrorReplay.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'globalHandler' is assigned a value but never used.","line":51,"column":11,"nodeType":"Identifier","messageId":"unusedVar","endLine":51,"endColumn":24},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":290,"column":43,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":290,"endColumn":46,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[8312,8315],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[8312,8315],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":308,"column":28,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":308,"endColumn":31,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[8768,8771],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[8768,8771],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":3,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Error Replay System\n * Allows developers to replay errors with the exact same context\n */\n\nimport { getGlobalErrorHandler } from './GlobalErrorHandler';\nimport { getGlobalApiLogger } from './ApiRequestLogger';\nimport { ApiError } from '../api/base/ApiError';\n\nexport interface ReplayContext {\n timestamp: string;\n error: {\n message: string;\n type: string;\n stack?: string;\n context?: unknown;\n };\n environment: {\n userAgent: string;\n url: string;\n viewport: { width: number; height: number };\n language: string;\n platform: string;\n };\n apiRequests: Array<{\n url: string;\n method: string;\n duration?: number;\n status?: number;\n error?: string;\n }>;\n reactErrors: Array<{\n message: string;\n componentStack?: string;\n }>;\n metadata: {\n mode: string;\n timestamp: string;\n replayId: string;\n };\n}\n\nexport class ErrorReplaySystem {\n private replayHistory: ReplayContext[] = [];\n private readonly MAX_REPLAYS = 20;\n\n /**\n * Capture current state for replay\n */\n captureReplay(error: Error | ApiError, additionalContext: Record = {}): ReplayContext {\n const globalHandler = getGlobalErrorHandler();\n const apiLogger = getGlobalApiLogger();\n\n const replayId = `replay_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n\n const replay: ReplayContext = {\n timestamp: new Date().toISOString(),\n error: {\n message: error.message,\n type: error instanceof ApiError ? error.type : error.name || 'Error',\n stack: error.stack,\n context: error instanceof ApiError ? error.context : additionalContext,\n },\n environment: {\n userAgent: navigator.userAgent,\n url: window.location.href,\n viewport: {\n width: window.innerWidth,\n height: window.innerHeight,\n },\n language: navigator.language,\n platform: navigator.platform,\n },\n apiRequests: apiLogger.getHistory().slice(-10).map(log => ({\n url: log.url,\n method: log.method,\n duration: log.response?.duration,\n status: log.response?.status,\n error: log.error?.message,\n })),\n reactErrors: (window as { __GRIDPILOT_REACT_ERRORS__?: Array<{ error?: { message?: string }; componentStack?: string }> }).__GRIDPILOT_REACT_ERRORS__?.slice(-5).map((e) => ({\n message: e.error?.message || 'Unknown React error',\n componentStack: e.componentStack,\n })) || [],\n metadata: {\n mode: process.env.NODE_ENV || 'unknown',\n timestamp: new Date().toISOString(),\n replayId,\n },\n };\n\n this.replayHistory.push(replay);\n\n // Keep only last N replays\n if (this.replayHistory.length > this.MAX_REPLAYS) {\n this.replayHistory = this.replayHistory.slice(-this.MAX_REPLAYS);\n }\n\n // Store in localStorage for persistence across sessions\n this.persistReplay(replay);\n\n return replay;\n }\n\n /**\n * Persist replay to localStorage\n */\n private persistReplay(replay: ReplayContext): void {\n try {\n const key = `gridpilot_replay_${replay.metadata.replayId}`;\n localStorage.setItem(key, JSON.stringify(replay));\n \n // Also add to index\n const indexKey = 'gridpilot_replay_index';\n const existing = JSON.parse(localStorage.getItem(indexKey) || '[]');\n existing.push({\n id: replay.metadata.replayId,\n timestamp: replay.timestamp,\n error: replay.error.message,\n type: replay.error.type,\n });\n localStorage.setItem(indexKey, JSON.stringify(existing.slice(-this.MAX_REPLAYS)));\n } catch (e) {\n // Storage might be full or disabled\n console.warn('Failed to persist replay:', e);\n }\n }\n\n /**\n * Get all replays\n */\n getReplays(): ReplayContext[] {\n return [...this.replayHistory];\n }\n\n /**\n * Get replay by ID\n */\n getReplay(replayId: string): ReplayContext | null {\n // Check memory first\n const inMemory = this.replayHistory.find(r => r.metadata.replayId === replayId);\n if (inMemory) return inMemory;\n\n // Check localStorage\n try {\n const key = `gridpilot_replay_${replayId}`;\n const stored = localStorage.getItem(key);\n if (stored) {\n return JSON.parse(stored);\n }\n } catch (e) {\n console.warn('Failed to load replay from storage:', e);\n }\n\n return null;\n }\n\n /**\n * Replay an error by re-executing it with the same context\n */\n async replay(replayId: string): Promise {\n const replay = this.getReplay(replayId);\n if (!replay) {\n console.error(`Replay ${replayId} not found`);\n return;\n }\n\n console.groupCollapsed(`%c[REPLAY] Replaying error: ${replay.error.message}`, \n 'color: #00ff88; font-weight: bold; font-size: 14px;'\n );\n\n console.log('Original Error:', replay.error);\n console.log('Environment:', replay.environment);\n console.log('API Requests:', replay.apiRequests);\n console.log('React Errors:', replay.reactErrors);\n console.log('Metadata:', replay.metadata);\n\n // Recreate the error\n const error = replay.error.type === 'ApiError'\n ? new ApiError(\n replay.error.message,\n ((replay.error.context as { type?: string } | undefined)?.type as import('../api/base/ApiError').ApiErrorType) || 'UNKNOWN_ERROR',\n {\n timestamp: replay.timestamp,\n ...(replay.error.context as Record | undefined),\n }\n )\n : new Error(replay.error.message);\n\n if (replay.error.stack) {\n error.stack = replay.error.stack;\n }\n\n // Report through global handler\n const globalHandler = getGlobalErrorHandler();\n globalHandler.report(error, {\n source: 'replay',\n replayId: replay.metadata.replayId,\n originalTimestamp: replay.timestamp,\n environment: replay.environment,\n apiRequests: replay.apiRequests,\n reactErrors: replay.reactErrors,\n });\n\n console.groupEnd();\n\n // Show a notification\n if (typeof window !== 'undefined') {\n const notificationEvent = new CustomEvent('gridpilot-notification', {\n detail: {\n type: 'replay_success',\n title: 'Error Replay Complete',\n message: `Replayed error from ${new Date(replay.timestamp).toLocaleString()}`,\n variant: 'toast',\n }\n });\n window.dispatchEvent(notificationEvent);\n }\n }\n\n /**\n * Export replay data\n */\n exportReplay(replayId: string, format: 'json' | 'text' = 'json'): string {\n const replay = this.getReplay(replayId);\n if (!replay) {\n return 'Replay not found';\n }\n\n if (format === 'json') {\n return JSON.stringify(replay, null, 2);\n }\n\n // Text format\n return `\nError Replay Report\n===================\n\nReplay ID: ${replay.metadata.replayId}\nTimestamp: ${replay.timestamp}\n\nERROR\n-----\nType: ${replay.error.type}\nMessage: ${replay.error.message}\nStack: ${replay.error.stack || 'N/A'}\n\nENVIRONMENT\n-----------\nUser Agent: ${replay.environment.userAgent}\nURL: ${replay.environment.url}\nViewport: ${replay.environment.viewport.width}x${replay.environment.viewport.height}\nLanguage: ${replay.environment.language}\nPlatform: ${replay.environment.platform}\n\nAPI REQUESTS (${replay.apiRequests.length})\n----------------${replay.apiRequests.map(req => `\n ${req.method} ${req.url}\n ${req.status ? `Status: ${req.status}` : ''} ${req.duration ? `Duration: ${req.duration}ms` : ''}\n ${req.error ? `Error: ${req.error}` : ''}\n`).join('')}\n\nREACT ERRORS (${replay.reactErrors.length})\n----------------${replay.reactErrors.map(react => `\n ${react.message}\n ${react.componentStack ? `Component Stack: ${react.componentStack}` : ''}\n`).join('')}\n\nMETADATA\n--------\nMode: ${replay.metadata.mode}\nOriginal Timestamp: ${replay.metadata.timestamp}\n`;\n }\n\n /**\n * Delete replay\n */\n deleteReplay(replayId: string): void {\n // Remove from memory\n this.replayHistory = this.replayHistory.filter(r => r.metadata.replayId !== replayId);\n\n // Remove from localStorage\n try {\n localStorage.removeItem(`gridpilot_replay_${replayId}`);\n \n // Update index\n const indexKey = 'gridpilot_replay_index';\n const existing = JSON.parse(localStorage.getItem(indexKey) || '[]');\n const updated = existing.filter((r: any) => r.id !== replayId);\n localStorage.setItem(indexKey, JSON.stringify(updated));\n } catch (e) {\n console.warn('Failed to delete replay:', e);\n }\n }\n\n /**\n * Clear all replays\n */\n clearAll(): void {\n this.replayHistory = [];\n\n // Clear from localStorage\n try {\n const indexKey = 'gridpilot_replay_index';\n const existing = JSON.parse(localStorage.getItem(indexKey) || '[]');\n \n existing.forEach((r: any) => {\n localStorage.removeItem(`gridpilot_replay_${r.id}`);\n });\n \n localStorage.removeItem(indexKey);\n } catch (e) {\n console.warn('Failed to clear replays:', e);\n }\n }\n\n /**\n * Get replay index (summary of all available replays)\n */\n getReplayIndex(): Array<{ id: string; timestamp: string; error: string; type: string }> {\n try {\n const indexKey = 'gridpilot_replay_index';\n const stored = localStorage.getItem(indexKey);\n if (stored) {\n return JSON.parse(stored);\n }\n } catch (e) {\n console.warn('Failed to load replay index:', e);\n }\n\n // Return in-memory index\n return this.replayHistory.map(r => ({\n id: r.metadata.replayId,\n timestamp: r.timestamp,\n error: r.error.message,\n type: r.error.type,\n }));\n }\n\n /**\n * Auto-capture errors for replay\n */\n autoCapture(error: Error | ApiError, context: Record = {}): void {\n // Only capture in development or if explicitly enabled\n if (process.env.NODE_ENV !== 'development') {\n return;\n }\n\n const replay = this.captureReplay(error, context);\n \n if (console) {\n console.log('%c[REPLAY] Captured error for replay', 'color: #00ff88; font-weight: bold;', {\n replayId: replay.metadata.replayId,\n message: replay.error.message,\n });\n }\n }\n}\n\n/**\n * Global instance accessor\n */\nlet globalReplayInstance: ErrorReplaySystem | null = null;\n\nexport function getGlobalReplaySystem(): ErrorReplaySystem {\n if (!globalReplayInstance) {\n globalReplayInstance = new ErrorReplaySystem();\n }\n return globalReplayInstance;\n}\n\n/**\n * Initialize replay system\n */\nexport function initializeReplaySystem(): ErrorReplaySystem {\n const system = new ErrorReplaySystem();\n globalReplayInstance = system;\n return system;\n}\n\n/**\n * React hook for error replay\n */\nexport function useErrorReplay() {\n const system = getGlobalReplaySystem();\n\n return {\n capture: (error: Error | ApiError, context?: Record) => \n system.captureReplay(error, context),\n replay: (replayId: string) => system.replay(replayId),\n getReplays: () => system.getReplays(),\n getReplay: (replayId: string) => system.getReplay(replayId),\n exportReplay: (replayId: string, format?: 'json' | 'text') => \n system.exportReplay(replayId, format),\n deleteReplay: (replayId: string) => system.deleteReplay(replayId),\n clearAll: () => system.clearAll(),\n getReplayIndex: () => system.getReplayIndex(),\n };\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/infrastructure/GlobalErrorHandler.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":233,"column":16,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":233,"endColumn":19,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[6962,6965],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[6962,6965],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":257,"column":31,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":257,"endColumn":34,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[7687,7690],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[7687,7690],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":258,"column":41,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":258,"endColumn":44,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[7743,7746],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[7743,7746],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":259,"column":42,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":259,"endColumn":45,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[7812,7815],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[7812,7815],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":261,"column":33,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":261,"endColumn":36,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[7889,7892],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[7889,7892],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":262,"column":38,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":262,"endColumn":41,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[7946,7949],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[7946,7949],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":263,"column":33,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":263,"endColumn":36,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[8009,8012],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[8009,8012],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":264,"column":28,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":264,"endColumn":31,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[8062,8065],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[8062,8065],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":470,"column":23,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":470,"endColumn":26,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[14614,14617],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[14614,14617],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":471,"column":37,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":471,"endColumn":40,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[14673,14676],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[14673,14676],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":10,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Enhanced Global Error Handler for Maximum Developer Transparency\n * Captures all uncaught errors, promise rejections, and React errors\n */\n\nimport { ApiError } from '../api/base/ApiError';\nimport { getGlobalErrorReporter } from './EnhancedErrorReporter';\nimport { ConsoleLogger } from './logging/ConsoleLogger';\nimport { getGlobalReplaySystem } from './ErrorReplay';\n\nexport interface GlobalErrorHandlerOptions {\n /**\n * Enable detailed error overlays in development\n */\n showDevOverlay?: boolean;\n \n /**\n * Log all errors to console with maximum detail\n */\n verboseLogging?: boolean;\n \n /**\n * Capture stack traces with enhanced context\n */\n captureEnhancedStacks?: boolean;\n \n /**\n * Report to external services (Sentry, etc.)\n */\n reportToExternal?: boolean;\n \n /**\n * Custom error filter to ignore certain errors\n */\n errorFilter?: (error: Error) => boolean;\n}\n\nexport class GlobalErrorHandler {\n private options: GlobalErrorHandlerOptions;\n private logger: ConsoleLogger;\n private errorReporter: ReturnType;\n private errorHistory: Array<{\n error: Error | ApiError;\n timestamp: string;\n context?: unknown;\n stackEnhanced?: string;\n }> = [];\n private readonly MAX_HISTORY = 100;\n private isInitialized = false;\n\n constructor(options: GlobalErrorHandlerOptions = {}) {\n this.options = {\n showDevOverlay: options.showDevOverlay ?? process.env.NODE_ENV === 'development',\n verboseLogging: options.verboseLogging ?? process.env.NODE_ENV === 'development',\n captureEnhancedStacks: options.captureEnhancedStacks ?? process.env.NODE_ENV === 'development',\n reportToExternal: options.reportToExternal ?? process.env.NODE_ENV === 'production',\n errorFilter: options.errorFilter,\n };\n\n this.logger = new ConsoleLogger();\n this.errorReporter = getGlobalErrorReporter();\n }\n\n /**\n * Initialize global error handlers\n */\n initialize(): void {\n if (this.isInitialized) {\n console.warn('[GlobalErrorHandler] Already initialized');\n return;\n }\n\n // Only initialize in browser environment\n if (typeof window === 'undefined') {\n if (this.options.verboseLogging) {\n this.logger.info('Global error handler skipped (server-side)');\n }\n return;\n }\n\n // Handle uncaught JavaScript errors\n window.addEventListener('error', this.handleWindowError);\n \n // Handle unhandled promise rejections\n window.addEventListener('unhandledrejection', this.handleUnhandledRejection);\n \n // Override console.error to capture framework errors\n this.overrideConsoleError();\n \n // React error boundary fallback\n this.setupReactErrorHandling();\n\n this.isInitialized = true;\n\n if (this.options.verboseLogging) {\n this.logger.info('Global error handler initialized', {\n devOverlay: this.options.showDevOverlay,\n verboseLogging: this.options.verboseLogging,\n enhancedStacks: this.options.captureEnhancedStacks,\n });\n }\n }\n\n /**\n * Handle window errors (uncaught JavaScript errors)\n */\n private handleWindowError = (event: ErrorEvent): void => {\n const error = event.error;\n \n // Apply error filter if provided\n if (this.options.errorFilter && !this.options.errorFilter(error)) {\n return;\n }\n\n // Check if this is a network/CORS error (expected in some cases)\n if (error instanceof TypeError && error.message.includes('fetch')) {\n this.logger.warn('Network error detected', {\n type: 'network_error',\n message: error.message,\n url: event.filename,\n line: event.lineno,\n col: event.colno,\n });\n return; // Don't prevent default for network errors\n }\n\n const enhancedContext = this.captureEnhancedContext('window_error', {\n filename: event.filename,\n lineno: event.lineno,\n colno: event.colno,\n message: event.message,\n });\n\n // Log with appropriate detail\n this.logErrorWithMaximumDetail(error, enhancedContext);\n\n // Store in history\n this.addToHistory(error, enhancedContext);\n\n // Report to external if enabled (but not for network errors)\n if (this.options.reportToExternal) {\n this.reportToExternal(error, enhancedContext);\n }\n\n // Auto-capture for replay in development\n if (this.options.showDevOverlay) {\n const replaySystem = getGlobalReplaySystem();\n replaySystem.autoCapture(error, enhancedContext);\n }\n\n // Prevent default error logging in dev to avoid duplicates\n if (this.options.showDevOverlay) {\n event.preventDefault();\n }\n };\n\n /**\n * Handle unhandled promise rejections\n */\n private handleUnhandledRejection = (event: PromiseRejectionEvent): void => {\n const error = event.reason;\n \n // Apply error filter if provided\n if (this.options.errorFilter && !this.options.errorFilter(error)) {\n return;\n }\n\n // Check if this is a network error (expected)\n if (error instanceof TypeError && error.message.includes('fetch')) {\n this.logger.warn('Unhandled promise rejection - network error', {\n type: 'network_error',\n message: error.message,\n });\n return;\n }\n\n const enhancedContext = this.captureEnhancedContext('unhandled_promise', {\n promise: event.promise,\n reason: typeof error === 'string' ? error : error?.message || 'Unknown promise rejection',\n });\n\n // Log with appropriate detail\n this.logErrorWithMaximumDetail(error, enhancedContext);\n\n // Store in history\n this.addToHistory(error, enhancedContext);\n\n // Report to external if enabled (but not for network errors)\n if (this.options.reportToExternal) {\n this.reportToExternal(error, enhancedContext);\n }\n\n // Prevent default logging\n if (this.options.showDevOverlay) {\n event.preventDefault();\n }\n };\n\n /**\n * Override console.error to capture framework errors\n */\n private overrideConsoleError(): void {\n const originalError = console.error;\n \n console.error = (...args: unknown[]): void => {\n // Call original first\n originalError.apply(console, args);\n\n // Try to extract error from arguments\n const error = args.find(arg => arg instanceof Error) || \n args.find(arg => typeof arg === 'object' && arg !== null && 'message' in arg) ||\n new Error(args.map(a => String(a)).join(' '));\n\n if (error instanceof Error) {\n const enhancedContext = this.captureEnhancedContext('console_error', {\n originalArgs: args,\n });\n\n // Store in history\n this.addToHistory(error, enhancedContext);\n\n // No overlay - just enhanced console logging\n }\n };\n }\n\n /**\n * Setup React-specific error handling\n */\n private setupReactErrorHandling(): void {\n // This will be used by React Error Boundaries\n // We'll provide a global registry for React errors\n (window as any).__GRIDPILOT_REACT_ERRORS__ = [];\n }\n\n /**\n * Capture enhanced context with stack trace and environment info\n */\n private captureEnhancedContext(type: string, additionalContext: Record = {}): Record {\n const stack = new Error().stack;\n \n return {\n type,\n timestamp: new Date().toISOString(),\n userAgent: navigator.userAgent,\n url: window.location.href,\n language: navigator.language,\n platform: navigator.platform,\n viewport: {\n width: window.innerWidth,\n height: window.innerHeight,\n },\n screen: {\n width: window.screen.width,\n height: window.screen.height,\n },\n memory: (performance as any).memory ? {\n usedJSHeapSize: (performance as any).memory.usedJSHeapSize,\n totalJSHeapSize: (performance as any).memory.totalJSHeapSize,\n } : null,\n connection: (navigator as any).connection ? {\n effectiveType: (navigator as any).connection.effectiveType,\n downlink: (navigator as any).connection.downlink,\n rtt: (navigator as any).connection.rtt,\n } : null,\n ...additionalContext,\n enhancedStack: this.options.captureEnhancedStacks ? this.enhanceStackTrace(stack) : undefined,\n };\n }\n\n /**\n * Enhance stack trace with additional context\n */\n private enhanceStackTrace(stack?: string): string | undefined {\n if (!stack) return undefined;\n\n // Add source map information if available\n const lines = stack.split('\\n').slice(1); // Remove first line (error message)\n \n const enhanced = lines.map(line => {\n // Try to extract file and line info\n const match = line.match(/at (.+) \\((.+):(\\d+):(\\d+)\\)/) || \n line.match(/at (.+):(\\d+):(\\d+)/);\n \n if (match) {\n const func = match[1] || 'anonymous';\n const file = match[2] || match[1];\n const lineNum = match[3] || match[2];\n const colNum = match[4] || match[3];\n \n // Add source map comment if in development\n if (process.env.NODE_ENV === 'development' && file && file.includes('.js')) {\n return `at ${func} (${file}:${lineNum}:${colNum}) [Source Map: ${file}.map]`;\n }\n \n return `at ${func} (${file}:${lineNum}:${colNum})`;\n }\n \n return line.trim();\n });\n\n return enhanced.join('\\n');\n }\n\n /**\n * Log error with appropriate detail\n */\n private logErrorWithMaximumDetail(error: Error | ApiError, context: Record): void {\n if (!this.options.verboseLogging) return;\n\n const isApiError = error instanceof ApiError;\n const isWarning = isApiError && error.getSeverity() === 'warn';\n\n if (isWarning) {\n // Simplified warning output\n this.logger.warn(error.message, context);\n return;\n }\n\n // Full error details for actual errors\n this.logger.error(error.message, error, context);\n\n // In development, show additional details\n if (process.env.NODE_ENV === 'development') {\n console.groupCollapsed(`%c[ERROR DETAIL] ${error.name || 'Error'}`, 'color: #ff4444; font-weight: bold; font-size: 14px;');\n \n console.log('%cError Details:', 'color: #666; font-weight: bold;', {\n name: error.name,\n message: error.message,\n type: isApiError ? error.type : 'N/A',\n severity: isApiError ? error.getSeverity() : 'error',\n retryable: isApiError ? error.isRetryable() : 'N/A',\n connectivity: isApiError ? error.isConnectivityIssue() : 'N/A',\n });\n\n console.log('%cContext:', 'color: #666; font-weight: bold;', context);\n\n if (isApiError && error.context?.developerHint) {\n console.log('%c💡 Developer Hint:', 'color: #00aaff; font-weight: bold;', error.context.developerHint);\n }\n\n console.groupEnd();\n }\n }\n\n\n /**\n * Report error to external services\n */\n private reportToExternal(error: Error | ApiError, context: Record): void {\n // This is a placeholder for external error reporting (Sentry, LogRocket, etc.)\n // In a real implementation, you would send structured data to your error tracking service\n \n if (this.options.verboseLogging) {\n console.log('[EXTERNAL REPORT] Would send to error tracking service:', {\n error: {\n name: error.name,\n message: error.message,\n stack: error.stack,\n type: error instanceof ApiError ? error.type : undefined,\n },\n context,\n timestamp: new Date().toISOString(),\n });\n }\n }\n\n /**\n * Add error to history\n */\n private addToHistory(error: Error | ApiError, context: Record): void {\n const entry = {\n error,\n timestamp: new Date().toISOString(),\n context,\n stackEnhanced: context.enhancedStack as string | undefined,\n };\n\n this.errorHistory.push(entry);\n\n // Keep only last N errors\n if (this.errorHistory.length > this.MAX_HISTORY) {\n this.errorHistory = this.errorHistory.slice(-this.MAX_HISTORY);\n }\n }\n\n /**\n * Get error history\n */\n getErrorHistory(): Array<{ error: Error | ApiError; timestamp: string; context?: unknown; stackEnhanced?: string }> {\n return [...this.errorHistory];\n }\n\n /**\n * Clear error history\n */\n clearHistory(): void {\n this.errorHistory = [];\n if (this.options.verboseLogging) {\n this.logger.info('Error history cleared');\n }\n }\n\n /**\n * Get statistics about errors\n */\n getStats(): {\n total: number;\n byType: Record;\n recent: Array<{ timestamp: string; message: string; type: string }>;\n } {\n const stats = {\n total: this.errorHistory.length,\n byType: {} as Record,\n recent: this.errorHistory.slice(-10).map(entry => ({\n timestamp: entry.timestamp,\n message: entry.error.message,\n type: entry.error instanceof ApiError ? entry.error.type : entry.error.name || 'Error',\n })),\n };\n\n this.errorHistory.forEach(entry => {\n const type = entry.error instanceof ApiError ? entry.error.type : entry.error.name || 'Error';\n stats.byType[type] = (stats.byType[type] || 0) + 1;\n });\n\n return stats;\n }\n\n /**\n * Manually report an error\n */\n report(error: Error | ApiError, additionalContext: Record = {}): void {\n const context = this.captureEnhancedContext('manual_report', additionalContext);\n \n // Check if this is a network error (don't report to external services)\n const isNetworkError = error.message.includes('fetch') ||\n error.message.includes('Failed to fetch') ||\n error.message.includes('NetworkError');\n\n if (isNetworkError) {\n this.logger.warn(`Manual error report: ${error.message}`, context);\n } else {\n this.logErrorWithMaximumDetail(error, context);\n }\n\n this.addToHistory(error, context);\n\n // Auto-capture for replay in development\n if (this.options.showDevOverlay) {\n const replaySystem = getGlobalReplaySystem();\n replaySystem.autoCapture(error, context);\n }\n\n // Only report non-network errors to external services\n if (this.options.reportToExternal && !isNetworkError) {\n this.reportToExternal(error, context);\n }\n }\n\n /**\n * Destroy the error handler and remove all listeners\n */\n destroy(): void {\n if (typeof window !== 'undefined') {\n window.removeEventListener('error', this.handleWindowError);\n window.removeEventListener('unhandledrejection', this.handleUnhandledRejection);\n \n // Restore original console.error\n if ((console as any)._originalError) {\n console.error = (console as any)._originalError;\n }\n }\n\n this.isInitialized = false;\n\n if (this.options.verboseLogging) {\n this.logger.info('Global error handler destroyed');\n }\n }\n}\n\n/**\n * Global instance accessor\n */\nlet globalErrorHandlerInstance: GlobalErrorHandler | null = null;\n\nexport function getGlobalErrorHandler(): GlobalErrorHandler {\n if (!globalErrorHandlerInstance) {\n globalErrorHandlerInstance = new GlobalErrorHandler();\n }\n return globalErrorHandlerInstance;\n}\n\n/**\n * Initialize global error handling\n */\nexport function initializeGlobalErrorHandling(options?: GlobalErrorHandlerOptions): GlobalErrorHandler {\n const handler = new GlobalErrorHandler(options);\n handler.initialize();\n globalErrorHandlerInstance = handler;\n return handler;\n}\n\n/**\n * React hook for manual error reporting\n */\nexport function useGlobalErrorHandler() {\n const handler = getGlobalErrorHandler();\n \n return {\n report: (error: Error | ApiError, context?: Record) => handler.report(error, context),\n getHistory: () => handler.getErrorHistory(),\n getStats: () => handler.getStats(),\n clearHistory: () => handler.clearHistory(),\n };\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/infrastructure/logging/ConsoleErrorReporter.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/infrastructure/logging/ConsoleLogger.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":44,"column":19,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":44,"endColumn":22,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1362,1365],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1362,1365],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":76,"column":19,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":76,"endColumn":22,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2701,2704],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2701,2704],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Logger } from '../../interfaces/Logger';\n\ntype LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\nexport class ConsoleLogger implements Logger {\n private readonly COLORS: Record = {\n debug: '#888888',\n info: '#00aaff',\n warn: '#ffaa00',\n error: '#ff4444',\n };\n\n private readonly EMOJIS: Record = {\n debug: '🐛',\n info: 'ℹ️',\n warn: '⚠️',\n error: '❌',\n };\n\n private readonly PREFIXES: Record = {\n debug: 'DEBUG',\n info: 'INFO',\n warn: 'WARN',\n error: 'ERROR',\n };\n\n private shouldLog(level: LogLevel): boolean {\n if (process.env.NODE_ENV === 'test') return level === 'error';\n if (process.env.NODE_ENV === 'production') return level !== 'debug';\n return true;\n }\n\n private formatOutput(level: LogLevel, source: string, message: string, context?: unknown, error?: Error): void {\n const color = this.COLORS[level];\n const emoji = this.EMOJIS[level];\n const prefix = this.PREFIXES[level];\n \n // Edge runtime doesn't support console.groupCollapsed/groupEnd\n // Fallback to simple logging for compatibility\n const supportsGrouping = typeof console.groupCollapsed === 'function' && typeof console.groupEnd === 'function';\n \n if (supportsGrouping) {\n // Safe to call - we've verified both functions exist\n (console as any).groupCollapsed(`%c${emoji} [${source.toUpperCase()}] ${prefix}: ${message}`, `color: ${color}; font-weight: bold;`);\n } else {\n // Simple format for edge runtime\n console.log(`${emoji} [${source.toUpperCase()}] ${prefix}: ${message}`);\n }\n \n console.log(`%cTimestamp:`, 'color: #666; font-weight: bold;', new Date().toISOString());\n console.log(`%cSource:`, 'color: #666; font-weight: bold;', source);\n \n if (context) {\n console.log(`%cContext:`, 'color: #666; font-weight: bold;');\n // console.dir may not be available in edge runtime\n if (typeof console.dir === 'function') {\n console.dir(context, { depth: 3, colors: true });\n } else {\n console.log(JSON.stringify(context, null, 2));\n }\n }\n \n if (error) {\n console.log(`%cError Details:`, 'color: #666; font-weight: bold;');\n console.log(`%cType:`, 'color: #ff4444; font-weight: bold;', error.name);\n console.log(`%cMessage:`, 'color: #ff4444; font-weight: bold;', error.message);\n \n if (process.env.NODE_ENV === 'development' && error.stack) {\n console.log(`%cStack Trace:`, 'color: #666; font-weight: bold;');\n console.log(error.stack);\n }\n }\n \n if (supportsGrouping) {\n // Safe to call - we've verified the function exists\n (console as any).groupEnd();\n }\n }\n\n debug(message: string, context?: unknown): void {\n if (!this.shouldLog('debug')) return;\n this.formatOutput('debug', 'website', message, context);\n }\n\n info(message: string, context?: unknown): void {\n if (!this.shouldLog('info')) return;\n this.formatOutput('info', 'website', message, context);\n }\n\n warn(message: string, context?: unknown): void {\n if (!this.shouldLog('warn')) return;\n this.formatOutput('warn', 'website', message, context);\n }\n\n error(message: string, error?: Error, context?: unknown): void {\n if (!this.shouldLog('error')) return;\n this.formatOutput('error', 'website', message, context, error);\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/infrastructure/logging/logger.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/interfaces/ErrorReporter.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/interfaces/Logger.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/leagueCovers.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/leagueMembership.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/leagueRoles.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/mutations/admin/DeleteUserMutation.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'input' is defined but never used.","line":18,"column":17,"nodeType":"Identifier","messageId":"unusedVar","endLine":18,"endColumn":42}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { AdminService } from '@/lib/services/admin/AdminService';\nimport { Result } from '@/lib/contracts/Result';\nimport { MutationError, mapToMutationError } from '@/lib/contracts/mutations/MutationError';\nimport { Mutation } from '@/lib/contracts/mutations/Mutation';\n\n/**\n * DeleteUserMutation\n *\n * Framework-agnostic mutation for deleting users.\n * Called from Server Actions.\n *\n * Input: { userId: string }\n * Output: Result\n *\n * Pattern: Server Action → Mutation → Service → API Client\n */\nexport class DeleteUserMutation implements Mutation<{ userId: string }, void, MutationError> {\n async execute(input: { userId: string }): Promise> {\n try {\n // Manual construction: Service creates its own dependencies\n const service = new AdminService();\n \n const result = await service.deleteUser();\n \n if (result.isErr()) {\n return Result.err(mapToMutationError(result.getError()));\n }\n \n return Result.ok(undefined);\n } catch (err) {\n return Result.err('deleteFailed');\n }\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/mutations/admin/UpdateUserStatusMutation.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/mutations/auth/ForgotPasswordMutation.ts","messages":[{"ruleId":"gridpilot-rules/mutation-contract","severity":2,"message":"Mutation classes must implement Mutation - see apps/website/lib/contracts/mutations/Mutation.ts","line":15,"column":14,"nodeType":"Identifier","messageId":"mustImplementMutationInterface","endLine":15,"endColumn":36},{"ruleId":"gridpilot-rules/mutation-must-use-builders","severity":2,"message":"Mutations must use ViewDataBuilder to transform DTOs or return simple types - see apps/website/lib/contracts/builders/ViewDataBuilder.ts","line":16,"column":3,"nodeType":"MethodDefinition","messageId":"mustUseBuilder","endLine":28,"endColumn":4},{"ruleId":"gridpilot-rules/mutation-must-map-errors","severity":2,"message":"Mutations must map service errors via mapToMutationError(result.getError()) before returning Result.err(...) - see apps/website/lib/contracts/mutations/Mutation.ts","line":21,"column":9,"nodeType":"ReturnStatement","messageId":"mustMapMutationError","endLine":21,"endColumn":54},{"ruleId":"gridpilot-rules/mutation-must-use-builders","severity":2,"message":"Mutations must not return DTOs directly, use builders to create ViewData or return simple types like void, string, or primitive values","line":23,"column":7,"nodeType":"ReturnStatement","messageId":"noDirectDtoReturn","endLine":23,"endColumn":41},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":24,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":24,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[874,877],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[874,877],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":5,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Forgot Password Mutation\n *\n * Framework-agnostic mutation for forgot password operations.\n * Called from Server Actions.\n *\n * Pattern: Server Action → Mutation → Service → API Client\n */\n\nimport { Result } from '@/lib/contracts/Result';\nimport { AuthService } from '@/lib/services/auth/AuthService';\nimport { ForgotPasswordDTO } from '@/lib/types/generated/ForgotPasswordDTO';\nimport { ForgotPasswordResult } from '@/lib/mutations/auth/types/ForgotPasswordResult';\n\nexport class ForgotPasswordMutation {\n async execute(params: ForgotPasswordDTO): Promise> {\n try {\n const authService = new AuthService();\n const result = await authService.forgotPassword(params);\n if (result.isErr()) {\n return Result.err(result.getError().message);\n }\n return Result.ok(result.unwrap());\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : 'Failed to send reset link';\n return Result.err(errorMessage);\n }\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/mutations/auth/LoginMutation.ts","messages":[{"ruleId":"gridpilot-rules/mutation-contract","severity":2,"message":"Mutation classes must implement Mutation - see apps/website/lib/contracts/mutations/Mutation.ts","line":15,"column":14,"nodeType":"Identifier","messageId":"mustImplementMutationInterface","endLine":15,"endColumn":27},{"ruleId":"gridpilot-rules/mutation-must-map-errors","severity":2,"message":"Mutations must map service errors via mapToMutationError(result.getError()) before returning Result.err(...) - see apps/website/lib/contracts/mutations/Mutation.ts","line":21,"column":9,"nodeType":"ReturnStatement","messageId":"mustMapMutationError","endLine":21,"endColumn":54},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":24,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":24,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[833,836],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[833,836],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":3,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Login Mutation\n *\n * Framework-agnostic mutation for login operations.\n * Called from Server Actions.\n *\n * Pattern: Server Action → Mutation → Service → API Client\n */\n\nimport { Result } from '@/lib/contracts/Result';\nimport { AuthService } from '@/lib/services/auth/AuthService';\nimport { SessionViewModel } from '@/lib/view-models/SessionViewModel';\nimport { LoginParamsDTO } from '@/lib/types/generated/LoginParamsDTO';\n\nexport class LoginMutation {\n async execute(params: LoginParamsDTO): Promise> {\n try {\n const authService = new AuthService();\n const result = await authService.login(params);\n if (result.isErr()) {\n return Result.err(result.getError().message);\n }\n return Result.ok(new SessionViewModel(result.unwrap().user));\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : 'Login failed';\n return Result.err(errorMessage);\n }\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/mutations/auth/LogoutMutation.ts","messages":[{"ruleId":"gridpilot-rules/mutation-contract","severity":2,"message":"Mutation classes must implement Mutation - see apps/website/lib/contracts/mutations/Mutation.ts","line":13,"column":14,"nodeType":"Identifier","messageId":"mustImplementMutationInterface","endLine":13,"endColumn":28}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Logout Mutation\n *\n * Framework-agnostic mutation for logout operations.\n * Called from Server Actions.\n *\n * Pattern: Server Action → Mutation → Service → API Client\n */\n\nimport { Result } from '@/lib/contracts/Result';\nimport { AuthService } from '@/lib/services/auth/AuthService';\n\nexport class LogoutMutation {\n async execute(): Promise> {\n try {\n const authService = new AuthService();\n await authService.logout();\n return Result.ok(undefined);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Logout failed';\n return Result.err(errorMessage);\n }\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/mutations/auth/ResetPasswordMutation.ts","messages":[{"ruleId":"gridpilot-rules/mutation-contract","severity":2,"message":"Mutation classes must implement Mutation - see apps/website/lib/contracts/mutations/Mutation.ts","line":15,"column":14,"nodeType":"Identifier","messageId":"mustImplementMutationInterface","endLine":15,"endColumn":35},{"ruleId":"gridpilot-rules/mutation-must-use-builders","severity":2,"message":"Mutations must use ViewDataBuilder to transform DTOs or return simple types - see apps/website/lib/contracts/builders/ViewDataBuilder.ts","line":16,"column":3,"nodeType":"MethodDefinition","messageId":"mustUseBuilder","endLine":28,"endColumn":4},{"ruleId":"gridpilot-rules/mutation-must-map-errors","severity":2,"message":"Mutations must map service errors via mapToMutationError(result.getError()) before returning Result.err(...) - see apps/website/lib/contracts/mutations/Mutation.ts","line":21,"column":9,"nodeType":"ReturnStatement","messageId":"mustMapMutationError","endLine":21,"endColumn":54},{"ruleId":"gridpilot-rules/mutation-must-use-builders","severity":2,"message":"Mutations must not return DTOs directly, use builders to create ViewData or return simple types like void, string, or primitive values","line":23,"column":7,"nodeType":"ReturnStatement","messageId":"noDirectDtoReturn","endLine":23,"endColumn":41},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":24,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":24,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[864,867],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[864,867],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":5,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Reset Password Mutation\n *\n * Framework-agnostic mutation for reset password operations.\n * Called from Server Actions.\n *\n * Pattern: Server Action → Mutation → Service → API Client\n */\n\nimport { Result } from '@/lib/contracts/Result';\nimport { AuthService } from '@/lib/services/auth/AuthService';\nimport { ResetPasswordDTO } from '@/lib/types/generated/ResetPasswordDTO';\nimport { ResetPasswordResult } from '@/lib/mutations/auth/types/ResetPasswordResult';\n\nexport class ResetPasswordMutation {\n async execute(params: ResetPasswordDTO): Promise> {\n try {\n const authService = new AuthService();\n const result = await authService.resetPassword(params);\n if (result.isErr()) {\n return Result.err(result.getError().message);\n }\n return Result.ok(result.unwrap());\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : 'Failed to reset password';\n return Result.err(errorMessage);\n }\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/mutations/auth/SignupMutation.ts","messages":[{"ruleId":"gridpilot-rules/mutation-contract","severity":2,"message":"Mutation classes must implement Mutation - see apps/website/lib/contracts/mutations/Mutation.ts","line":15,"column":14,"nodeType":"Identifier","messageId":"mustImplementMutationInterface","endLine":15,"endColumn":28},{"ruleId":"gridpilot-rules/mutation-must-map-errors","severity":2,"message":"Mutations must map service errors via mapToMutationError(result.getError()) before returning Result.err(...) - see apps/website/lib/contracts/mutations/Mutation.ts","line":21,"column":9,"nodeType":"ReturnStatement","messageId":"mustMapMutationError","endLine":21,"endColumn":54},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":24,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":24,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[840,843],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[840,843],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":3,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Signup Mutation\n *\n * Framework-agnostic mutation for signup operations.\n * Called from Server Actions.\n *\n * Pattern: Server Action → Mutation → Service → API Client\n */\n\nimport { Result } from '@/lib/contracts/Result';\nimport { AuthService } from '@/lib/services/auth/AuthService';\nimport { SessionViewModel } from '@/lib/view-models/SessionViewModel';\nimport { SignupParamsDTO } from '@/lib/types/generated/SignupParamsDTO';\n\nexport class SignupMutation {\n async execute(params: SignupParamsDTO): Promise> {\n try {\n const authService = new AuthService();\n const result = await authService.signup(params);\n if (result.isErr()) {\n return Result.err(result.getError().message);\n }\n return Result.ok(new SessionViewModel(result.unwrap().user));\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : 'Signup failed';\n return Result.err(errorMessage);\n }\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/mutations/auth/types/ForgotPasswordResult.ts","messages":[{"ruleId":"gridpilot-rules/clean-error-handling","severity":2,"message":"PageQueries and Mutations must use Services for data access, not API Clients directly.","line":8,"column":1,"nodeType":"Program","messageId":"mustUseServices","endLine":11,"endColumn":2}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Forgot Password Mutation Result\n *\n * Result type for forgot password operations.\n * This represents the successful outcome of a forgot password mutation.\n */\n\nexport interface ForgotPasswordResult {\n message: string;\n magicLink?: string;\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/mutations/auth/types/ResetPasswordResult.ts","messages":[{"ruleId":"gridpilot-rules/clean-error-handling","severity":2,"message":"PageQueries and Mutations must use Services for data access, not API Clients directly.","line":8,"column":1,"nodeType":"Program","messageId":"mustUseServices","endLine":10,"endColumn":2}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Reset Password Mutation Result\n *\n * Result type for reset password operations.\n * This represents the successful outcome of a reset password mutation.\n */\n\nexport interface ResetPasswordResult {\n message: string;\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/mutations/drivers/UpdateDriverProfileMutation.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_error' is defined but never used.","line":13,"column":29,"nodeType":"Identifier","messageId":"unusedVar","endLine":13,"endColumn":48}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Result } from '@/lib/contracts/Result';\nimport type { Mutation } from '@/lib/contracts/mutations/Mutation';\nimport type { DomainError } from '@/lib/contracts/services/Service';\nimport { DriverProfileUpdateService } from '@/lib/services/drivers/DriverProfileUpdateService';\n\nexport interface UpdateDriverProfileCommand {\n bio?: string;\n country?: string;\n}\n\ntype UpdateDriverProfileMutationError = 'DRIVER_PROFILE_UPDATE_FAILED';\n\nconst mapToMutationError = (_error: DomainError): UpdateDriverProfileMutationError => {\n return 'DRIVER_PROFILE_UPDATE_FAILED';\n};\n\nexport class UpdateDriverProfileMutation\n implements Mutation\n{\n async execute(\n command: UpdateDriverProfileCommand,\n ): Promise> {\n const service = new DriverProfileUpdateService();\n const result = await service.updateProfile({ bio: command.bio, country: command.country });\n\n if (result.isErr()) {\n return Result.err(mapToMutationError(result.getError()));\n }\n\n return Result.ok(undefined);\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/mutations/leagues/CreateLeagueMutation.ts","messages":[{"ruleId":"gridpilot-rules/mutation-contract","severity":2,"message":"Mutation classes must implement Mutation - see apps/website/lib/contracts/mutations/Mutation.ts","line":12,"column":14,"nodeType":"Identifier","messageId":"mustImplementMutationInterface","endLine":12,"endColumn":34},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":26,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":26,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[859,862],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[859,862],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Result } from '@/lib/contracts/Result';\nimport { LeagueService } from '@/lib/services/leagues/LeagueService';\nimport type { CreateLeagueInputDTO } from '@/lib/types/generated/CreateLeagueInputDTO';\nimport { DomainError } from '@/lib/contracts/services/Service';\n\n/**\n * CreateLeagueMutation\n * \n * Framework-agnostic mutation for creating leagues.\n * Can be called from Server Actions or other contexts.\n */\nexport class CreateLeagueMutation {\n private service: LeagueService;\n\n constructor() {\n this.service = new LeagueService();\n }\n\n async execute(input: CreateLeagueInputDTO): Promise> {\n try {\n const result = await this.service.createLeague(input);\n if (result.isErr()) {\n return Result.err(result.getError());\n }\n return Result.ok(result.unwrap().leagueId);\n } catch (error: any) {\n console.error('CreateLeagueMutation failed:', error);\n return Result.err({ type: 'serverError', message: error.message || 'Failed to create league' });\n }\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/mutations/leagues/ProtestReviewMutation.ts","messages":[{"ruleId":"gridpilot-rules/mutation-contract","severity":2,"message":"Mutation classes must implement Mutation - see apps/website/lib/contracts/mutations/Mutation.ts","line":13,"column":14,"nodeType":"Identifier","messageId":"mustImplementMutationInterface","endLine":13,"endColumn":35},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":23,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":23,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[854,857],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[854,857],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":32,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":32,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1213,1216],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1213,1216],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":40,"column":56,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":40,"endColumn":59,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1605,1608],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1605,1608],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":41,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":41,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1631,1634],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1631,1634],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":5,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Result } from '@/lib/contracts/Result';\nimport { ProtestService } from '@/lib/services/protests/ProtestService';\nimport type { ApplyPenaltyCommandDTO } from '@/lib/types/generated/ApplyPenaltyCommandDTO';\nimport type { RequestProtestDefenseCommandDTO } from '@/lib/types/generated/RequestProtestDefenseCommandDTO';\nimport { DomainError } from '@/lib/contracts/services/Service';\n\n/**\n * ProtestReviewMutation\n * \n * Framework-agnostic mutation for protest review operations.\n * Can be called from Server Actions or other contexts.\n */\nexport class ProtestReviewMutation {\n private service: ProtestService;\n\n constructor() {\n this.service = new ProtestService();\n }\n\n async applyPenalty(input: ApplyPenaltyCommandDTO): Promise> {\n try {\n return await this.service.applyPenalty(input);\n } catch (error: any) {\n console.error('applyPenalty failed:', error);\n return Result.err({ type: 'serverError', message: error.message || 'Failed to apply penalty' });\n }\n }\n\n async requestDefense(input: RequestProtestDefenseCommandDTO): Promise> {\n try {\n return await this.service.requestDefense(input);\n } catch (error: any) {\n console.error('requestDefense failed:', error);\n return Result.err({ type: 'serverError', message: error.message || 'Failed to request defense' });\n }\n }\n\n async reviewProtest(input: { protestId: string; stewardId: string; decision: string; decisionNotes: string }): Promise> {\n try {\n return await this.service.reviewProtest(input as any);\n } catch (error: any) {\n console.error('reviewProtest failed:', error);\n return Result.err({ type: 'serverError', message: error.message || 'Failed to review protest' });\n }\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/mutations/leagues/RosterAdminMutation.ts","messages":[{"ruleId":"gridpilot-rules/mutation-contract","severity":2,"message":"Mutation classes must implement Mutation - see apps/website/lib/contracts/mutations/Mutation.ts","line":14,"column":14,"nodeType":"Identifier","messageId":"mustImplementMutationInterface","endLine":14,"endColumn":33},{"ruleId":"gridpilot-rules/no-direct-process-env","severity":2,"message":"Do not read process.env directly here. Use `getWebsiteServerEnv()` / `getWebsitePublicEnv()` (apps/website/lib/config/env.ts) or a dedicated config helper (e.g. getWebsiteApiBaseUrl()).","line":19,"column":21,"nodeType":"MemberExpression","messageId":"noProcessEnv","endLine":19,"endColumn":52},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'apiClient' is assigned a value but never used.","line":22,"column":11,"nodeType":"Identifier","messageId":"unusedVar","endLine":22,"endColumn":20},{"ruleId":"gridpilot-rules/clean-error-handling","severity":2,"message":"PageQueries and Mutations must use Services for data access, not API Clients directly.","line":22,"column":23,"nodeType":"NewExpression","messageId":"mustUseServices","endLine":22,"endColumn":75}],"suppressedMessages":[],"errorCount":4,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Result } from '@/lib/contracts/Result';\nimport { LeagueService } from '@/lib/services/leagues/LeagueService';\nimport { LeaguesApiClient } from '@/lib/api/leagues/LeaguesApiClient';\nimport { ConsoleErrorReporter } from '@/lib/infrastructure/logging/ConsoleErrorReporter';\nimport { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';\nimport type { MembershipRole } from '@/lib/types/MembershipRole';\n\n/**\n * RosterAdminMutation\n * \n * Framework-agnostic mutation for roster administration operations.\n * Can be called from Server Actions or other contexts.\n */\nexport class RosterAdminMutation {\n private service: LeagueService;\n\n constructor() {\n // Manual wiring for serverless\n const baseUrl = process.env.NEXT_PUBLIC_API_URL || '';\n const errorReporter = new ConsoleErrorReporter();\n const logger = new ConsoleLogger();\n const apiClient = new LeaguesApiClient(baseUrl, errorReporter, logger);\n \n this.service = new LeagueService();\n }\n\n async approveJoinRequest(leagueId: string, joinRequestId: string): Promise> {\n try {\n await this.service.approveJoinRequest(leagueId, joinRequestId);\n return Result.ok(undefined);\n } catch (error) {\n console.error('approveJoinRequest failed:', error);\n return Result.err('Failed to approve join request');\n }\n }\n\n async rejectJoinRequest(leagueId: string, joinRequestId: string): Promise> {\n try {\n await this.service.rejectJoinRequest(leagueId, joinRequestId);\n return Result.ok(undefined);\n } catch (error) {\n console.error('rejectJoinRequest failed:', error);\n return Result.err('Failed to reject join request');\n }\n }\n\n async updateMemberRole(leagueId: string, driverId: string, role: MembershipRole): Promise> {\n try {\n await this.service.updateMemberRole(leagueId, driverId, role);\n return Result.ok(undefined);\n } catch (error) {\n console.error('updateMemberRole failed:', error);\n return Result.err('Failed to update member role');\n }\n }\n\n async removeMember(leagueId: string, driverId: string): Promise> {\n try {\n await this.service.removeMember(leagueId, driverId);\n return Result.ok(undefined);\n } catch (error) {\n console.error('removeMember failed:', error);\n return Result.err('Failed to remove member');\n }\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/mutations/leagues/ScheduleAdminMutation.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'CreateLeagueScheduleRaceInputDTO' is defined but never used.","line":6,"column":15,"nodeType":"Identifier","messageId":"unusedVar","endLine":6,"endColumn":47},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'UpdateLeagueScheduleRaceInputDTO' is defined but never used.","line":7,"column":15,"nodeType":"Identifier","messageId":"unusedVar","endLine":7,"endColumn":47},{"ruleId":"gridpilot-rules/mutation-contract","severity":2,"message":"Mutation classes must implement Mutation - see apps/website/lib/contracts/mutations/Mutation.ts","line":15,"column":14,"nodeType":"Identifier","messageId":"mustImplementMutationInterface","endLine":15,"endColumn":35},{"ruleId":"gridpilot-rules/no-direct-process-env","severity":2,"message":"Do not read process.env directly here. Use `getWebsiteServerEnv()` / `getWebsitePublicEnv()` (apps/website/lib/config/env.ts) or a dedicated config helper (e.g. getWebsiteApiBaseUrl()).","line":20,"column":21,"nodeType":"MemberExpression","messageId":"noProcessEnv","endLine":20,"endColumn":52},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'apiClient' is assigned a value but never used.","line":23,"column":11,"nodeType":"Identifier","messageId":"unusedVar","endLine":23,"endColumn":20},{"ruleId":"gridpilot-rules/clean-error-handling","severity":2,"message":"PageQueries and Mutations must use Services for data access, not API Clients directly.","line":23,"column":23,"nodeType":"NewExpression","messageId":"mustUseServices","endLine":23,"endColumn":75}],"suppressedMessages":[],"errorCount":6,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Result } from '@/lib/contracts/Result';\nimport { LeagueService } from '@/lib/services/leagues/LeagueService';\nimport { LeaguesApiClient } from '@/lib/api/leagues/LeaguesApiClient';\nimport { ConsoleErrorReporter } from '@/lib/infrastructure/logging/ConsoleErrorReporter';\nimport { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';\nimport type { CreateLeagueScheduleRaceInputDTO } from '@/lib/types/generated/CreateLeagueScheduleRaceInputDTO';\nimport type { UpdateLeagueScheduleRaceInputDTO } from '@/lib/types/generated/UpdateLeagueScheduleRaceInputDTO';\n\n/**\n * ScheduleAdminMutation\n * \n * Framework-agnostic mutation for schedule administration operations.\n * Can be called from Server Actions or other contexts.\n */\nexport class ScheduleAdminMutation {\n private service: LeagueService;\n\n constructor() {\n // Manual wiring for serverless\n const baseUrl = process.env.NEXT_PUBLIC_API_URL || '';\n const errorReporter = new ConsoleErrorReporter();\n const logger = new ConsoleLogger();\n const apiClient = new LeaguesApiClient(baseUrl, errorReporter, logger);\n \n this.service = new LeagueService();\n }\n\n async publishSchedule(leagueId: string, seasonId: string): Promise> {\n try {\n await this.service.publishAdminSchedule(leagueId, seasonId);\n return Result.ok(undefined);\n } catch (error) {\n console.error('publishSchedule failed:', error);\n return Result.err('Failed to publish schedule');\n }\n }\n\n async unpublishSchedule(leagueId: string, seasonId: string): Promise> {\n try {\n await this.service.unpublishAdminSchedule(leagueId, seasonId);\n return Result.ok(undefined);\n } catch (error) {\n console.error('unpublishSchedule failed:', error);\n return Result.err('Failed to unpublish schedule');\n }\n }\n\n async createRace(leagueId: string, seasonId: string, input: { track: string; car: string; scheduledAtIso: string }): Promise> {\n try {\n await this.service.createAdminScheduleRace(leagueId, seasonId, input);\n return Result.ok(undefined);\n } catch (error) {\n console.error('createRace failed:', error);\n return Result.err('Failed to create race');\n }\n }\n\n async updateRace(leagueId: string, seasonId: string, raceId: string, input: Partial<{ track: string; car: string; scheduledAtIso: string }>): Promise> {\n try {\n await this.service.updateAdminScheduleRace(leagueId, seasonId, raceId, input);\n return Result.ok(undefined);\n } catch (error) {\n console.error('updateRace failed:', error);\n return Result.err('Failed to update race');\n }\n }\n\n async deleteRace(leagueId: string, seasonId: string, raceId: string): Promise> {\n try {\n await this.service.deleteAdminScheduleRace(leagueId, seasonId, raceId);\n return Result.ok(undefined);\n } catch (error) {\n console.error('deleteRace failed:', error);\n return Result.err('Failed to delete race');\n }\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/mutations/leagues/StewardingMutation.ts","messages":[{"ruleId":"gridpilot-rules/mutation-contract","severity":2,"message":"Mutation classes must implement Mutation - see apps/website/lib/contracts/mutations/Mutation.ts","line":13,"column":14,"nodeType":"Identifier","messageId":"mustImplementMutationInterface","endLine":13,"endColumn":32},{"ruleId":"gridpilot-rules/no-direct-process-env","severity":2,"message":"Do not read process.env directly here. Use `getWebsiteServerEnv()` / `getWebsitePublicEnv()` (apps/website/lib/config/env.ts) or a dedicated config helper (e.g. getWebsiteApiBaseUrl()).","line":18,"column":21,"nodeType":"MemberExpression","messageId":"noProcessEnv","endLine":18,"endColumn":52},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'apiClient' is assigned a value but never used.","line":21,"column":11,"nodeType":"Identifier","messageId":"unusedVar","endLine":21,"endColumn":20},{"ruleId":"gridpilot-rules/clean-error-handling","severity":2,"message":"PageQueries and Mutations must use Services for data access, not API Clients directly.","line":21,"column":23,"nodeType":"NewExpression","messageId":"mustUseServices","endLine":21,"endColumn":75}],"suppressedMessages":[],"errorCount":4,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Result } from '@/lib/contracts/Result';\nimport { LeagueService } from '@/lib/services/leagues/LeagueService';\nimport { LeaguesApiClient } from '@/lib/api/leagues/LeaguesApiClient';\nimport { ConsoleErrorReporter } from '@/lib/infrastructure/logging/ConsoleErrorReporter';\nimport { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';\n\n/**\n * StewardingMutation\n * \n * Framework-agnostic mutation for stewarding operations.\n * Can be called from Server Actions or other contexts.\n */\nexport class StewardingMutation {\n private service: LeagueService;\n\n constructor() {\n // Manual wiring for serverless\n const baseUrl = process.env.NEXT_PUBLIC_API_URL || '';\n const errorReporter = new ConsoleErrorReporter();\n const logger = new ConsoleLogger();\n const apiClient = new LeaguesApiClient(baseUrl, errorReporter, logger);\n \n this.service = new LeagueService();\n }\n\n async applyPenalty(input: {\n protestId: string;\n penaltyType: string;\n penaltyValue: number;\n stewardNotes: string;\n raceId: string;\n accusedDriverId: string;\n reason: string;\n }): Promise> {\n try {\n // TODO: Implement when penalty API is available\n // For now, return success\n console.log('applyPenalty called with:', input);\n return Result.ok(undefined);\n } catch (error) {\n console.error('applyPenalty failed:', error);\n return Result.err('Failed to apply penalty');\n }\n }\n\n async requestDefense(input: {\n protestId: string;\n stewardId: string;\n }): Promise> {\n try {\n // TODO: Implement when defense API is available\n // For now, return success\n console.log('requestDefense called with:', input);\n return Result.ok(undefined);\n } catch (error) {\n console.error('requestDefense failed:', error);\n return Result.err('Failed to request defense');\n }\n }\n\n async quickPenalty(input: {\n leagueId: string;\n driverId: string;\n raceId: string;\n penaltyType: string;\n penaltyValue: number;\n reason: string;\n adminId: string;\n }): Promise> {\n try {\n // TODO: Implement when quick penalty API is available\n // For now, return success\n console.log('quickPenalty called with:', input);\n return Result.ok(undefined);\n } catch (error) {\n console.error('quickPenalty failed:', error);\n return Result.err('Failed to apply quick penalty');\n }\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/mutations/leagues/WalletMutation.ts","messages":[{"ruleId":"gridpilot-rules/mutation-contract","severity":2,"message":"Mutation classes must implement Mutation - see apps/website/lib/contracts/mutations/Mutation.ts","line":13,"column":14,"nodeType":"Identifier","messageId":"mustImplementMutationInterface","endLine":13,"endColumn":28},{"ruleId":"gridpilot-rules/no-direct-process-env","severity":2,"message":"Do not read process.env directly here. Use `getWebsiteServerEnv()` / `getWebsitePublicEnv()` (apps/website/lib/config/env.ts) or a dedicated config helper (e.g. getWebsiteApiBaseUrl()).","line":18,"column":21,"nodeType":"MemberExpression","messageId":"noProcessEnv","endLine":18,"endColumn":52},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'apiClient' is assigned a value but never used.","line":21,"column":11,"nodeType":"Identifier","messageId":"unusedVar","endLine":21,"endColumn":20},{"ruleId":"gridpilot-rules/clean-error-handling","severity":2,"message":"PageQueries and Mutations must use Services for data access, not API Clients directly.","line":21,"column":23,"nodeType":"NewExpression","messageId":"mustUseServices","endLine":21,"endColumn":75}],"suppressedMessages":[],"errorCount":4,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Result } from '@/lib/contracts/Result';\nimport { LeagueService } from '@/lib/services/leagues/LeagueService';\nimport { LeaguesApiClient } from '@/lib/api/leagues/LeaguesApiClient';\nimport { ConsoleErrorReporter } from '@/lib/infrastructure/logging/ConsoleErrorReporter';\nimport { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';\n\n/**\n * WalletMutation\n * \n * Framework-agnostic mutation for wallet operations.\n * Can be called from Server Actions or other contexts.\n */\nexport class WalletMutation {\n private service: LeagueService;\n\n constructor() {\n // Manual wiring for serverless\n const baseUrl = process.env.NEXT_PUBLIC_API_URL || '';\n const errorReporter = new ConsoleErrorReporter();\n const logger = new ConsoleLogger();\n const apiClient = new LeaguesApiClient(baseUrl, errorReporter, logger);\n \n this.service = new LeagueService();\n }\n\n async withdraw(leagueId: string, amount: number): Promise> {\n try {\n // TODO: Implement when wallet withdrawal API is available\n // For now, return success\n console.log('withdraw called with:', { leagueId, amount });\n return Result.ok(undefined);\n } catch (error) {\n console.error('withdraw failed:', error);\n return Result.err('Failed to withdraw funds');\n }\n }\n\n async exportTransactions(leagueId: string): Promise> {\n try {\n // TODO: Implement when export API is available\n // For now, return success\n console.log('exportTransactions called with:', { leagueId });\n return Result.ok(undefined);\n } catch (error) {\n console.error('exportTransactions failed:', error);\n return Result.err('Failed to export transactions');\n }\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/mutations/onboarding/CompleteOnboardingMutation.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/mutations/onboarding/GenerateAvatarsMutation.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/mutations/sponsors/AcceptSponsorshipRequestMutation.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/mutations/sponsors/RejectSponsorshipRequestMutation.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/AdminDashboardPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/AdminUsersPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/CreateLeaguePageQuery.ts","messages":[{"ruleId":"gridpilot-rules/page-query-must-use-builders","severity":2,"message":"PageQueries must use ViewDataBuilder to transform DTOs - see apps/website/lib/contracts/builders/ViewDataBuilder.ts","line":1,"column":1,"nodeType":"Program","messageId":"mustUseBuilder","endLine":50,"endColumn":2},{"ruleId":"gridpilot-rules/clean-error-handling","severity":2,"message":"PageQueries and Mutations must use Services for data access, not API Clients directly.","line":1,"column":1,"nodeType":"Program","messageId":"mustUseServices","endLine":50,"endColumn":2},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":12,"column":57,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":12,"endColumn":60,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[499,502],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[499,502],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":13,"column":35,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":13,"endColumn":38,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[546,549],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[546,549],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"gridpilot-rules/no-direct-process-env","severity":2,"message":"Do not read process.env directly here. Use `getWebsiteServerEnv()` / `getWebsitePublicEnv()` (apps/website/lib/config/env.ts) or a dedicated config helper (e.g. getWebsiteApiBaseUrl()).","line":15,"column":21,"nodeType":"MemberExpression","messageId":"noProcessEnv","endLine":15,"endColumn":52},{"ruleId":"gridpilot-rules/clean-error-handling","severity":2,"message":"PageQueries and Mutations must use Services for data access, not API Clients directly.","line":18,"column":23,"nodeType":"NewExpression","messageId":"mustUseServices","endLine":18,"endColumn":75},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":46,"column":42,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":46,"endColumn":45,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1718,1721],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1718,1721],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":7,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { PageQuery } from '@/lib/contracts/page-queries/PageQuery';\nimport { Result } from '@/lib/contracts/Result';\nimport { LeaguesApiClient } from '@/lib/api/leagues/LeaguesApiClient';\nimport { ConsoleErrorReporter } from '@/lib/infrastructure/logging/ConsoleErrorReporter';\nimport { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';\n\n/**\n * CreateLeaguePageQuery\n * \n * Fetches data needed for the create league page.\n */\nexport class CreateLeaguePageQuery implements PageQuery {\n async execute(): Promise> {\n // Manual wiring: create API client\n const baseUrl = process.env.NEXT_PUBLIC_API_URL || '';\n const errorReporter = new ConsoleErrorReporter();\n const logger = new ConsoleLogger();\n const apiClient = new LeaguesApiClient(baseUrl, errorReporter, logger);\n \n try {\n // Get scoring presets for the form\n const presetsData = await apiClient.getScoringPresets();\n \n return Result.ok({\n scoringPresets: presetsData.presets || [],\n });\n } catch (error) {\n console.error('CreateLeaguePageQuery failed:', error);\n \n if (error instanceof Error) {\n if (error.message.includes('403') || error.message.includes('401')) {\n return Result.err('redirect');\n }\n if (error.message.includes('404')) {\n return Result.err('notFound');\n }\n if (error.message.includes('5') || error.message.includes('server')) {\n return Result.err('CREATE_LEAGUE_FETCH_FAILED');\n }\n }\n \n return Result.err('UNKNOWN_ERROR');\n }\n }\n\n static async execute(): Promise> {\n const query = new CreateLeaguePageQuery();\n return query.execute();\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/DashboardPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/DriverProfilePageQuery.ts","messages":[{"ruleId":"gridpilot-rules/page-query-contract","severity":2,"message":"PageQuery class must implement PageQuery interface - see apps/website/lib/contracts/page-queries/PageQuery.ts","line":13,"column":8,"nodeType":"ClassDeclaration","messageId":"message","endLine":55,"endColumn":2}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Result } from '@/lib/contracts/Result';\nimport { DriverProfilePageService } from '@/lib/services/drivers/DriverProfilePageService';\nimport { DriverProfileViewDataBuilder } from '@/lib/builders/view-data/DriverProfileViewDataBuilder';\nimport type { DriverProfileViewData } from '@/lib/types/view-data/DriverProfileViewData';\n\n/**\n * DriverProfilePageQuery\n *\n * Server-side data fetcher for the driver profile page.\n * Returns Result\n * Uses Service for data access and ViewDataBuilder for transformation.\n */\nexport class DriverProfilePageQuery {\n /**\n * Execute the driver profile page query\n *\n * @param driverId - The driver ID to fetch profile for\n * @returns Result with ViewData or error\n */\n static async execute(driverId: string | null): Promise> {\n if (!driverId) {\n return Result.err('NotFound');\n }\n\n try {\n // Manual wiring: construct dependencies explicitly\n const service = new DriverProfilePageService();\n\n const result = await service.getDriverProfile(driverId);\n\n if (result.isErr()) {\n const error = result.getError();\n\n if (error === 'notFound') {\n return Result.err('NotFound');\n }\n\n if (error === 'unauthorized') {\n return Result.err('Unauthorized');\n }\n\n return Result.err('Error');\n }\n\n // Build ViewData from DTO\n const dto = result.unwrap();\n const viewData = DriverProfileViewDataBuilder.build(dto);\n return Result.ok(viewData);\n\n } catch (error) {\n console.error('DriverProfilePageQuery failed:', error);\n return Result.err('Error');\n }\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/DriverRankingsPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/DriversPageQuery.ts","messages":[{"ruleId":"gridpilot-rules/page-query-contract","severity":2,"message":"PageQuery class must implement PageQuery interface - see apps/website/lib/contracts/page-queries/PageQuery.ts","line":13,"column":8,"nodeType":"ClassDeclaration","messageId":"message","endLine":46,"endColumn":2}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Result } from '@/lib/contracts/Result';\nimport { DriversPageService } from '@/lib/services/drivers/DriversPageService';\nimport { DriversViewDataBuilder } from '@/lib/builders/view-data/DriversViewDataBuilder';\nimport type { DriversViewData } from '@/lib/types/view-data/DriversViewData';\n\n/**\n * DriversPageQuery\n *\n * Server-side data fetcher for the drivers listing page.\n * Returns Result\n * Uses Service for data access and ViewDataBuilder for transformation.\n */\nexport class DriversPageQuery {\n /**\n * Execute the drivers page query\n *\n * @returns Result with ViewData or error\n */\n static async execute(): Promise> {\n try {\n // Manual wiring: construct dependencies explicitly\n const service = new DriversPageService();\n\n const result = await service.getLeaderboard();\n\n if (result.isErr()) {\n const error = result.getError();\n\n if (error === 'notFound') {\n return Result.err('NotFound');\n }\n\n return Result.err('Error');\n }\n\n // Build ViewData from DTO\n const dto = result.unwrap();\n const viewData = DriversViewDataBuilder.build(dto);\n return Result.ok(viewData);\n\n } catch (error) {\n console.error('DriversPageQuery failed:', error);\n return Result.err('Error');\n }\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/LeaderboardsPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/LeagueDetailPageQuery.ts","messages":[{"ruleId":"gridpilot-rules/page-query-must-use-builders","severity":2,"message":"PageQueries must use ViewDataBuilder to transform DTOs - see apps/website/lib/contracts/builders/ViewDataBuilder.ts","line":1,"column":1,"nodeType":"Program","messageId":"mustUseBuilder","endLine":29,"endColumn":1},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":11,"column":57,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":11,"endColumn":60,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[508,511],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[508,511],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":12,"column":51,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":12,"endColumn":54,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[592,595],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[592,595],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":24,"column":58,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":24,"endColumn":61,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[990,993],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[990,993],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":4,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { PageQuery } from '@/lib/contracts/page-queries/PageQuery';\nimport { Result } from '@/lib/contracts/Result';\nimport { LeagueService } from '@/lib/services/leagues/LeagueService';\nimport { type PresentationError, mapToPresentationError } from '@/lib/contracts/page-queries/PresentationError';\n\n/**\n * LeagueDetail page query\n * Returns the raw API DTO for the league detail page\n * No DI container usage - constructs dependencies explicitly\n */\nexport class LeagueDetailPageQuery implements PageQuery {\n async execute(leagueId: string): Promise> {\n const service = new LeagueService();\n const result = await service.getLeagueDetailData(leagueId);\n\n if (result.isErr()) {\n return Result.err(mapToPresentationError(result.getError()));\n }\n\n return Result.ok(result.unwrap());\n }\n\n // Static method to avoid object construction in server code\n static async execute(leagueId: string): Promise> {\n const query = new LeagueDetailPageQuery();\n return query.execute(leagueId);\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/LeagueProtestDetailPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/LeagueProtestReviewPageQuery.ts","messages":[{"ruleId":"gridpilot-rules/page-query-must-use-builders","severity":2,"message":"PageQueries must use ViewDataBuilder to transform DTOs - see apps/website/lib/contracts/builders/ViewDataBuilder.ts","line":1,"column":1,"nodeType":"Program","messageId":"mustUseBuilder","endLine":77,"endColumn":2},{"ruleId":"gridpilot-rules/clean-error-handling","severity":2,"message":"PageQueries and Mutations must use Services for data access, not API Clients directly.","line":1,"column":1,"nodeType":"Program","messageId":"mustUseServices","endLine":77,"endColumn":2},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":13,"column":64,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":13,"endColumn":67,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[579,582],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[579,582],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":14,"column":81,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":14,"endColumn":84,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[707,710],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[707,710],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"gridpilot-rules/no-direct-process-env","severity":2,"message":"Do not read process.env directly here. Use `getWebsiteServerEnv()` / `getWebsitePublicEnv()` (apps/website/lib/config/env.ts) or a dedicated config helper (e.g. getWebsiteApiBaseUrl()).","line":16,"column":21,"nodeType":"MemberExpression","messageId":"noProcessEnv","endLine":16,"endColumn":52},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'leaguesApiClient' is assigned a value but never used.","line":19,"column":11,"nodeType":"Identifier","messageId":"unusedVar","endLine":19,"endColumn":27},{"ruleId":"gridpilot-rules/clean-error-handling","severity":2,"message":"PageQueries and Mutations must use Services for data access, not API Clients directly.","line":19,"column":30,"nodeType":"NewExpression","messageId":"mustUseServices","endLine":19,"endColumn":82},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'protestsApiClient' is assigned a value but never used.","line":20,"column":11,"nodeType":"Identifier","messageId":"unusedVar","endLine":20,"endColumn":28},{"ruleId":"gridpilot-rules/clean-error-handling","severity":2,"message":"PageQueries and Mutations must use Services for data access, not API Clients directly.","line":20,"column":31,"nodeType":"NewExpression","messageId":"mustUseServices","endLine":20,"endColumn":84},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":73,"column":88,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":73,"endColumn":91,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2762,2765],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2762,2765],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":10,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { PageQuery } from '@/lib/contracts/page-queries/PageQuery';\nimport { Result } from '@/lib/contracts/Result';\nimport { LeaguesApiClient } from '@/lib/api/leagues/LeaguesApiClient';\nimport { ProtestsApiClient } from '@/lib/api/protests/ProtestsApiClient';\nimport { ConsoleErrorReporter } from '@/lib/infrastructure/logging/ConsoleErrorReporter';\nimport { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';\n\n/**\n * LeagueProtestReviewPageQuery\n * \n * Fetches protest detail data for review.\n */\nexport class LeagueProtestReviewPageQuery implements PageQuery {\n async execute(input: { leagueId: string; protestId: string }): Promise> {\n // Manual wiring: create API clients\n const baseUrl = process.env.NEXT_PUBLIC_API_URL || '';\n const errorReporter = new ConsoleErrorReporter();\n const logger = new ConsoleLogger();\n const leaguesApiClient = new LeaguesApiClient(baseUrl, errorReporter, logger);\n const protestsApiClient = new ProtestsApiClient(baseUrl, errorReporter, logger);\n \n try {\n // Get protest details\n // Note: This would need a getProtestDetail method on ProtestsApiClient\n // For now, return placeholder data\n const protestDetail = {\n protest: {\n id: input.protestId,\n raceId: 'placeholder',\n protestingDriverId: 'placeholder',\n accusedDriverId: 'placeholder',\n description: 'Placeholder protest',\n status: 'pending',\n submittedAt: new Date().toISOString(),\n },\n race: {\n id: 'placeholder',\n name: 'Placeholder Race',\n scheduledAt: new Date().toISOString(),\n },\n protestingDriver: {\n id: 'placeholder',\n name: 'Placeholder Protester',\n },\n accusedDriver: {\n id: 'placeholder',\n name: 'Placeholder Accused',\n },\n penaltyTypes: [],\n defaultReasons: {},\n };\n \n return Result.ok(protestDetail);\n } catch (error) {\n console.error('LeagueProtestReviewPageQuery failed:', error);\n \n if (error instanceof Error) {\n if (error.message.includes('403') || error.message.includes('401')) {\n return Result.err('redirect');\n }\n if (error.message.includes('404')) {\n return Result.err('notFound');\n }\n if (error.message.includes('5') || error.message.includes('server')) {\n return Result.err('PROTEST_FETCH_FAILED');\n }\n }\n \n return Result.err('UNKNOWN_ERROR');\n }\n }\n\n static async execute(input: { leagueId: string; protestId: string }): Promise> {\n const query = new LeagueProtestReviewPageQuery();\n return query.execute(input);\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/LeagueRosterAdminPageQuery.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":12,"column":62,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":12,"endColumn":65,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[579,582],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[579,582],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":13,"column":51,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":13,"endColumn":54,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[663,666],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[663,666],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":25,"column":58,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":25,"endColumn":61,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1068,1071],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1068,1071],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":3,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { PageQuery } from '@/lib/contracts/page-queries/PageQuery';\nimport { Result } from '@/lib/contracts/Result';\nimport { LeagueService } from '@/lib/services/leagues/LeagueService';\nimport { LeagueRosterAdminViewDataBuilder } from '@/lib/builders/view-data/LeagueRosterAdminViewDataBuilder';\nimport { type PresentationError, mapToPresentationError } from '@/lib/contracts/page-queries/PresentationError';\n\n/**\n * LeagueRosterAdminPageQuery\n * \n * Fetches league roster admin data (members and join requests).\n */\nexport class LeagueRosterAdminPageQuery implements PageQuery {\n async execute(leagueId: string): Promise> {\n const service = new LeagueService();\n const result = await service.getRosterAdminData(leagueId);\n\n if (result.isErr()) {\n return Result.err(mapToPresentationError(result.getError()));\n }\n\n const viewData = LeagueRosterAdminViewDataBuilder.build(result.unwrap());\n return Result.ok(viewData);\n }\n\n static async execute(leagueId: string): Promise> {\n const query = new LeagueRosterAdminPageQuery();\n return query.execute(leagueId);\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/LeagueRulebookPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/LeagueScheduleAdminPageQuery.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":12,"column":64,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":12,"endColumn":67,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[551,554],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[551,554],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":13,"column":81,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":13,"endColumn":84,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[679,682],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[679,682],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":24,"column":42,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":24,"endColumn":45,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1101,1104],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1101,1104],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":36,"column":88,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":36,"endColumn":91,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1404,1407],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1404,1407],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":4,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { PageQuery } from '@/lib/contracts/page-queries/PageQuery';\nimport { Result } from '@/lib/contracts/Result';\nimport { LeagueService } from '@/lib/services/leagues/LeagueService';\nimport { LeagueScheduleViewDataBuilder } from '@/lib/builders/view-data/LeagueScheduleViewDataBuilder';\nimport { type PresentationError, mapToPresentationError } from '@/lib/contracts/page-queries/PresentationError';\n\n/**\n * LeagueScheduleAdminPageQuery\n * \n * Fetches league schedule admin data.\n */\nexport class LeagueScheduleAdminPageQuery implements PageQuery {\n async execute(input: { leagueId: string; seasonId?: string }): Promise> {\n const service = new LeagueService();\n const result = await service.getScheduleAdminData(input.leagueId, input.seasonId);\n\n if (result.isErr()) {\n return Result.err(mapToPresentationError(result.getError()));\n }\n\n const data = result.unwrap();\n const viewData = LeagueScheduleViewDataBuilder.build({\n leagueId: data.leagueId,\n races: data.schedule.races.map((r: any) => ({\n id: r.id,\n name: r.name,\n date: r.scheduledAt,\n track: r.track,\n car: r.car,\n sessionType: r.sessionType,\n })),\n });\n return Result.ok(viewData);\n }\n\n static async execute(input: { leagueId: string; seasonId?: string }): Promise> {\n const query = new LeagueScheduleAdminPageQuery();\n return query.execute(input);\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/LeagueSchedulePageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/LeagueSettingsPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/LeagueSponsorshipsPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/LeagueStandingsPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/LeagueStewardingPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/LeagueWalletPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/LeaguesPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/OnboardingPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/ProfileLeaguesPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/ProfilePageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/SponsorDashboardPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/SponsorshipRequestsPageDto.ts","messages":[{"ruleId":"gridpilot-rules/page-query-filename","severity":2,"message":"PageQuery files must end with PageQuery.ts - see apps/website/lib/contracts/page-queries/PageQuery.ts","line":1,"column":1,"nodeType":null,"messageId":"message"},{"ruleId":"gridpilot-rules/page-query-must-use-builders","severity":2,"message":"PageQueries must use ViewDataBuilder to transform DTOs - see apps/website/lib/contracts/builders/ViewDataBuilder.ts","line":1,"column":1,"nodeType":"Program","messageId":"mustUseBuilder","endLine":16,"endColumn":1},{"ruleId":"gridpilot-rules/clean-error-handling","severity":2,"message":"PageQueries and Mutations must use Services for data access, not API Clients directly.","line":1,"column":1,"nodeType":"Program","messageId":"mustUseServices","endLine":16,"endColumn":1}],"suppressedMessages":[],"errorCount":3,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"export interface SponsorshipRequestsPageDto {\n sections: Array<{\n entityType: 'driver' | 'team' | 'season';\n entityId: string;\n entityName: string;\n requests: Array<{\n requestId: string;\n sponsorId: string;\n sponsorName: string;\n message: string | null;\n createdAtIso: string;\n raw: unknown;\n }>;\n }>;\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/SponsorshipRequestsPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/TeamDetailPageQuery.ts","messages":[{"ruleId":"gridpilot-rules/single-export-per-file","severity":2,"message":"File should have exactly one export. Found 2 exports: TeamDetailPageDto, TeamDetailPageQuery","line":1,"column":1,"nodeType":"Program","messageId":"multipleExports","endLine":120,"endColumn":1}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { PageQuery } from '@/lib/contracts/page-queries/PageQuery';\nimport { Result } from '@/lib/contracts/Result';\nimport { TeamService } from '@/lib/services/teams/TeamService';\nimport { TeamDetailViewDataBuilder } from '@/lib/builders/view-data/TeamDetailViewDataBuilder';\nimport type { TeamDetailViewData } from '@/lib/view-data/TeamDetailViewData';\nimport { type PresentationError, mapToPresentationError } from '@/lib/contracts/page-queries/PresentationError';\nimport { SessionGateway } from '@/lib/gateways/SessionGateway';\nimport type { TeamMemberViewModel } from '@/lib/view-models/TeamMemberViewModel';\n\n/**\n * TeamDetailPageDto - Raw serializable data for team detail page\n * Contains only raw data, no derived/computed properties\n */\nexport interface TeamDetailPageDto {\n team: {\n id: string;\n name: string;\n tag: string;\n description?: string;\n ownerId: string;\n leagues: string[];\n createdAt?: string;\n specialization?: string;\n region?: string;\n languages?: string[];\n category?: string;\n membership?: {\n role: string;\n joinedAt: string;\n isActive: boolean;\n } | null;\n canManage: boolean;\n };\n memberships: Array<{\n driverId: string;\n driverName: string;\n role: 'owner' | 'manager' | 'member';\n joinedAt: string;\n isActive: boolean;\n avatarUrl: string;\n }>;\n currentDriverId: string;\n}\n\n/**\n * TeamDetailPageQuery - Server-side composition for team detail page\n */\nexport class TeamDetailPageQuery implements PageQuery {\n async execute(teamId: string): Promise> {\n // Get session to determine current driver\n const sessionGateway = new SessionGateway();\n const session = await sessionGateway.getSession();\n \n if (!session?.user?.primaryDriverId) {\n return Result.err('notFound');\n }\n\n const currentDriverId = session.user.primaryDriverId;\n const service = new TeamService();\n \n // Fetch team details\n const teamResult = await service.getTeamDetails(teamId, currentDriverId);\n \n if (teamResult.isErr()) {\n return Result.err(mapToPresentationError(teamResult.getError()));\n }\n\n const teamData = teamResult.unwrap();\n\n // Fetch team members\n const membersResult = await service.getTeamMembers(teamId, currentDriverId, teamData.ownerId);\n \n if (membersResult.isErr()) {\n return Result.err(mapToPresentationError(membersResult.getError()));\n }\n\n const membersData = membersResult.unwrap();\n \n // Transform to raw serializable DTO\n const dto: TeamDetailPageDto = {\n team: {\n id: teamData.id,\n name: teamData.name,\n tag: teamData.tag,\n description: teamData.description,\n ownerId: teamData.ownerId,\n leagues: teamData.leagues,\n createdAt: teamData.createdAt,\n specialization: teamData.specialization,\n region: teamData.region,\n languages: teamData.languages,\n category: teamData.category,\n membership: teamData.membership ? {\n role: teamData.membership.role,\n joinedAt: teamData.membership.joinedAt,\n isActive: teamData.membership.isActive,\n } : null,\n canManage: teamData.canManage,\n },\n memberships: membersData.map((member: TeamMemberViewModel) => ({\n driverId: member.driverId,\n driverName: member.driverName,\n role: member.role,\n joinedAt: member.joinedAt,\n isActive: member.isActive,\n avatarUrl: member.avatarUrl,\n })),\n currentDriverId,\n };\n\n const viewData = TeamDetailViewDataBuilder.build(dto);\n return Result.ok(viewData);\n }\n\n static async execute(teamId: string): Promise> {\n const query = new TeamDetailPageQuery();\n return query.execute(teamId);\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/TeamsPageQuery.ts","messages":[{"ruleId":"gridpilot-rules/single-export-per-file","severity":2,"message":"File should have exactly one export. Found 2 exports: TeamsPageDto, TeamsPageQuery","line":1,"column":1,"nodeType":"Program","messageId":"multipleExports","endLine":41,"endColumn":1}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Result } from '@/lib/contracts/Result';\nimport { PageQuery } from '@/lib/contracts/page-queries/PageQuery';\nimport { PresentationError, mapToPresentationError } from '@/lib/contracts/page-queries/PresentationError';\nimport { TeamService } from '@/lib/services/teams/TeamService';\nimport type { TeamsViewData } from '@/lib/view-data/TeamsViewData';\nimport { TeamsViewDataBuilder } from '@/lib/builders/view-data/TeamsViewDataBuilder';\nimport type { TeamListItemDTO } from '@/lib/types/generated/TeamListItemDTO';\n\nexport interface TeamsPageDto {\n teams: TeamListItemDTO[];\n}\n\n/**\n * TeamsPageQuery - Server-side composition for teams list page\n * Manual wiring only; no ContainerManager; no PageDataFetcher\n */\nexport class TeamsPageQuery implements PageQuery {\n async execute(): Promise> {\n try {\n // Manual dependency creation\n const service = new TeamService();\n \n // Fetch teams\n const result = await service.getAllTeams();\n \n if (result.isErr()) {\n return Result.err(mapToPresentationError(result.getError()));\n }\n\n const teams = result.unwrap();\n \n // Transform to ViewData using builder\n const viewData = TeamsViewDataBuilder.build({ teams });\n\n return Result.ok(viewData);\n } catch (error) {\n return Result.err('unknown');\n }\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/auth/ForgotPasswordPageQuery.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":30,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":30,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1453,1456],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1453,1456],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Result } from '@/lib/contracts/Result';\nimport { PageQuery } from '@/lib/contracts/page-queries/PageQuery';\nimport { ForgotPasswordViewDataBuilder } from '@/lib/builders/view-data/ForgotPasswordViewDataBuilder';\nimport { ForgotPasswordViewData } from '@/lib/builders/view-data/types/ForgotPasswordViewData';\nimport { AuthPageService } from '@/lib/services/auth/AuthPageService';\nimport { SearchParamParser } from '@/lib/routing/search-params/SearchParamParser';\n\nexport class ForgotPasswordPageQuery implements PageQuery {\n async execute(searchParams: URLSearchParams): Promise> {\n // Parse and validate search parameters\n const parsedResult = SearchParamParser.parseAuth(searchParams);\n if (parsedResult.isErr()) {\n return Result.err(`Invalid search parameters: ${parsedResult.getError()}`);\n }\n\n const { returnTo, token } = parsedResult.unwrap();\n\n try {\n // Use service to process parameters\n const authService = new AuthPageService();\n const serviceResult = await authService.processForgotPasswordParams({ returnTo, token });\n \n if (serviceResult.isErr()) {\n return Result.err(serviceResult.getError().message);\n }\n\n // Transform to ViewData using builder\n const viewData = ForgotPasswordViewDataBuilder.build(serviceResult.unwrap());\n return Result.ok(viewData);\n } catch (error: any) {\n return Result.err(error.message || 'Failed to execute forgot password page query');\n }\n }\n\n // Static factory method for convenience\n static async execute(searchParams: URLSearchParams): Promise> {\n const query = new ForgotPasswordPageQuery();\n return query.execute(searchParams);\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/auth/LoginPageQuery.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":30,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":30,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1372,1375],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1372,1375],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Result } from '@/lib/contracts/Result';\nimport { PageQuery } from '@/lib/contracts/page-queries/PageQuery';\nimport { LoginViewDataBuilder } from '@/lib/builders/view-data/LoginViewDataBuilder';\nimport { LoginViewData } from '@/lib/builders/view-data/types/LoginViewData';\nimport { AuthPageService } from '@/lib/services/auth/AuthPageService';\nimport { SearchParamParser } from '@/lib/routing/search-params/SearchParamParser';\n\nexport class LoginPageQuery implements PageQuery {\n async execute(searchParams: URLSearchParams): Promise> {\n // Parse and validate search parameters\n const parsedResult = SearchParamParser.parseAuth(searchParams);\n if (parsedResult.isErr()) {\n return Result.err(`Invalid search parameters: ${parsedResult.getError()}`);\n }\n\n const { returnTo, token } = parsedResult.unwrap();\n\n try {\n // Use service to process parameters\n const authService = new AuthPageService();\n const serviceResult = await authService.processLoginParams({ returnTo, token });\n \n if (serviceResult.isErr()) {\n return Result.err(serviceResult.getError().message);\n }\n\n // Transform to ViewData using builder\n const viewData = LoginViewDataBuilder.build(serviceResult.unwrap());\n return Result.ok(viewData);\n } catch (error: any) {\n return Result.err(error.message || 'Failed to execute login page query');\n }\n }\n\n // Static factory method for convenience\n static async execute(searchParams: URLSearchParams): Promise> {\n const query = new LoginPageQuery();\n return query.execute(searchParams);\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/auth/ResetPasswordPageQuery.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":30,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":30,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1444,1447],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1444,1447],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Result } from '@/lib/contracts/Result';\nimport { PageQuery } from '@/lib/contracts/page-queries/PageQuery';\nimport { ResetPasswordViewDataBuilder } from '@/lib/builders/view-data/ResetPasswordViewDataBuilder';\nimport { ResetPasswordViewData } from '@/lib/builders/view-data/types/ResetPasswordViewData';\nimport { AuthPageService } from '@/lib/services/auth/AuthPageService';\nimport { SearchParamParser } from '@/lib/routing/search-params/SearchParamParser';\n\nexport class ResetPasswordPageQuery implements PageQuery {\n async execute(searchParams: URLSearchParams): Promise> {\n // Parse and validate search parameters\n const parsedResult = SearchParamParser.parseAuth(searchParams);\n if (parsedResult.isErr()) {\n return Result.err(`Invalid search parameters: ${parsedResult.getError()}`);\n }\n\n const { returnTo, token } = parsedResult.unwrap();\n\n try {\n // Use service to process parameters\n const authService = new AuthPageService();\n const serviceResult = await authService.processResetPasswordParams({ returnTo, token });\n \n if (serviceResult.isErr()) {\n return Result.err(serviceResult.getError().message);\n }\n\n // Transform to ViewData using builder\n const viewData = ResetPasswordViewDataBuilder.build(serviceResult.unwrap());\n return Result.ok(viewData);\n } catch (error: any) {\n return Result.err(error.message || 'Failed to execute reset password page query');\n }\n }\n\n // Static factory method for convenience\n static async execute(searchParams: URLSearchParams): Promise> {\n const query = new ResetPasswordPageQuery();\n return query.execute(searchParams);\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/auth/SignupPageQuery.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":30,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":30,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1381,1384],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1381,1384],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { SignupViewDataBuilder } from '@/lib/builders/view-data/SignupViewDataBuilder';\nimport { SignupViewData } from '@/lib/builders/view-data/types/SignupViewData';\nimport { Result } from '@/lib/contracts/Result';\nimport { PageQuery } from '@/lib/contracts/page-queries/PageQuery';\nimport { AuthPageService } from '@/lib/services/auth/AuthPageService';\nimport { SearchParamParser } from '@/lib/routing/search-params/SearchParamParser';\n\nexport class SignupPageQuery implements PageQuery {\n async execute(searchParams: URLSearchParams): Promise> {\n // Parse and validate search parameters\n const parsedResult = SearchParamParser.parseAuth(searchParams);\n if (parsedResult.isErr()) {\n return Result.err(`Invalid search parameters: ${parsedResult.getError()}`);\n }\n\n const { returnTo, token } = parsedResult.unwrap();\n\n try {\n // Use service to process parameters\n const authService = new AuthPageService();\n const serviceResult = await authService.processSignupParams({ returnTo, token });\n \n if (serviceResult.isErr()) {\n return Result.err(serviceResult.getError().message);\n }\n\n // Transform to ViewData using builder\n const viewData = SignupViewDataBuilder.build(serviceResult.unwrap());\n return Result.ok(viewData);\n } catch (error: any) {\n return Result.err(error.message || 'Failed to execute signup page query');\n }\n }\n\n // Static factory method for convenience\n static async execute(searchParams: URLSearchParams): Promise> {\n const query = new SignupPageQuery();\n return query.execute(searchParams);\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/media/GetAvatarPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/media/GetCategoryIconPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/media/GetLeagueCoverPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/media/GetLeagueLogoPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/media/GetSponsorLogoPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/media/GetTeamLogoPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/media/GetTrackImagePageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/page-dtos/DriverRankingsPageDto.ts","messages":[{"ruleId":"gridpilot-rules/page-query-filename","severity":2,"message":"PageQuery files must end with PageQuery.ts - see apps/website/lib/contracts/page-queries/PageQuery.ts","line":1,"column":1,"nodeType":null,"messageId":"message"},{"ruleId":"gridpilot-rules/page-query-must-use-builders","severity":2,"message":"PageQueries must use ViewDataBuilder to transform DTOs - see apps/website/lib/contracts/builders/ViewDataBuilder.ts","line":1,"column":1,"nodeType":"Program","messageId":"mustUseBuilder","endLine":10,"endColumn":2},{"ruleId":"gridpilot-rules/clean-error-handling","severity":2,"message":"PageQueries and Mutations must use Services for data access, not API Clients directly.","line":1,"column":1,"nodeType":"Program","messageId":"mustUseServices","endLine":10,"endColumn":2}],"suppressedMessages":[],"errorCount":3,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import type { DriverLeaderboardItemDTO } from '@/lib/types/generated/DriverLeaderboardItemDTO';\n\n/**\n * DriverRankingsPageDto - Raw data structure for Driver Rankings page\n * Plain data, no methods, no business logic\n */\n\nexport interface DriverRankingsPageDto {\n drivers: DriverLeaderboardItemDTO[];\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/page-dtos/LeaderboardsPageDto.ts","messages":[{"ruleId":"gridpilot-rules/page-query-filename","severity":2,"message":"PageQuery files must end with PageQuery.ts - see apps/website/lib/contracts/page-queries/PageQuery.ts","line":1,"column":1,"nodeType":null,"messageId":"message"},{"ruleId":"gridpilot-rules/page-query-must-use-builders","severity":2,"message":"PageQueries must use ViewDataBuilder to transform DTOs - see apps/website/lib/contracts/builders/ViewDataBuilder.ts","line":1,"column":1,"nodeType":"Program","messageId":"mustUseBuilder","endLine":7,"endColumn":2},{"ruleId":"gridpilot-rules/clean-error-handling","severity":2,"message":"PageQueries and Mutations must use Services for data access, not API Clients directly.","line":1,"column":1,"nodeType":"Program","messageId":"mustUseServices","endLine":7,"endColumn":2}],"suppressedMessages":[],"errorCount":3,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import type { DriverLeaderboardItemDTO } from '@/lib/types/generated/DriverLeaderboardItemDTO';\nimport type { TeamListItemDTO } from '@/lib/types/generated/TeamListItemDTO';\n\nexport interface LeaderboardsPageDto {\n drivers: { drivers: DriverLeaderboardItemDTO[] };\n teams: { teams: TeamListItemDTO[] };\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/races/RaceDetailPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/races/RaceResultsPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/races/RaceStewardingPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/races/RacesAllPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page-queries/races/RacesPageQuery.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page/PageDataFetcher.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":30,"column":55,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":30,"endColumn":58,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[842,845],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[842,845],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"export interface FetchResult {\n data: T | null;\n errors: Record;\n hasErrors: boolean;\n}\n\nexport class PageDataFetcher {\n /**\n * Fetch using manual service instantiation\n * Use for: Multiple dependencies, request-scoped services, or auth context\n * RECOMMENDED for SSR\n */\n static async fetchManual(\n serviceFactory: () => Promise | TData\n ): Promise {\n try {\n const result = await serviceFactory();\n return result;\n } catch (error) {\n console.error('Failed to fetch manual:', error);\n return null;\n }\n }\n\n /**\n * Fetch multiple datasets in parallel with error aggregation\n * Use for: Pages needing multiple service calls\n * UPDATED: Returns both data and errors for proper handling\n */\n static async fetchMultiple>(\n queries: T\n ): Promise> {\n const results = {} as { [K in keyof T]: T[K] };\n const errors = {} as Record;\n \n const entries = await Promise.all(\n Object.entries(queries).map(async ([key, query]) => {\n try {\n const result = await query();\n return [key, { success: true, data: result }] as const;\n } catch (error) {\n console.error(`Failed to fetch ${key}:`, error);\n return [key, { success: false, error: error instanceof Error ? error : new Error(String(error)) }] as const;\n }\n })\n );\n\n entries.forEach(([key, result]) => {\n if (typeof result === 'object' && result !== null && 'success' in result) {\n if (result.success) {\n results[key as keyof T] = (result as { data: T[keyof T] }).data;\n } else {\n errors[key] = (result as { error: Error }).error;\n }\n }\n });\n\n return {\n data: results,\n errors,\n hasErrors: Object.keys(errors).length > 0\n };\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/page/usePageData.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'UseQueryOptions' is defined but never used.","line":4,"column":32,"nodeType":"Identifier","messageId":"unusedVar","endLine":4,"endColumn":47},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":28,"column":23,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":28,"endColumn":26,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[766,769],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[766,769],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":58,"column":62,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":58,"endColumn":65,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1539,1542],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1539,1542],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'key' is defined but never used.","line":64,"column":44,"nodeType":"Identifier","messageId":"unusedVar","endLine":64,"endColumn":47},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":65,"column":27,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":65,"endColumn":30,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1733,1736],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1733,1736],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'queryKey' is defined but never used.","line":135,"column":3,"nodeType":"Identifier","messageId":"unusedVar","endLine":135,"endColumn":21},{"ruleId":"import/no-named-as-default-member","severity":2,"message":"Caution: `React` also has a named export `useState`. Check if you meant to write `import {useState} from 'react'` instead.","line":137,"column":39,"nodeType":"MemberExpression","endLine":137,"endColumn":53},{"ruleId":"import/no-named-as-default-member","severity":2,"message":"Caution: `React` also has a named export `useEffect`. Check if you meant to write `import {useEffect} from 'react'` instead.","line":139,"column":3,"nodeType":"MemberExpression","endLine":139,"endColumn":18}],"suppressedMessages":[],"errorCount":8,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"'use client';\n\nimport React from 'react';\nimport { useQuery, useQueries, UseQueryOptions, useMutation, UseMutationOptions } from '@tanstack/react-query';\nimport { ApiError } from '@/lib/api/base/ApiError';\n\nexport interface PageDataConfig {\n queryKey: string[];\n queryFn: () => Promise;\n enabled?: boolean;\n staleTime?: number;\n onError?: (error: TError) => void;\n}\n\n/**\n * Single query hook - STANDARDIZED PATTERN\n * Use for: Simple CSR pages\n *\n * @example\n * const { data, isLoading, error, refetch } = usePageData({\n * queryKey: ['profile'],\n * queryFn: () => driverService.getProfile(),\n * });\n */\nexport function usePageData(\n config: PageDataConfig\n) {\n const queryOptions: any = {\n queryKey: config.queryKey,\n queryFn: config.queryFn,\n enabled: config.enabled ?? true,\n staleTime: config.staleTime ?? 1000 * 60 * 5,\n };\n \n if (config.onError) {\n queryOptions.onError = config.onError;\n }\n \n return useQuery(queryOptions);\n}\n\n/**\n * Multiple queries hook - STANDARDIZED PATTERN\n * Use for: Complex CSR pages with multiple data sources\n *\n * @example\n * const { data, isLoading, error, refetch } = usePageDataMultiple({\n * results: {\n * queryKey: ['raceResults', raceId],\n * queryFn: () => service.getResults(raceId),\n * },\n * sof: {\n * queryKey: ['raceSOF', raceId],\n * queryFn: () => service.getSOF(raceId),\n * },\n * });\n */\nexport function usePageDataMultiple>(\n queries: {\n [K in keyof T]: PageDataConfig;\n }\n) {\n const queryResults = useQueries({\n queries: Object.entries(queries).map(([key, config]) => {\n const queryOptions: any = {\n queryKey: config.queryKey,\n queryFn: config.queryFn,\n enabled: config.enabled ?? true,\n staleTime: config.staleTime ?? 1000 * 60 * 5,\n };\n if (config.onError) {\n queryOptions.onError = config.onError;\n }\n return queryOptions;\n }),\n });\n\n // Combine results\n const combined = {} as { [K in keyof T]: T[K] | null };\n const keys = Object.keys(queries) as (keyof T)[];\n \n keys.forEach((key, index) => {\n const result = queryResults[index]?.data;\n if (result !== undefined) {\n combined[key] = result as T[typeof key];\n } else {\n combined[key] = null as T[typeof key] | null;\n }\n });\n\n const isLoading = queryResults.some(q => q.isLoading);\n const error = queryResults.find(q => q.error)?.error ?? null;\n\n return {\n data: combined,\n isLoading,\n error,\n refetch: () => queryResults.forEach(q => q.refetch()),\n };\n}\n\n/**\n * Mutation hook wrapper - STANDARDIZED PATTERN\n * Use for: All mutation operations\n *\n * @example\n * const mutation = usePageMutation(\n * (variables) => service.mutateData(variables),\n * { onSuccess: () => refetch() }\n * );\n */\nexport function usePageMutation(\n mutationFn: (variables: TVariables) => Promise,\n options?: Omit, 'mutationFn'>\n) {\n return useMutation({\n mutationFn,\n ...options,\n });\n}\n\n/**\n * SSR Hydration Hook - NEW\n * Use for: Passing SSR data to CSR to avoid re-fetching\n *\n * @example\n * // In SSR page\n * const ssrData = await PageDataFetcher.fetch(...);\n *\n * // In client component\n * const { data } = useHydrateSSRData(ssrData, ['queryKey']);\n */\nexport function useHydrateSSRData(\n ssrData: TData | null,\n queryKey: string[]\n): { data: TData | null; isHydrated: boolean } {\n const [isHydrated, setIsHydrated] = React.useState(false);\n \n React.useEffect(() => {\n if (ssrData !== null) {\n setIsHydrated(true);\n }\n }, [ssrData]);\n\n return {\n data: ssrData,\n isHydrated,\n };\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/providers/QueryClientProvider.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/rate-limit.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/routing/RouteConfig.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_locale' is defined but never used.","line":360,"column":3,"nodeType":"Identifier","messageId":"unusedVar","endLine":360,"endColumn":19},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":366,"column":14,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":366,"endColumn":17,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[9939,9942],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[9939,9942],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * @file RouteConfig.ts\n * Centralized routing configuration for clean, maintainable paths\n *\n * Design Principles:\n * - Single source of truth for all routes\n * - i18n-ready: paths can be localized\n * - Type-safe: compile-time checking\n * - Easy to refactor: change in one place\n * - Environment-specific: can vary by mode\n */\n\nimport { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';\n\nconst logger = new ConsoleLogger();\n\nexport interface RouteDefinition {\n path: string;\n name: string;\n description?: string;\n}\n\nexport interface RouteGroup {\n auth: {\n login: string;\n signup: string;\n forgotPassword: string;\n resetPassword: string;\n };\n public: {\n home: string;\n leagues: string;\n drivers: string;\n teams: string;\n leaderboards: string;\n races: string;\n sponsorSignup: string;\n };\n protected: {\n dashboard: string;\n onboarding: string;\n profile: string;\n profileSettings: string;\n profileLeagues: string;\n profileLiveries: string;\n profileLiveryUpload: string;\n profileSponsorshipRequests: string;\n };\n sponsor: {\n root: string;\n dashboard: string;\n billing: string;\n campaigns: string;\n leagues: string;\n leagueDetail: (id: string) => string;\n settings: string;\n };\n admin: {\n root: string;\n users: string;\n };\n league: {\n detail: (id: string) => string;\n rosterAdmin: (id: string) => string;\n rulebook: (id: string) => string;\n schedule: (id: string) => string;\n scheduleAdmin: (id: string) => string;\n settings: (id: string) => string;\n sponsorships: (id: string) => string;\n standings: (id: string) => string;\n stewarding: (id: string) => string;\n wallet: (id: string) => string;\n create: string;\n };\n race: {\n root: string;\n all: string;\n detail: (id: string) => string;\n results: (id: string) => string;\n stewarding: (id: string) => string;\n };\n team: {\n root: string;\n leaderboard: string;\n detail: (id: string) => string;\n };\n driver: {\n root: string;\n detail: (id: string) => string;\n };\n leaderboards: {\n root: string;\n drivers: string;\n };\n error: {\n notFound: string;\n serverError: string;\n };\n}\n\n/**\n * Route configuration with i18n support\n * \n * Usage:\n * ```typescript\n * import { routes } from '@/lib/routing/RouteConfig';\n * \n * // Navigate to login\n * router.push(routes.auth.login);\n * \n * // Navigate to league detail\n * router.push(routes.league.detail('league-123'));\n * \n * // Check if current path is protected\n * if (currentPath.startsWith(routes.protected.dashboard)) {\n * // Handle protected route\n * }\n * ```\n */\nexport const routes: RouteGroup & { leaderboards: { root: string; drivers: string } } = {\n auth: {\n login: '/auth/login',\n signup: '/auth/signup',\n forgotPassword: '/auth/forgot-password',\n resetPassword: '/auth/reset-password',\n },\n public: {\n home: '/',\n leagues: '/leagues',\n drivers: '/drivers',\n teams: '/teams',\n leaderboards: '/leaderboards',\n races: '/races',\n sponsorSignup: '/sponsor/signup',\n },\n protected: {\n dashboard: '/dashboard',\n onboarding: '/onboarding',\n profile: '/profile',\n profileSettings: '/profile/settings',\n profileLeagues: '/profile/leagues',\n profileLiveries: '/profile/liveries',\n profileLiveryUpload: '/profile/liveries/upload',\n profileSponsorshipRequests: '/profile/sponsorship-requests',\n },\n sponsor: {\n root: '/sponsor',\n dashboard: '/sponsor/dashboard',\n billing: '/sponsor/billing',\n campaigns: '/sponsor/campaigns',\n leagues: '/sponsor/leagues',\n leagueDetail: (id: string) => `/sponsor/leagues/${id}`,\n settings: '/sponsor/settings',\n },\n admin: {\n root: '/admin',\n users: '/admin/users',\n },\n league: {\n detail: (id: string) => `/leagues/${id}`,\n rosterAdmin: (id: string) => `/leagues/${id}/roster/admin`,\n rulebook: (id: string) => `/leagues/${id}/rulebook`,\n schedule: (id: string) => `/leagues/${id}/schedule`,\n scheduleAdmin: (id: string) => `/leagues/${id}/schedule/admin`,\n settings: (id: string) => `/leagues/${id}/settings`,\n sponsorships: (id: string) => `/leagues/${id}/sponsorships`,\n standings: (id: string) => `/leagues/${id}/standings`,\n stewarding: (id: string) => `/leagues/${id}/stewarding`,\n wallet: (id: string) => `/leagues/${id}/wallet`,\n create: '/leagues/create',\n },\n race: {\n root: '/races',\n all: '/races/all',\n detail: (id: string) => `/races/${id}`,\n results: (id: string) => `/races/${id}/results`,\n stewarding: (id: string) => `/races/${id}/stewarding`,\n },\n team: {\n root: '/teams',\n leaderboard: '/teams/leaderboard',\n detail: (id: string) => `/teams/${id}`,\n },\n driver: {\n root: '/drivers',\n detail: (id: string) => `/drivers/${id}`,\n },\n leaderboards: {\n root: '/leaderboards',\n drivers: '/leaderboards/drivers',\n },\n error: {\n notFound: '/404',\n serverError: '/500',\n },\n};\n\n/**\n * Route matcher utilities for pattern matching\n */\nexport const routeMatchers = {\n /**\n * Check if path matches a pattern\n */\n matches(path: string, pattern: string): boolean {\n // Exact match\n if (pattern === path) return true;\n \n // Wildcard match (starts with)\n if (pattern.endsWith('/*') && path.startsWith(pattern.slice(0, -2))) {\n return true;\n }\n \n // Parameterized match (e.g., /leagues/[id])\n const paramPattern = pattern.replace(/\\[([^\\]]+)\\]/g, '([^/]+)');\n const regex = new RegExp(`^${paramPattern}$`);\n return regex.test(path);\n },\n\n /**\n * Check if path is in a route group\n */\n isInGroup(path: string, group: keyof RouteGroup): boolean {\n const groupRoutes = routes[group];\n \n // Handle nested objects (like sponsor.leagueDetail)\n const values = Object.values(groupRoutes);\n \n return values.some(value => {\n if (typeof value === 'function') {\n // For parameterized routes, check pattern\n const pattern = value('placeholder');\n return path.startsWith(pattern.replace('/placeholder', ''));\n }\n return path.startsWith(value as string);\n });\n },\n\n /**\n * Get all public route patterns\n */\n getPublicPatterns(): string[] {\n return [\n routes.public.home,\n routes.public.leagues,\n routes.public.drivers,\n routes.public.teams,\n routes.public.leaderboards,\n routes.public.races,\n routes.public.sponsorSignup,\n routes.auth.login,\n routes.auth.signup,\n routes.auth.forgotPassword,\n routes.auth.resetPassword,\n routes.error.notFound,\n routes.error.serverError,\n ];\n },\n\n /**\n * Check if path is public\n */\n isPublic(path: string): boolean {\n logger.info('[RouteConfig] isPublic check', { path });\n \n const publicPatterns = this.getPublicPatterns();\n\n // Check exact matches\n if (publicPatterns.includes(path)) {\n logger.info('[RouteConfig] Path is public (exact match)', { path });\n return true;\n }\n\n // Treat top-level detail pages as public (e2e relies on this)\n // Examples: /leagues/:id, /races/:id, /drivers/:id, /teams/:id\n const segments = path.split('/').filter(Boolean);\n if (segments.length === 2) {\n const [group, slug] = segments;\n if (group === 'leagues' && slug !== 'create') {\n logger.info('[RouteConfig] Path is public (league detail)', { path });\n return true;\n }\n if (group === 'races') {\n logger.info('[RouteConfig] Path is public (race detail)', { path });\n return true;\n }\n if (group === 'drivers') {\n logger.info('[RouteConfig] Path is public (driver detail)', { path });\n return true;\n }\n if (group === 'teams') {\n logger.info('[RouteConfig] Path is public (team detail)', { path });\n return true;\n }\n }\n\n // Check parameterized patterns\n const isPublicParam = publicPatterns.some(pattern => {\n if (pattern.includes('[')) {\n const paramPattern = pattern.replace(/\\[([^\\]]+)\\]/g, '([^/]+)');\n const regex = new RegExp(`^${paramPattern}$`);\n return regex.test(path);\n }\n return false;\n });\n \n if (isPublicParam) {\n logger.info('[RouteConfig] Path is public (parameterized match)', { path });\n } else {\n logger.info('[RouteConfig] Path is NOT public', { path });\n }\n \n return isPublicParam;\n },\n\n /**\n * Check if path requires authentication\n */\n requiresAuth(path: string): boolean {\n return !this.isPublic(path);\n },\n\n /**\n * Check if path requires specific role\n */\n requiresRole(path: string): string[] | null {\n logger.info('[RouteConfig] requiresRole check', { path });\n \n if (this.isInGroup(path, 'admin')) {\n // Website session roles come from the API and are more specific than just \"admin\".\n // Keep \"admin\"/\"owner\" for backwards compatibility.\n const roles = ['admin', 'owner', 'league-admin', 'league-steward', 'league-owner', 'system-owner', 'super-admin'];\n logger.info('[RouteConfig] Path requires admin roles', { path, roles });\n return roles;\n }\n if (this.isInGroup(path, 'sponsor')) {\n logger.info('[RouteConfig] Path requires sponsor role', { path });\n return ['sponsor'];\n }\n logger.info('[RouteConfig] Path requires no specific role', { path });\n return null;\n },\n};\n\n/**\n * i18n-ready path builder\n * \n * Usage:\n * ```typescript\n * // With current locale\n * const path = buildPath('leagueDetail', { id: '123' });\n * \n * // With specific locale\n * const path = buildPath('leagueDetail', { id: '123' }, 'de');\n * ```\n */\nexport function buildPath(\n routeName: string,\n params: Record = {},\n _locale?: string\n): string {\n // This is a placeholder for future i18n implementation\n // For now, it just builds the path using the route config\n \n const parts = routeName.split('.');\n let route: any = routes;\n \n for (const part of parts) {\n route = route[part];\n if (!route) {\n throw new Error(`Unknown route: ${routeName}`);\n }\n }\n \n if (typeof route === 'function') {\n const paramKeys = Object.keys(params);\n const paramKey = paramKeys[0];\n if (!paramKey) {\n throw new Error(`Route ${routeName} requires parameters`);\n }\n return route(params[paramKey]);\n }\n \n return route as string;\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/routing/search-params/SearchParamBuilder.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/routing/search-params/SearchParamParser.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/routing/search-params/SearchParamTypes.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/routing/search-params/SearchParamValidators.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'value' is defined but never used.","line":87,"column":27,"nodeType":"Identifier","messageId":"unusedVar","endLine":87,"endColumn":47}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * @file SearchParamValidators.ts\n * Pure validation logic for search parameters\n * No side effects, no dependencies\n */\n\nexport interface ValidationResult {\n isValid: boolean;\n errors: string[];\n}\n\nexport class SearchParamValidators {\n // Auth validators\n static validateReturnTo(value: string | null): ValidationResult {\n if (value === null) return { isValid: true, errors: [] };\n if (!value.startsWith('/')) {\n return { isValid: false, errors: ['returnTo must start with /'] };\n }\n if (value.includes('://') || value.includes('//')) {\n return { isValid: false, errors: ['returnTo must be a relative path'] };\n }\n return { isValid: true, errors: [] };\n }\n\n static validateToken(value: string | null): ValidationResult {\n if (value === null) return { isValid: true, errors: [] };\n if (value.length === 0) {\n return { isValid: false, errors: ['token cannot be empty'] };\n }\n return { isValid: true, errors: [] };\n }\n\n static validateEmail(value: string | null): ValidationResult {\n if (value === null) return { isValid: true, errors: [] };\n if (!value.includes('@')) {\n return { isValid: false, errors: ['email must be valid'] };\n }\n return { isValid: true, errors: [] };\n }\n\n // Sponsor validators\n static validateCampaignType(value: string | null): ValidationResult {\n if (value === null) return { isValid: true, errors: [] };\n const validTypes = ['leagues', 'teams', 'drivers', 'races', 'platform'];\n if (!validTypes.includes(value)) {\n return { isValid: false, errors: [`type must be one of: ${validTypes.join(', ')}`] };\n }\n return { isValid: true, errors: [] };\n }\n\n // Pagination validators\n static validatePage(value: string | null): ValidationResult {\n if (value === null) return { isValid: true, errors: [] };\n const num = parseInt(value);\n if (isNaN(num) || num < 1) {\n return { isValid: false, errors: ['page must be a positive integer'] };\n }\n return { isValid: true, errors: [] };\n }\n\n static validateLimit(value: string | null): ValidationResult {\n if (value === null) return { isValid: true, errors: [] };\n const num = parseInt(value);\n if (isNaN(num) || num < 1) {\n return { isValid: false, errors: ['limit must be a positive integer'] };\n }\n return { isValid: true, errors: [] };\n }\n\n // Sorting validators\n static validateOrder(value: string | null): ValidationResult {\n if (value === null) return { isValid: true, errors: [] };\n if (!['asc', 'desc'].includes(value)) {\n return { isValid: false, errors: ['order must be asc or desc'] };\n }\n return { isValid: true, errors: [] };\n }\n\n // Generic validators\n static validateRequired(value: string | null, fieldName: string): ValidationResult {\n if (value === null || value.length === 0) {\n return { isValid: false, errors: [`${fieldName} is required`] };\n }\n return { isValid: true, errors: [] };\n }\n\n static validateOptional(value: string | null): ValidationResult {\n return { isValid: true, errors: [] };\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/admin/AdminService.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/analytics/DashboardService.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/auth/AuthPageParams.ts","messages":[{"ruleId":"gridpilot-rules/service-function-format","severity":2,"message":"Service files should only export the Service class.","line":7,"column":1,"nodeType":"Program","messageId":"multipleExports","endLine":10,"endColumn":2}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Auth Page Parameters\n * \n * Input parameters for auth page processing.\n */\n\nexport interface AuthPageParams {\n returnTo?: string | null;\n token?: string | null;\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/auth/AuthPageService.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/auth/AuthService.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":38,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":38,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1627,1630],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1627,1630],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":47,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":47,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1940,1943],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1940,1943],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":56,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":56,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2208,2211],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2208,2211],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":65,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":65,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2570,2573],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2570,2573],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":74,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":74,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2926,2929],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2926,2929],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":83,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":83,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3233,3236],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3233,3236],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":6,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { AuthApiClient } from '@/lib/api/auth/AuthApiClient';\nimport { Result } from '@/lib/contracts/Result';\nimport { DomainError, Service } from '@/lib/contracts/services/Service';\nimport { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';\nimport { EnhancedErrorReporter } from '@/lib/infrastructure/EnhancedErrorReporter';\nimport { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl';\nimport type { AuthSessionDTO } from '@/lib/types/generated/AuthSessionDTO';\nimport type { LoginParamsDTO } from '@/lib/types/generated/LoginParamsDTO';\nimport type { SignupParamsDTO } from '@/lib/types/generated/SignupParamsDTO';\nimport type { ForgotPasswordDTO } from '@/lib/types/generated/ForgotPasswordDTO';\nimport type { ResetPasswordDTO } from '@/lib/types/generated/ResetPasswordDTO';\nimport { isProductionEnvironment } from '@/lib/config/env';\n\n/**\n * Auth Service\n *\n * Orchestrates authentication operations.\n * Returns raw API DTOs. No ViewModels or UX logic.\n */\nexport class AuthService implements Service {\n private apiClient: AuthApiClient;\n\n constructor() {\n const baseUrl = getWebsiteApiBaseUrl();\n const logger = new ConsoleLogger();\n const errorReporter = new EnhancedErrorReporter(logger, {\n showUserNotifications: false,\n logToConsole: true,\n reportToExternal: isProductionEnvironment(),\n });\n this.apiClient = new AuthApiClient(baseUrl, errorReporter, logger);\n }\n\n async login(params: LoginParamsDTO): Promise> {\n try {\n const dto = await this.apiClient.login(params);\n return Result.ok(dto);\n } catch (error: any) {\n return Result.err({ type: 'unauthorized', message: error.message || 'Login failed' });\n }\n }\n\n async signup(params: SignupParamsDTO): Promise> {\n try {\n const dto = await this.apiClient.signup(params);\n return Result.ok(dto);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Signup failed' });\n }\n }\n\n async logout(): Promise> {\n try {\n await this.apiClient.logout();\n return Result.ok(undefined);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Logout failed' });\n }\n }\n\n async forgotPassword(params: ForgotPasswordDTO): Promise> {\n try {\n const result = await this.apiClient.forgotPassword(params);\n return Result.ok(result);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Forgot password request failed' });\n }\n }\n\n async resetPassword(params: ResetPasswordDTO): Promise> {\n try {\n const result = await this.apiClient.resetPassword(params);\n return Result.ok(result);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Reset password failed' });\n }\n }\n\n async getSession(): Promise> {\n try {\n const dto = await this.apiClient.getSession();\n return Result.ok(dto);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to fetch session' });\n }\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/auth/SessionService.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/auth/types/ForgotPasswordPageDTO.ts","messages":[{"ruleId":"gridpilot-rules/service-function-format","severity":2,"message":"Service files should only export the Service class.","line":8,"column":1,"nodeType":"Program","messageId":"multipleExports","endLine":10,"endColumn":2}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Forgot Password Page DTO\n * \n * Data transfer object for forgot password page composition.\n * Used by AuthPageService and ForgotPasswordViewDataBuilder.\n */\n\nexport interface ForgotPasswordPageDTO {\n returnTo: string;\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/auth/types/LoginPageDTO.ts","messages":[{"ruleId":"gridpilot-rules/service-function-format","severity":2,"message":"Service files should only export the Service class.","line":8,"column":1,"nodeType":"Program","messageId":"multipleExports","endLine":11,"endColumn":2}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Login Page DTO\n * \n * Data transfer object for login page composition.\n * Used by AuthPageService and LoginViewDataBuilder.\n */\n\nexport interface LoginPageDTO {\n returnTo: string;\n hasInsufficientPermissions: boolean;\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/auth/types/ResetPasswordPageDTO.ts","messages":[{"ruleId":"gridpilot-rules/service-function-format","severity":2,"message":"Service files should only export the Service class.","line":8,"column":1,"nodeType":"Program","messageId":"multipleExports","endLine":11,"endColumn":2}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Reset Password Page DTO\n * \n * Data transfer object for reset password page composition.\n * Used by AuthPageService and ResetPasswordViewDataBuilder.\n */\n\nexport interface ResetPasswordPageDTO {\n token: string;\n returnTo: string;\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/auth/types/SignupPageDTO.ts","messages":[{"ruleId":"gridpilot-rules/service-function-format","severity":2,"message":"Service files should only export the Service class.","line":8,"column":1,"nodeType":"Program","messageId":"multipleExports","endLine":10,"endColumn":2}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Signup Page DTO\n * \n * Data transfer object for signup page composition.\n * Used by AuthPageService and SignupViewDataBuilder.\n */\n\nexport interface SignupPageDTO {\n returnTo: string;\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/drivers/DriverProfilePageService.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/drivers/DriverProfileReadService.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/drivers/DriverProfileService.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/drivers/DriverProfileUpdateService.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/drivers/DriverService.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":32,"column":48,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":32,"endColumn":51,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1476,1479],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1476,1479],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":36,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":36,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1615,1618],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1615,1618],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":48,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":48,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2052,2055],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2052,2055],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":60,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":60,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2420,2423],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2420,2423],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":72,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":72,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2826,2829],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2826,2829],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":84,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":84,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3247,3250],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3247,3250],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":96,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":96,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3621,3624],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3621,3624],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":108,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":108,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[4088,4091],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[4088,4091],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":8,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { DriversApiClient } from '@/lib/api/drivers/DriversApiClient';\nimport type { CompleteOnboardingInputDTO } from '@/lib/types/generated/CompleteOnboardingInputDTO';\nimport type { GetDriverOutputDTO } from '@/lib/types/generated/GetDriverOutputDTO';\nimport type { CompleteOnboardingOutputDTO } from '@/lib/types/generated/CompleteOnboardingOutputDTO';\nimport type { DriverDTO } from '@/lib/types/generated/DriverDTO';\nimport type { GetDriverProfileOutputDTO } from '@/lib/types/generated/GetDriverProfileOutputDTO';\nimport { Result } from '@/lib/contracts/Result';\nimport { DomainError, Service } from '@/lib/contracts/services/Service';\nimport { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl';\nimport { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';\nimport { EnhancedErrorReporter } from '@/lib/infrastructure/EnhancedErrorReporter';\n\n/**\n * Driver Service - DTO Only\n *\n * Returns raw API DTOs. No ViewModels or UX logic.\n * All client-side presentation logic must be handled by hooks/components.\n */\nexport class DriverService implements Service {\n private readonly apiClient: DriversApiClient;\n\n constructor() {\n const baseUrl = getWebsiteApiBaseUrl();\n const logger = new ConsoleLogger();\n const errorReporter = new EnhancedErrorReporter(logger);\n this.apiClient = new DriversApiClient(baseUrl, errorReporter, logger);\n }\n\n /**\n * Get driver leaderboard (returns DTO)\n */\n async getDriverLeaderboard(): Promise> {\n try {\n const data = await this.apiClient.getLeaderboard();\n return Result.ok(data);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to get leaderboard' });\n }\n }\n\n /**\n * Complete driver onboarding (returns DTO)\n */\n async completeDriverOnboarding(input: CompleteOnboardingInputDTO): Promise> {\n try {\n const data = await this.apiClient.completeOnboarding(input);\n return Result.ok(data);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to complete onboarding' });\n }\n }\n\n /**\n * Get current driver (returns DTO)\n */\n async getCurrentDriver(): Promise> {\n try {\n const data = await this.apiClient.getCurrent();\n return Result.ok(data);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to get current driver' });\n }\n }\n\n /**\n * Get driver profile (returns DTO)\n */\n async getDriverProfile(driverId: string): Promise> {\n try {\n const data = await this.apiClient.getDriverProfile(driverId);\n return Result.ok(data);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to get driver profile' });\n }\n }\n\n /**\n * Update current driver profile (returns DTO)\n */\n async updateProfile(updates: { bio?: string; country?: string }): Promise> {\n try {\n const data = await this.apiClient.updateProfile(updates);\n return Result.ok(data);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to update profile' });\n }\n }\n\n /**\n * Find driver by ID (returns DTO)\n */\n async findById(id: string): Promise> {\n try {\n const data = await this.apiClient.getDriver(id);\n return Result.ok(data);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to find driver' });\n }\n }\n\n /**\n * Find multiple drivers by IDs (returns DTOs)\n */\n async findByIds(ids: string[]): Promise> {\n try {\n const drivers = await Promise.all(ids.map(id => this.apiClient.getDriver(id)));\n return Result.ok(drivers.filter((d): d is GetDriverOutputDTO => d !== null));\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to find drivers' });\n }\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/drivers/DriversPageService.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/drivers/LiveryService.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_driverId' is defined but never used.","line":11,"column":21,"nodeType":"Identifier","messageId":"unusedVar","endLine":11,"endColumn":38},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_driverId' is defined but never used.","line":34,"column":22,"nodeType":"Identifier","messageId":"unusedVar","endLine":34,"endColumn":39},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_file' is defined but never used.","line":34,"column":41,"nodeType":"Identifier","messageId":"unusedVar","endLine":34,"endColumn":52}],"suppressedMessages":[],"errorCount":3,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Result } from '@/lib/contracts/Result';\nimport type { DomainError, Service } from '@/lib/contracts/services/Service';\nimport type { GetLiveriesOutputDTO } from '@/lib/types/tbd/GetLiveriesOutputDTO';\n\n/**\n * Livery Service\n *\n * Provides livery management functionality.\n */\nexport class LiveryService implements Service {\n async getLiveries(_driverId: string): Promise> {\n // Mock data for now\n const mockLiveries: GetLiveriesOutputDTO = {\n liveries: [\n {\n id: 'livery-1',\n name: 'Default Livery',\n imageUrl: '/mock-livery-1.png',\n createdAt: new Date().toISOString(),\n isActive: true,\n },\n {\n id: 'livery-2',\n name: 'Custom Livery',\n imageUrl: '/mock-livery-2.png',\n createdAt: new Date(Date.now() - 86400000).toISOString(),\n isActive: false,\n },\n ],\n };\n return Result.ok(mockLiveries);\n }\n\n async uploadLivery(_driverId: string, _file: File): Promise> {\n // Mock implementation\n return Result.ok({ liveryId: 'new-livery-id' });\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/drivers/SettingsService.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/error/ErrorAnalyticsService.ts","messages":[{"ruleId":"gridpilot-rules/service-function-format","severity":2,"message":"Service files should only export the Service class.","line":1,"column":1,"nodeType":"Program","messageId":"multipleExports","endLine":100,"endColumn":1},{"ruleId":"gridpilot-rules/services-must-be-pure","severity":2,"message":"Services must be pure functions, no side effects allowed - see apps/website/lib/contracts/services/Service.ts","line":54,"column":26,"nodeType":"CallExpression","messageId":"message","endLine":56,"endColumn":52},{"ruleId":"gridpilot-rules/services-must-be-pure","severity":2,"message":"Services must be pure functions, no side effects allowed - see apps/website/lib/contracts/services/Service.ts","line":58,"column":26,"nodeType":"CallExpression","messageId":"message","endLine":58,"endColumn":59},{"ruleId":"gridpilot-rules/no-direct-process-env","severity":2,"message":"Do not read process.env directly here. Use `getWebsiteServerEnv()` / `getWebsitePublicEnv()` (apps/website/lib/config/env.ts) or a dedicated config helper (e.g. getWebsiteApiBaseUrl()).","line":86,"column":18,"nodeType":"MemberExpression","messageId":"noProcessEnv","endLine":86,"endColumn":53},{"ruleId":"gridpilot-rules/no-direct-process-env","severity":2,"message":"Do not read process.env directly here. Use `getWebsiteServerEnv()` / `getWebsitePublicEnv()` (apps/website/lib/config/env.ts) or a dedicated config helper (e.g. getWebsiteApiBaseUrl()).","line":87,"column":20,"nodeType":"MemberExpression","messageId":"noProcessEnv","endLine":87,"endColumn":54},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":95,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":95,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3089,3092],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3089,3092],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":6,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { getGlobalErrorHandler } from '@/lib/infrastructure/GlobalErrorHandler';\nimport { getGlobalApiLogger } from '@/lib/infrastructure/ApiRequestLogger';\nimport { ApiError } from '@/lib/api/base/ApiError';\nimport { Result } from '@/lib/contracts/Result';\nimport { DomainError, Service } from '@/lib/contracts/services/Service';\nimport { getWebsiteServerEnv } from '@/lib/config/env';\n\nexport interface ErrorStats {\n totalErrors: number;\n errorsByType: Record;\n errorsByTime: Array<{ time: string; count: number }>;\n recentErrors: Array<{\n timestamp: string;\n message: string;\n type: string;\n context?: unknown;\n }>;\n apiStats: {\n totalRequests: number;\n successful: number;\n failed: number;\n averageDuration: number;\n slowestRequests: Array<{ url: string; duration: number }>;\n };\n environment: {\n mode: string;\n version?: string;\n buildTime?: string;\n };\n}\n\nexport class ErrorAnalyticsService implements Service {\n static getErrorAnalyticsStats(): ErrorStats {\n const globalHandler = getGlobalErrorHandler();\n const apiLogger = getGlobalApiLogger();\n\n const errorHistory = globalHandler.getErrorHistory();\n const errorStats = globalHandler.getStats();\n const apiStats = apiLogger.getStats();\n\n // Group errors by time (last 10 minutes)\n const timeGroups = new Map();\n const now = Date.now();\n const tenMinutesAgo = now - (10 * 60 * 1000);\n\n errorHistory.forEach(entry => {\n const entryTime = new Date(entry.timestamp).getTime();\n if (entryTime >= tenMinutesAgo) {\n const timeKey = new Date(entry.timestamp).toLocaleTimeString();\n timeGroups.set(timeKey, (timeGroups.get(timeKey) || 0) + 1);\n }\n });\n\n const errorsByTime = Array.from(timeGroups.entries())\n .map(([time, count]) => ({ time, count }))\n .sort((a, b) => a.time.localeCompare(b.time));\n\n const recentErrors = errorHistory.slice(-10).reverse().map(entry => ({\n timestamp: entry.timestamp,\n message: entry.error.message,\n type: entry.error instanceof ApiError ? entry.error.type : entry.error.name || 'Error',\n context: entry.context,\n }));\n\n const slowestRequests = apiLogger.getSlowestRequests(5).map(log => ({\n url: log.url,\n duration: log.response?.duration || 0,\n }));\n\n const env = getWebsiteServerEnv();\n\n return {\n totalErrors: errorStats.total,\n errorsByType: errorStats.byType,\n errorsByTime,\n recentErrors,\n apiStats: {\n totalRequests: apiStats.total,\n successful: apiStats.successful,\n failed: apiStats.failed,\n averageDuration: apiStats.averageDuration,\n slowestRequests,\n },\n environment: {\n mode: env.NODE_ENV || 'unknown',\n version: process.env.NEXT_PUBLIC_APP_VERSION,\n buildTime: process.env.NEXT_PUBLIC_BUILD_TIME,\n },\n };\n }\n\n async getErrorAnalyticsStats(): Promise> {\n try {\n return Result.ok(ErrorAnalyticsService.getErrorAnalyticsStats());\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to get error analytics stats' });\n }\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/home/getHomeData.ts","messages":[{"ruleId":"gridpilot-rules/service-function-format","severity":2,"message":"Services must be classes named *Service, not functions. Found function \"getHomeData\" in lib/services/","line":1,"column":1,"nodeType":"Program","messageId":"notAClass","endLine":74,"endColumn":1},{"ruleId":"gridpilot-rules/service-function-format","severity":2,"message":"Services cannot use redirect(). Use PageQueries or Client Components for navigation.","line":1,"column":1,"nodeType":"Program","messageId":"noRedirect","endLine":74,"endColumn":1},{"ruleId":"gridpilot-rules/lib-no-next-imports","severity":2,"message":"redirect() must be used in app/ directory, not lib/ directory","line":1,"column":10,"nodeType":"ImportSpecifier","messageId":"noNextRedirect","endLine":1,"endColumn":18}],"suppressedMessages":[],"errorCount":3,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { redirect } from 'next/navigation';\nimport { routes } from '@/lib/routing/RouteConfig';\nimport { FeatureFlagService } from '@/lib/feature/FeatureFlagService';\n\n// API Clients\nimport { RacesApiClient } from '@/lib/api/races/RacesApiClient';\nimport { LeaguesApiClient } from '@/lib/api/leagues/LeaguesApiClient';\nimport { TeamsApiClient } from '@/lib/api/teams/TeamsApiClient';\n\n// Services\nimport { SessionService } from '@/lib/services/auth/SessionService';\n\n// Infrastructure\nimport { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';\nimport { ConsoleErrorReporter } from '@/lib/infrastructure/logging/ConsoleErrorReporter';\nimport { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl';\n\n// DTO types\nimport type { HomeViewData } from '@/templates/HomeTemplate';\n\nexport async function getHomeData(): Promise {\n // Manual wiring: construct dependencies explicitly\n const baseUrl = getWebsiteApiBaseUrl();\n const errorReporter = new ConsoleErrorReporter();\n const logger = new ConsoleLogger();\n\n // Construct API clients\n const racesApiClient = new RacesApiClient(baseUrl, errorReporter, logger);\n const leaguesApiClient = new LeaguesApiClient(baseUrl, errorReporter, logger);\n const teamsApiClient = new TeamsApiClient(baseUrl, errorReporter, logger);\n\n // Construct services\n const sessionService = new SessionService();\n\n // Check session and redirect if logged in\n const sessionResult = await sessionService.getSession();\n if (sessionResult.isOk() && sessionResult.unwrap()) {\n redirect(routes.protected.dashboard);\n }\n\n // Get feature flags\n const featureService = await FeatureFlagService.fromAPI();\n const isAlpha = featureService.isEnabled('alpha_features');\n\n // Get home discovery data (manual implementation)\n const [racesDto, leaguesDto, teamsDto] = await Promise.all([\n racesApiClient.getPageData(),\n leaguesApiClient.getAllWithCapacity(),\n teamsApiClient.getAll(),\n ]);\n\n // Return DTOs directly (no ViewModels)\n return {\n isAlpha,\n upcomingRaces: racesDto.races.slice(0, 4).map(r => ({\n id: r.id,\n track: r.track,\n car: r.car,\n formattedDate: new Date(r.scheduledAt).toLocaleDateString(),\n })),\n topLeagues: leaguesDto.leagues.slice(0, 4).map(l => ({\n id: l.id,\n name: l.name,\n description: l.description,\n })),\n teams: teamsDto.teams.slice(0, 4).map(t => ({\n id: t.id,\n name: t.name,\n description: t.description,\n logoUrl: t.logoUrl,\n })),\n };\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/landing/LandingService.ts","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'email' is assigned a value but never used.","line":45,"column":11,"nodeType":"Identifier","messageId":"unusedVar","endLine":45,"endColumn":16,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/leaderboards/DriverRankingsService.ts","messages":[{"ruleId":"gridpilot-rules/service-function-format","severity":2,"message":"Service files should only export the Service class.","line":1,"column":1,"nodeType":"Program","messageId":"multipleExports","endLine":59,"endColumn":2}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { DriversApiClient } from '@/lib/api/drivers/DriversApiClient';\nimport { Result } from '@/lib/contracts/Result';\nimport { Service, DomainError } from '@/lib/contracts/services/Service';\nimport { ConsoleErrorReporter } from '@/lib/infrastructure/logging/ConsoleErrorReporter';\nimport { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';\nimport type { DriverLeaderboardItemDTO } from '@/lib/types/generated/DriverLeaderboardItemDTO';\nimport { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl';\nimport { ApiError } from '@/lib/api/base/ApiError';\n\nexport interface DriverRankingsData {\n drivers: DriverLeaderboardItemDTO[];\n}\n\nexport class DriverRankingsService implements Service {\n async getDriverRankings(): Promise> {\n try {\n const baseUrl = getWebsiteApiBaseUrl();\n const errorReporter = new ConsoleErrorReporter();\n const logger = new ConsoleLogger();\n \n const apiClient = new DriversApiClient(baseUrl, errorReporter, logger);\n const result = await apiClient.getLeaderboard();\n \n if (!result || !result.drivers) {\n return Result.err({ type: 'notFound', message: 'No driver rankings available' });\n }\n\n const data: DriverRankingsData = {\n drivers: result.drivers,\n };\n \n return Result.ok(data);\n } catch (error) {\n // Convert ApiError to DomainError\n if (error instanceof ApiError) {\n switch (error.type) {\n case 'NOT_FOUND':\n return Result.err({ type: 'notFound', message: error.message });\n case 'AUTH_ERROR':\n return Result.err({ type: 'unauthorized', message: error.message });\n case 'SERVER_ERROR':\n return Result.err({ type: 'serverError', message: error.message });\n case 'NETWORK_ERROR':\n case 'TIMEOUT_ERROR':\n return Result.err({ type: 'networkError', message: error.message });\n default:\n return Result.err({ type: 'unknown', message: error.message });\n }\n }\n \n // Handle non-ApiError cases\n if (error instanceof Error) {\n return Result.err({ type: 'unknown', message: error.message });\n }\n \n return Result.err({ type: 'unknown', message: 'Driver rankings fetch failed' });\n }\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/leaderboards/LeaderboardsService.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/league/LeagueActivityService.ts","messages":[{"ruleId":"gridpilot-rules/services-implement-contract","severity":2,"message":"Service methods must return Promise>","line":5,"column":8,"nodeType":"ClassDeclaration","messageId":"mustReturnResult","endLine":45,"endColumn":2},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":6,"column":37,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":6,"endColumn":40,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[294,297],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[294,297],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"gridpilot-rules/services-must-be-pure","severity":2,"message":"Services must be pure functions, no side effects allowed - see apps/website/lib/contracts/services/Service.ts","line":9,"column":28,"nodeType":"CallExpression","messageId":"message","endLine":11,"endColumn":93},{"ruleId":"gridpilot-rules/services-must-be-pure","severity":2,"message":"Services must be pure functions, no side effects allowed - see apps/website/lib/contracts/services/Service.ts","line":14,"column":27,"nodeType":"CallExpression","messageId":"message","endLine":16,"endColumn":93},{"ruleId":"gridpilot-rules/services-must-be-pure","severity":2,"message":"Services must be pure functions, no side effects allowed - see apps/website/lib/contracts/services/Service.ts","line":20,"column":7,"nodeType":"CallExpression","messageId":"message","endLine":25,"endColumn":9},{"ruleId":"gridpilot-rules/services-must-be-pure","severity":2,"message":"Services must be pure functions, no side effects allowed - see apps/website/lib/contracts/services/Service.ts","line":29,"column":7,"nodeType":"CallExpression","messageId":"message","endLine":34,"endColumn":9},{"ruleId":"gridpilot-rules/services-must-be-pure","severity":2,"message":"Services must be pure functions, no side effects allowed - see apps/website/lib/contracts/services/Service.ts","line":38,"column":5,"nodeType":"CallExpression","messageId":"message","endLine":38,"endColumn":77},{"ruleId":"gridpilot-rules/services-must-be-pure","severity":2,"message":"Services must be pure functions, no side effects allowed - see apps/website/lib/contracts/services/Service.ts","line":40,"column":7,"nodeType":"CallExpression","messageId":"message","endLine":40,"endColumn":31}],"suppressedMessages":[],"errorCount":8,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import type { LeagueActivity } from '@/components/leagues/LeagueActivityFeed';\nimport { Result } from '@/lib/contracts/Result';\nimport { DomainError, Service } from '@/lib/contracts/services/Service';\n\nexport class LeagueActivityService implements Service {\n processLeagueActivities(raceList: any[], limit: number): Result {\n const activities: LeagueActivity[] = [];\n \n const completedRaces = raceList\n .filter((r) => r.status === 'completed')\n .sort((a, b) => new Date(b.scheduledAt).getTime() - new Date(a.scheduledAt).getTime())\n .slice(0, 5);\n\n const upcomingRaces = raceList\n .filter((r) => r.status === 'scheduled')\n .sort((a, b) => new Date(b.scheduledAt).getTime() - new Date(a.scheduledAt).getTime())\n .slice(0, 3);\n\n for (const race of completedRaces) {\n activities.push({\n type: 'race_completed',\n raceId: race.id,\n raceName: `${race.track} - ${race.car}`,\n timestamp: new Date(race.scheduledAt),\n });\n }\n\n for (const race of upcomingRaces) {\n activities.push({\n type: 'race_scheduled',\n raceId: race.id,\n raceName: `${race.track} - ${race.car}`,\n timestamp: new Date(new Date(race.scheduledAt).getTime() - 7 * 24 * 60 * 60 * 1000), // Simulate schedule announcement\n });\n }\n\n // Sort all activities by timestamp\n activities.sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime());\n if (activities.length > limit) {\n activities.splice(limit);\n }\n\n return Result.ok(activities);\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/leagues/LeagueMembershipService.ts","messages":[{"ruleId":"gridpilot-rules/service-function-format","severity":2,"message":"Service files should only export the Service class.","line":1,"column":1,"nodeType":"Program","messageId":"multipleExports","endLine":123,"endColumn":1},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":19,"column":54,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":19,"endColumn":57,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[969,972],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[969,972],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":32,"column":61,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":32,"endColumn":64,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1405,1408],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1405,1408],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":38,"column":46,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":38,"endColumn":49,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1620,1623],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1620,1623],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":42,"column":56,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":42,"endColumn":59,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1743,1746],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1743,1746],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":43,"column":27,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":43,"endColumn":30,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1777,1780],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1777,1780],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"gridpilot-rules/services-must-be-pure","severity":2,"message":"Services must be pure functions, no side effects allowed - see apps/website/lib/contracts/services/Service.ts","line":47,"column":9,"nodeType":"CallExpression","messageId":"message","endLine":47,"endColumn":57},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":56,"column":75,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":56,"endColumn":78,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2279,2282],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2279,2282],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":62,"column":54,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":62,"endColumn":57,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2445,2448],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2445,2448],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":66,"column":39,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":66,"endColumn":42,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2571,2574],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2571,2574],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_leagueId' is defined but never used.","line":70,"column":20,"nodeType":"Identifier","messageId":"unusedVar","endLine":70,"endColumn":37},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_driverId' is defined but never used.","line":70,"column":39,"nodeType":"Identifier","messageId":"unusedVar","endLine":70,"endColumn":56},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_leagueId' is defined but never used.","line":74,"column":21,"nodeType":"Identifier","messageId":"unusedVar","endLine":74,"endColumn":38},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_driverId' is defined but never used.","line":74,"column":40,"nodeType":"Identifier","messageId":"unusedVar","endLine":74,"endColumn":57},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":90,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":90,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3405,3408],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3405,3408],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":100,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":100,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3894,3897],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3894,3897],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":109,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":109,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[4307,4310],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[4307,4310],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":118,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":118,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[4725,4728],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[4725,4728],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":18,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { LeaguesApiClient } from '@/lib/api/leagues/LeaguesApiClient';\nimport { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl';\nimport { Result } from '@/lib/contracts/Result';\nimport { Service, type DomainError } from '@/lib/contracts/services/Service';\nimport { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';\nimport { EnhancedErrorReporter } from '@/lib/infrastructure/EnhancedErrorReporter';\nimport { isProductionEnvironment } from '@/lib/config/env';\nimport type { LeagueRosterMemberDTO } from '@/lib/types/generated/LeagueRosterMemberDTO';\nimport type { LeagueRosterJoinRequestDTO } from '@/lib/types/generated/LeagueRosterJoinRequestDTO';\n\nexport interface LeagueRosterAdminData {\n leagueId: string;\n members: LeagueRosterMemberDTO[];\n joinRequests: LeagueRosterJoinRequestDTO[];\n}\n\nexport class LeagueMembershipService implements Service {\n private apiClient: LeaguesApiClient;\n private static cachedMemberships = new Map();\n\n constructor() {\n const baseUrl = getWebsiteApiBaseUrl();\n const logger = new ConsoleLogger();\n const errorReporter = new EnhancedErrorReporter(logger, {\n showUserNotifications: false,\n logToConsole: true,\n reportToExternal: isProductionEnvironment(),\n });\n this.apiClient = new LeaguesApiClient(baseUrl, errorReporter, logger);\n }\n\n static getMembership(leagueId: string, driverId: string): any | null {\n const members = this.cachedMemberships.get(leagueId);\n if (!members) return null;\n return members.find(m => m.driverId === driverId) || null;\n }\n\n static getLeagueMembers(leagueId: string): any[] {\n return this.cachedMemberships.get(leagueId) || [];\n }\n\n static getAllMembershipsForDriver(driverId: string): any[] {\n const allMemberships: any[] = [];\n for (const [leagueId, members] of this.cachedMemberships.entries()) {\n const membership = members.find(m => m.driverId === driverId);\n if (membership) {\n allMemberships.push({ ...membership, leagueId });\n }\n }\n return allMemberships;\n }\n\n async fetchLeagueMemberships(leagueId: string): Promise {\n try {\n const members = await this.apiClient.getMemberships(leagueId);\n LeagueMembershipService.cachedMemberships.set(leagueId, (members as any).members || []);\n } catch (error) {\n console.error('Failed to fetch memberships', error);\n }\n }\n\n getMembership(leagueId: string, driverId: string): any | null {\n return LeagueMembershipService.getMembership(leagueId, driverId);\n }\n\n getLeagueMembers(leagueId: string): any[] {\n return LeagueMembershipService.getLeagueMembers(leagueId);\n }\n\n async joinLeague(_leagueId: string, _driverId: string): Promise> {\n return Result.err({ type: 'notImplemented', message: 'joinLeague' });\n }\n\n async leaveLeague(_leagueId: string, _driverId: string): Promise> {\n return Result.err({ type: 'notImplemented', message: 'leaveLeague' });\n }\n\n async getRosterAdminData(leagueId: string): Promise> {\n try {\n const [members, joinRequests] = await Promise.all([\n this.apiClient.getAdminRosterMembers(leagueId),\n this.apiClient.getAdminRosterJoinRequests(leagueId),\n ]);\n\n return Result.ok({\n leagueId,\n members,\n joinRequests,\n });\n } catch (error: any) {\n console.error('LeagueMembershipService.getRosterAdminData failed:', error);\n return Result.err({ type: 'serverError', message: error.message || 'Failed to fetch roster data' });\n }\n }\n\n async removeMember(leagueId: string, targetDriverId: string): Promise> {\n try {\n const dto = await this.apiClient.removeRosterMember(leagueId, targetDriverId);\n return Result.ok({ success: dto.success });\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to remove member' });\n }\n }\n\n async approveJoinRequest(leagueId: string, joinRequestId: string): Promise> {\n try {\n const dto = await this.apiClient.approveRosterJoinRequest(leagueId, joinRequestId);\n return Result.ok({ success: dto.success });\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to approve join request' });\n }\n }\n\n async rejectJoinRequest(leagueId: string, joinRequestId: string): Promise> {\n try {\n const dto = await this.apiClient.rejectRosterJoinRequest(leagueId, joinRequestId);\n return Result.ok({ success: dto.success });\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to reject join request' });\n }\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/leagues/LeagueRulebookService.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/leagues/LeagueScheduleService.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/leagues/LeagueService.ts","messages":[{"ruleId":"gridpilot-rules/service-function-format","severity":2,"message":"Service files should only export the Service class.","line":1,"column":1,"nodeType":"Program","messageId":"multipleExports","endLine":376,"endColumn":1},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":75,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":75,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3738,3741],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3738,3741],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":98,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":98,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[4514,4517],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[4514,4517],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":121,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":121,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[5419,5422],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[5419,5422],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":139,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":139,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[6034,6037],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[6034,6037],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":153,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":153,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[6595,6598],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[6595,6598],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":162,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":162,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[6939,6942],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[6939,6942],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":171,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":171,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[7291,7294],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[7291,7294],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":184,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":184,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[7822,7825],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[7822,7825],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":193,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":193,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[8228,8231],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[8228,8231],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":202,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":202,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[8634,8637],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[8634,8637],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":216,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":216,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[9213,9216],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[9213,9216],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":231,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":231,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[9825,9828],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[9825,9828],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":240,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":240,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[10252,10255],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[10252,10255],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":265,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":265,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[11313,11316],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[11313,11316],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":279,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":279,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[11816,11819],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[11816,11819],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":296,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":296,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[12414,12417],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[12414,12417],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":305,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":305,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[12759,12762],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[12759,12762],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":314,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":314,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[13162,13165],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[13162,13165],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":323,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":323,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[13607,13610],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[13607,13610],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":332,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":332,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[13971,13974],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[13971,13974],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":341,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":341,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[14352,14355],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[14352,14355],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":350,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":350,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[14771,14774],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[14771,14774],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":359,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":359,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[15189,15192],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[15189,15192],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":24,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { LeaguesApiClient } from \"@/lib/api/leagues/LeaguesApiClient\";\nimport { DriversApiClient } from \"@/lib/api/drivers/DriversApiClient\";\nimport { SponsorsApiClient } from \"@/lib/api/sponsors/SponsorsApiClient\";\nimport { RacesApiClient } from \"@/lib/api/races/RacesApiClient\";\nimport { CreateLeagueInputDTO } from \"@/lib/types/generated/CreateLeagueInputDTO\";\nimport { CreateLeagueOutputDTO } from \"@/lib/types/generated/CreateLeagueOutputDTO\";\nimport type { MembershipRole } from \"@/lib/types/MembershipRole\";\nimport type { LeagueRosterJoinRequestDTO } from \"@/lib/types/generated/LeagueRosterJoinRequestDTO\";\nimport type { TotalLeaguesDTO } from '@/lib/types/generated/TotalLeaguesDTO';\nimport type { LeagueSeasonSummaryDTO } from '@/lib/types/generated/LeagueSeasonSummaryDTO';\nimport type { LeagueScheduleDTO } from '@/lib/types/generated/LeagueScheduleDTO';\nimport type { CreateLeagueScheduleRaceInputDTO } from '@/lib/types/generated/CreateLeagueScheduleRaceInputDTO';\nimport type { CreateLeagueScheduleRaceOutputDTO } from '@/lib/types/generated/CreateLeagueScheduleRaceOutputDTO';\nimport type { UpdateLeagueScheduleRaceInputDTO } from '@/lib/types/generated/UpdateLeagueScheduleRaceInputDTO';\nimport type { LeagueScheduleRaceMutationSuccessDTO } from '@/lib/types/generated/LeagueScheduleRaceMutationSuccessDTO';\nimport type { LeagueSeasonSchedulePublishOutputDTO } from '@/lib/types/generated/LeagueSeasonSchedulePublishOutputDTO';\nimport type { LeagueRosterMemberDTO } from '@/lib/types/generated/LeagueRosterMemberDTO';\nimport type { LeagueMembershipsDTO } from '@/lib/types/generated/LeagueMembershipsDTO';\nimport { Result } from '@/lib/contracts/Result';\nimport { DomainError, Service } from '@/lib/contracts/services/Service';\nimport { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';\nimport { EnhancedErrorReporter } from '@/lib/infrastructure/EnhancedErrorReporter';\nimport { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl';\nimport { isProductionEnvironment } from '@/lib/config/env';\nimport { AllLeaguesWithCapacityAndScoringDTO } from '@/lib/types/AllLeaguesWithCapacityAndScoringDTO';\nimport type { LeagueWithCapacityAndScoringDTO } from '@/lib/types/generated/LeagueWithCapacityAndScoringDTO';\n\nexport interface LeagueScheduleAdminData {\n leagueId: string;\n seasonId: string;\n seasons: LeagueSeasonSummaryDTO[];\n schedule: LeagueScheduleDTO;\n}\n\nexport interface LeagueRosterAdminData {\n leagueId: string;\n members: LeagueRosterMemberDTO[];\n joinRequests: LeagueRosterJoinRequestDTO[];\n}\n\nexport interface LeagueDetailData {\n league: LeagueWithCapacityAndScoringDTO;\n apiDto: AllLeaguesWithCapacityAndScoringDTO;\n}\n\n/**\n * League Service - DTO Only\n *\n * Returns Result. No ViewModels or UX logic.\n * All client-side presentation logic must be handled by hooks/components.\n * @server-safe\n */\nexport class LeagueService implements Service {\n private apiClient: LeaguesApiClient;\n private driversApiClient?: DriversApiClient;\n private sponsorsApiClient?: SponsorsApiClient;\n private racesApiClient?: RacesApiClient;\n\n constructor() {\n const baseUrl = getWebsiteApiBaseUrl();\n const logger = new ConsoleLogger();\n const errorReporter = new EnhancedErrorReporter(logger, {\n showUserNotifications: false,\n logToConsole: true,\n reportToExternal: isProductionEnvironment(),\n });\n this.apiClient = new LeaguesApiClient(baseUrl, errorReporter, logger);\n // Optional clients can be initialized if needed\n }\n\n async getAllLeagues(): Promise> {\n try {\n const dto = await this.apiClient.getAllWithCapacityAndScoring();\n return Result.ok(dto);\n } catch (error: any) {\n console.error('LeagueService.getAllLeagues failed:', error);\n return Result.err({ type: 'serverError', message: error.message || 'Failed to fetch leagues' });\n }\n }\n\n async getLeagueDetailData(leagueId: string): Promise> {\n try {\n const apiDto = await this.apiClient.getAllWithCapacityAndScoring();\n \n if (!apiDto || !apiDto.leagues) {\n return Result.err({ type: 'notFound', message: 'Leagues not found' });\n }\n \n const league = apiDto.leagues.find(l => l.id === leagueId);\n if (!league) {\n return Result.err({ type: 'notFound', message: 'League not found' });\n }\n \n return Result.ok({\n league,\n apiDto,\n });\n } catch (error: any) {\n console.error('LeagueService.getLeagueDetailData failed:', error);\n return Result.err({ type: 'serverError', message: error.message || 'Failed to fetch league detail' });\n }\n }\n\n async getScheduleAdminData(leagueId: string, seasonId?: string): Promise> {\n try {\n const seasons = await this.apiClient.getSeasons(leagueId);\n \n if (!seasons || seasons.length === 0) {\n return Result.err({ type: 'notFound', message: 'No seasons found for league' });\n }\n \n const targetSeasonId = seasonId || (seasons.find(s => s.status === 'active')?.seasonId || seasons[0].seasonId);\n const schedule = await this.apiClient.getSchedule(leagueId, targetSeasonId);\n \n return Result.ok({\n leagueId,\n seasonId: targetSeasonId,\n seasons,\n schedule,\n });\n } catch (error: any) {\n console.error('LeagueService.getScheduleAdminData failed:', error);\n return Result.err({ type: 'serverError', message: error.message || 'Failed to fetch schedule admin data' });\n }\n }\n\n async getRosterAdminData(leagueId: string): Promise> {\n try {\n const [members, joinRequests] = await Promise.all([\n this.apiClient.getAdminRosterMembers(leagueId),\n this.apiClient.getAdminRosterJoinRequests(leagueId),\n ]);\n\n return Result.ok({\n leagueId,\n members,\n joinRequests,\n });\n } catch (error: any) {\n console.error('LeagueService.getRosterAdminData failed:', error);\n return Result.err({ type: 'serverError', message: error.message || 'Failed to fetch roster data' });\n }\n }\n\n async getLeagueStandings(): Promise> {\n return Result.err({ type: 'notImplemented', message: 'League standings endpoint not implemented' });\n }\n\n async getLeagueStats(): Promise> {\n try {\n const data = await this.apiClient.getTotal();\n return Result.ok(data);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to fetch league stats' });\n }\n }\n\n async getLeagueSchedule(leagueId: string): Promise> {\n try {\n const data = await this.apiClient.getSchedule(leagueId);\n return Result.ok(data);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to fetch league schedule' });\n }\n }\n\n async getLeagueSeasons(leagueId: string): Promise> {\n try {\n const data = await this.apiClient.getSeasons(leagueId);\n return Result.ok(data);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to fetch league seasons' });\n }\n }\n\n async getLeagueSeasonSummaries(leagueId: string): Promise> {\n return this.getLeagueSeasons(leagueId);\n }\n\n async getAdminSchedule(leagueId: string, seasonId: string): Promise> {\n try {\n const data = await this.apiClient.getSchedule(leagueId, seasonId);\n return Result.ok(data);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to fetch admin schedule' });\n }\n }\n\n async publishAdminSchedule(leagueId: string, seasonId: string): Promise> {\n try {\n const data = await this.apiClient.publishSeasonSchedule(leagueId, seasonId);\n return Result.ok(data);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to publish schedule' });\n }\n }\n\n async unpublishAdminSchedule(leagueId: string, seasonId: string): Promise> {\n try {\n const data = await this.apiClient.unpublishSeasonSchedule(leagueId, seasonId);\n return Result.ok(data);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to unpublish schedule' });\n }\n }\n\n async createAdminScheduleRace(\n leagueId: string,\n seasonId: string,\n input: { track: string; car: string; scheduledAtIso: string },\n ): Promise> {\n try {\n const payload: CreateLeagueScheduleRaceInputDTO = { ...input, example: '' };\n const data = await this.apiClient.createSeasonScheduleRace(leagueId, seasonId, payload);\n return Result.ok(data);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to create race' });\n }\n }\n\n async updateAdminScheduleRace(\n leagueId: string,\n seasonId: string,\n raceId: string,\n input: Partial<{ track: string; car: string; scheduledAtIso: string }>,\n ): Promise> {\n try {\n const payload: UpdateLeagueScheduleRaceInputDTO = { ...input, example: '' };\n const data = await this.apiClient.updateSeasonScheduleRace(leagueId, seasonId, raceId, payload);\n return Result.ok(data);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to update race' });\n }\n }\n\n async deleteAdminScheduleRace(leagueId: string, seasonId: string, raceId: string): Promise> {\n try {\n const data = await this.apiClient.deleteSeasonScheduleRace(leagueId, seasonId, raceId);\n return Result.ok(data);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to delete race' });\n }\n }\n\n async getLeagueScheduleDto(leagueId: string, seasonId: string): Promise> {\n return this.getAdminSchedule(leagueId, seasonId);\n }\n\n async publishLeagueSeasonSchedule(leagueId: string, seasonId: string): Promise> {\n return this.publishAdminSchedule(leagueId, seasonId);\n }\n\n async unpublishLeagueSeasonSchedule(leagueId: string, seasonId: string): Promise> {\n return this.unpublishAdminSchedule(leagueId, seasonId);\n }\n\n async createLeagueSeasonScheduleRace(\n leagueId: string,\n seasonId: string,\n input: CreateLeagueScheduleRaceInputDTO,\n ): Promise> {\n try {\n const data = await this.apiClient.createSeasonScheduleRace(leagueId, seasonId, input);\n return Result.ok(data);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to create race' });\n }\n }\n\n async updateLeagueSeasonScheduleRace(\n leagueId: string,\n seasonId: string,\n raceId: string,\n input: UpdateLeagueScheduleRaceInputDTO,\n ): Promise> {\n try {\n const data = await this.apiClient.updateSeasonScheduleRace(leagueId, seasonId, raceId, input);\n return Result.ok(data);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to update race' });\n }\n }\n\n async deleteLeagueSeasonScheduleRace(\n leagueId: string,\n seasonId: string,\n raceId: string,\n ): Promise> {\n return this.deleteAdminScheduleRace(leagueId, seasonId, raceId);\n }\n\n async getLeagueMemberships(leagueId: string): Promise> {\n try {\n const data = await this.apiClient.getMemberships(leagueId);\n return Result.ok(data);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to fetch memberships' });\n }\n }\n\n async createLeague(input: CreateLeagueInputDTO): Promise> {\n try {\n const data = await this.apiClient.create(input);\n return Result.ok(data);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to create league' });\n }\n }\n\n async removeMember(leagueId: string, targetDriverId: string): Promise> {\n try {\n const dto = await this.apiClient.removeRosterMember(leagueId, targetDriverId);\n return Result.ok({ success: dto.success });\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to remove member' });\n }\n }\n\n async updateMemberRole(leagueId: string, targetDriverId: string, newRole: MembershipRole): Promise> {\n try {\n const dto = await this.apiClient.updateRosterMemberRole(leagueId, targetDriverId, newRole);\n return Result.ok({ success: dto.success });\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to update member role' });\n }\n }\n\n async getAdminRosterMembers(leagueId: string): Promise> {\n try {\n const data = await this.apiClient.getAdminRosterMembers(leagueId);\n return Result.ok(data);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to fetch roster members' });\n }\n }\n\n async getAdminRosterJoinRequests(leagueId: string): Promise> {\n try {\n const data = await this.apiClient.getAdminRosterJoinRequests(leagueId);\n return Result.ok(data);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to fetch join requests' });\n }\n }\n\n async approveJoinRequest(leagueId: string, joinRequestId: string): Promise> {\n try {\n const dto = await this.apiClient.approveRosterJoinRequest(leagueId, joinRequestId);\n return Result.ok({ success: dto.success });\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to approve join request' });\n }\n }\n\n async rejectJoinRequest(leagueId: string, joinRequestId: string): Promise> {\n try {\n const dto = await this.apiClient.rejectRosterJoinRequest(leagueId, joinRequestId);\n return Result.ok({ success: dto.success });\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to reject join request' });\n }\n }\n\n async getLeagueDetail(): Promise> {\n return Result.err({ type: 'notImplemented', message: 'League detail endpoint not implemented' });\n }\n\n async getLeagueDetailPageData(): Promise> {\n return Result.err({ type: 'notImplemented', message: 'League detail page data endpoint not implemented' });\n }\n\n async getScoringPresets(): Promise> {\n return Result.err({ type: 'notImplemented', message: 'Scoring presets endpoint not implemented' });\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/leagues/LeagueSettingsService.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":38,"column":29,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":38,"endColumn":32,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1332,1335],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1332,1335],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Result } from '@/lib/contracts/Result';\nimport { Service, type DomainError } from '@/lib/contracts/services/Service';\nimport { type LeagueSettingsApiDto } from '@/lib/types/tbd/LeagueSettingsApiDto';\n\nexport class LeagueSettingsService implements Service {\n private static cachedMemberships = new Map();\n\n async getSettingsData(leagueId: string): Promise> {\n // Mock data since backend not implemented\n const mockData: LeagueSettingsApiDto = {\n leagueId,\n league: {\n id: leagueId,\n name: 'Mock League',\n description: 'A mock league for demonstration',\n visibility: 'public',\n ownerId: 'owner-123',\n createdAt: '2024-01-01T00:00:00Z',\n updatedAt: '2024-01-01T00:00:00Z',\n },\n config: {\n maxDrivers: 20,\n scoringPresetId: 'preset-1',\n allowLateJoin: true,\n requireApproval: false,\n },\n };\n return Result.ok(mockData);\n }\n\n static getCachedMembershipsIterator(): IterableIterator<[string, unknown[]]> {\n return this.cachedMemberships.entries();\n }\n\n static getMembership(leagueId: string, driverId: string): unknown | null {\n const members = this.cachedMemberships.get(leagueId);\n if (!members) return null;\n return members.find((m: any) => m.driverId === driverId) || null;\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/leagues/LeagueSponsorshipsService.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/leagues/LeagueStandingsService.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_leagueId' is defined but never used.","line":21,"column":26,"nodeType":"Identifier","messageId":"unusedVar","endLine":21,"endColumn":43}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Result } from '@/lib/contracts/Result';\nimport { Service, type DomainError } from '@/lib/contracts/services/Service';\nimport { type LeagueStandingsApiDto, type LeagueMembershipsApiDto } from '@/lib/types/tbd/LeagueStandingsApiDto';\nimport { LeaguesApiClient } from '@/lib/api/leagues/LeaguesApiClient';\nimport { ConsoleErrorReporter } from '@/lib/infrastructure/logging/ConsoleErrorReporter';\nimport { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';\nimport { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl';\n\nexport class LeagueStandingsService implements Service {\n private apiClient: LeaguesApiClient;\n\n constructor() {\n const baseUrl = getWebsiteApiBaseUrl();\n this.apiClient = new LeaguesApiClient(\n baseUrl,\n new ConsoleErrorReporter(),\n new ConsoleLogger()\n );\n }\n\n async getStandingsData(_leagueId: string): Promise> {\n // Mock data since backend may not be implemented\n const mockStandings: LeagueStandingsApiDto = {\n standings: [\n {\n driverId: 'driver1',\n driver: {\n id: 'driver1',\n name: 'John Doe',\n iracingId: '12345',\n country: 'US',\n joinedAt: new Date().toISOString(),\n },\n points: 100,\n position: 1,\n wins: 2,\n podiums: 3,\n races: 5,\n },\n {\n driverId: 'driver2',\n driver: {\n id: 'driver2',\n name: 'Jane Smith',\n iracingId: '67890',\n country: 'UK',\n joinedAt: new Date().toISOString(),\n },\n points: 80,\n position: 2,\n wins: 1,\n podiums: 2,\n races: 5,\n },\n ],\n };\n\n const mockMemberships: LeagueMembershipsApiDto = {\n members: [\n {\n driverId: 'driver1',\n driver: {\n id: 'driver1',\n name: 'John Doe',\n iracingId: '12345',\n country: 'US',\n joinedAt: new Date().toISOString(),\n },\n role: 'member',\n joinedAt: new Date().toISOString(),\n },\n {\n driverId: 'driver2',\n driver: {\n id: 'driver2',\n name: 'Jane Smith',\n iracingId: '67890',\n country: 'UK',\n joinedAt: new Date().toISOString(),\n },\n role: 'member',\n joinedAt: new Date().toISOString(),\n },\n ],\n };\n\n return Result.ok({ standings: mockStandings, memberships: mockMemberships });\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/leagues/LeagueStewardingService.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_leagueId' is defined but never used.","line":19,"column":35,"nodeType":"Identifier","messageId":"unusedVar","endLine":19,"endColumn":52},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_protestId' is defined but never used.","line":19,"column":54,"nodeType":"Identifier","messageId":"unusedVar","endLine":19,"endColumn":72},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":19,"column":90,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":19,"endColumn":93,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[698,701],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[698,701],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":3,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Result } from '@/lib/contracts/Result';\nimport { Service, type DomainError } from '@/lib/contracts/services/Service';\nimport { type StewardingApiDto } from '@/lib/types/tbd/StewardingApiDto';\n\nexport class LeagueStewardingService implements Service {\n async getStewardingData(leagueId: string): Promise> {\n // Mock data since backend not implemented\n const mockData: StewardingApiDto = {\n leagueId,\n totalPending: 0,\n totalResolved: 0,\n totalPenalties: 0,\n races: [],\n drivers: []\n };\n return Result.ok(mockData);\n }\n\n async getProtestDetailViewModel(_leagueId: string, _protestId: string): Promise> {\n return Result.err({ type: 'notImplemented', message: 'getProtestDetailViewModel' });\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/leagues/LeagueWalletService.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/leagues/ProfileLeaguesService.ts","messages":[{"ruleId":"gridpilot-rules/service-function-format","severity":2,"message":"Service files should only export the Service class.","line":1,"column":1,"nodeType":"Program","messageId":"multipleExports","endLine":96,"endColumn":1},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":81,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":81,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2985,2988],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2985,2988],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { ApiClient } from '@/lib/api';\nimport { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl';\nimport { Result } from '@/lib/contracts/Result';\nimport { Service, type DomainError } from '@/lib/contracts/services/Service';\n\nexport interface ProfileLeaguesPageDto {\n ownedLeagues: Array<{\n leagueId: string;\n name: string;\n description: string;\n membershipRole: 'owner' | 'admin' | 'steward' | 'member';\n }>;\n memberLeagues: Array<{\n leagueId: string;\n name: string;\n description: string;\n membershipRole: 'owner' | 'admin' | 'steward' | 'member';\n }>;\n}\n\ninterface MembershipDTO {\n driverId: string;\n role: string;\n status?: 'active' | 'inactive';\n}\n\nexport class ProfileLeaguesService implements Service {\n async getProfileLeagues(driverId: string): Promise> {\n try {\n const baseUrl = getWebsiteApiBaseUrl();\n const apiClient = new ApiClient(baseUrl);\n \n const leaguesDto = await apiClient.leagues.getAllWithCapacity();\n \n if (!leaguesDto?.leagues) {\n return Result.err({ type: 'notFound', message: 'Leagues not found' });\n }\n\n // Fetch all memberships in parallel\n const leagueMemberships = await Promise.all(\n leaguesDto.leagues.map(async (league) => {\n try {\n const membershipsDto = await apiClient.leagues.getMemberships(league.id);\n \n let memberships: MembershipDTO[] = [];\n if (membershipsDto && typeof membershipsDto === 'object') {\n if ('members' in membershipsDto && Array.isArray((membershipsDto as { members?: unknown }).members)) {\n memberships = (membershipsDto as { members: MembershipDTO[] }).members;\n } else if ('memberships' in membershipsDto && Array.isArray((membershipsDto as { memberships?: unknown }).memberships)) {\n memberships = (membershipsDto as { memberships: MembershipDTO[] }).memberships;\n }\n }\n \n const currentMembership = memberships.find((m) => m.driverId === driverId);\n \n if (currentMembership && currentMembership.status === 'active') {\n return {\n leagueId: league.id,\n name: league.name,\n description: league.description,\n membershipRole: currentMembership.role as 'owner' | 'admin' | 'steward' | 'member',\n };\n }\n return null;\n } catch {\n return null;\n }\n })\n );\n\n // Filter and categorize\n const validLeagues = leagueMemberships.filter((l): l is NonNullable => l !== null);\n \n const ownedLeagues = validLeagues.filter((l) => l.membershipRole === 'owner');\n const memberLeagues = validLeagues.filter((l) => l.membershipRole !== 'owner');\n\n return Result.ok({\n ownedLeagues,\n memberLeagues,\n });\n } catch (error: any) {\n const errorAny = error as { statusCode?: number; message?: string };\n \n if (errorAny.statusCode === 404 || errorAny.message?.toLowerCase().includes('not found')) {\n return Result.err({ type: 'notFound', message: 'Profile leagues not found' });\n }\n \n if (errorAny.statusCode === 302 || errorAny.message?.toLowerCase().includes('redirect')) {\n return Result.err({ type: 'unauthorized', message: 'Unauthorized access' });\n }\n\n return Result.err({ type: 'unknown', message: error.message || 'Failed to fetch profile leagues' });\n }\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/leagues/ProtestDetailService.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/media/MediaService.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/onboarding/OnboardingService.ts","messages":[],"suppressedMessages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'input' is defined but never used.","line":58,"column":25,"nodeType":"Identifier","messageId":"unusedVar","endLine":58,"endColumn":63,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/payments/PaymentService.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/payments/WalletService.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_driverId' is defined but never used.","line":13,"column":26,"nodeType":"Identifier","messageId":"unusedVar","endLine":13,"endColumn":43}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Result } from '@/lib/contracts/Result';\nimport { DomainError, Service } from '@/lib/contracts/services/Service';\n\n/**\n * Wallet Service - DTO Only\n *\n * Returns raw API DTOs. No ViewModels or UX logic.\n * All client-side presentation logic must be handled by hooks/components.\n */\nexport class WalletService implements Service {\n constructor() {}\n\n async getWalletBalance(_driverId: string): Promise> {\n return Result.ok({ balance: 0, currency: 'USD' });\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/penalties/PenaltyService.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":28,"column":54,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":28,"endColumn":57,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1117,1120],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1117,1120],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":32,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":32,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1274,1277],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1274,1277],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":44,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":44,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1674,1677],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1674,1677],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":52,"column":29,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":52,"endColumn":32,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1860,1863],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1860,1863],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":56,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":56,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2016,2019],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2016,2019],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":5,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { PenaltiesApiClient } from '@/lib/api/penalties/PenaltiesApiClient';\nimport type { PenaltyTypesReferenceDTO } from '@/lib/types/PenaltyTypesReferenceDTO';\nimport { Result } from '@/lib/contracts/Result';\nimport { DomainError, Service } from '@/lib/contracts/services/Service';\nimport { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl';\nimport { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';\nimport { EnhancedErrorReporter } from '@/lib/infrastructure/EnhancedErrorReporter';\n\n/**\n * Penalty Service\n *\n * Orchestrates penalty operations by coordinating API calls and view model creation.\n * All dependencies are injected via constructor.\n */\nexport class PenaltyService implements Service {\n private readonly apiClient: PenaltiesApiClient;\n\n constructor() {\n const baseUrl = getWebsiteApiBaseUrl();\n const logger = new ConsoleLogger();\n const errorReporter = new EnhancedErrorReporter(logger);\n this.apiClient = new PenaltiesApiClient(baseUrl, errorReporter, logger);\n }\n\n /**\n * Find penalties by race ID\n */\n async findByRaceId(raceId: string): Promise> {\n try {\n const dto = await this.apiClient.getRacePenalties(raceId);\n return Result.ok(dto.penalties);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to find penalties' });\n }\n }\n\n /**\n * Get allowed penalty types and semantics\n */\n async getPenaltyTypesReference(): Promise> {\n try {\n const data = await this.apiClient.getPenaltyTypesReference();\n return Result.ok(data);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to get penalty types' });\n }\n }\n\n /**\n * Apply a penalty\n */\n async applyPenalty(input: any): Promise> {\n try {\n await this.apiClient.applyPenalty(input);\n return Result.ok(undefined);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to apply penalty' });\n }\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/policy/PolicyService.ts","messages":[{"ruleId":"gridpilot-rules/service-function-format","severity":2,"message":"Service files should only export the Service class.","line":1,"column":1,"nodeType":"Program","messageId":"multipleExports","endLine":100,"endColumn":1},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":30,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":30,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1179,1182],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1179,1182],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { PolicyApiClient, type FeatureState, type PolicySnapshotDto } from '@/lib/api/policy/PolicyApiClient';\nimport { Result } from '@/lib/contracts/Result';\nimport { DomainError, Service } from '@/lib/contracts/services/Service';\nimport { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl';\nimport { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';\nimport { EnhancedErrorReporter } from '@/lib/infrastructure/EnhancedErrorReporter';\n\nexport interface CapabilityEvaluationResult {\n isLoading: boolean;\n isError: boolean;\n capabilityState: FeatureState | null;\n shouldShowChildren: boolean;\n shouldShowComingSoon: boolean;\n}\n\nexport class PolicyService implements Service {\n private readonly apiClient: PolicyApiClient;\n\n constructor() {\n const baseUrl = getWebsiteApiBaseUrl();\n const logger = new ConsoleLogger();\n const errorReporter = new EnhancedErrorReporter(logger);\n this.apiClient = new PolicyApiClient(baseUrl, errorReporter, logger);\n }\n\n async getSnapshot(): Promise> {\n try {\n const data = await this.apiClient.getSnapshot();\n return Result.ok(data);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to get policy snapshot' });\n }\n }\n\n getCapabilityState(snapshot: PolicySnapshotDto, capabilityKey: string): FeatureState {\n return snapshot.capabilities[capabilityKey] ?? 'hidden';\n }\n\n isCapabilityEnabled(snapshot: PolicySnapshotDto, capabilityKey: string): boolean {\n return this.getCapabilityState(snapshot, capabilityKey) === 'enabled';\n }\n\n /**\n * Evaluate capability state and determine what should be rendered\n * Centralizes the logic for capability-based UI rendering\n */\n evaluateCapability(\n snapshot: PolicySnapshotDto | null,\n capabilityKey: string,\n isLoading: boolean,\n isError: boolean\n ): CapabilityEvaluationResult {\n if (isLoading || isError || !snapshot) {\n return {\n isLoading,\n isError,\n capabilityState: null,\n shouldShowChildren: false,\n shouldShowComingSoon: false,\n };\n }\n\n const capabilityState = this.getCapabilityState(snapshot, capabilityKey);\n \n return {\n isLoading,\n isError,\n capabilityState,\n shouldShowChildren: capabilityState === 'enabled',\n shouldShowComingSoon: capabilityState === 'coming_soon',\n };\n }\n\n /**\n * Get the appropriate content based on capability state\n * Handles fallback and coming soon logic\n */\n getCapabilityContent(\n snapshot: PolicySnapshotDto | null,\n capabilityKey: string,\n isLoading: boolean,\n isError: boolean,\n children: React.ReactNode,\n fallback: React.ReactNode = null,\n comingSoon: React.ReactNode = null\n ): React.ReactNode {\n const evaluation = this.evaluateCapability(snapshot, capabilityKey, isLoading, isError);\n\n if (evaluation.shouldShowChildren) {\n return children;\n }\n\n if (evaluation.shouldShowComingSoon) {\n return comingSoon ?? fallback;\n }\n\n return fallback;\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/protests/ProtestService.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":27,"column":61,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":27,"endColumn":64,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1288,1291],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1288,1291],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":31,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":31,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1438,1441],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1438,1441],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":36,"column":77,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":36,"endColumn":80,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1641,1644],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1641,1644],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":40,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":40,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1801,1804],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1801,1804],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":49,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":49,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2123,2126],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2123,2126],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":58,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":58,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2460,2463],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2460,2463],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":67,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":67,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2789,2792],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2789,2792],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":72,"column":54,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":72,"endColumn":57,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2964,2967],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2964,2967],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":76,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":76,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3110,3113],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3110,3113],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":9,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { ProtestsApiClient } from '@/lib/api/protests/ProtestsApiClient';\nimport type { ApplyPenaltyCommandDTO } from '@/lib/types/generated/ApplyPenaltyCommandDTO';\nimport type { RequestProtestDefenseCommandDTO } from '@/lib/types/generated/RequestProtestDefenseCommandDTO';\nimport type { ReviewProtestCommandDTO } from '@/lib/types/generated/ReviewProtestCommandDTO';\nimport { Result } from '@/lib/contracts/Result';\nimport { DomainError, Service } from '@/lib/contracts/services/Service';\nimport { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl';\nimport { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';\nimport { EnhancedErrorReporter } from '@/lib/infrastructure/EnhancedErrorReporter';\n\n/**\n * Protest Service - DTO Only\n *\n * Returns raw API DTOs. No ViewModels or UX logic.\n * All client-side presentation logic must be handled by hooks/components.\n */\nexport class ProtestService implements Service {\n private readonly apiClient: ProtestsApiClient;\n\n constructor() {\n const baseUrl = getWebsiteApiBaseUrl();\n const logger = new ConsoleLogger();\n const errorReporter = new EnhancedErrorReporter(logger);\n this.apiClient = new ProtestsApiClient(baseUrl, errorReporter, logger);\n }\n\n async getLeagueProtests(leagueId: string): Promise> {\n try {\n const data = await this.apiClient.getLeagueProtests(leagueId);\n return Result.ok(data);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to get league protests' });\n }\n }\n\n async getProtestById(leagueId: string, protestId: string): Promise> {\n try {\n const data = await this.apiClient.getLeagueProtest(leagueId, protestId);\n return Result.ok(data);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to get protest' });\n }\n }\n\n async applyPenalty(input: ApplyPenaltyCommandDTO): Promise> {\n try {\n await this.apiClient.applyPenalty(input);\n return Result.ok(undefined);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to apply penalty' });\n }\n }\n\n async requestDefense(input: RequestProtestDefenseCommandDTO): Promise> {\n try {\n await this.apiClient.requestDefense(input);\n return Result.ok(undefined);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to request defense' });\n }\n }\n\n async reviewProtest(input: ReviewProtestCommandDTO): Promise> {\n try {\n await this.apiClient.reviewProtest(input);\n return Result.ok(undefined);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to review protest' });\n }\n }\n\n async findByRaceId(raceId: string): Promise> {\n try {\n const data = await this.apiClient.getRaceProtests(raceId);\n return Result.ok(data);\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to find protests' });\n }\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/races/RaceResultsService.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":31,"column":62,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":31,"endColumn":65,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1129,1132],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1129,1132],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":35,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":35,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1276,1279],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1276,1279],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":53,"column":52,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":53,"endColumn":55,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1734,1737],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1734,1737],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":57,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":57,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1875,1878],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1875,1878],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":4,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { RacesApiClient } from '@/lib/api/races/RacesApiClient';\nimport { Result } from '@/lib/contracts/Result';\nimport { DomainError, Service } from '@/lib/contracts/services/Service';\nimport { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';\nimport { ConsoleErrorReporter } from '@/lib/infrastructure/logging/ConsoleErrorReporter';\nimport { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl';\nimport { ApiError } from '@/lib/api/base/ApiError';\n\n/**\n * Race Results Service\n * \n * Orchestration service for race results operations.\n * Returns raw API DTOs. No ViewModels or UX logic.\n */\nexport class RaceResultsService implements Service {\n private apiClient: RacesApiClient;\n\n constructor() {\n // Service creates its own dependencies\n const baseUrl = getWebsiteApiBaseUrl();\n const logger = new ConsoleLogger();\n const errorReporter = new ConsoleErrorReporter();\n \n this.apiClient = new RacesApiClient(baseUrl, errorReporter, logger);\n }\n\n /**\n * Get race results detail\n * Returns results for a specific race\n */\n async getRaceResultsDetail(raceId: string): Promise> {\n try {\n const data = await this.apiClient.getResultsDetail(raceId);\n return Result.ok(data);\n } catch (error: any) {\n if (error instanceof ApiError) {\n return Result.err({\n type: this.mapApiErrorType(error.type),\n message: error.message\n });\n }\n return Result.err({\n type: 'unknown',\n message: error.message || 'Failed to fetch race results'\n });\n }\n }\n\n /**\n * Get race with strength of field\n * Returns race data with SOF calculation\n */\n async getWithSOF(raceId: string): Promise> {\n try {\n const data = await this.apiClient.getWithSOF(raceId);\n return Result.ok(data);\n } catch (error: any) {\n if (error instanceof ApiError) {\n return Result.err({\n type: this.mapApiErrorType(error.type),\n message: error.message\n });\n }\n return Result.err({\n type: 'unknown',\n message: error.message || 'Failed to fetch race SOF'\n });\n }\n }\n\n private mapApiErrorType(apiErrorType: string): DomainError['type'] {\n switch (apiErrorType) {\n case 'NOT_FOUND':\n return 'notFound';\n case 'AUTH_ERROR':\n return 'unauthorized';\n case 'VALIDATION_ERROR':\n return 'validation';\n case 'SERVER_ERROR':\n return 'serverError';\n case 'NETWORK_ERROR':\n return 'networkError';\n default:\n return 'unknown';\n }\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/races/RaceService.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":25,"column":53,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":25,"endColumn":56,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1005,1008],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1005,1008],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":30,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":30,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1243,1246],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1243,1246],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":35,"column":62,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":35,"endColumn":65,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1399,1402],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1399,1402],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":39,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":39,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1543,1546],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1543,1546],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":44,"column":58,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":44,"endColumn":61,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1703,1706],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1703,1706],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":48,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":48,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1865,1868],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1865,1868],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_raceId' is defined but never used.","line":53,"column":25,"nodeType":"Identifier","messageId":"unusedVar","endLine":53,"endColumn":40},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_leagueId' is defined but never used.","line":53,"column":42,"nodeType":"Identifier","messageId":"unusedVar","endLine":53,"endColumn":59},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_driverId' is defined but never used.","line":53,"column":61,"nodeType":"Identifier","messageId":"unusedVar","endLine":53,"endColumn":78},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_raceId' is defined but never used.","line":57,"column":26,"nodeType":"Identifier","messageId":"unusedVar","endLine":57,"endColumn":41},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_driverId' is defined but never used.","line":57,"column":43,"nodeType":"Identifier","messageId":"unusedVar","endLine":57,"endColumn":60},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_command' is defined but never used.","line":61,"column":21,"nodeType":"Identifier","messageId":"unusedVar","endLine":61,"endColumn":34},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":61,"column":31,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":61,"endColumn":34,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2382,2385],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2382,2385],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":13,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { RacesApiClient } from '@/lib/api/races/RacesApiClient';\nimport { Result } from '@/lib/contracts/Result';\nimport { DomainError, Service } from '@/lib/contracts/services/Service';\nimport { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';\nimport { ConsoleErrorReporter } from '@/lib/infrastructure/logging/ConsoleErrorReporter';\nimport { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl';\nimport { ApiError } from '@/lib/api/base/ApiError';\n\n/**\n * Race Service - DTO Only\n *\n * Returns raw API DTOs. No ViewModels or UX logic.\n * All client-side presentation logic must be handled by hooks/components.\n */\nexport class RaceService implements Service {\n private apiClient: RacesApiClient;\n\n constructor() {\n const baseUrl = getWebsiteApiBaseUrl();\n const logger = new ConsoleLogger();\n const errorReporter = new ConsoleErrorReporter();\n this.apiClient = new RacesApiClient(baseUrl, errorReporter, logger);\n }\n\n async getRaceById(raceId: string): Promise> {\n try {\n // This would need a driverId, but for now we'll use a placeholder\n const data = await this.apiClient.getDetail(raceId, 'placeholder-driver-id');\n return Result.ok(data);\n } catch (error: any) {\n return Result.err(this.mapError(error, 'Failed to fetch race by ID'));\n }\n }\n\n async getRacesByLeagueId(leagueId: string): Promise> {\n try {\n const data = await this.apiClient.getPageData(leagueId);\n return Result.ok(data);\n } catch (error: any) {\n return Result.err(this.mapError(error, 'Failed to fetch races by league ID'));\n }\n }\n\n async findByLeagueId(leagueId: string): Promise> {\n try {\n const result = await this.apiClient.getPageData(leagueId);\n return Result.ok(result.races || []);\n } catch (error: any) {\n return Result.err(this.mapError(error, 'Failed to find races by league ID'));\n }\n }\n\n async registerForRace(_raceId: string, _leagueId: string, _driverId: string): Promise> {\n return Result.err({ type: 'notImplemented', message: 'registerForRace' });\n }\n\n async withdrawFromRace(_raceId: string, _driverId: string): Promise> {\n return Result.err({ type: 'notImplemented', message: 'withdrawFromRace' });\n }\n\n async fileProtest(_command: any): Promise> {\n return Result.err({ type: 'notImplemented', message: 'fileProtest' });\n }\n\n private mapError(error: unknown, defaultMessage: string): DomainError {\n if (error instanceof ApiError) {\n return {\n type: this.mapApiErrorType(error.type),\n message: error.message\n };\n }\n return {\n type: 'unknown',\n message: defaultMessage\n };\n }\n\n private mapApiErrorType(apiErrorType: string): DomainError['type'] {\n switch (apiErrorType) {\n case 'NOT_FOUND':\n return 'notFound';\n case 'AUTH_ERROR':\n return 'unauthorized';\n case 'VALIDATION_ERROR':\n return 'validation';\n case 'SERVER_ERROR':\n return 'serverError';\n case 'NETWORK_ERROR':\n return 'networkError';\n default:\n return 'unknown';\n }\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/races/RaceStewardingService.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":37,"column":59,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":37,"endColumn":62,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1571,1574],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1571,1574],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":47,"column":54,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":47,"endColumn":57,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1985,1988],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1985,1988],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":59,"column":55,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":59,"endColumn":58,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2319,2322],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2319,2322],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":60,"column":56,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":60,"endColumn":59,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2438,2441],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2438,2441],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":80,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":80,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3044,3047],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3044,3047],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":5,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { RacesApiClient } from '@/lib/api/races/RacesApiClient';\nimport { ProtestsApiClient } from '@/lib/api/protests/ProtestsApiClient';\nimport { PenaltiesApiClient } from '@/lib/api/penalties/PenaltiesApiClient';\nimport { Result } from '@/lib/contracts/Result';\nimport { DomainError, Service } from '@/lib/contracts/services/Service';\nimport { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';\nimport { ConsoleErrorReporter } from '@/lib/infrastructure/logging/ConsoleErrorReporter';\nimport { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl';\nimport { ApiError } from '@/lib/api/base/ApiError';\n\n/**\n * Race Stewarding Service\n * \n * Orchestration service for race stewarding operations.\n * Returns raw API DTOs. No ViewModels or UX logic.\n */\nexport class RaceStewardingService implements Service {\n private racesApiClient: RacesApiClient;\n private protestsApiClient: ProtestsApiClient;\n private penaltiesApiClient: PenaltiesApiClient;\n\n constructor() {\n // Service creates its own dependencies\n const baseUrl = getWebsiteApiBaseUrl();\n const logger = new ConsoleLogger();\n const errorReporter = new ConsoleErrorReporter();\n \n this.racesApiClient = new RacesApiClient(baseUrl, errorReporter, logger);\n this.protestsApiClient = new ProtestsApiClient(baseUrl, errorReporter, logger);\n this.penaltiesApiClient = new PenaltiesApiClient(baseUrl, errorReporter, logger);\n }\n\n /**\n * Get race stewarding data\n * Returns protests and penalties for a race\n */\n async getRaceStewarding(raceId: string): Promise> {\n try {\n // Fetch data in parallel\n const [raceDetail, protests, penalties] = await Promise.all([\n this.racesApiClient.getDetail(raceId, ''),\n this.protestsApiClient.getRaceProtests(raceId),\n this.penaltiesApiClient.getRacePenalties(raceId),\n ]);\n\n // Transform data to match view model structure\n const protestsData = protests.protests.map((p: any) => ({\n id: p.id,\n protestingDriverId: p.protestingDriverId,\n accusedDriverId: p.accusedDriverId,\n incident: {\n lap: p.lap,\n description: p.description,\n },\n filedAt: p.filedAt,\n status: p.status,\n }));\n\n const pendingProtests = protestsData.filter((p: any) => p.status === 'pending' || p.status === 'under_review');\n const resolvedProtests = protestsData.filter((p: any) =>\n p.status === 'upheld' ||\n p.status === 'dismissed' ||\n p.status === 'withdrawn'\n );\n\n const data = {\n race: raceDetail.race,\n league: raceDetail.league,\n protests: protestsData,\n penalties: penalties.penalties,\n driverMap: { ...protests.driverMap, ...penalties.driverMap },\n pendingProtests,\n resolvedProtests,\n pendingCount: pendingProtests.length,\n resolvedCount: resolvedProtests.length,\n penaltiesCount: penalties.penalties.length,\n };\n\n return Result.ok(data);\n } catch (error: any) {\n if (error instanceof ApiError) {\n return Result.err({\n type: this.mapApiErrorType(error.type),\n message: error.message\n });\n }\n return Result.err({\n type: 'unknown',\n message: error.message || 'Failed to fetch stewarding data'\n });\n }\n }\n\n private mapApiErrorType(apiErrorType: string): DomainError['type'] {\n switch (apiErrorType) {\n case 'NOT_FOUND':\n return 'notFound';\n case 'AUTH_ERROR':\n return 'unauthorized';\n case 'VALIDATION_ERROR':\n return 'validation';\n case 'SERVER_ERROR':\n return 'serverError';\n case 'NETWORK_ERROR':\n return 'networkError';\n default:\n return 'unknown';\n }\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/races/RacesService.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/sponsors/SponsorService.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":45,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":45,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2192,2195],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2192,2195],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":57,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":57,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2646,2649],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2646,2649],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":69,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":69,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3117,3120],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3117,3120],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_sponsorId' is defined but never used.","line":74,"column":20,"nodeType":"Identifier","messageId":"unusedVar","endLine":74,"endColumn":38},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":98,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":98,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[4315,4318],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[4315,4318],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":107,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":107,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[4736,4739],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[4736,4739],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":116,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":116,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[5167,5170],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[5167,5170],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":7,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Result } from '@/lib/contracts/Result';\nimport { DomainError, Service } from '@/lib/contracts/services/Service';\nimport { SponsorsApiClient } from '@/lib/api/sponsors/SponsorsApiClient';\nimport { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';\nimport { EnhancedErrorReporter } from '@/lib/infrastructure/EnhancedErrorReporter';\nimport { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl';\nimport { getWebsiteServerEnv } from '@/lib/config/env';\nimport type { SponsorDashboardDTO } from '@/lib/types/generated/SponsorDashboardDTO';\nimport type { SponsorSponsorshipsDTO } from '@/lib/types/generated/SponsorSponsorshipsDTO';\nimport type { GetSponsorOutputDTO } from '@/lib/types/generated/GetSponsorOutputDTO';\nimport type { GetPendingSponsorshipRequestsOutputDTO } from '@/lib/types/generated/GetPendingSponsorshipRequestsOutputDTO';\nimport type { SponsorBillingDTO } from '@/lib/types/tbd/SponsorBillingDTO';\nimport type { AvailableLeaguesDTO } from '@/lib/types/tbd/AvailableLeaguesDTO';\nimport type { LeagueDetailForSponsorDTO } from '@/lib/types/tbd/LeagueDetailForSponsorDTO';\nimport type { SponsorSettingsDTO } from '@/lib/types/tbd/SponsorSettingsDTO';\n\n/**\n * Sponsor Service - DTO Only\n *\n * Returns raw API DTOs. No ViewModels or UX logic.\n * All client-side presentation logic must be handled by hooks/components.\n */\nexport class SponsorService implements Service {\n private apiClient: SponsorsApiClient;\n\n constructor() {\n const baseUrl = getWebsiteApiBaseUrl();\n const logger = new ConsoleLogger();\n const { NODE_ENV } = getWebsiteServerEnv();\n const errorReporter = new EnhancedErrorReporter(logger, {\n showUserNotifications: true,\n logToConsole: true,\n reportToExternal: NODE_ENV === 'production',\n });\n this.apiClient = new SponsorsApiClient(baseUrl, errorReporter, logger);\n }\n\n async getSponsorById(sponsorId: string): Promise> {\n try {\n const result = await this.apiClient.getSponsor(sponsorId);\n if (!result) {\n return Result.err({ type: 'notFound', message: 'Sponsor not found' });\n }\n return Result.ok(result);\n } catch (error: any) {\n return Result.err({ type: 'unknown', message: error.message || 'Failed to get sponsor' });\n }\n }\n\n async getSponsorDashboard(sponsorId: string): Promise> {\n try {\n const result = await this.apiClient.getDashboard(sponsorId);\n if (!result) {\n return Result.err({ type: 'notFound', message: 'Dashboard not found' });\n }\n return Result.ok(result);\n } catch (error: any) {\n return Result.err({ type: 'notImplemented', message: error.message || 'getSponsorDashboard' });\n }\n }\n\n async getSponsorSponsorships(sponsorId: string): Promise> {\n try {\n const result = await this.apiClient.getSponsorships(sponsorId);\n if (!result) {\n return Result.err({ type: 'notFound', message: 'Sponsorships not found' });\n }\n return Result.ok(result);\n } catch (error: any) {\n return Result.err({ type: 'notImplemented', message: error.message || 'getSponsorSponsorships' });\n }\n }\n\n async getBilling(_sponsorId: string): Promise> {\n return Result.err({ type: 'notImplemented', message: 'getBilling' });\n }\n\n async getAvailableLeagues(): Promise> {\n return Result.err({ type: 'notImplemented', message: 'getAvailableLeagues' });\n }\n\n async getLeagueDetail(): Promise> {\n return Result.err({ type: 'notImplemented', message: 'getLeagueDetail' });\n }\n\n async getSettings(): Promise> {\n return Result.err({ type: 'notImplemented', message: 'getSettings' });\n }\n\n async updateSettings(): Promise> {\n return Result.err({ type: 'notImplemented', message: 'updateSettings' });\n }\n\n async acceptSponsorshipRequest(requestId: string, sponsorId: string): Promise> {\n try {\n await this.apiClient.acceptSponsorshipRequest(requestId, { respondedBy: sponsorId });\n return Result.ok(undefined);\n } catch (error: any) {\n return Result.err({ type: 'unknown', message: error.message || 'Failed to accept sponsorship request' });\n }\n }\n\n async rejectSponsorshipRequest(requestId: string, sponsorId: string, reason?: string): Promise> {\n try {\n await this.apiClient.rejectSponsorshipRequest(requestId, { respondedBy: sponsorId, reason });\n return Result.ok(undefined);\n } catch (error: any) {\n return Result.err({ type: 'unknown', message: error.message || 'Failed to reject sponsorship request' });\n }\n }\n\n async getPendingSponsorshipRequests(input: { entityType: string; entityId: string }): Promise> {\n try {\n const result = await this.apiClient.getPendingSponsorshipRequests(input);\n return Result.ok(result);\n } catch (error: any) {\n return Result.err({ type: 'notImplemented', message: error.message || 'getPendingSponsorshipRequests' });\n }\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/sponsors/SponsorshipRequestsReadService.ts","messages":[{"ruleId":"gridpilot-rules/service-function-format","severity":2,"message":"Service files should only export the Service class.","line":1,"column":1,"nodeType":"Program","messageId":"multipleExports","endLine":88,"endColumn":1},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":80,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":80,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2535,2538],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2535,2538],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { SponsorsApiClient } from '@/lib/api/sponsors/SponsorsApiClient';\nimport { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl';\nimport { isProductionEnvironment } from '@/lib/config/env';\nimport { Result } from '@/lib/contracts/Result';\nimport type { Service, DomainError } from '@/lib/contracts/services/Service';\nimport { EnhancedErrorReporter } from '@/lib/infrastructure/EnhancedErrorReporter';\nimport { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';\n\nexport interface PendingSponsorshipRequestDto {\n requestId: string;\n sponsorId: string;\n sponsorName: string;\n message: string | null;\n createdAtIso: string;\n}\n\nexport interface SponsorshipRequestsReadApiDto {\n sections: Array<{\n entityType: 'driver' | 'team' | 'season';\n entityId: string;\n entityName: string;\n requests: PendingSponsorshipRequestDto[];\n }>;\n}\n\nexport class SponsorshipRequestsReadService implements Service {\n private readonly client: SponsorsApiClient;\n\n constructor() {\n const baseUrl = getWebsiteApiBaseUrl();\n const logger = new ConsoleLogger();\n const errorReporter = new EnhancedErrorReporter(logger, {\n showUserNotifications: true,\n logToConsole: true,\n reportToExternal: isProductionEnvironment(),\n });\n\n this.client = new SponsorsApiClient(baseUrl, errorReporter, logger);\n }\n\n async getPendingRequestsForDriver(\n driverId: string,\n ): Promise> {\n try {\n const response = await this.client.getPendingSponsorshipRequests({\n entityType: 'driver',\n entityId: driverId,\n });\n\n const requests = (response.requests ?? []).map((r) => {\n const raw = r as unknown as {\n id?: string;\n requestId?: string;\n sponsorId?: string;\n sponsorName?: string;\n message?: unknown;\n createdAt?: string;\n createdAtIso?: string;\n };\n\n return {\n requestId: String(raw.id ?? raw.requestId ?? ''),\n sponsorId: String(raw.sponsorId ?? ''),\n sponsorName: String(raw.sponsorName ?? 'Sponsor'),\n message: typeof raw.message === 'string' ? raw.message : null,\n createdAtIso: String(raw.createdAt ?? raw.createdAtIso ?? ''),\n };\n });\n\n return Result.ok({\n sections: [\n {\n entityType: 'driver',\n entityId: driverId,\n entityName: 'Your Profile',\n requests,\n },\n ],\n });\n } catch (error: any) {\n const errorAny = error as { statusCode?: number; message?: string };\n if (errorAny.statusCode === 401) return Result.err({ type: 'unauthorized', message: 'Unauthorized' });\n if (errorAny.statusCode === 404) return Result.err({ type: 'notFound', message: 'Not found' });\n return Result.err({ type: 'serverError', message: error.message || 'Server error' });\n }\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/sponsors/SponsorshipRequestsService.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/teams/TeamJoinService.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":36,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":36,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1536,1539],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1536,1539],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { TeamsApiClient } from '@/lib/api/teams/TeamsApiClient';\nimport { TeamJoinRequestViewModel } from '@/lib/view-models/TeamJoinRequestViewModel';\nimport { Result } from '@/lib/contracts/Result';\nimport { DomainError, Service } from '@/lib/contracts/services/Service';\nimport { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';\nimport { EnhancedErrorReporter } from '@/lib/infrastructure/EnhancedErrorReporter';\nimport { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl';\nimport { isProductionEnvironment } from '@/lib/config/env';\n\n/**\n * Team Join Service - ViewModels\n *\n * Returns ViewModels for team join requests.\n * Handles presentation logic for join request management.\n */\nexport class TeamJoinService implements Service {\n private apiClient: TeamsApiClient;\n\n constructor() {\n const baseUrl = getWebsiteApiBaseUrl();\n const logger = new ConsoleLogger();\n const errorReporter = new EnhancedErrorReporter(logger, {\n showUserNotifications: true,\n logToConsole: true,\n reportToExternal: isProductionEnvironment(),\n });\n this.apiClient = new TeamsApiClient(baseUrl, errorReporter, logger);\n }\n\n async getJoinRequests(teamId: string, currentDriverId: string, isOwner: boolean): Promise> {\n try {\n const result = await this.apiClient.getJoinRequests(teamId);\n return Result.ok(result.requests.map(request => \n new TeamJoinRequestViewModel(request, currentDriverId, isOwner)\n ));\n } catch (error: any) {\n return Result.err({ type: 'serverError', message: error.message || 'Failed to fetch join requests' });\n }\n }\n\n async approveJoinRequest(): Promise> {\n return Result.err({ type: 'notImplemented', message: 'Not implemented: API endpoint for approving join requests' });\n }\n\n async rejectJoinRequest(): Promise> {\n return Result.err({ type: 'notImplemented', message: 'Not implemented: API endpoint for rejecting join requests' });\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/services/teams/TeamService.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":35,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":35,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1431,1434],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1431,1434],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_currentDriverId' is defined but never used.","line":40,"column":41,"nodeType":"Identifier","messageId":"unusedVar","endLine":40,"endColumn":65},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":40,"column":83,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":40,"endColumn":86,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1628,1631],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1628,1631],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":47,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":47,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1879,1882],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1879,1882],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":56,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":56,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2342,2345],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2342,2345],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_teamId' is defined but never used.","line":61,"column":29,"nodeType":"Identifier","messageId":"unusedVar","endLine":61,"endColumn":44},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":61,"column":62,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":61,"endColumn":65,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2525,2528],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2525,2528],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_input' is defined but never used.","line":65,"column":20,"nodeType":"Identifier","messageId":"unusedVar","endLine":65,"endColumn":31},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":65,"column":28,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":65,"endColumn":31,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2661,2664],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2661,2664],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":65,"column":49,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":65,"endColumn":52,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2682,2685],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2682,2685],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_teamId' is defined but never used.","line":69,"column":20,"nodeType":"Identifier","messageId":"unusedVar","endLine":69,"endColumn":35},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_input' is defined but never used.","line":69,"column":37,"nodeType":"Identifier","messageId":"unusedVar","endLine":69,"endColumn":48},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":69,"column":45,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":69,"endColumn":48,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2826,2829],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2826,2829],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":69,"column":66,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":69,"endColumn":69,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2847,2850],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2847,2850],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_driverId' is defined but never used.","line":73,"column":23,"nodeType":"Identifier","messageId":"unusedVar","endLine":73,"endColumn":40},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":73,"column":58,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":73,"endColumn":61,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3004,3007],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3004,3007],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_teamId' is defined but never used.","line":77,"column":23,"nodeType":"Identifier","messageId":"unusedVar","endLine":77,"endColumn":38},{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'_driverId' is defined but never used.","line":77,"column":40,"nodeType":"Identifier","messageId":"unusedVar","endLine":77,"endColumn":57},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":77,"column":75,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":77,"endColumn":78,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3181,3184],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3181,3184],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":19,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { TeamsApiClient } from '@/lib/api/teams/TeamsApiClient';\nimport type { TeamListItemDTO } from '@/lib/types/generated/TeamListItemDTO';\nimport { TeamMemberViewModel } from '@/lib/view-models/TeamMemberViewModel';\nimport { Result } from '@/lib/contracts/Result';\nimport { DomainError, Service } from '@/lib/contracts/services/Service';\nimport { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';\nimport { EnhancedErrorReporter } from '@/lib/infrastructure/EnhancedErrorReporter';\nimport { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl';\nimport { isProductionEnvironment } from '@/lib/config/env';\n\n/**\n * Team Service - DTO Only\n *\n * Returns raw API DTOs. No ViewModels or UX logic.\n * All client-side presentation logic must be handled by hooks/components.\n */\nexport class TeamService implements Service {\n private apiClient: TeamsApiClient;\n\n constructor() {\n const baseUrl = getWebsiteApiBaseUrl();\n const logger = new ConsoleLogger();\n const errorReporter = new EnhancedErrorReporter(logger, {\n showUserNotifications: true,\n logToConsole: true,\n reportToExternal: isProductionEnvironment(),\n });\n this.apiClient = new TeamsApiClient(baseUrl, errorReporter, logger);\n }\n\n async getAllTeams(): Promise> {\n try {\n const result = await this.apiClient.getAll();\n return Result.ok(result.teams);\n } catch (error: any) {\n return Result.err({ type: 'unknown', message: error.message || 'Failed to fetch teams' });\n }\n }\n\n async getTeamDetails(_teamId: string, _currentDriverId: string): Promise> {\n try {\n const result = await this.apiClient.getDetails(_teamId);\n if (!result) {\n return Result.err({ type: 'notFound', message: 'Team not found' });\n }\n return Result.ok(result);\n } catch (error: any) {\n return Result.err({ type: 'unknown', message: error.message || 'Failed to fetch team details' });\n }\n }\n\n async getTeamMembers(teamId: string, currentDriverId: string, ownerId: string): Promise> {\n try {\n const result = await this.apiClient.getMembers(teamId);\n return Result.ok(result.members.map(member => new TeamMemberViewModel(member, currentDriverId, ownerId)));\n } catch (error: any) {\n return Result.err({ type: 'unknown', message: error.message || 'Failed to fetch team members' });\n }\n }\n\n async getTeamJoinRequests(_teamId: string): Promise> {\n return Result.err({ type: 'notImplemented', message: 'getTeamJoinRequests' });\n }\n\n async createTeam(_input: any): Promise> {\n return Result.err({ type: 'notImplemented', message: 'createTeam' });\n }\n\n async updateTeam(_teamId: string, _input: any): Promise> {\n return Result.err({ type: 'notImplemented', message: 'updateTeam' });\n }\n\n async getDriverTeam(_driverId: string): Promise> {\n return Result.err({ type: 'notImplemented', message: 'getDriverTeam' });\n }\n\n async getMembership(_teamId: string, _driverId: string): Promise> {\n return Result.err({ type: 'notImplemented', message: 'getMembership' });\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/siteConfig.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/AllLeaguesWithCapacityAndScoringDTO.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/LeaderboardsData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/League.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/LeagueConfigFormModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/LeagueMembership.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/MediaBinaryDTO.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/MembershipRole.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/PenaltyTypesReferenceDTO.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/Weekday.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/WizardErrors.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/admin.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/tbd/AdminUserDto.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/tbd/AvailableLeaguesDTO.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/tbd/FilteredRacesPageDataDTO.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/tbd/GetLiveriesOutputDTO.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/tbd/LeagueDetailForSponsorDTO.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/tbd/LeagueScheduleApiDto.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/tbd/LeagueSettingsApiDto.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/tbd/LeagueSponsorshipsApiDto.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/tbd/LeagueStandingsApiDto.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/tbd/LeagueWalletApiDto.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/tbd/ProtestDetailApiDto.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/tbd/RulebookApiDto.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/tbd/SponsorBillingDTO.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/tbd/SponsorSettingsDTO.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/tbd/StewardingApiDto.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/tbd/TeamsLeaderboardDto.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/view-data/DriverProfileViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/types/view-data/DriversViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/utilities/LeagueMembershipUtility.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":11,"column":28,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":11,"endColumn":31,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[539,542],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[539,542],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":22,"column":83,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":22,"endColumn":86,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[880,883],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[880,883],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { LeagueSettingsService } from '@/lib/services/leagues/LeagueSettingsService';\nimport { LeagueRoleUtility } from '@/lib/utilities/LeagueRoleUtility';\n\nexport class LeagueMembershipUtility {\n /**\n * Derive a driver's primary league from cached memberships.\n * Prefers any active membership and returns the first matching league.\n */\n static getPrimaryLeagueIdForDriver(driverId: string): string | null {\n for (const [leagueId, members] of LeagueSettingsService.getCachedMembershipsIterator()) {\n if (members.some((m: any) => m.driverId === driverId && m.status === 'active')) {\n return leagueId;\n }\n }\n return null;\n }\n\n /**\n * Check if a driver is owner or admin of a league.\n */\n static isOwnerOrAdmin(leagueId: string, driverId: string): boolean {\n const membership = LeagueSettingsService.getMembership(leagueId, driverId) as any;\n if (!membership) return false;\n return LeagueRoleUtility.isLeagueAdminOrHigherRole(membership.role);\n }\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/utilities/LeagueRoleUtility.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/utilities/ScoringPresetApplier.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/utilities/authValidation.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/utilities/media.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/utilities/raceStatus.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":4,"column":9,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":4,"endColumn":12,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[122,125],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[122,125],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { Clock, PlayCircle, CheckCircle2, XCircle } from 'lucide-react';\n\nexport interface RaceStatusConfigData {\n icon: any;\n color: string;\n bg: string;\n border: string;\n label: string;\n}\n\nexport const raceStatusConfig: Record = {\n scheduled: {\n icon: Clock,\n color: 'text-primary-blue',\n bg: 'bg-primary-blue/10',\n border: 'border-primary-blue/30',\n label: 'Scheduled',\n },\n running: {\n icon: PlayCircle,\n color: 'text-performance-green',\n bg: 'bg-performance-green/10',\n border: 'border-performance-green/30',\n label: 'LIVE',\n },\n completed: {\n icon: CheckCircle2,\n color: 'text-gray-400',\n bg: 'bg-gray-500/10',\n border: 'border-gray-500/30',\n label: 'Completed',\n },\n cancelled: {\n icon: XCircle,\n color: 'text-warning-amber',\n bg: 'bg-warning-amber/10',\n border: 'border-warning-amber/30',\n label: 'Cancelled',\n },\n} as const;","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/utilities/roster-utils.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/utils.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/utils/errorUtils.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":56,"column":64,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":56,"endColumn":67,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1614,1617],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1614,1617],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":64,"column":63,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":64,"endColumn":66,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2035,2038],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2035,2038],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Enhanced Error Utilities for GridPilot\n * \n * Provides comprehensive error handling, validation, and user-friendly error messages\n * for both end users and developers.\n */\n\nimport { ApiError } from '@/lib/api/base/ApiError';\n\nexport interface ValidationError {\n field: string;\n message: string;\n value?: unknown;\n}\n\nexport interface EnhancedErrorContext {\n timestamp?: string;\n component?: string;\n action?: string;\n formData?: Record;\n userId?: string;\n sessionId?: string;\n}\n\n/**\n * Parse API error response to extract validation errors or user-friendly messages\n */\nexport function parseApiError(error: unknown): {\n userMessage: string;\n developerMessage: string;\n validationErrors: ValidationError[];\n isValidationError: boolean;\n} {\n const result = {\n userMessage: 'An unexpected error occurred',\n developerMessage: '',\n validationErrors: [] as ValidationError[],\n isValidationError: false,\n };\n\n if (error instanceof ApiError) {\n result.developerMessage = error.getDeveloperMessage();\n \n // Check if it's a validation error\n if (error.type === 'VALIDATION_ERROR') {\n result.isValidationError = true;\n result.userMessage = 'Please check your input and try again';\n \n // Try to parse validation details from response\n try {\n if (error.context.responseText) {\n const parsed = JSON.parse(error.context.responseText);\n \n // Handle NestJS validation error format\n if (parsed.message && Array.isArray(parsed.message)) {\n result.validationErrors = parsed.message.map((msg: any) => ({\n field: msg.property || msg.field || 'unknown',\n message: msg.constraints ? Object.values(msg.constraints).join(', ') : msg.message || 'Invalid value',\n value: msg.value,\n }));\n } \n // Handle custom error format\n else if (parsed.errors && Array.isArray(parsed.errors)) {\n result.validationErrors = parsed.errors.map((err: any) => ({\n field: err.field || err.property || 'unknown',\n message: err.message || 'Invalid value',\n value: err.value,\n }));\n }\n // Handle single message\n else if (parsed.message && typeof parsed.message === 'string') {\n result.userMessage = parsed.message;\n }\n }\n } catch (e) {\n // If parsing fails, use default messages\n }\n } else {\n result.userMessage = error.getUserMessage();\n }\n } else if (error instanceof Error) {\n result.userMessage = error.message;\n result.developerMessage = error.message;\n } else {\n result.userMessage = 'An unknown error occurred';\n result.developerMessage = String(error);\n }\n\n return result;\n}\n\n/**\n * Format validation errors for display in forms\n */\nexport function formatValidationErrorsForForm(\n validationErrors: ValidationError[]\n): Record {\n const formErrors: Record = {};\n \n validationErrors.forEach((error) => {\n // Map API field names to form field names\n const fieldName = mapApiFieldToFormField(error.field);\n formErrors[fieldName] = error.message;\n });\n \n return formErrors;\n}\n\n/**\n * Map API field names to form field names\n */\nfunction mapApiFieldToFormField(apiField: string): string {\n const fieldMap: Record = {\n 'rememberMe': 'rememberMe',\n 'email': 'email',\n 'password': 'password',\n 'displayName': 'displayName',\n 'firstName': 'firstName',\n 'lastName': 'lastName',\n 'confirmPassword': 'confirmPassword',\n 'role': 'role',\n };\n \n return fieldMap[apiField] || apiField;\n}\n\n/**\n * Create enhanced error context for debugging\n */\nexport function createErrorContext(\n error: unknown,\n context: EnhancedErrorContext\n): EnhancedErrorContext {\n return {\n timestamp: new Date().toISOString(),\n ...context,\n };\n}\n\n/**\n * Check if error is retryable\n */\nexport function isRetryable(error: unknown): boolean {\n if (error instanceof ApiError) {\n return error.isRetryable();\n }\n return false;\n}\n\n/**\n * Check if error is a network connectivity issue\n */\nexport function isConnectivityError(error: unknown): boolean {\n if (error instanceof ApiError) {\n return error.isConnectivityIssue();\n }\n return false;\n}\n\n/**\n * Get error severity for logging and display\n */\nexport function getErrorSeverity(error: unknown): 'error' | 'warning' | 'info' {\n if (error instanceof ApiError) {\n const severity = error.getSeverity();\n if (severity === 'error') return 'error';\n if (severity === 'warn') return 'warning';\n return 'info';\n }\n return 'error';\n}\n\n/**\n * Create user-friendly error summary\n */\nexport function createUserErrorSummary(error: unknown): {\n title: string;\n description: string;\n action: string;\n} {\n const parsed = parseApiError(error);\n \n if (parsed.isValidationError) {\n return {\n title: 'Invalid Input',\n description: parsed.userMessage,\n action: 'Please review your input and try again',\n };\n }\n \n if (isConnectivityError(error)) {\n return {\n title: 'Connection Issue',\n description: 'Unable to connect to the server',\n action: 'Check your internet connection and try again',\n };\n }\n \n if (isRetryable(error)) {\n return {\n title: 'Temporary Issue',\n description: parsed.userMessage,\n action: 'Please try again in a moment',\n };\n }\n \n return {\n title: 'Error',\n description: parsed.userMessage,\n action: 'Please try again or contact support if the issue persists',\n };\n}\n\n/**\n * Log error with context (only in development)\n */\nexport function logErrorWithContext(\n error: unknown,\n context: EnhancedErrorContext\n): void {\n if (process.env.NODE_ENV !== 'development') return;\n \n const parsed = parseApiError(error);\n const severity = getErrorSeverity(error);\n \n console.group(`🚨 [${severity.toUpperCase()}] ${context.component || 'Unknown'} - ${context.action || 'Unknown action'}`);\n console.error('User Message:', parsed.userMessage);\n console.error('Developer Message:', parsed.developerMessage);\n if (parsed.validationErrors.length > 0) {\n console.error('Validation Errors:', parsed.validationErrors);\n }\n if (context.formData) {\n console.error('Form Data:', context.formData);\n }\n console.error('Context:', context);\n console.error('Original Error:', error);\n console.groupEnd();\n}\n\n/**\n * Delay execution for retry logic\n */\nexport async function delay(ms: number): Promise {\n await new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * Retry operation with exponential backoff\n */\nexport async function retryWithBackoff(\n operation: () => Promise,\n maxRetries: number = 3,\n baseDelay: number = 1000\n): Promise {\n let lastError: unknown;\n \n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await operation();\n } catch (error) {\n lastError = error;\n \n if (attempt === maxRetries || !isRetryable(error)) {\n throw error;\n }\n \n // Exponential backoff: 1s, 2s, 4s\n const delayMs = baseDelay * Math.pow(2, attempt);\n await delay(delayMs);\n }\n }\n \n throw lastError;\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/utils/validation.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/AdminDashboardViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/AdminUsersViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/AvatarViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/CategoryIconViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/DashboardViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/DriverRankingItem.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/DriverRankingsViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/LeaderboardDriverItem.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/LeaderboardTeamItem.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/LeaderboardsViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/LeagueAdminScheduleViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/LeagueCoverViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/LeagueDetailViewData.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":49,"column":9,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":49,"endColumn":12,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[994,997],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[994,997],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * LeagueDetailViewData - Pure ViewData for LeagueDetailTemplate\n * Contains only raw serializable data, no methods or computed properties\n */\n\nexport interface LeagueInfoData {\n name: string;\n description?: string;\n membersCount: number;\n racesCount: number;\n avgSOF: number | null;\n structure: string;\n scoring: string;\n createdAt: string;\n discordUrl?: string;\n youtubeUrl?: string;\n websiteUrl?: string;\n}\n\nexport interface SponsorInfo {\n id: string;\n name: string;\n tier: 'main' | 'secondary';\n logoUrl?: string;\n websiteUrl?: string;\n tagline?: string;\n}\n\nexport interface LiveRaceData {\n id: string;\n name: string;\n date: string;\n registeredCount?: number;\n strengthOfField?: number;\n}\n\nexport interface DriverSummaryData {\n driverId: string;\n driverName: string;\n avatarUrl: string | null;\n rating: number | null;\n rank: number | null;\n roleBadgeText: string;\n roleBadgeClasses: string;\n profileUrl: string;\n}\n\nexport interface SponsorMetric {\n icon: any; // React component (lucide-react icon)\n label: string;\n value: string | number;\n color?: string;\n trend?: {\n value: number;\n isPositive: boolean;\n };\n}\n\nexport interface SponsorshipSlot {\n tier: 'main' | 'secondary';\n available: boolean;\n price: number;\n benefits: string[];\n}\n\nexport interface LeagueDetailViewData {\n // Basic info\n leagueId: string;\n name: string;\n description: string;\n \n // Info card data\n info: LeagueInfoData;\n \n // Live races\n runningRaces: LiveRaceData[];\n \n // Sponsors\n sponsors: SponsorInfo[];\n \n // Management\n ownerSummary: DriverSummaryData | null;\n adminSummaries: DriverSummaryData[];\n stewardSummaries: DriverSummaryData[];\n \n // Sponsor insights (for sponsor mode)\n sponsorInsights: {\n avgViewsPerRace: number;\n engagementRate: string;\n estimatedReach: number;\n tier: 'premium' | 'standard' | 'starter';\n trustScore: number;\n discordMembers: number;\n monthlyActivity: number;\n mainSponsorAvailable: boolean;\n secondarySlotsAvailable: number;\n mainSponsorPrice: number;\n secondaryPrice: number;\n totalImpressions: number;\n metrics: SponsorMetric[];\n slots: SponsorshipSlot[];\n } | null;\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/LeagueLogoViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/LeagueRosterAdminViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/LeagueRulebookViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/LeagueScheduleViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/LeagueStandingsViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/LeaguesViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/OnboardingPageViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/PodiumDriver.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/ProfileLeaguesViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/ProfileViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/RacesViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/SponsorDashboardViewData.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":21,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":21,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[682,685],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[682,685],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":22,"column":19,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":22,"endColumn":22,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[707,710],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[707,710],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"export interface SponsorDashboardViewData {\n sponsorName: string;\n totalImpressions: string;\n totalInvestment: string;\n metrics: {\n impressionsChange: number;\n viewersChange: number;\n exposureChange: number;\n };\n categoryData: {\n leagues: { count: number; impressions: number };\n teams: { count: number; impressions: number };\n drivers: { count: number; impressions: number };\n races: { count: number; impressions: number };\n platform: { count: number; impressions: number };\n };\n sponsorships: Record; // From DTO\n activeSponsorships: number;\n formattedTotalInvestment: string;\n costPerThousandViews: string;\n upcomingRenewals: any[];\n recentActivity: any[];\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/SponsorLogoViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/SponsorshipRequestsViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/TeamDetailViewData.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":7,"column":9,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":7,"endColumn":12,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[185,188],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[185,188],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * TeamDetailViewData - Pure ViewData for TeamDetailTemplate\n * Contains only raw serializable data, no methods or computed properties\n */\n\nexport interface SponsorMetric {\n icon: any; // React component (lucide-react icon)\n label: string;\n value: string | number;\n color?: string;\n trend?: {\n value: number;\n isPositive: boolean;\n };\n}\n\nexport interface TeamDetailData {\n id: string;\n name: string;\n tag: string;\n description?: string;\n ownerId: string;\n leagues: string[];\n createdAt?: string;\n specialization?: string;\n region?: string;\n languages?: string[];\n category?: string;\n membership?: {\n role: string;\n joinedAt: string;\n isActive: boolean;\n } | null;\n canManage: boolean;\n}\n\nexport interface TeamMemberData {\n driverId: string;\n driverName: string;\n role: 'owner' | 'manager' | 'member';\n joinedAt: string;\n isActive: boolean;\n avatarUrl: string;\n}\n\nexport interface TeamTab {\n id: 'overview' | 'roster' | 'standings' | 'admin';\n label: string;\n visible: boolean;\n}\n\nexport interface TeamDetailViewData {\n team: TeamDetailData;\n memberships: TeamMemberData[];\n currentDriverId: string;\n isAdmin: boolean;\n teamMetrics: SponsorMetric[];\n tabs: TeamTab[];\n}\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/TeamLeaderboardViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/TeamLogoViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/TeamsViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/TrackImageViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/leagues/LeagueScheduleViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/leagues/LeagueSettingsViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/leagues/LeagueSponsorshipsViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/leagues/LeagueWalletViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/leagues/ProtestDetailViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/leagues/RulebookViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/leagues/StewardingViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/races/RaceDetailViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/races/RaceResultsViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/races/RaceStewardingViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/races/RacesAllViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-data/races/RacesViewData.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/ActivityItemViewModel.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":13,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":13,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[271,274],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[271,274],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Activity Item View Model\n *\n * View model for recent activity items.\n */\nexport class ActivityItemViewModel {\n id: string;\n type: 'race' | 'league' | 'team' | 'driver' | 'platform';\n message: string;\n time: string;\n impressions?: number;\n\n constructor(data: any) {\n this.id = data.id;\n this.type = data.type;\n this.message = data.message;\n this.time = data.time;\n this.impressions = data.impressions;\n }\n\n get typeColor(): string {\n const colors = {\n race: 'bg-warning-amber',\n league: 'bg-primary-blue',\n team: 'bg-purple-400',\n driver: 'bg-performance-green',\n platform: 'bg-racing-red',\n };\n return colors[this.type] || 'bg-gray-500';\n }\n\n get formattedImpressions(): string | null {\n return this.impressions ? this.impressions.toLocaleString() : null;\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/AdminUserViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/AnalyticsDashboardViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/AnalyticsMetricsViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/AvailableLeaguesViewModel.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":9,"column":24,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":9,"endColumn":27,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[200,203],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[200,203],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":28,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":28,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[737,740],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[737,740],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Available Leagues View Model\n *\n * View model for leagues available for sponsorship.\n */\nexport class AvailableLeaguesViewModel {\n leagues: AvailableLeagueViewModel[];\n\n constructor(leagues: any[]) {\n this.leagues = leagues.map(league => new AvailableLeagueViewModel(league));\n }\n}\n\nexport class AvailableLeagueViewModel {\n id: string;\n name: string;\n game: string;\n drivers: number;\n avgViewsPerRace: number;\n mainSponsorSlot: { available: boolean; price: number };\n secondarySlots: { available: number; total: number; price: number };\n rating: number;\n tier: 'premium' | 'standard' | 'starter';\n nextRace?: string;\n seasonStatus: 'active' | 'upcoming' | 'completed';\n description: string;\n\n constructor(data: any) {\n this.id = data.id;\n this.name = data.name;\n this.game = data.game;\n this.drivers = data.drivers;\n this.avgViewsPerRace = data.avgViewsPerRace;\n this.mainSponsorSlot = data.mainSponsorSlot;\n this.secondarySlots = data.secondarySlots;\n this.rating = data.rating;\n this.tier = data.tier;\n this.nextRace = data.nextRace;\n this.seasonStatus = data.seasonStatus;\n this.description = data.description;\n }\n\n get formattedAvgViews(): string {\n return `${(this.avgViewsPerRace / 1000).toFixed(1)}k`;\n }\n\n get cpm(): number {\n return Math.round((this.mainSponsorSlot.price / this.avgViewsPerRace) * 1000);\n }\n\n get formattedCpm(): string {\n return `$${this.cpm}`;\n }\n\n get hasAvailableSlots(): boolean {\n return this.mainSponsorSlot.available || this.secondarySlots.available > 0;\n }\n\n get tierConfig() {\n const configs = {\n premium: { color: 'text-yellow-400', bgColor: 'bg-yellow-500/10', border: 'border-yellow-500/30', icon: '⭐' },\n standard: { color: 'text-primary-blue', bgColor: 'bg-primary-blue/10', border: 'border-primary-blue/30', icon: '🏆' },\n starter: { color: 'text-gray-400', bgColor: 'bg-gray-500/10', border: 'border-gray-500/30', icon: '🚀' },\n };\n return configs[this.tier];\n }\n\n get statusConfig() {\n const configs = {\n active: { color: 'text-performance-green', bg: 'bg-performance-green/10', label: 'Active Season' },\n upcoming: { color: 'text-warning-amber', bg: 'bg-warning-amber/10', label: 'Starting Soon' },\n completed: { color: 'text-gray-400', bg: 'bg-gray-400/10', label: 'Season Ended' },\n };\n return configs[this.seasonStatus];\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/AvatarGenerationViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/AvatarViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/BillingViewModel.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":12,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":12,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[289,292],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[289,292],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":13,"column":15,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":13,"endColumn":18,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[310,313],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[310,313],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":14,"column":12,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":14,"endColumn":15,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[328,331],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[328,331],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":32,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":32,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[797,800],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[797,800],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":71,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":71,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1805,1808],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1805,1808],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":110,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":110,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2982,2985],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2982,2985],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":6,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Billing View Model\n *\n * View model for sponsor billing data with UI-specific transformations.\n */\nexport class BillingViewModel {\n paymentMethods: PaymentMethodViewModel[];\n invoices: InvoiceViewModel[];\n stats: BillingStatsViewModel;\n\n constructor(data: {\n paymentMethods: any[];\n invoices: any[];\n stats: any;\n }) {\n this.paymentMethods = data.paymentMethods.map(pm => new PaymentMethodViewModel(pm));\n this.invoices = data.invoices.map(inv => new InvoiceViewModel(inv));\n this.stats = new BillingStatsViewModel(data.stats);\n }\n}\n\nexport class PaymentMethodViewModel {\n id: string;\n type: 'card' | 'bank' | 'sepa';\n last4: string;\n brand?: string;\n isDefault: boolean;\n expiryMonth?: number;\n expiryYear?: number;\n bankName?: string;\n\n constructor(data: any) {\n this.id = data.id;\n this.type = data.type;\n this.last4 = data.last4;\n this.brand = data.brand;\n this.isDefault = data.isDefault;\n this.expiryMonth = data.expiryMonth;\n this.expiryYear = data.expiryYear;\n this.bankName = data.bankName;\n }\n\n get displayLabel(): string {\n if (this.type === 'sepa' && this.bankName) {\n return `${this.bankName} •••• ${this.last4}`;\n }\n return `${this.brand} •••• ${this.last4}`;\n }\n\n get expiryDisplay(): string | null {\n if (this.expiryMonth && this.expiryYear) {\n return `${String(this.expiryMonth).padStart(2, '0')}/${this.expiryYear}`;\n }\n return null;\n }\n}\n\nexport class InvoiceViewModel {\n id: string;\n invoiceNumber: string;\n date: Date;\n dueDate: Date;\n amount: number;\n vatAmount: number;\n totalAmount: number;\n status: 'paid' | 'pending' | 'overdue' | 'failed';\n description: string;\n sponsorshipType: 'league' | 'team' | 'driver' | 'race' | 'platform';\n pdfUrl: string;\n\n constructor(data: any) {\n this.id = data.id;\n this.invoiceNumber = data.invoiceNumber;\n this.date = new Date(data.date);\n this.dueDate = new Date(data.dueDate);\n this.amount = data.amount;\n this.vatAmount = data.vatAmount;\n this.totalAmount = data.totalAmount;\n this.status = data.status;\n this.description = data.description;\n this.sponsorshipType = data.sponsorshipType;\n this.pdfUrl = data.pdfUrl;\n }\n\n get formattedTotalAmount(): string {\n return `€${this.totalAmount.toLocaleString('de-DE', { minimumFractionDigits: 2 })}`;\n }\n\n get formattedVatAmount(): string {\n return `€${this.vatAmount.toLocaleString('de-DE', { minimumFractionDigits: 2 })}`;\n }\n\n get formattedDate(): string {\n return this.date.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });\n }\n\n get isOverdue(): boolean {\n return this.status === 'overdue' || (this.status === 'pending' && new Date() > this.dueDate);\n }\n}\n\nexport class BillingStatsViewModel {\n totalSpent: number;\n pendingAmount: number;\n nextPaymentDate: Date;\n nextPaymentAmount: number;\n activeSponsorships: number;\n averageMonthlySpend: number;\n\n constructor(data: any) {\n this.totalSpent = data.totalSpent;\n this.pendingAmount = data.pendingAmount;\n this.nextPaymentDate = new Date(data.nextPaymentDate);\n this.nextPaymentAmount = data.nextPaymentAmount;\n this.activeSponsorships = data.activeSponsorships;\n this.averageMonthlySpend = data.averageMonthlySpend;\n }\n\n get formattedTotalSpent(): string {\n return `€${this.totalSpent.toLocaleString('de-DE')}`;\n }\n\n get formattedPendingAmount(): string {\n return `€${this.pendingAmount.toLocaleString('de-DE', { minimumFractionDigits: 2 })}`;\n }\n\n get formattedNextPaymentAmount(): string {\n return `€${this.nextPaymentAmount.toLocaleString('de-DE', { minimumFractionDigits: 2 })}`;\n }\n\n get formattedAverageMonthlySpend(): string {\n return `€${this.averageMonthlySpend.toLocaleString('de-DE')}`;\n }\n\n get formattedNextPaymentDate(): string {\n return this.nextPaymentDate.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/CompleteOnboardingViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/CreateLeagueViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/CreateTeamViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/DeleteMediaViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/DriverLeaderboardItemViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/DriverLeaderboardViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/DriverProfileDriverSummaryViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/DriverProfileViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/DriverRegistrationStatusViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/DriverSummaryViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/DriverTeamViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/DriverViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/EmailSignupViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/HomeDiscoveryViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/ImportRaceResultsSummaryViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/LeagueAdminRosterJoinRequestViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/LeagueAdminRosterMemberViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/LeagueAdminScheduleViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/LeagueAdminViewModel.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":9,"column":11,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":9,"endColumn":14,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[282,285],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[282,285],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":14,"column":13,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":14,"endColumn":16,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[403,406],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[403,406],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import type { LeagueMemberViewModel } from './LeagueMemberViewModel';\nimport type { LeagueJoinRequestViewModel } from './LeagueJoinRequestViewModel';\n\n/**\n * League admin view model\n * Transform from DTO to ViewModel with UI fields\n */\nexport class LeagueAdminViewModel {\n config: any;\n members: LeagueMemberViewModel[];\n joinRequests: LeagueJoinRequestViewModel[];\n\n constructor(dto: {\n config: any;\n members: LeagueMemberViewModel[];\n joinRequests: LeagueJoinRequestViewModel[];\n }) {\n this.config = dto.config;\n this.members = dto.members;\n this.joinRequests = dto.joinRequests;\n }\n\n /** UI-specific: Total pending requests count */\n get pendingRequestsCount(): number {\n return this.joinRequests.length;\n }\n\n /** UI-specific: Whether there are any pending requests */\n get hasPendingRequests(): boolean {\n return this.joinRequests.length > 0;\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/LeagueCardViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/LeagueDetailPageViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/LeagueDetailViewModel.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":11,"column":31,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":11,"endColumn":34,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[250,253],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[250,253],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":11,"column":45,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":11,"endColumn":48,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[264,267],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[264,267],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":11,"column":59,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":11,"endColumn":62,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[278,281],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[278,281],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":40,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":40,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1155,1158],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1155,1158],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":107,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":107,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3069,3072],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3069,3072],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":129,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":129,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[3535,3538],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[3535,3538],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":6,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * League Detail View Model\n *\n * View model for detailed league information for sponsors.\n */\nexport class LeagueDetailViewModel {\n league: LeagueViewModel;\n drivers: DriverViewModel[];\n races: RaceViewModel[];\n\n constructor(data: { league: any; drivers: any[]; races: any[] }) {\n this.league = new LeagueViewModel(data.league);\n this.drivers = data.drivers.map(driver => new DriverViewModel(driver));\n this.races = data.races.map(race => new RaceViewModel(race));\n }\n}\n\nexport class LeagueViewModel {\n id: string;\n name: string;\n game: string;\n tier: 'premium' | 'standard' | 'starter';\n season: string;\n description: string;\n drivers: number;\n races: number;\n completedRaces: number;\n totalImpressions: number;\n avgViewsPerRace: number;\n engagement: number;\n rating: number;\n seasonStatus: 'active' | 'upcoming' | 'completed';\n seasonDates: { start: string; end: string };\n nextRace?: { name: string; date: string };\n sponsorSlots: {\n main: { available: boolean; price: number; benefits: string[] };\n secondary: { available: number; total: number; price: number; benefits: string[] };\n };\n\n constructor(data: any) {\n this.id = data.id;\n this.name = data.name;\n this.game = data.game;\n this.tier = data.tier;\n this.season = data.season;\n this.description = data.description;\n this.drivers = data.drivers;\n this.races = data.races;\n this.completedRaces = data.completedRaces;\n this.totalImpressions = data.totalImpressions;\n this.avgViewsPerRace = data.avgViewsPerRace;\n this.engagement = data.engagement;\n this.rating = data.rating;\n this.seasonStatus = data.seasonStatus;\n this.seasonDates = data.seasonDates;\n this.nextRace = data.nextRace;\n this.sponsorSlots = data.sponsorSlots;\n }\n\n get formattedTotalImpressions(): string {\n return this.totalImpressions.toLocaleString();\n }\n\n get formattedAvgViewsPerRace(): string {\n return this.avgViewsPerRace.toLocaleString();\n }\n\n get projectedTotalViews(): number {\n return Math.round(this.avgViewsPerRace * this.races);\n }\n\n get formattedProjectedTotal(): string {\n return this.projectedTotalViews.toLocaleString();\n }\n\n get mainSponsorCpm(): number {\n return Math.round((this.sponsorSlots.main.price / this.projectedTotalViews) * 1000);\n }\n\n get formattedMainSponsorCpm(): string {\n return `$${this.mainSponsorCpm.toFixed(2)}`;\n }\n\n get racesLeft(): number {\n return this.races - this.completedRaces;\n }\n\n get tierConfig() {\n const configs = {\n premium: { color: 'text-yellow-400', bgColor: 'bg-yellow-500/10', border: 'border-yellow-500/30' },\n standard: { color: 'text-primary-blue', bgColor: 'bg-primary-blue/10', border: 'border-primary-blue/30' },\n starter: { color: 'text-gray-400', bgColor: 'bg-gray-500/10', border: 'border-gray-500/30' },\n };\n return configs[this.tier];\n }\n}\n\nexport class DriverViewModel {\n id: string;\n name: string;\n country: string;\n position: number;\n races: number;\n impressions: number;\n team: string;\n\n constructor(data: any) {\n this.id = data.id;\n this.name = data.name;\n this.country = data.country;\n this.position = data.position;\n this.races = data.races;\n this.impressions = data.impressions;\n this.team = data.team;\n }\n\n get formattedImpressions(): string {\n return this.impressions.toLocaleString();\n }\n}\n\nexport class RaceViewModel {\n id: string;\n name: string;\n date: Date;\n views: number;\n status: 'upcoming' | 'completed';\n\n constructor(data: any) {\n this.id = data.id;\n this.name = data.name;\n this.date = new Date(data.date);\n this.views = data.views;\n this.status = data.status;\n }\n\n get formattedDate(): string {\n return this.date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });\n }\n\n get formattedViews(): string {\n return this.views.toLocaleString();\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/LeagueJoinRequestViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/LeagueMemberViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/LeagueMembershipsViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/LeaguePageDetailViewModel.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":15,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":15,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[335,338],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[335,338],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * League Page Detail View Model\n *\n * View model for league page details.\n */\nexport class LeaguePageDetailViewModel {\n id: string;\n name: string;\n description: string;\n ownerId: string;\n ownerName: string;\n isAdmin: boolean;\n mainSponsor: { name: string; logoUrl: string; websiteUrl: string } | null;\n\n constructor(data: any) {\n this.id = data.id;\n this.name = data.name;\n this.description = data.description;\n this.ownerId = data.ownerId;\n this.ownerName = data.ownerName;\n this.isAdmin = data.isAdmin;\n this.mainSponsor = data.mainSponsor;\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/LeagueScheduleViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/LeagueScoringChampionshipViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/LeagueScoringConfigViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/LeagueScoringPresetViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/LeagueScoringPresetsViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/LeagueScoringSectionViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/LeagueSeasonSummaryViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/LeagueSettingsViewModel.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'LeagueScoringPresetsViewModel' is defined but never used.","line":3,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":3,"endColumn":39}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import type { LeagueConfigFormModel } from '@/lib/types/LeagueConfigFormModel';\nimport type { LeagueScoringPresetDTO } from '@/lib/types/generated/LeagueScoringPresetDTO';\nimport { LeagueScoringPresetsViewModel } from './LeagueScoringPresetsViewModel';\nimport { DriverSummaryViewModel } from './DriverSummaryViewModel';\n\n/**\n * View Model for league settings page\n * Combines league config, presets, owner, and members\n */\nexport class LeagueSettingsViewModel {\n league: {\n id: string;\n name: string;\n ownerId: string;\n };\n config: LeagueConfigFormModel;\n presets: LeagueScoringPresetDTO[];\n owner: DriverSummaryViewModel | null;\n members: DriverSummaryViewModel[];\n\n constructor(dto: {\n league: {\n id: string;\n name: string;\n ownerId: string;\n createdAt: string;\n };\n config: LeagueConfigFormModel;\n presets: LeagueScoringPresetDTO[];\n owner: DriverSummaryViewModel | null;\n members: DriverSummaryViewModel[];\n }) {\n this.league = dto.league;\n this.config = dto.config;\n this.presets = dto.presets;\n this.owner = dto.owner;\n this.members = dto.members;\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/LeagueStandingsViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/LeagueStatsViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/LeagueStewardingViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/LeagueSummaryViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/LeagueWalletViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/MediaViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/MembershipFeeViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/OnboardingViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/PaymentViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/PrizeViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/ProfileOverviewViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/ProtestDetailViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/ProtestDriverViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/ProtestViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/RaceDetailEntryViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/RaceDetailUserResultViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/RaceDetailsViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/RaceListItemViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/RaceResultViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/RaceResultsDetailViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/RaceStatsViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/RaceStewardingViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/RaceViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/RaceWithSOFViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/RacesPageViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/RecordEngagementInputViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/RecordEngagementOutputViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/RecordPageViewInputViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/RecordPageViewOutputViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/RemoveMemberViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/RenewalAlertViewModel.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":13,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":13,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[266,269],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[266,269],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Renewal Alert View Model\n *\n * View model for upcoming renewal alerts.\n */\nexport class RenewalAlertViewModel {\n id: string;\n name: string;\n type: 'league' | 'team' | 'driver' | 'race' | 'platform';\n renewDate: Date;\n price: number;\n\n constructor(data: any) {\n this.id = data.id;\n this.name = data.name;\n this.type = data.type;\n this.renewDate = new Date(data.renewDate);\n this.price = data.price;\n }\n\n get formattedPrice(): string {\n return `$${this.price}`;\n }\n\n get formattedRenewDate(): string {\n return this.renewDate.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });\n }\n\n get typeIcon() {\n const icons = {\n league: 'Trophy',\n team: 'Users',\n driver: 'Car',\n race: 'Flag',\n platform: 'Megaphone',\n };\n return icons[this.type] || 'Trophy';\n }\n\n get daysUntilRenewal(): number {\n const now = new Date();\n const diffTime = this.renewDate.getTime() - now.getTime();\n return Math.ceil(diffTime / (1000 * 60 * 60 * 24));\n }\n\n get isUrgent(): boolean {\n return this.daysUntilRenewal <= 30;\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/RequestAvatarGenerationViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/ScoringConfigurationViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/SessionViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/SponsorSettingsViewModel.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":11,"column":32,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":11,"endColumn":35,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[276,279],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[276,279],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":11,"column":52,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":11,"endColumn":55,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[296,299],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[296,299],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":11,"column":66,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":11,"endColumn":69,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[310,313],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[310,313],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":40,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":40,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[979,982],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[979,982],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":67,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":67,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1807,1810],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1807,1810],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":83,"column":21,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":83,"endColumn":24,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[2330,2333],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[2330,2333],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":6,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Sponsor Settings View Model\n *\n * View model for sponsor settings data.\n */\nexport class SponsorSettingsViewModel {\n profile: SponsorProfileViewModel;\n notifications: NotificationSettingsViewModel;\n privacy: PrivacySettingsViewModel;\n\n constructor(data: { profile: any; notifications: any; privacy: any }) {\n this.profile = new SponsorProfileViewModel(data.profile);\n this.notifications = new NotificationSettingsViewModel(data.notifications);\n this.privacy = new PrivacySettingsViewModel(data.privacy);\n }\n}\n\nexport class SponsorProfileViewModel {\n companyName: string;\n contactName: string;\n contactEmail: string;\n contactPhone: string;\n website: string;\n description: string;\n logoUrl: string | null;\n industry: string;\n address: {\n street: string;\n city: string;\n country: string;\n postalCode: string;\n };\n taxId: string;\n socialLinks: {\n twitter: string;\n linkedin: string;\n instagram: string;\n };\n\n constructor(data: any) {\n this.companyName = data.companyName;\n this.contactName = data.contactName;\n this.contactEmail = data.contactEmail;\n this.contactPhone = data.contactPhone;\n this.website = data.website;\n this.description = data.description;\n this.logoUrl = data.logoUrl;\n this.industry = data.industry;\n this.address = data.address;\n this.taxId = data.taxId;\n this.socialLinks = data.socialLinks;\n }\n\n get fullAddress(): string {\n return `${this.address.street}, ${this.address.city}, ${this.address.postalCode}, ${this.address.country}`;\n }\n}\n\nexport class NotificationSettingsViewModel {\n emailNewSponsorships: boolean;\n emailWeeklyReport: boolean;\n emailRaceAlerts: boolean;\n emailPaymentAlerts: boolean;\n emailNewOpportunities: boolean;\n emailContractExpiry: boolean;\n\n constructor(data: any) {\n this.emailNewSponsorships = data.emailNewSponsorships;\n this.emailWeeklyReport = data.emailWeeklyReport;\n this.emailRaceAlerts = data.emailRaceAlerts;\n this.emailPaymentAlerts = data.emailPaymentAlerts;\n this.emailNewOpportunities = data.emailNewOpportunities;\n this.emailContractExpiry = data.emailContractExpiry;\n }\n}\n\nexport class PrivacySettingsViewModel {\n publicProfile: boolean;\n showStats: boolean;\n showActiveSponsorships: boolean;\n allowDirectContact: boolean;\n\n constructor(data: any) {\n this.publicProfile = data.publicProfile;\n this.showStats = data.showStats;\n this.showActiveSponsorships = data.showActiveSponsorships;\n this.allowDirectContact = data.allowDirectContact;\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/SponsorSponsorshipsViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/SponsorViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/SponsorshipDetailViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/SponsorshipPricingViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/SponsorshipRequestViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/SponsorshipViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/StandingEntryViewModel.ts","messages":[{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":36,"column":12,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":36,"endColumn":15,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[1104,1107],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[1104,1107],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { LeagueStandingDTO } from '@/lib/types/generated/LeagueStandingDTO';\n\nexport class StandingEntryViewModel {\n driverId: string;\n position: number;\n points: number;\n wins: number;\n podiums: number;\n races: number;\n\n private leaderPoints: number;\n private nextPoints: number;\n private currentUserId: string;\n private previousPosition?: number;\n\n constructor(dto: LeagueStandingDTO, leaderPoints: number, nextPoints: number, currentUserId: string, previousPosition?: number) {\n this.driverId = dto.driverId;\n this.position = dto.position;\n this.points = dto.points;\n this.wins = dto.wins ?? 0;\n this.podiums = dto.podiums ?? 0;\n this.races = dto.races ?? 0;\n this.leaderPoints = leaderPoints;\n this.nextPoints = nextPoints;\n this.currentUserId = currentUserId;\n this.previousPosition = previousPosition;\n }\n\n /** UI-specific: Badge for position display */\n get positionBadge(): string {\n return this.position.toString();\n }\n\n // Note: The generated DTO is incomplete\n // These fields will need to be added when the OpenAPI spec is updated\n driver?: any;\n\n /** UI-specific: Points difference to leader */\n get pointsGapToLeader(): number {\n return this.points - this.leaderPoints;\n }\n\n /** UI-specific: Points difference to next position */\n get pointsGapToNext(): number {\n return this.points - this.nextPoints;\n }\n\n /** UI-specific: Whether this entry is the current user */\n get isCurrentUser(): boolean {\n return this.driverId === this.currentUserId;\n }\n\n /** UI-specific: Trend compared to previous */\n get trend(): 'up' | 'down' | 'same' {\n if (!this.previousPosition) return 'same';\n if (this.position < this.previousPosition) return 'up';\n if (this.position > this.previousPosition) return 'down';\n return 'same';\n }\n\n /** UI-specific: Arrow for trend */\n get trendArrow(): string {\n switch (this.trend) {\n case 'up': return '↑';\n case 'down': return '↓';\n default: return '-';\n }\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/TeamCardViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/TeamDetailsViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/TeamJoinRequestViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/TeamMemberViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/TeamSummaryViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/UpcomingRaceCardViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/UpdateAvatarViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/UpdateTeamViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/UploadMediaViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/UserProfileViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/WalletTransactionViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/WalletViewModel.ts","messages":[{"ruleId":"@typescript-eslint/no-unused-vars","severity":2,"message":"'FullTransactionDto' is defined but never used.","line":2,"column":10,"nodeType":"Identifier","messageId":"unusedVar","endLine":2,"endColumn":28},{"ruleId":"@typescript-eslint/no-explicit-any","severity":2,"message":"Unexpected any. Specify a different type.","line":14,"column":49,"nodeType":"TSAnyKeyword","messageId":"unexpectedAny","endLine":14,"endColumn":52,"suggestions":[{"messageId":"suggestUnknown","fix":{"range":[410,413],"text":"unknown"},"desc":"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct."},{"messageId":"suggestNever","fix":{"range":[410,413],"text":"never"},"desc":"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of."}]}],"suppressedMessages":[],"errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"import { WalletDTO } from '@/lib/types/generated/WalletDTO';\nimport { FullTransactionDto, WalletTransactionViewModel } from './WalletTransactionViewModel';\n\nexport class WalletViewModel {\n id: string;\n leagueId: string;\n balance: number;\n totalRevenue: number;\n totalPlatformFees: number;\n totalWithdrawn: number;\n createdAt: string;\n currency: string;\n\n constructor(dto: WalletDTO & { transactions?: any[] }) {\n this.id = dto.id;\n this.leagueId = dto.leagueId;\n this.balance = dto.balance;\n this.totalRevenue = dto.totalRevenue;\n this.totalPlatformFees = dto.totalPlatformFees;\n this.totalWithdrawn = dto.totalWithdrawn;\n this.createdAt = dto.createdAt;\n this.currency = dto.currency;\n\n // Map transactions if provided\n this.transactions = dto.transactions?.map(t => new WalletTransactionViewModel(t)) || [];\n }\n\n transactions: WalletTransactionViewModel[] = [];\n\n /** UI-specific: Formatted balance */\n get formattedBalance(): string {\n return `${this.currency} ${this.balance.toFixed(2)}`;\n }\n\n /** UI-specific: Balance color */\n get balanceColor(): string {\n return this.balance >= 0 ? 'green' : 'red';\n }\n\n /** UI-specific: Recent transactions (last 5) */\n get recentTransactions(): WalletTransactionViewModel[] {\n return this.transactions.slice(0, 5);\n }\n\n /** UI-specific: Total transactions count */\n get totalTransactions(): number {\n return this.transactions.length;\n }\n}","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/auth/ForgotPasswordViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/auth/LoginViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/auth/ResetPasswordViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/auth/SignupViewModel.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/lib/view-models/index.ts","messages":[{"ruleId":"gridpilot-rules/no-index-files","severity":2,"message":"Index files are banned. Use explicit imports and barrel exports. Example: Instead of \"import { foo } from \"./\", use \"import { foo } from \"./foo\" and export from \"./foo\" explicitly.","line":1,"column":1,"nodeType":null,"messageId":"indexFile"}],"suppressedMessages":[],"errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":"export * from './ActivityItemViewModel';\nexport * from './AnalyticsDashboardViewModel';\nexport * from './AnalyticsMetricsViewModel';\nexport * from './AvailableLeaguesViewModel';\nexport * from './AvatarGenerationViewModel';\nexport * from './AvatarViewModel';\nexport * from './BillingViewModel';\nexport * from './CompleteOnboardingViewModel';\nexport * from './CreateLeagueViewModel';\nexport * from './CreateTeamViewModel';\nexport * from './DeleteMediaViewModel';\nexport * from './DriverLeaderboardItemViewModel';\nexport * from './DriverLeaderboardViewModel';\nexport * from './DriverProfileViewModel';\nexport * from './DriverRegistrationStatusViewModel';\nexport * from './DriverSummaryViewModel';\nexport * from './DriverTeamViewModel';\nexport * from './DriverViewModel';\nexport * from './EmailSignupViewModel';\nexport * from './HomeDiscoveryViewModel';\nexport * from './ImportRaceResultsSummaryViewModel';\nexport * from './LeagueAdminViewModel';\nexport * from './LeagueCardViewModel';\nexport * from './LeagueDetailPageViewModel';\nexport { LeagueDetailViewModel, LeagueViewModel } from './LeagueDetailViewModel';\nexport * from './LeagueJoinRequestViewModel';\nexport * from './LeagueMembershipsViewModel';\nexport * from './LeagueMemberViewModel';\nexport * from './LeaguePageDetailViewModel';\nexport * from './LeagueScheduleViewModel';\nexport * from './LeagueScoringChampionshipViewModel';\nexport * from './LeagueScoringConfigViewModel';\nexport * from './LeagueScoringPresetsViewModel';\nexport * from './LeagueScoringPresetViewModel';\nexport * from './LeagueScoringSectionViewModel';\nexport * from './LeagueSettingsViewModel';\nexport * from './LeagueStandingsViewModel';\nexport * from './LeagueStatsViewModel';\nexport * from './LeagueStewardingViewModel';\nexport * from './LeagueSummaryViewModel';\nexport * from './LeagueWalletViewModel';\nexport * from './MediaViewModel';\nexport * from './MembershipFeeViewModel';\nexport * from './PaymentViewModel';\nexport * from './PrizeViewModel';\nexport * from './ProfileOverviewViewModel';\nexport * from './ProtestDriverViewModel';\nexport * from './ProtestViewModel';\nexport * from './RaceDetailEntryViewModel';\nexport * from './RaceDetailUserResultViewModel';\nexport * from './RaceDetailsViewModel';\nexport * from './RaceListItemViewModel';\nexport * from './RaceResultsDetailViewModel';\nexport * from './RaceResultViewModel';\nexport * from './RacesPageViewModel';\nexport * from './RaceStatsViewModel';\nexport * from './RaceStewardingViewModel';\nexport * from './RaceViewModel';\nexport * from './RaceWithSOFViewModel';\nexport * from './RecordEngagementInputViewModel';\nexport * from './RecordEngagementOutputViewModel';\nexport * from './RecordPageViewInputViewModel';\nexport * from './RecordPageViewOutputViewModel';\nexport * from './RemoveMemberViewModel';\nexport * from './RenewalAlertViewModel';\nexport * from './RequestAvatarGenerationViewModel';\nexport * from './ScoringConfigurationViewModel';\nexport * from './SessionViewModel';\nexport * from './SponsorSettingsViewModel';\nexport * from './SponsorshipDetailViewModel';\nexport * from './SponsorshipPricingViewModel';\nexport * from './SponsorshipRequestViewModel';\nexport * from './SponsorshipViewModel';\nexport * from './SponsorSponsorshipsViewModel';\nexport * from './SponsorViewModel';\nexport * from './StandingEntryViewModel';\nexport * from './TeamCardViewModel';\nexport * from './TeamDetailsViewModel';\nexport * from './TeamJoinRequestViewModel';\nexport * from './TeamMemberViewModel';\nexport * from './TeamSummaryViewModel';\nexport * from './UpcomingRaceCardViewModel';\nexport * from './UpdateAvatarViewModel';\nexport * from './UpdateTeamViewModel';\nexport * from './UploadMediaViewModel';\nexport * from './UserProfileViewModel';\nexport * from './WalletTransactionViewModel';\nexport * from './WalletViewModel';\n","usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/middleware.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/next-env.d.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/AdminDashboardTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/AdminUsersTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/DashboardTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/DriverProfileTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/DriverRankingsTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/DriversTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/HomeTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/LeaderboardsTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/LeagueAdminScheduleTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/LeagueDetailTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/LeagueRulebookTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/LeagueScheduleTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/LeagueSettingsTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/LeagueSponsorshipsTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/LeagueStandingsTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/ProfileLeaguesTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/ProfileTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/RaceDetailTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/RaceResultsTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/RaceStewardingTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/RacesAllTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/RacesTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/RosterAdminTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/RulebookTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/SponsorDashboardTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/SponsorLeagueDetailTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/SponsorLeaguesTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/SponsorshipRequestsTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/TeamDetailTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/TeamLeaderboardTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/TeamsTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/auth/ForgotPasswordTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/auth/LoginTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/auth/ResetPasswordTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/templates/auth/SignupTemplate.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/types/third-party-shims.d.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Accordion.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/AchievementCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/ActiveDriverCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/ActivityItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/AuthContainer.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/AuthError.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/AuthLoading.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/AvailableLeagueCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Avatar.tsx","messages":[],"suppressedMessages":[{"ruleId":"@next/next/no-img-element","severity":2,"message":"Using `` could result in slower LCP and higher bandwidth. Consider using `` from `next/image` or a custom image loader to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element","line":17,"column":5,"nodeType":"JSXOpeningElement","endLine":25,"endColumn":7,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Badge.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/BorderTabs.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Box.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Breadcrumbs.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Button.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Card.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/CareerHighlights.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/CareerStats.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/CategoryDistribution.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/CategoryDistributionCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/CategoryIcon.tsx","messages":[],"suppressedMessages":[{"ruleId":"@next/next/no-img-element","severity":2,"message":"Using `` could result in slower LCP and higher bandwidth. Consider using `` from `next/image` or a custom image loader to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element","line":17,"column":5,"nodeType":"JSXOpeningElement","endLine":25,"endColumn":7,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Checkbox.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/CircularProgress.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Container.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/CountryFlag.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/DangerZone.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/DashboardHero.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/DashboardLayoutWrapper.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/DateHeader.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/DecorativeBlur.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/DiscordCTA.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/DriverRatingPill.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/DriverStats.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/DriverSummaryPill.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/DriversSearch.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/DurationField.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/ErrorActionButtons.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/ErrorBanner.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/ErrorPageContainer.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/FeedEmptyState.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/FeedItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/FilePicker.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/FilterGroup.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/FinishDistributionChart.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Footer.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/FormField.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/FriendItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/FriendsList.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/GoalCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Grid.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/GridItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Header.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Heading.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Hero.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/HorizontalBarChart.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/HorizontalStatCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/HorizontalStatItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Icon.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/IconButton.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Image.tsx","messages":[],"suppressedMessages":[{"ruleId":"@next/next/no-img-element","severity":2,"message":"Using `` could result in slower LCP and higher bandwidth. Consider using `` from `next/image` or a custom image loader to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element","line":27,"column":5,"nodeType":"JSXOpeningElement","endLine":39,"endColumn":7,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/InfoBanner.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/InfoBox.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/InfoItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/InlinePenaltyButton.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Input.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/JoinRequestItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/JoinRequestList.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Layout.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/LeaderboardList.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/LeagueCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/LeagueCover.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/LeagueCoverWrapper.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/LeagueHeader.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/LeagueListItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/LeagueLogo.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/LeagueLogoWrapper.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/LeagueMemberTable.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/LeagueSummaryCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Link.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/LiveRaceBanner.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/LiveRaceItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/LiveryCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/LoadingSpinner.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/MainContent.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/MedalBadge.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/MilestoneItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/MiniStat.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Modal.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/ModalIcon.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/NextRaceCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/OnboardingCardAccent.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/OnboardingContainer.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/OnboardingError.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/OnboardingForm.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/OnboardingHeader.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/OnboardingHelpText.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/OnboardingNavigation.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/PageHeader.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/PageHero.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Pagination.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/PenaltyFAB.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/PenaltyRow.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/PerformanceMetrics.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/PerformanceOverview.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/PlaceholderImage.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Podium.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/PointsTable.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/PresetCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/ProfileBio.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/ProfileLayoutShell.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/ProfileStatGrid.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/ProfileTabs.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/ProgressBar.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/QuickActionItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/QuickActionLink.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RaceCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RaceDetailCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RaceFilterModal.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RaceHero.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RaceHeroWrapper.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RaceJoinButton.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RacePageHeader.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RacePenaltyRowWrapper.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RaceResultCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RaceResultHero.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RaceResultList.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RaceResultsHeader.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RaceResultsTable.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RaceStats.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RaceStatusBadge.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RaceStewardingStats.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RaceSummaryItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RaceUserResultWrapper.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RacingProfile.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RankBadge.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RankingsPodium.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RankingsTable.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RatingBreakdown.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RatingComponent.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RatingHistoryItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RecruitingTeamCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RecruitingTeamGrid.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RenewalItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/RulebookTabs.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Section.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/SectionHeader.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/SegmentedControl.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Select.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/SidebarActionLink.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/SidebarRaceItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Skeleton.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/SkillDistribution.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/SkillLevelButton.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/SkillLevelHeader.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/SponsorActivityItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/SponsorLogo.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/SponsorMetricCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/SponsorSlotCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/SponsorTierCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/SponsorshipCategoryCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/SponsorshipRequestItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/SponsorshipTierBadge.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Stack.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/StandingsItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/StandingsList.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/StatBox.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/StatCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/StatGridItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/StatItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/StatusBadge.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/StatusIndicator.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/StepIndicator.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/StewardingTabs.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/SummaryItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Surface.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/TabContent.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/TabNavigation.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Table.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/TeamCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/TeamCardWrapper.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/TeamFilter.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/TeamGrid.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/TeamLadderRow.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/TeamLadderTable.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/TeamLeaderboardItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/TeamLeaderboardPreview.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/TeamLogo.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/TeamMembershipCard.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/TeamMembershipGrid.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/TeamRosterList.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/TeamSearchBar.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/TeamStatItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/TeamTag.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Text.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/TextArea.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/Toggle.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/TrackImage.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/UpcomingRaceItem.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/icons/DiscordIcon.tsx","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]},{"filePath":"/Users/marcmintel/Projects/gridpilot/apps/website/ui/state-types.ts","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[]}]