Refactor draft preferences to use season IDs and simplify registration - #134
Merged
Merged
Conversation
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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
seasonIdforeign key columns toDraftSlotandDraftSlotPreferencetablesseason(year integer) columns from both tablesrankingcolumn fromDraftSlotPreference(preferences are now unranked availability selections)seasonIdvalues from existing year data and enforce referential integritySeason.yearto prevent duplicate season yearsRegistration Flow
registerWithDraftPreferences()functionDashboard Component
parseSelectedSlotIds()helper to sanitize and deduplicate user inputuseNavigation()hookData Models
getDraftSlotsWithUserPreferences()to useseasonIdand returnisSelectedboolean instead ofuserRankinggetUserDraftSlotPreferences()to acceptseasonIdinstead of year integerupsertUserDraftSlotPreferences()to accept array of slot IDs instead of ranked preferencesgetRegistrationCountByYear()helper functionAdmin Routes
seasonIdinstead ofseasonyearNotable Implementation Details
MINIMUM_DRAFT_TIMES = 3) centralized for consistencyhttps://claude.ai/code/session_01Xx4rW2iFPG832esrijChzJ