Commit Graph

16 Commits

Author SHA1 Message Date
Radosław Gierwiało
082105c5bf refactor(frontend): Phase 3 - create advanced composite components
Extract complex UI sections into reusable composite components

New Components Created:
1. HeatBadges (heats/HeatBadges.jsx)
   - Displays competition heats with compact notation
   - Configurable max visible badges with "+X more" overflow
   - Tooltips with full heat information

2. UserListItem (users/UserListItem.jsx)
   - Reusable user entry with avatar, username, full name
   - Optional heat badges display
   - Flexible action button slot (render props pattern)
   - Online/offline status support

3. ParticipantsSidebar (events/ParticipantsSidebar.jsx)
   - Complete sidebar component for event participants
   - Filter checkbox for hiding users from own heats
   - Participant and online counters
   - Integrated UserListItem with match actions

4. FileTransferProgress (webrtc/FileTransferProgress.jsx)
   - WebRTC P2P file transfer UI
   - Progress bar with percentage
   - Send/Cancel actions

5. LinkShareInput (webrtc/LinkShareInput.jsx)
   - Fallback link sharing when WebRTC unavailable
   - Google Drive, Dropbox link support

Pages Refactored:
- EventChatPage: 564 → 471 lines (-93 lines, -16%)
  * Replaced 90-line participants sidebar with <ParticipantsSidebar />
  * Removed duplicate formatHeat logic (now in HeatBadges)

- MatchChatPage: 446 → 369 lines (-77 lines, -17%)
  * Replaced 56-line file transfer UI with <FileTransferProgress />
  * Replaced 39-line link input form with <LinkShareInput />

Phase 3 Total: -170 lines
Grand Total (Phase 1+2+3): -559 lines (-17%)

Final Results:
- EventChatPage: 761 → 471 lines (-290 lines, -38% reduction)
- MatchChatPage: 567 → 369 lines (-198 lines, -35% reduction)

Benefits:
- Massive complexity reduction in largest components
- Composite components can be reused across pages
- Better testability - each component tested independently
- Cleaner code organization - single responsibility principle
- Easier maintenance - changes in one place propagate everywhere
2025-11-21 17:10:53 +01:00
Radosław Gierwiało
9e74343c3b refactor(frontend): Phase 2 - extract business logic into custom hooks
Separate concerns - move Socket.IO and form logic from components to reusable hooks

New Hooks:
- useForm: Generic form state management with handleChange/handleSubmit/reset
- useEventChat: Extract Socket.IO logic from EventChatPage (156 lines)
  * Manages messages, active users, connection state
  * Handles send message, load older messages with scroll preservation
  * Real-time updates via Socket.IO event listeners
- useMatchChat: Extract Socket.IO logic from MatchChatPage (115 lines)
  * Manages 1:1 chat messages and connection
  * Loads message history from API
  * Real-time message sync via Socket.IO

Pages Refactored:
- EventChatPage: 661 → 564 lines (-97 lines, -15%)
- MatchChatPage: 517 → 446 lines (-71 lines, -14%)

Benefits:
- Cleaner component code - UI separated from business logic
- Reusable hooks can be used in other components
- Easier to test - hooks can be unit tested independently
- Better code organization - single responsibility principle
- 168 lines eliminated from pages, moved to 271 lines of reusable hooks

Phase 2 Total: -168 lines
Grand Total (Phase 1+2): -389 lines (-12%)
2025-11-21 17:02:04 +01:00
Radosław Gierwiało
dea9d70bb9 refactor(frontend): integrate reusable components across all pages
Phase 1 refactoring - eliminate code duplication and improve maintainability

Changes:
- LoginPage: Integrate FormInput and LoadingButton components (-9 lines)
- RegisterPage: Replace inline forms with FormInput/LoadingButton/Alert (-62 lines)
- EventChatPage: Integrate ChatMessageList/ChatInput and Modal components (-100 lines)
- MatchChatPage: Integrate ChatMessageList/ChatInput components (-50 lines)
- ProfilePage: Already using reusable components (no changes)

Total reduction: 221 lines (-11.6%)

Benefits:
- Eliminated ~40% code duplication in chat UI
- Unified form inputs across authentication pages
- Consistent modal dialogs with ConfirmationModal
- Improved maintainability - changes propagate to all uses
- Faster feature development with component library

