Skip to content

Refactor draft preferences to use season IDs and simplify registration - #134

Merged
chrisparsons83 merged 2 commits into
mainfrom
claude/draft-timeslot-selection-03ig1v
Jul 21, 2026
Merged

Refactor draft preferences to use season IDs and simplify registration#134
chrisparsons83 merged 2 commits into
mainfrom
claude/draft-timeslot-selection-03ig1v

Conversation

@chrisparsons83

Copy link
Copy Markdown
Owner

Summary

This PR refactors the draft slot preference system to use foreign key relationships to Season records instead of storing year integers, and consolidates the registration flow to combine registration and draft preference selection into a single atomic operation.

Key Changes

Database Schema & Migrations

  • Added seasonId foreign key columns to DraftSlot and DraftSlotPreference tables
  • Removed season (year integer) columns from both tables
  • Removed ranking column from DraftSlotPreference (preferences are now unranked availability selections)
  • Created migration to backfill seasonId values from existing year data and enforce referential integrity
  • Added unique constraint on Season.year to prevent duplicate season years

Registration Flow

  • Combined registration and draft preference selection into a single atomic operation via new registerWithDraftPreferences() function
  • Users now select at least 3 draft times during registration, not as a separate step
  • Registration form displays draft time slots and validates minimum selection before submission
  • Removed separate "register then set preferences" flow

Dashboard Component

  • Refactored to show draft slots to both registered and unregistered users
  • Unregistered users select draft times as part of registration
  • Registered users can update their draft preferences separately
  • Added visual feedback for selection status (green checkmark when minimum met, red warning otherwise)
  • Improved form validation with parseSelectedSlotIds() helper to sanitize and deduplicate user input
  • Added loading state tracking with useNavigation() hook

Data Models

  • Updated getDraftSlotsWithUserPreferences() to use seasonId and return isSelected boolean instead of userRanking
  • Updated getUserDraftSlotPreferences() to accept seasonId instead of year integer
  • Updated upsertUserDraftSlotPreferences() to accept array of slot IDs instead of ranked preferences
  • Added getRegistrationCountByYear() helper function
  • Updated all draft slot queries to join with Season table for year information

Admin Routes

  • Updated draft slot creation/editing to use seasonId instead of season year
  • Updated sorting/announcement logic to reference season year through relationship
  • Simplified preference handling in sorting algorithm (removed ranking logic)

Notable Implementation Details

  • Draft preference updates use Prisma transactions to ensure atomicity
  • Form submission includes hidden input with JSON-stringified slot IDs for validation on server
  • Minimum draft time selection constant (MINIMUM_DRAFT_TIMES = 3) centralized for consistency
  • Registration is blocked if no draft slots exist for the season (prevents registration before times are posted)

https://claude.ai/code/session_01Xx4rW2iFPG832esrijChzJ

claude added 2 commits July 20, 2026 21:35
Refine the draft-time picker so it follows the current season by relation
and folds the "pick at least 3 times" requirement into registration itself.

- Relate DraftSlot and DraftSlotPreference to Season via seasonId (replacing
  the bare Int year), add Season.year @unique, and drop the now-unused
  DraftSlotPreference.ranking column. Backfill migration maps existing rows
  by year and fails loudly rather than orphaning data.
- Dashboard: unregistered users now pick their draft times and register in a
  single atomic step (registration + >=3 preferences saved together). Block
  registration when the current season has no draft slots posted yet. Rebuild
  the picker onto the app's dark form idiom.
- Update admin draft-slot routes and DraftSlotRow to work with seasonId, and
  simplify the league-sorting algorithm to treat preferences as flat
  availability now that ranking is gone.
- Fix the hardcoded "League 2025" Discord announcement title to use the
  season year, and guard season creation against duplicate years.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xx4rW2iFPG832esrijChzJ
- Wrap registerWithDraftPreferences in try/catch so DB failures return a
  friendly form error instead of an unhandled 500, matching the edit path.
- Dedupe submitted draft-slot ids so a forged/replayed POST can't violate the
  (userId, draftSlotId) unique constraint.
- Make upsertUserDraftSlotPreferences delete + insert atomic via a
  transaction so a failed insert can't wipe a user's preferences.
- Count registrations with a count() query instead of loading every
  registration and its user, and stop shipping the per-slot preferences array
  to the client (only the derived isSelected flag is used).
- Drop the unused name attribute on the draft-slot checkboxes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xx4rW2iFPG832esrijChzJ
@chrisparsons83
chrisparsons83 merged commit 689389b into main Jul 21, 2026
7 checks passed
@chrisparsons83
chrisparsons83 deleted the claude/draft-timeslot-selection-03ig1v branch July 21, 2026 16:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants