Implement gamification system with XP, levels, badges, and leaderboards.
Created Badge.cs with:
- Tenant isolation (ITenantEntity)
- Slug, Name, Description, Icon fields
- XpReward for awarding XP when badge earned
- IsActive flag for enabling/disabling badges
- SortOrder for display ordering
- Predefined badge slugs (FirstListing, FirstConnection, etc.)
Created UserBadge.cs with:
- User/Badge junction
- EarnedAt timestamp
- Unique constraint (one badge per user)
Created XpLog.cs with:
- User reference
- Amount, Source, ReferenceId, Description fields
- Predefined sources (listing_created, connection_made, etc.)
- Default XP amounts for various actions
Added to User.cs:
- TotalXp field (cumulative XP earned)
- Level field (calculated from XP)
- UserBadges navigation property
- XpLogs navigation property
- Static methods for level calculation
Created GamificationService.cs with:
AwardXpAsync()- Awards XP and handles level-upsAwardBadgeAsync()- Awards badges with XP rewardsCheckAndAwardBadgesAsync()- Automatic badge checks based on actions
Added to NexusDbContext:
- badges, user_badges, xp_logs tables
- Global query filters for tenant isolation
- Unique constraints for badge slugs and user badges
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/gamification/profile | Current user's gamification profile |
| GET | /api/gamification/profile/{userId} | Another user's profile |
| GET | /api/gamification/badges | All available badges with earned status |
| GET | /api/gamification/badges/my | Current user's earned badges |
| GET | /api/gamification/leaderboard | XP leaderboard (all/week/month/year) |
| GET | /api/gamification/xp-history | Current user's XP history |
Added XP awards to existing controllers:
- ListingsController: XP for creating listings
- ConnectionsController: XP for accepted connections
- WalletController: XP for completed transactions
- GroupsController: XP for creating groups
- EventsController: XP for creating events
- FeedController: XP for creating posts and comments
Added 10 badges per tenant to SeedData:
- First Listing (25 XP)
- First Connection (25 XP)
- First Transaction (30 XP)
- First Post (15 XP)
- Event Host (30 XP)
- Helpful Neighbor (100 XP) - 10 transactions
- Community Builder (50 XP) - created a group
- Event Organizer (75 XP) - 5 events
- Popular Post (40 XP) - 10+ likes
- Veteran (100 XP) - 1 year member
# Start the Docker stack (migrations run automatically)
docker compose up -d
# Or run migrations manually inside container
docker compose exec api dotnet ef database updateRun after API is running:
powershell -ExecutionPolicy Bypass -File "C:\Users\jaspe\AppData\Local\Temp\claude\c--xampp-htdocs-asp-net-backend\18a553b7-f5b3-4456-9c43-ff9a0cd73a0b\scratchpad\test-gamification.ps1"src/Nexus.Api/Entities/Badge.cssrc/Nexus.Api/Entities/UserBadge.cssrc/Nexus.Api/Entities/XpLog.cssrc/Nexus.Api/Services/GamificationService.cssrc/Nexus.Api/Controllers/GamificationController.cs
src/Nexus.Api/Entities/User.cs- Added TotalXp, Level, helper methodssrc/Nexus.Api/Data/NexusDbContext.cs- Added 3 new DbSets and configurationssrc/Nexus.Api/Data/SeedData.cs- Added badge seedingsrc/Nexus.Api/Program.cs- Registered GamificationServicesrc/Nexus.Api/Controllers/ListingsController.cs- Added XP integrationsrc/Nexus.Api/Controllers/ConnectionsController.cs- Added XP integrationsrc/Nexus.Api/Controllers/WalletController.cs- Added XP integrationsrc/Nexus.Api/Controllers/GroupsController.cs- Added XP integrationsrc/Nexus.Api/Controllers/EventsController.cs- Added XP integrationsrc/Nexus.Api/Controllers/FeedController.cs- Added XP integration
| Action | XP Amount |
|---|---|
| Create listing | 10 |
| Make connection | 5 |
| Complete transaction | 20 |
| Create post | 5 |
| Create event | 15 |
| Attend event | 10 |
| Create group | 20 |
| Add comment | 2 |
Levels are calculated using the formula: XP needed for level N = 50 × N × (N - 1)
| Level | XP Required |
|---|---|
| 1 | 0 |
| 2 | 100 |
| 3 | 300 |
| 4 | 600 |
| 5 | 1000 |
| 10 | 4500 |
| 20 | 19000 |
=== Phase 13: Gamification Tests ===
(Run the test script after migration to populate results)