* Add oxlint and fix all lint errors
- Install oxlint, add .oxlintrc.json with rules for TypeScript/React
- Add npm run lint / lint:fix scripts
- Add Claude PostToolUse hook to run oxlint on every edited file
- Fix 101 errors: unused vars/imports, eqeqeq, prefer-const, no-new-array
- Fix no-array-index-key (use stable keys or suppress positional cases)
- Fix exhaustive-deps missing dependency in useEffect
- Promote exhaustive-deps and no-array-index-key to errors
- Fix Map.get() !== null bug in $leagueId.server.ts (should be !== undefined)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix no-explicit-any warnings and upgrade tsconfig to ES2023
- Replace all `any` types with proper types or `unknown` across ~20 files
- Add typed socket payload interfaces in draft route and useDraftSocket
- Use any[] with eslint-disable for socket.io callbacks (legitimate escape hatch)
- Bump all tsconfigs from ES2022 → ES2023 to support toSorted/toReversed
- Fix cascading type errors uncovered by removing any: Map.get narrowing,
participant relation types, ChartDataPoint, Partial<NewSeason> indexing
- Add ParticipantResultWithParticipant type to participant-result model
- Fix test fixtures to match updated interfaces (DraftCell, ParticipantResult)
- Fix duplicate getQPStandings import in sportsSeasonId.server.ts
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Promote no-explicit-any to error
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Include participant EV/futures data in data sync export/import
The export now includes the full participantExpectedValues records
(placement probabilities, source, sourceOdds) alongside participants.
On import, EV records are upserted in merge mode and created fresh in
replace mode (cascade handles cleanup). Backward-compatible with older
exports that lack the participantExpectedValues field.
https://claude.ai/code/session_01TVzuuDR7jPtmihaXTrsX7B
* Address all data-sync code review findings
- Wrap importSportsDataFromJSON in a db.transaction() so any mid-import
failure rolls back cleanly instead of leaving partial data
- Add zod validation of imported JSON before any DB writes, giving a
clear error on malformed/incompatible files
- Fix N+1 queries: build participantIdMap during participant import so
the EV and results sections resolve IDs from memory, not extra queries
- Fix merge mode silently skipping existing participants — now updates
shortName, externalId, and expectedValue
- Add participantResults to export/import (was deleted in replace mode
but never exported, so results were permanently lost)
- Restore calculatedAt timestamp on EV import instead of defaulting to
now(); stored as ISO string in the export for portability
- Document that onDelete:cascade covers participantExpectedValues and
participantResults when participants is deleted; remove the now-
redundant explicit participantResults delete from replace mode
- Bump export version to 1.1; old v1.0 files still import cleanly since
participantExpectedValues, participantResults, and calculatedAt are
all optional in the zod schema
- Collapse all six DB fetches in exportSportsDataToJSON into one
Promise.all for parallel execution
- Add countAllParticipants() and countAllParticipantEVs() model funcs
- Show Participants and EV Records counts on the dashboard stat cards
- Replace raw DOM form creation/submit in handleImport with useFetcher,
giving proper loading state, no full-page reload, and type-safe data
- Remove dead export intent handler from the action function
https://claude.ai/code/session_01TVzuuDR7jPtmihaXTrsX7B
---------
Co-authored-by: Claude <noreply@anthropic.com>
* feat: sync odds-based EV to participants table for draft room ranking
When admin enters futures odds or manual probabilities, the calculated EV
is now synced from participantExpectedValues to participants.expectedValue.
This closes the gap where EVs were calculated but never reflected in the
draft room ranking. Also changes expectedValue from integer to decimal(10,2)
for better precision, and displays "—" for participants with no odds data.
https://claude.ai/code/session_01JWG2zg2EMzCn6RgEufPC1T
* fix: correct expectedValue type to string in participants route
Missed instance of `expectedValue: 0` (number) that failed typecheck
after schema change from integer to decimal.
https://claude.ai/code/session_01JWG2zg2EMzCn6RgEufPC1T
---------
Co-authored-by: Claude <noreply@anthropic.com>