Skip to content

feat: add badge system - #209

Open
TheSKBroook wants to merge 33 commits into
mainfrom
feature/badge-admin-frontend
Open

TheSKBroook wants to merge 33 commits into
mainfrom
feature/badge-admin-frontend

Conversation

@TheSKBroook

Copy link
Copy Markdown

Badge system: event badges, admin management, and badges on profiles

Summary

Adds badges to the site. Admins can attach an optional badge to an event when creating or editing it. The event, badge and images are saved together or not at all. Members' badges show on their profile and public profile.

Database

Tables used: badges, member_badges

Migrations
Long story short,
-> I first think that deleting an event should NOT delete the badge associated with it,
-> then I think it should, so I change it to the opposite ( delete event also delete the badge )

Click here to see the migration detail

(in supabase/migrations/; each one runs once in the Supabase SQL Editor):

  • 20261001120000_badge_event_links_and_save_function.sql
    • member_badges.badgeid → ON DELETE CASCADE (deleting a badge deletes all awards of it)
    • UNIQUE (badgeid, memberid) (a member can't hold the same badge twice)
    • save_event_with_badge database function
  • 20261007120000_delete_event_badge_with_event.sql
    • badges.eventid → ON DELETE CASCADE (deleting an event deletes its badge)
    • function updated: removing a badge deletes it (p_remove_badge)

Existing rules: badges.eventid is unique (at most one badge per event); member_badges.memberid → registrations.id.

Storage: the badges bucket is public, and images are stored as badge_image/<uuid>.<ext>.

Security: only the server (service role) can call save_event_with_badge. The public anon key is blocked.

What admins can do (Admin → Events)

Create

  • Add Badge (optional), next to Event Image, opens a pop-up: name (required), description, criteria, image (round preview)
  • Nothing is saved until Create Event. The event, badge and both images go in one request
  • All or nothing: if anything fails, nothing is saved and the uploaded images are deleted again. The form keeps its values so the admin can fix and retry

Update

  • Edit loads the event's saved badge
  • Changing the badge updates the same badge, so members keep it. A replaced image's old file is deleted

Delete

  • Remove (while editing) deletes the badge and every member's award of it on save, with a red warning and an Undo option
  • ⚠️ Deleting an event also deletes its badge and every member's award of that badge. The confirmation dialog warns about this when the event has a badge. The event image and badge image files are deleted too

What members see

  • Their badges on /profile and on their public profile /profile/[id]: round images, with name, category, description, criteria and award date on hover
  • The Badges section is aligned with Events Attended

API

  • PUT /api/admin/events: now multipart (payload JSON + event_image + badge_image). Creates or updates the event and its badge in one transaction. The old JSON body still works for event-only saves
  • DELETE /api/admin/events: deletes the event, its badge, the awards and both image files. Returns 404 for an unknown id
  • Removed: POST /api/admin/events/image (images now go with the save)
  • POST /api/admin/badges and POST /api/admin/badges/image: create a standalone badge and upload a badge image (not used by the UI yet)

Services

  • BadgesService: CRUD, uploadBadgeImage, getBadgeImagePath (only our own public links), deleteBadgeImage
  • MemberBadgesService: award (idempotent), check, list (with badge details), revoke
  • EventService: saveEventWithBadge, deleteEvent, and the image helpers take the server client

Testing

Automated

  • badges-service.test.ts: 36 passing (CRUD, image upload, path parsing, image delete)
  • Both migrations were run against a copy of the schema in a throwaway Postgres (PGlite): 22/22 checks pass (cascades, uniqueness, function behaviour, rollback, permissions, safe to re-run)

Manual (to do before merging)

  • Create an event with a badge and image → event and badge rows are linked (category = EVENT), and both files are in Storage
  • A failed save (e.g. end time before start time) → no event, no badge, no leftover files
  • Edit the badge's name and image → same badge row, old image file deleted
  • Remove the badge and save → badge and awards deleted, image file deleted; check Undo
  • Delete an event with a badge → warning shown; event, badge, awards and both files deleted
  • An awarded badge shows on /profile and /profile/[id]

Not in this PR / follow-ups

  • Awarding badges on attendance. Badges can currently only be awarded directly in the database
  • Potentially a badge management page (POST /api/admin/badges is ready for it)

…ath, in case when image is stored but badge is not created.
@vercel

vercel Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
web3 Ready Ready Preview Oct 8, 2026 2:03am UTC

@TheSKBroook TheSKBroook changed the title Feature/badge admin frontend feat: add badge system Oct 7, 2026

This branch was successfully deployed

1 active deployment
Preview — f5c66089 Deployed Oct 8, 2026 by vercel[bot]
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