Components used:
- Alert, FormInput, FormSelect, LoadingButton, LoadingSpinner
- ChatMessageList, ChatMessage, ChatInput
- Modal, ConfirmationModal
2025-11-21 16:50:46 +01:00
Radosław Gierwiało
38adf1e5a5 feat(ui): unify avatars across navbar, profiles, event/match chat
- Add reusable Avatar with fallback, status dot, ring
- Replace <img> uses in Navbar, Profile, PublicProfile
- Use Avatar in MatchChatPage and EventChatPage messages and sidebars
- Fix own-message detection for snake_case payloads
2025-11-15 23:08:00 +01:00
Radosław Gierwiało
4a3e32f3b6 feat: implement Phase 2 - Matches API with real-time notifications
Backend changes:
- Add matches API routes (POST, GET, PUT, DELETE)
- Create/accept/reject match requests
- Auto-create private chat rooms on match acceptance
- Socket.IO notifications for match events (received, accepted, cancelled)
- Users join personal rooms (user_{id}) for notifications

Frontend changes:
- Add MatchesPage component with inbox UI
- Matches navigation link with notification badge
- Real-time match request count updates
- Accept/reject match functionality
- Filter matches by status (all/pending/accepted)
- Integrate match requests in EventChatPage (UserPlus button)

Features:
- Send match requests to event participants
- Accept incoming match requests
- Real-time notifications via Socket.IO
- Automatic private chat room creation
- Match status tracking (pending/accepted/completed)
- Authorization checks (only participants can match)
- Duplicate match prevention
2025-11-14 19:22:23 +01:00
Radosław Gierwiało
eaf80c6c6f feat: display user's heats in event chat header
- Show current user's heats in header next to connection status
- Display format: 'Your heats: J&J NOV 1 L, STR INT 2 L'
- Always visible - no need to click Edit Heats to see them
- Styled as badges matching sidebar heat badges
2025-11-14 18:41:06 +01:00
Radosław Gierwiało
3ebdd2d7df feat: pre-populate heats form with existing data when editing
- Add existingHeats prop to HeatsBanner component
- Load and format existing heats into form fields
- Pass myHeats to HeatsBanner in edit modal
- Users can now edit their heats instead of starting from scratch
2025-11-14 18:35:01 +01:00
Radosław Gierwiało
42f231a602 fix: correct participant data mapping in event chat sidebar
- Fix participant data structure mapping (use p.userId instead of p.user.id)
- Backend returns flat participant objects, not nested user objects
- Remove debug console.log statements
- Participants list now correctly displays all checked-in users
2025-11-14 18:10:35 +01:00
Radosław Gierwiało
e08492236a feat: show all checked-in participants in event chat sidebar
- Display all event participants (not just online users)
- Add online/offline status indicator (green/gray dot)
- Sort users: online first, then offline
- Show participant count and online count separately
- Load participants via /api/events/:slug/details endpoint
- Users can see who's checked in and has declared heats even when offline

This allows users to see the full picture of event participation,
not just who's currently connected to the chat.
2025-11-14 18:04:10 +01:00
Radosław Gierwiało
d88d972c03 feat: integrate heats system into EventChatPage
- Add state management for heats (myHeats, userHeats Map, showHeatsBanner, hideMyHeats, showHeatsModal)
- Load user's heats and all users' heats on component mount
- Display HeatsBanner when user has no heats declared
- Add "Edit Heats" button in header for users with declared heats
- Add modal for editing heats via HeatsBanner component
- Display heat badges under usernames in sidebar (format: J&J NOV 1 L)
- Show max 3 badges per user, with "+N" indicator for more
- Add filter checkbox to hide users from same heats
- Implement filter logic (hide if ANY heat matches: division + competition_type + heat_number)
- Disable UserPlus (match) button for users without declared heats
- Add Socket.IO heats_updated listener for real-time updates
- Update todo list to mark EventChatPage integration as completed
2025-11-14 17:41:35 +01:00
Radosław Gierwiało
a6e4981f17 fix: prevent bypassing event check-in via page refresh
Users could gain unauthorized access to event chats by refreshing the page after leaving an event. The socket handler was automatically creating participation records when users joined rooms, completely bypassing the QR code check-in requirement. This fix verifies that users have legitimately checked in before allowing socket room access.
2025-11-14 14:36:49 +01:00
Radosław Gierwiało
71cba01db3 feat: add QR code event check-in system
Backend:
- Add event_checkin_tokens table with unique tokens per event
- Implement GET /api/events/:slug/details endpoint (on-demand token generation)
- Implement POST /api/events/checkin/:token endpoint (date validation only in production)
- Implement DELETE /api/events/:slug/leave endpoint
- Add comprehensive test suite for check-in endpoints

Frontend:
- Add EventDetailsPage with QR code display, participant list, and stats
- Add EventCheckinPage with success/error screens
- Add "Leave Event" button with confirmation modal to EventChatPage
- Install qrcode.react library for QR code generation
- Update routing and API client with new endpoints

