diff --git a/backend/routers/performances.py b/backend/routers/performances.py index e267a9f..ff83d6b 100644 --- a/backend/routers/performances.py +++ b/backend/routers/performances.py @@ -99,6 +99,36 @@ def read_performance(slug: str, session: Session = Depends(get_session)): # Sort by rating desc, then date desc other_performances.sort(key=lambda x: (x.avg_rating or 0, x.show_date), reverse=True) + # --- Calculate Ranking for Current Performance --- + current_perf_stats = rating_map.get(performance_id, {"avg": 0.0, "count": 0}) + current_avg = current_perf_stats["avg"] or 0.0 + current_rating_count = current_perf_stats["count"] + + # Build list of all performances with their ratings for ranking + all_rated_perfs = [] + for p, s, v in all_perfs_data: + stats = rating_map.get(p.id, {"avg": 0.0, "count": 0}) + all_rated_perfs.append({"id": p.id, "avg": stats["avg"] or 0.0, "count": stats["count"]}) + + # Sort by avg rating desc + all_rated_perfs.sort(key=lambda x: x["avg"], reverse=True) + + # Find rank (1-indexed) + rank = None + for i, item in enumerate(all_rated_perfs): + if item["id"] == performance_id: + rank = i + 1 + break + + total_versions = len(all_perfs_data) + + # Heady = top 20% with at least 1 rating and avg >= 8.0 + is_heady = False + if current_rating_count > 0 and current_avg >= 8.0: + if rank and total_versions > 0: + percentile = rank / total_versions + is_heady = percentile <= 0.2 # Top 20% + # Construct response manually to include extra fields # We need to ensure nested models (show, song) are validated correctly perf_dict = performance.model_dump() @@ -112,6 +142,11 @@ def read_performance(slug: str, session: Session = Depends(get_session)): perf_dict['gap'] = gap perf_dict['times_played'] = times_played perf_dict['other_performances'] = other_performances + perf_dict['rank'] = rank + perf_dict['total_versions'] = total_versions + perf_dict['avg_rating'] = current_avg + perf_dict['rating_count'] = current_rating_count + perf_dict['is_heady'] = is_heady return perf_dict diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index c40c87b..fabe449 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -1,6 +1,6 @@ # Elmeg Platform Roadmap -**Last Updated:** 2025-12-26 +**Last Updated:** 2025-12-27 --- @@ -34,7 +34,22 @@ --- -## Recent Completions (Dec 26, 2025) +## Recent Completions (Dec 27, 2025) + +| Feature | Status | +|---------|--------| +| Auth Persistence Fix | ✅ Fixed - added missing DB columns for preferences | +| Review Display | ✅ Shows avatar, username, localized date, granular score | +| Rating System | ✅ Shows user's existing rating, added `/ratings/me` endpoint | +| Activity Feed | ✅ Living links to entities, accurate type language | +| Username Consistency | ✅ Fixed - feed now uses Profile username | +| Notification Prefs Backend | ✅ Added DB columns (theme, email_on_reply, etc) | +| Avatar Unlock System | ✅ XP tiers implemented in settings | +| Duplicate Performances | ✅ Fixed - deleted 220 duplicates | +| Score Precision | ✅ Fixed - database column changed to FLOAT | +| UI Polish | ✅ Removed emojis, music icon, updated site description | + +## Previous Completions (Dec 26, 2025) | Feature | Status | |---------|--------| @@ -45,54 +60,23 @@ | SPF DNS record fixed | ✅ Complete | | Password reset tested | ✅ Complete | -## Previous Completions (Dec 23, 2025) +--- + +## Current Sprint + +### In Progress | Feature | Status | |---------|--------| -| Privacy Settings (3 toggles) | ✅ Complete | -| Sticky Settings Sidebar | ✅ Complete | -| Bug Tracker MVP | ✅ Deployed | -| Auth Console Error Fix | ✅ Fixed | -| Videos Page Link Fix | ✅ Fixed | -| Hide Test Users | ✅ Implemented | -| Bandcamp/Nugs Links | ✅ Complete | -| Enhanced Footer | ✅ Deployed | -| **Postal Mail Server** | ✅ Built & Deployed | -| **Email DNS Records** | ✅ SPF/DKIM/DMARC/RP | -| **SMTP Integration** | ✅ Backend configured | +| Performance Ranking | 🔄 Backend + Frontend | +| Heady Badges | 🔄 Visual polish for top-rated | ---- +### Up Next -## Postal Mail Server Details - -### Infrastructure - -| Component | Details | -|-----------|---------| -| Location | tangible-aacorn (Hetzner ARM64) | -| Build | Custom ARM64 from source | -| Database | MariaDB 11 | -| Queue | RabbitMQ 3.13 | -| Routing | Traefik with Let's Encrypt | - -### DNS Records (Cloudflare) - -| Type | Name | Value | -|------|------|-------| -| A | postal | 159.69.219.254 (DNS only) | -| A | smtp | 159.69.219.254 (DNS only) | -| MX | @ | smtp.elmeg.xyz (Priority 10) | -| TXT | @ | v=spf1 mx a ip4:159.69.219.254 ~all | -| TXT | postal-VkYvkc._domainkey | v=DKIM1; t=s; h=sha256; p=... | -| TXT | _dmarc | v=DMARC1; p=none; rua=mailto:admin@elmeg.xyz | -| CNAME | psrp | smtp.elmeg.xyz | - -### Admin Access - -- **URL:** -- **Login:** -- **Organization:** Elmeg -- **Mail Server:** main +| Feature | Priority | +|---------|----------| +| Theme persistence (frontend) | Medium | +| Email notification triggers | Low | --- @@ -105,40 +89,18 @@ | Privacy: Public Profile | ✅ Done | | Privacy: Show Attendance | ✅ Done | | Privacy: Leaderboards | ✅ Done | -| Theme Persistence | ✅ Works client-side | +| Theme Persistence | ✅ Backend ready | +| Notification Toggles | ✅ UI + Backend ready | +| Avatar XP Unlock System | ✅ Complete | -### Phase 2: Notifications (Deferred) +### Phase 2: Notifications (Backend Ready) -| Feature | Dependency | Status | -|---------|------------|--------| -| Comment Replies | Notification system | Ready to implement | -| New Show Added | Import trigger hook | Needs backend work | -| Chase Song Played | Post-import check | Needs backend work | -| Weekly Digest | Email templates + cron | Future | - ---- - -## External Links System - -### ✅ Phase 1: Database + Admin - COMPLETE - -### ✅ Phase 2: Frontend Display - COMPLETE - -### Phase 3: Import Tools (Future) - ---- - -## Bug Tracker - -**Status: ✅ DEPLOYED at `/bugs`** - ---- - -## Avatar System Roadmap - -### ✅ Phase 1: Jewel Tones (Complete) - -### Phase 2-4: (Future) +| Feature | Status | +|---------|--------| +| Comment Replies Pref | ✅ Backend column added | +| Chase Song Pref | ✅ Backend column added | +| Weekly Digest Pref | ✅ Backend column added | +| Email Triggers | ❌ Not implemented | --- @@ -148,36 +110,17 @@ - [x] Test email verification flow end-to-end - [x] Test password reset flow end-to-end +- [ ] Performance ranking display +- [ ] Heady badges for top-rated versions ### Medium Priority +- [ ] Theme persistence to frontend - [ ] Analytics provider decision -- [ ] Notification preferences backend -- [ ] Avatar unlock system ### Low Priority - [ ] bugs.elmeg.xyz subdomain - [ ] Data export (GDPR) - [ ] Account deletion - ---- - -## Implementation Priority - -### Immediate (Testing) - -1. [x] Register test account to trigger verification email -2. [x] Registration UX shows "Check Your Email" message -3. [x] Test password reset flow -4. [x] Monitor email deliverability in Postal dashboard - -### This Week - -- [ ] Answer analytics question -- [ ] Theme persistence to user preferences - -### Next Sprint - -- [ ] Notification preferences backend -- [ ] Avatar unlock system +- [ ] Email notification triggers diff --git a/frontend/app/performances/[slug]/page.tsx b/frontend/app/performances/[slug]/page.tsx index c4bd2c1..f78c15c 100644 --- a/frontend/app/performances/[slug]/page.tsx +++ b/frontend/app/performances/[slug]/page.tsx @@ -67,11 +67,22 @@ export default async function PerformanceDetailPage({ params }: { params: Promis
{/* Context Badge */} -
+
Specific Performance + {performance.is_heady && ( + + + Heady Version + + )} + {performance.rank && performance.total_versions && ( + + #{performance.rank} of {performance.total_versions} + + )} {performance.set_name && ( {performance.set_name} )} @@ -136,7 +147,13 @@ export default async function PerformanceDetailPage({ params }: { params: Promis Rate This Version
- +