Files
spotlightcam/docs/TODO.md

575 lines
20 KiB
Markdown
Raw Normal View History

# TODO - spotlight.cam
**Active tasks and roadmap - optimized for quick reference**
---
## 🎯 CURRENT STATUS
**Phase:** 3 (MVP Finalization) - ✅ COMPLETED
**Previous Phases:**
- Phase 2.5 (WebRTC Implementation) - ✅ COMPLETED
- Phase 2 (Matches & Ratings API) - ✅ COMPLETED
- Phase 1.6 (Competition Heats System) - ✅ COMPLETED
**Progress:** 100% MVP complete
**Status:** Ready for production deployment
### 🔧 CURRENT STATUS - Backend Tests (2025-11-20) - ✅ ALL PASSING!
**Test Status:** 223/223 passing (100%) - ✅ ALL TESTS FIXED!
- **Initial state:** 145/223 (65%)
- **After cleanup fixes:** 189/223 (84.8%)
- **Final state:** 223/223 (100%)
- **Total improvement:** +78 tests (+35%)
**Code Coverage:** 71.31% (up from ~45%)
**✅ All fixes completed:**
1. **Test cleanup** - replaced `deleteMany({})` with selective deletion:
- `backend/src/__tests__/events.test.js` - selective deletion by username/email/slug
- `backend/src/__tests__/matches.test.js` - selective deletion by username/email/slug
- `backend/src/__tests__/csrf.test.js` - selective deletion by username/email
2. **Cleanup resilience** - replaced `delete()` with `deleteMany()`:
- `backend/src/__tests__/socket.test.js` - all afterAll + inline cleanup
- `backend/src/__tests__/matches.test.js` - inline cleanup (2 locations)
- `backend/src/__tests__/socket-webrtc.test.js` - inline cleanup
3. **Socket tests fixes:**
- Changed `eventId``slug` in socket event handlers
- Added `EventParticipant` creation before join_event_room
- Added safety checks before creating FK relationships
4. **Auth tests fixes:**
- `app.test.js` - CORS origin localhost:8080
- `security.js` - added localhost:3000 to allowed origins (dev)
- `auth-phase1.5.test.js` - fixed error message expectations
5. **Test isolation** - unique test data per suite to prevent race conditions:
- `users.test.js` - prefixed usernames with `users_` (users_john_dancer, users_sarah_swings)
- `matches.test.js` - prefixed with `matches_` (matches_john_dancer, etc.) + unique event slug
- `events.test.js` - prefixed with `events_` (events_john_dancer, etc.) + unique slugs + unique worldsdc_id
**Commits made:**
- `test: fix socket.test.js cleanup and event room parameters`
- `test: improve test cleanup - selective deletion instead of wiping tables`
- `test: fix test isolation by using unique test data per suite`
### 📋 FUTURE UX/UI IMPROVEMENTS
**Dashboard Page (Post-Login):**
- [ ] Create `/dashboard` route as default landing page after login
- [ ] Show current user information (profile summary, stats)
- [ ] Quick access buttons to active chats (event rooms, match chats)
- [ ] Display ongoing discussions/conversations
- [ ] Show upcoming events user is registered for
- [ ] Recent activity feed (new matches, messages, ratings)
- [ ] Navigation shortcuts to key features
**Event Chat Sidebar Enhancements:**
- [ ] Add competitor number display for each user in sidebar
- [ ] Show user nationality (flag + country code)
- [ ] Expand user info cards in sidebar:
- Competition heats (already implemented)
- Competitor number
- Country/nationality
- User role/level
- Years of experience (if available in profile)
- Average rating (if rated)
- [ ] Consider expandable user cards (click to see more details)
- [ ] Add filtering options:
- By nationality
- By division/level
- By competitor number range
- [ ] Improve mobile responsiveness for extended sidebar info
### ✅ Completed
- Phase 0: Frontend mockup with all views
- Phase 1: Backend Foundation
- Node.js + Express API
- PostgreSQL database with Prisma ORM
- JWT authentication (register, login)
- Socket.IO real-time chat (event & match rooms)
- Comprehensive test coverage (81%+)
docs: update README and docs to reflect Phase 1.5 completion Update documentation to accurately reflect all features implemented in Phase 1.5: README.md updates: - Replace outdated "mockup" references with real implementation status - Add comprehensive feature list with Phase 1.5 additions - Document 7 database tables (added event_participants) - Add user profile features (social media, location, public profiles) - Add event security features (unique slugs) - Update tech stack versions and test coverage (81%+) - Add detailed setup instructions for dev and prod profiles - Update roadmap to show Phase 1.5 as completed SESSION_CONTEXT.md updates: - Update current status to Phase 1.5 completed (65% overall) - Add new features to "What Works Now" section - Update database schema to 7 tables with all Phase 1.5 fields - Add new migrations (event slugs) - Update key files list with Phase 1.5 changes - Update frontend routes to use slugs (/events/:slug/chat) TODO.md updates: - Mark Phase 1.5 as completed with full feature list - Update progress tracking table (65% overall completion) - Update last modified date to 2025-11-13 Phase 1.5 features documented: - Email verification (AWS SES with link + PIN code) - Password reset workflow - WSDC API integration - User profiles (social media links: YouTube, Instagram, Facebook, TikTok) - User location (country dropdown with 195 countries, city) - Public profiles accessible at /{username} - Event participation tracking (auto-save joined events) - Event security (12-char unique slugs, prevent ID enumeration)
2025-11-13 21:51:11 +01:00
- Phase 1.5: Email & WSDC & Profiles & Security
- Email verification (AWS SES with link + PIN)
- Password reset workflow
- WSDC API integration (auto-fill registration)
- User profiles (social media links, location)
- Public profiles (/{username})
- Event participation tracking (auto-save joined events)
- Event security (unique slugs, prevent ID enumeration)
- QR code event check-in system (physical presence required at venue)
- Phase 1.6: Competition Heats System
- Database schema (divisions, competition_types, event_user_heats)
- Backend API (CRUD operations, validation)
- Frontend components (HeatsBanner, forms, badges)
- Phase 2: Matches & Ratings API
- Match requests with CUID slugs
- Real-time match notifications
- Ratings system (1-5 stars, comments, preferences)
- Public profile ratings display
- Profile links from chat/matches
- Message history persistence
- Duplicate rating prevention
**See:** `docs/archive/COMPLETED.md` for full list of completed tasks
---
## 📌 Phase 1: Backend Foundation - ✅ COMPLETED
**Completed:** 2025-11-12
**Time Spent:** ~14 hours
### ✅ Step 1: Backend Setup (COMPLETED)
- [x] Add `backend` service to docker-compose.yml
- [x] Initialize Node.js + Express project
- [x] Create folder structure (routes, controllers, middleware, etc.)
- [x] Add healthcheck endpoint: `GET /api/health`
- [x] Update nginx config to proxy `/api/*` to backend
- [x] Unit tests (7 tests passing)
### ✅ Step 2: PostgreSQL Setup (COMPLETED)
- [x] Add `db` service (PostgreSQL 15) to docker-compose.yml
- [x] Configure volumes for data persistence
- [x] Prisma ORM implementation
- [x] Create database schema (6 tables with relations)
- [x] Add indexes for performance
- [x] Create seed data (3 events, 2 users, chat rooms)
- [x] Fix OpenSSL compatibility issue for Prisma
### ✅ Step 3: Authentication API (COMPLETED)
- [x] Install dependencies: bcrypt, jsonwebtoken, express-validator
- [x] Implement password hashing with bcrypt (10 salt rounds)
- [x] Implement JWT token generation and verification
- [x] Create endpoints: register, login, /users/me
- [x] Create auth middleware for protected routes
- [x] Update frontend AuthContext to use real API
- [x] Unit tests (30 tests, 78%+ coverage)
### ✅ Step 4: WebSocket Chat (COMPLETED)
- [x] Install Socket.IO 4.8.1 on backend
- [x] Setup Socket.IO server with Express integration
- [x] JWT authentication for socket connections
- [x] Event rooms (join/leave/messages/active users)
- [x] Match rooms (private 1:1 chat)
- [x] Install socket.io-client on frontend
- [x] Update EventChatPage with real-time messaging
- [x] Update MatchChatPage with real-time chat
- [x] Unit tests (12 tests, 89% coverage for Socket.IO module)
---
## 📌 Phase 1.6: Competition Heats System - ✅ COMPLETED
**Completed:** 2025-11-14
**Time Spent:** ~8 hours
**Status:** Fully implemented and tested
### Business Logic Summary
- Users must declare their competition heats before matchmaking
- One user can compete in multiple divisions/heats (e.g., J&J Novice + Strictly Advanced)
- **Constraint:** Cannot compete in same role in same division+competition type (e.g., cannot have "J&J Novice Leader" twice)
- Role is optional (can be NULL = undeclared)
- Heat numbers: 1-9
- Format example: "J&J NOV 1 L" (Jack & Jill, Novice, Heat 1, Leader)
### Step 1: Database Schema - ✅ COMPLETED
- [x] Create migration for 3 new tables:
- `divisions` - Pre-defined competition divisions
- Columns: id, name (varchar), abbreviation (varchar 3), display_order (int)
- Seed data: Newcomer (NEW), Novice (NOV), Intermediate (INT), Advanced (ADV), All-Star (ALL), Champion (CHA)
- `competition_types` - Pre-defined competition types
- Columns: id, name (varchar), abbreviation (varchar 3)
- Seed data: Jack & Jill (J&J), Strictly (STR)
- `event_user_heats` - User's declared heats for event
- Columns: id, user_id, event_id, division_id, competition_type_id, heat_number (1-9), role (enum: Leader/Follower/NULL), created_at, updated_at
- **UNIQUE constraint:** (user_id, event_id, division_id, competition_type_id, role)
- Foreign keys: user_id → users.id, event_id → events.id, division_id → divisions.id, competition_type_id → competition_types.id
- Indexes: (user_id, event_id), (event_id)
- [x] Update Prisma schema
- [x] Run migration
- [x] Verify seed data
### Step 2: Backend API - ✅ COMPLETED
- [x] Create routes and controllers:
- `GET /api/divisions` - List all divisions (public)
- `GET /api/competition-types` - List all competition types (public)
- `POST /api/events/:slug/heats` - Add/update user's heats (authenticated)
- Input: array of { divisionId, competitionTypeId, heatNumber, role? }
- Validation: unique constraint, heat number 1-9
- Replace all existing heats (upsert pattern)
- `GET /api/events/:slug/heats/me` - Get current user's heats (authenticated)
- `GET /api/events/:slug/heats/all` - Get all users' heats for sidebar (authenticated)
- Returns: userId, username, avatar, heats[]
- `DELETE /api/events/:slug/heats/:id` - Delete specific heat (authenticated)
- [x] Validation middleware:
- Heat number 1-9
- Role enum (Leader/Follower/NULL)
- Unique constraint enforcement
- User must be event participant
- [x] Unit tests (CRUD operations, validation, constraints)
### Step 3: Socket.IO Events - ✅ COMPLETED
- [x] Add event: `heats_updated` - Broadcast when user updates heats
- Payload: { userId, username, heats[] }
- Send to all users in event room
- [x] Update active_users event to include heats data
### Step 4: Frontend Components - ✅ COMPLETED
- [x] Create HeatsBanner component (sticky between header and chat) - ✅ DONE
- [x] Show only if user has no heats declared
- [x] Form with dynamic heat entries (add/remove)
- [x] Fields per entry: Competition Type (select), Division (select), Heat Number (1-9), Role (optional: Leader/Follower)
- [x] "Save Heats" button → POST /api/events/:slug/heats
- [x] On save success: hide banner, show success message
- [x] Basic heats display in EventChatPage (⏳ Enhanced UI features remain for Phase 4)
- [x] Create frontend API methods in services/api.js - ✅ DONE
- [x] divisionsAPI.getAll()
- [x] competitionTypesAPI.getAll()
- [x] heatsAPI.saveHeats(slug, heats[])
- [x] heatsAPI.getMyHeats(slug)
- [x] heatsAPI.getAllHeats(slug)
- [x] heatsAPI.deleteHeat(slug, heatId)
- [x] Socket.IO integration - Basic support implemented
### Step 4.1: EventChatPage Integration - ⏳ OPTIONAL ENHANCEMENTS (Phase 4)
**What needs to be done:**
1. **Add state management for heats:**
```javascript
const [myHeats, setMyHeats] = useState([]);
const [userHeats, setUserHeats] = useState(new Map()); // userId → heats[]
const [showHeatsBanner, setShowHeatsBanner] = useState(false);
const [hideMyHeats, setHideMyHeats] = useState(false);
const [showHeatsModal, setShowHeatsModal] = useState(false);
```
2. **Load heats on component mount:**
```javascript
useEffect(() => {
const loadHeats = async () => {
const [myHeatsData, allHeatsData] = await Promise.all([
heatsAPI.getMyHeats(slug),
heatsAPI.getAllHeats(slug),
]);
setMyHeats(myHeatsData);
setShowHeatsBanner(myHeatsData.length === 0);
// Map userHeats
const heatsMap = new Map();
allHeatsData.forEach(userHeat => {
heatsMap.set(userHeat.userId, userHeat.heats);
});
setUserHeats(heatsMap);
};
loadHeats();
}, [slug]);
```
3. **Add HeatsBanner before chat:**
```jsx
{showHeatsBanner && (
<HeatsBanner
slug={slug}
onSave={() => {
setShowHeatsBanner(false);
// Reload heats
}}
/>
)}
```
4. **Add "Edit Heats" button in header (next to "Leave Event"):**
```jsx
<button
onClick={() => setShowHeatsModal(true)}
className="flex items-center gap-2 px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50"
>
<Edit size={16} />
Edit Heats
</button>
```
5. **Create modal for editing heats (reuse HeatsBanner logic)**
6. **Add heat badges to sidebar under username:**
```jsx
{activeUsers.map(activeUser => {
const userHeatsForThisUser = userHeats.get(activeUser.userId) || [];
const hasHeats = userHeatsForThisUser.length > 0;
return (
<div key={activeUser.userId}>
<div className="flex items-center">
<img src={activeUser.avatar} />
<span>{activeUser.username}</span>
</div>
{/* Heat badges */}
<div className="flex flex-wrap gap-1 mt-1">
{userHeatsForThisUser.slice(0, 3).map(heat => (
<span key={heat.id} className="text-xs px-2 py-0.5 bg-blue-100 text-blue-700 rounded">
{heat.competitionType.abbreviation} {heat.division.abbreviation} {heat.heatNumber}
{heat.role && ` ${heat.role[0]}`}
</span>
))}
{userHeatsForThisUser.length > 3 && (
<span className="text-xs px-2 py-0.5 bg-gray-100 text-gray-600 rounded">
+{userHeatsForThisUser.length - 3}
</span>
)}
</div>
{/* UserPlus button - disabled if no heats */}
<button
onClick={() => handleMatchWith(activeUser.userId)}
disabled={!hasHeats}
className="p-1 text-primary-600 hover:bg-primary-50 rounded disabled:opacity-30 disabled:cursor-not-allowed"
>
<UserPlus className="w-4 h-4" />
</button>
</div>
);
})}
```
7. **Add filter checkbox above active users:**
```jsx
<label className="flex items-center gap-2 text-sm text-gray-700 mb-2">
<input
type="checkbox"
checked={hideMyHeats}
onChange={(e) => setHideMyHeats(e.target.checked)}
className="rounded border-gray-300"
/>
Hide users from my heats
</label>
```
8. **Filter logic:**
```javascript
const filteredUsers = hideMyHeats
? activeUsers.filter(activeUser => {
const theirHeats = userHeats.get(activeUser.userId) || [];
return !theirHeats.some(theirHeat =>
myHeats.some(myHeat =>
myHeat.divisionId === theirHeat.divisionId &&
myHeat.competitionTypeId === theirHeat.competitionTypeId &&
myHeat.heatNumber === theirHeat.heatNumber
)
);
})
: activeUsers;
```
9. **Socket.IO heats_updated listener:**
```javascript
useEffect(() => {
const socket = getSocket();
if (!socket) return;
socket.on('heats_updated', ({ userId, username, heats }) => {
setUserHeats(prev => {
const newMap = new Map(prev);
newMap.set(userId, heats);
return newMap;
});
// If it's current user, update myHeats
if (userId === user.id) {
setMyHeats(heats);
setShowHeatsBanner(heats.length === 0);
}
});
return () => {
socket.off('heats_updated');
};
}, [user.id]);
```
### Step 5: Styling & UX - ✅ BASIC COMPLETE
- [x] Heat badges design
- [x] Banner responsive design (mobile + desktop)
- [x] Loading states for heat operations
- [x] Error handling & validation messages
### Step 6: Testing & Edge Cases - ✅ COMPLETED
- [x] Test unique constraint violation (frontend + backend)
- [x] Backend unit tests for heats API
- [x] Test role optional (NULL) handling
### Technical Notes
- **Abbreviations:**
- Divisions: NEW, NOV, INT, ADV, ALL, CHA
- Competition Types: J&J, STR
- Roles: L (Leader), F (Follower), empty (NULL)
- **Display format:** "{CompType} {Div} {Heat} {Role?}" → "J&J NOV 1 L"
- **Future enhancement:** When Matches API is implemented, editing heats with active match requires partner confirmation
---
## 📌 Phase 2.5: WebRTC P2P File Transfer - ✅ COMPLETED
**Completed:** 2025-11-15
**Time Spent:** ~10 hours
### Step 1: WebRTC Signaling - ✅ COMPLETED
- [x] Socket.IO signaling events (offer, answer, ICE candidates)
- [x] Frontend WebRTC setup (RTCPeerConnection)
- [x] STUN server configuration
- [x] Connection state monitoring
- [x] Unit tests (7 backend tests passing)
### Step 2: WebRTC File Transfer - ✅ COMPLETED
- [x] RTCDataChannel setup (ordered, reliable)
- [x] File metadata exchange
- [x] File chunking (16KB chunks)
- [x] Progress monitoring (sender & receiver)
- [x] Error handling & reconnection
- [x] Complete P2P video transfer flow
- [x] Tested up to 700MB files
- [x] Fallback: Link sharing UI
---
## 🎯 Future Phases (Reference)
### Phase 3: MVP Finalization - ✅ COMPLETED
- [x] ✅ Security hardening:
- Rate limiting (express-rate-limit) ✅
- Input validation & sanitization ✅
- CORS configuration ✅
- SQL injection prevention ✅
- XSS protection ✅
- CSRF protection ✅
- Account lockout ✅
- [x] ✅ Testing:
- Integration tests (API endpoints) ✅
- WebRTC connection tests ✅
- 223/223 tests passing (100%) ✅
- 71% code coverage ✅
- [x] ✅ PWA features:
- Web app manifest ✅
- Service worker (offline support) ✅
- App icons & splash screens ✅
- Install prompt ✅
- iOS support ✅
- [x] ✅ Deployment preparation:
- Production Docker images (Dockerfile.prod) ✅
- Environment configuration (.env.production) ✅
- Database backup scripts ✅
- Health check scripts ✅
- Monitoring documentation ✅
- Docker compose profiles (dev/prod) ✅
**Note:** E2E tests (Playwright/Cypress) and CI/CD pipeline are optional enhancements for Phase 4.
### Phase 5: Optional Extensions
- [ ] User badges & trust system
- [ ] Block users
- [ ] Public profiles
- [ ] Push notifications
- [ ] Video compression
- [ ] Multi-file transfer
---
## 📝 Active Development Tasks
### Documentation
- [x] ✅ README.md
- [x] ✅ docs/QUICKSTART.md
- [x] ✅ docs/CONTEXT.md
- [x] ✅ docs/TODO.md
- [x] ✅ docs/SESSION_CONTEXT.md
- [x] ✅ docs/ARCHITECTURE.md
- [x] ✅ docs/DEPLOYMENT.md
- [x] ✅ docs/MONITORING.md
- [x] ✅ docs/archive/COMPLETED.md
- [x] ✅ docs/archive/RESOURCES.md
- [ ] ⏳ API documentation (Swagger/OpenAPI) - after backend
- [ ] ⏳ Architecture diagrams - after backend
- [ ] ⏳ WebRTC flow diagram - after WebRTC implementation
### Infrastructure
- [x] ✅ Docker Compose (nginx, frontend, backend, db)
- [x] ✅ Production Dockerfiles (Dockerfile.prod for frontend & backend)
- [x] ✅ Docker Compose profiles (dev/prod)
- [x] ✅ Production environment configuration
- [x] ✅ Operations scripts (backup, restore, health-check)
- [ ] ⏳ CI/CD pipeline (GitHub Actions) - Optional
- [ ] ⏳ HTTPS setup (Let's Encrypt) - Requires server
### Testing
- [x] ✅ Backend tests (Jest + Supertest) - 223/223 passing, 71% coverage
- [x] ✅ WebRTC tests - 7 backend tests passing
- [x] ✅ Socket.IO tests - Complete coverage
- [x] ✅ Security tests (CSRF, rate limiting, auth)
- [ ] ⏳ Frontend tests (Vitest + React Testing Library) - Optional
- [ ] ⏳ E2E tests (Playwright / Cypress) - Optional
---
## 🚀 Quick Commands
**Start development:**
```bash
docker compose up --build
```
**Rebuild after changes:**
```bash
docker compose down && docker compose up --build
```
**Access:**
- Frontend: http://localhost:8080
- Backend (future): http://localhost:8080/api
**Git workflow:**
```bash
git status
git add .
git commit -m "feat: description"
```
---
## 📊 Progress Tracking
| Phase | Status | Progress | Time Spent |
|-------|--------|----------|------------|
| Phase 0: Frontend Mockup | ✅ Done | 100% | ~8h |
| Phase 1: Backend Foundation | ✅ Done | 100% | ~14h |
| Phase 1.5: Email & WSDC & Profiles | ✅ Done | 100% | ~12h |
| Phase 1.6: Competition Heats | ✅ Done | 100% | ~8h |
| Phase 2: Matches & Ratings API | ✅ Done | 100% | ~10h |
| Phase 2.5: WebRTC Implementation | ✅ Done | 100% | ~10h |
| Phase 3: MVP Finalization | ✅ Done | 100% | ~20h |
| **Total MVP** | **✅ Complete** | **100%** | **~82h** |
| Phase 4: Extensions | ⏳ Optional | - | TBD |
**Overall MVP Progress:** 100% ✅ Ready for production deployment
---
## 📝 Notes
- ✅ All MVP features implemented and tested
- ✅ 223/223 backend tests passing (71% coverage)
- ✅ Production deployment ready (Docker configs, scripts, monitoring)
- ✅ Security hardened (CSRF, rate limiting, account lockout)
- ✅ PWA enabled (offline support, iOS compatible)
- 🚀 Ready for production deployment (requires infrastructure setup)
---
**For detailed task history:** See `docs/archive/COMPLETED.md`
**For learning resources:** See `docs/archive/RESOURCES.md`
**For quick session context:** See `docs/SESSION_CONTEXT.md`
**For technical details:** See `docs/ARCHITECTURE.md`
---
**Last Updated:** 2025-11-20