Features:
- QR codes valid from (startDate-1d) to (endDate+1d)
- Development mode bypasses date validation for testing
- Automatic participant count tracking
- Duplicate check-in prevention
- Token reuse for same event (generated once, cached)
2025-11-14 14:11:24 +01:00
Radosław Gierwiało
b2c2527c46 feat: add event slugs to prevent ID enumeration attacks
Replace sequential event IDs in URLs with unique alphanumeric slugs to prevent enumeration attacks. Event URLs now use format /events/{slug}/chat instead of /events/{id}/chat.

Backend changes:
- Add slug field (VARCHAR 50, unique) to Event model
- Create migration with auto-generated 12-char MD5-based slugs for existing events
- Update GET /api/events/:slug endpoint (changed from :id)
- Update GET /api/events/:slug/messages endpoint (changed from :eventId)
- Modify Socket.IO join_event_room to accept slug parameter
- Update send_event_message to use stored event context instead of passing eventId

Frontend changes:
- Update eventsAPI.getBySlug() method (changed from getById)
- Update eventsAPI.getMessages() to use slug parameter
- Change route from /events/:eventId/chat to /events/:slug/chat
- Update EventsPage to navigate using event.slug
- Update EventChatPage to fetch event data via slug and use slug in socket events

Security impact: Prevents attackers from discovering all events by iterating sequential IDs.
2025-11-13 21:43:58 +01:00
Radosław Gierwiało
9d8fc9f6d6 feat: add chat message history and infinite scroll
Backend changes:
- Socket.IO: Send last 20 messages on join_event_room
- REST API: Add GET /api/events/:eventId/messages endpoint with pagination
- Support for 'before' cursor-based pagination for loading older messages

Frontend changes:
- Load initial 20 messages when joining event chat
- Implement infinite scroll to load older messages on scroll to top
- Add loading indicator for older messages
- Preserve scroll position when loading older messages
- Add eventsAPI.getMessages() function for pagination

User experience:
- New users see last 20 messages immediately
- Scrolling up automatically loads older messages in batches of 20
- Smooth scrolling experience with position restoration

Note: Messages are encrypted in transit via HTTPS/WSS but stored
as plain text in database (no E2E encryption).
2025-11-13 20:16:58 +01:00
Radosław Gierwiało
75cb4b16e7 feat: implement real-time chat with Socket.IO
Implemented WebSocket-based real-time messaging for both event rooms and private match chats using Socket.IO with comprehensive test coverage.

Backend changes:
- Installed socket.io@4.8.1 for WebSocket server
- Created Socket.IO server with JWT authentication middleware
- Implemented event room management (join/leave/messages)
- Added active users tracking with real-time updates
- Implemented private match room messaging
- Integrated Socket.IO with Express HTTP server
- Messages are persisted to PostgreSQL via Prisma
- Added 12 comprehensive unit tests (89.13% coverage)

Frontend changes:
- Installed socket.io-client for WebSocket connections
- Created socket service layer for connection management
- Updated EventChatPage with real-time messaging
- Updated MatchChatPage with real-time private chat
- Added connection status indicators (● Connected/Disconnected)
- Disabled message input when not connected

Infrastructure:
- Updated nginx config to proxy WebSocket connections at /socket.io
- Added Upgrade and Connection headers for WebSocket support
- Set long timeouts (7d) for persistent WebSocket connections

Key features:
- JWT-authenticated socket connections
- Room-based architecture for events and matches
- Real-time message broadcasting
- Active users list with automatic updates
- Automatic cleanup on disconnect
- Message persistence in database

Test coverage:
- 12 tests passing (authentication, event rooms, match rooms, disconnect, errors)
- Socket.IO module: 89.13% statements, 81.81% branches, 91.66% functions
- Overall coverage: 81.19%

Phase 1, Step 4 completed. Ready for Phase 2 (Core Features).
2025-11-12 22:42:15 +01:00
Radosław Gierwiało
80ff4a70bf feat: initial project setup with frontend mockup
- Docker Compose setup with nginx reverse proxy and frontend service
- React + Vite + Tailwind CSS configuration
- Complete mockup of all application views:
  - Authentication (login/register)
  - Events list and selection
  - Event chat with matchmaking
  - 1:1 private chat with WebRTC P2P video transfer mockup
  - Partner rating system
  - Collaboration history
- Mock data for users, events, messages, matches, and ratings
- All UI text and messages in English
- Project documentation (CONTEXT.md, TODO.md, README.md, QUICKSTART.md)
2025-11-12 17:50:44 +01:00