This resolves issue #65 by addressing multiple problems that were preventing base64-encoded cover images from being uploaded:
1. Increased Fastify body limit from 1MB to 10MB to accommodate base64-encoded images
2. Removed duplicate coverImage string length validation that was blocking base64 data URLs
3. Fixed base64 size calculation to properly extract and measure just the base64 data portion
4. Updated validateDataUrl regex to allow whitespace in base64 strings
5. Added proper error handling with 400 status codes and helpful error messages instead of 500 errors
Users can now successfully upload cover images as base64 data URLs up to 5MB (decoded size) and will receive clear validation error messages if uploads fail.
Closes#65
### Explanation
_No response_
### Issue
_No response_
### Attestations
- [ ] I have read and agree to the [Code of Conduct](https://docs.nhcarrigan.com/community/coc/)
- [ ] I have read and agree to the [Community Guidelines](https://docs.nhcarrigan.com/community/guide/).
- [ ] My contribution complies with the [Contributor Covenant](https://docs.nhcarrigan.com/dev/covenant/).
### Dependencies
- [ ] I have pinned the dependencies to a specific patch version.
### Style
- [ ] I have run the linter and resolved any errors.
- [ ] My pull request uses an appropriate title, matching the conventional commit standards.
- [ ] My scope of feat/fix/chore/etc. correctly matches the nature of changes in my pull request.
### Tests
- [ ] My contribution adds new code, and I have added tests to cover it.
- [ ] My contribution modifies existing code, and I have updated the tests to reflect these changes.
- [ ] All new and existing tests pass locally with my changes.
- [ ] Code coverage remains at or above the configured threshold.
### Documentation
_No response_
### Versioning
_No response_
Reviewed-on: #64
### Explanation
_No response_
### Issue
_No response_
### Attestations
- [ ] I have read and agree to the [Code of Conduct](https://docs.nhcarrigan.com/community/coc/)
- [ ] I have read and agree to the [Community Guidelines](https://docs.nhcarrigan.com/community/guide/).
- [ ] My contribution complies with the [Contributor Covenant](https://docs.nhcarrigan.com/dev/covenant/).
### Dependencies
- [ ] I have pinned the dependencies to a specific patch version.
### Style
- [ ] I have run the linter and resolved any errors.
- [ ] My pull request uses an appropriate title, matching the conventional commit standards.
- [ ] My scope of feat/fix/chore/etc. correctly matches the nature of changes in my pull request.
### Tests
- [ ] My contribution adds new code, and I have added tests to cover it.
- [ ] My contribution modifies existing code, and I have updated the tests to reflect these changes.
- [ ] All new and existing tests pass locally with my changes.
- [ ] Code coverage remains at or above the configured threshold.
### Documentation
_No response_
### Versioning
_No response_
Co-authored-by: Hikari <hikari@nhcarrigan.com>
Reviewed-on: #60
## Summary
This PR implements comprehensive user profile enhancements including:
- User profile pages showing stats, badges, social links, and bio
- Achievement system with 62 achievements across 5 categories
- Primary badge selection allowing users to display their preferred badge
- Admin profile editing capabilities
## Changes
### User Profiles (#45)
- **Frontend**: User profile pages with stats display
- Profile cards showing avatar, display name, username, and bio
- Social links section (Website, GitHub, Bluesky, LinkedIn, Twitch, YouTube, Discord)
- Stats display (suggestions, accepted suggestions, likes, comments)
- Recent achievements section
- Badge display
- Report button for other users' profiles
- **Backend**: Profile API endpoints
- Get user profile by username or ID
- Profile includes stats, badges, and achievement points
### Achievement System (#48)
- **Database**: UserAchievement model for tracking progress
- **62 Total Achievements** across 5 categories:
- **Suggestions (15)**: First suggestion through ultimate curator
- **Likes (12)**: First like through legendary fan
- **Comments (12)**: First comment through review legend
- **Engagement (15)**: Login streaks and activity milestones
- **Reports (8)**: Valid reports and accuracy tracking
- **Backend**: AchievementService with real-time checking
- Integrated into all user interaction points
- API endpoints for achievement data
- Progress tracking to avoid recalculation
- **Frontend**: Achievements page and profile integration
- Full achievements page with category filtering
- Tier-based styling (Bronze, Silver, Gold, Platinum, Diamond)
- Progress indicators for in-progress achievements
- Recent achievements on profile pages
### Primary Badge System (#49)
- **Database**: Add primaryBadge field to User model
- **Backend**: Update profile endpoints to include primary badge
- **Frontend**: Primary badge selection in settings
- Only shows badges the user has earned
- Displayed on profile page
- Displayed in comments (next to username)
- Falls back to no badge if selection is invalid
- **Admin Features**: Admin can edit any user's primary badge
### Admin Enhancements
- Comprehensive profile editing modal for admins
- Edit display name, bio, slug, social links
- Set primary badge for users
- Visual feedback for save/error states
- Admin action buttons in report review modals
- Ban user, delete comment, edit profile
- Integrated with report workflow
### Quality Improvements
- Improved dropdown option contrast for readability
- Hide all badges when no primary badge is selected
- "View All" achievements link only shown on own profile
- Improved achievement text readability
## Testing
- â User profiles display correctly with stats and badges
- â Achievement checking works for all interaction types
- â Primary badge selection persists and displays correctly
- â Admin profile editing saves successfully
- â Report workflow integrated with admin actions
- â Achievements page shows all 62 achievements with filtering
- â Text readability improved across components
Closes#45Closes#48Closes#49
Co-authored-by: Hikari <hikari@nhcarrigan.com>
Reviewed-on: #58
Co-authored-by: Naomi Carrigan <commits@nhcarrigan.com>
Co-committed-by: Naomi Carrigan <commits@nhcarrigan.com>
## Summary
This PR implements several improvements to the library application:
- Added start and finish date tracking for media items
- Added "Retired" category for abandoned media
- Implemented avatar-based user menu with dropdown navigation
- Added automatic background token refresh to prevent session expiry
- Created centralised logging system with frontend-to-API log forwarding
- Added toast notifications for error handling
## Changes
### Media Tracking (#41)
- Added `dateStarted` and `dateFinished` fields to Books, Games, Manga, Music, and Shows
- Updated TypeScript types, Prisma schema, and API services
- Added manual date input fields to frontend forms
- Properly converts HTML date strings to Date objects before API submission
### Retired Category (#43)
- Added `RETIRED` status to all media type enums
- Updated Prisma schema, frontend dropdowns, and filter buttons
- Added status label handling for retired items
### User Menu (#46)
- Replaced username text with avatar image in header
- Created dropdown menu with navigation items (Users, Audit, Suggestions)
- Added logout button to menu
- Implemented keyboard accessibility (tabindex, role, keyup handlers)
### Token Refresh (#44)
- Implemented automatic token refresh every 13 minutes in background
- Added proactive refresh to prevent token expiry during form filling
- Prevents users from losing form data due to expired sessions
### Centralised Logging (#1)
- Created `/log` endpoint on API to receive frontend logs
- Replaced API console.log calls with @nhcarrigan/logger
- Created ConsoleLoggerService to intercept all console methods on frontend
- Added global error handlers (window.error, unhandledrejection) on frontend
- Added process error handlers (uncaughtException, unhandledRejection, SIGTERM, SIGINT) on API
- All frontend console activity now forwarded to centralised logging
### Error Handling
- Created ToastService and ToastComponent for displaying errors
- Integrated with GlobalErrorHandler and HTTP interceptor
- Added accessibility features (keyboard navigation, ARIA attributes)
- Set toast opacity to 40% for optimal readability
### Testing & Build
- Fixed pre-existing test failure for GET / route (now returns version info)
- Added ESM module mocking (jsdom, marked, dompurify, @nhcarrigan/logger)
- Configured Jest with isolatedModules to handle TypeScript errors
- Excluded test-setup.ts from production build
- All tests passing (123 total)
- Build passing with no errors
## Test Plan
- [x] All tests pass (123 tests)
- [x] Build passes without errors
- [x] Lint passes (only pre-existing warnings)
- [x] Date fields work correctly on all media types
- [x] Retired status displays and filters properly
- [x] Avatar menu opens/closes correctly with keyboard and mouse
- [x] Token refresh prevents session expiry
- [x] Toast notifications appear for errors
- [x] Frontend logs forward to API successfully
- [x] Root route returns version information
Closes#41Closes#43Closes#44Closes#46Closes#1đ¤ Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Hikari <hikari@nhcarrigan.com>
Reviewed-on: #50
Co-authored-by: Naomi Carrigan <commits@nhcarrigan.com>
Co-committed-by: Naomi Carrigan <commits@nhcarrigan.com>