Skip to content

feat(voting): let projects target award categories - #149

Merged
HazAT merged 6 commits into
masterfrom
feat/project-category-selection
Aug 19, 2026
Merged

feat(voting): let projects target award categories#149
HazAT merged 6 commits into
masterfrom
feat/project-category-selection

Conversation

@HazAT

@HazAT HazAT commented Aug 19, 2026

Copy link
Copy Markdown
Member

Project teams can now leave their project open to every award category or focus it on one or two specific awards when creating, editing, or claiming it. Existing projects with no nominations remain eligible for all categories, so this requires no backfill or manual migration.

During voting, every award stays visible on the project page, but categories the team did not enter are clearly unavailable. Existing picks that no longer match a project's nominations remain visible and replaceable without counting toward ballot completion, while new casts and moves are enforced against nomination eligibility in D1.

The database migrations preserve existing nominations and votes, then freeze nomination rows once voting is live—including category-deletion cascades. The most useful review path is the project write lifecycle first, followed by the vote and nomination triggers, then the form and ballot state changes.

HazAT added 6 commits August 19, 2026 19:13
Expose year award categories and ordered project nominations through the shared project contracts and Worker APIs. Validate zero-to-two distinct same-year categories, preserve nomination-free ideas, and batch nomination writes with project membership changes across create, update, and claim flows.

Keep nomination sets immutable once effective voting opens while allowing unrelated permitted edits, and cover persistence, validation, claims, and voting-open behavior with focused tests.
Recreate the D1 vote insert and update triggers so projects with no nominations remain open to every category while restricted projects accept only their nominated categories. Map rejected vote writes to a validation error and expose nomination eligibility on each compact ballot selection.

Preserve historical conflicting votes in place so they remain visible and movable, and cover eligible casts, atomic rejected casts and moves, withdrawn picks, migration safety, and the retired admin nomination API.
Add an explicit all-categories default and an accessible focused mode for selecting one or two project award categories. Include nomination choices in form payloads and dirty-state protection, with responsive category cards, native controls, empty-state guidance, and a visible two-selection limit.

Initialize edit and claim flows from the correct nomination state, and lock saved targeting while effective voting is open without blocking unrelated edits. Cover new, edit, idea, claim, keyboard, limit, discard, empty, and read-only behavior with focused app tests.
Keep every award category visible on project details while limiting cast and move controls to categories entered by the project team. Give excluded, own-project, selected, replacement, pending, and confirmation states distinct copy and styling.

Count only active nomination-eligible selections toward ballot completion and personal pick badges. Preserve withdrawn and active ineligible selections with explicit replacement guidance, backed by focused component and route coverage.
Add D1 triggers that reject nomination inserts, updates, and deletes while voting is effectively live. This closes the enable-voting race and prevents category cascades from turning a restricted project into an all-category project.

Map the database constraint through project writes and category deletion, including explicit all-category behavior for live project creation and idea claims. Extend Worker and migration coverage for atomic failures, preserved rows, and existing ballot behavior.
Remove the decorative purple stripe from the left edge of the award targeting panel while preserving the panel's existing outline, gradient, and layout.
@HazAT
HazAT marked this pull request as ready for review August 19, 2026 18:44

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit d71154c. Configure here.


const users = options.data?.users ?? [];
const categories = options.data?.categories ?? [];
const nominationsLocked = Boolean(project && !claim && nominationsReadOnly);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create and claim ignore voting lock

Medium Severity

nominationsLocked is true only when an existing project is being edited, so create and claim still allow focused award targeting after voting opens. Those writes are rejected by the database lock, so teams can fill in one or two categories and then hit a conflict instead of seeing targeting frozen like the edit form.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit d71154c. Configure here.

@HazAT
HazAT merged commit 0ab0909 into master Aug 19, 2026
11 checks passed
@HazAT
HazAT deleted the feat/project-category-selection branch August 19, 2026 18:50
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.

1 participant