Commit Graph

8107 Commits

Author SHA1 Message Date
Nuwan 48ff1dfbb1 docs(12-01): document legacy AttachmentStore implementation
- Comprehensive analysis of CoffeeScript Reflux store patterns
- Upload flow breakdown with FormData construction
- Client-side validation logic (10 MB limit)
- Hidden file input trigger pattern
- Error handling for 413/422 responses
- Integration points with ChatStore and dialog system
- React port patterns and implementation checklist
- 538 lines, 42 code examples

ATTACHMENT_LEGACY.md: .planning/phases/12-attachment-research-&-backend-validation/docs/ATTACHMENT_LEGACY.md
2026-02-02 18:54:43 +05:30
Nuwan ec0607a1d4 docs(12-02): validate backend infrastructure for attachments
- Validated MusicNotation model with S3/CarrierWave integration
- Documented REST endpoints (upload, download, delete)
- Confirmed WebSocket attachment metadata fields
- Identified file type mismatch: mp3 in requirements but not backend
- Backend is 95% ready - only mp3 support decision pending

BACKEND_VALIDATION.md: 547 lines

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-02 18:54:27 +05:30
Nuwan 62f16edfdf docs(12): create phase plan
Phase 12: Attachment Research & Backend Validation
- 2 plan(s) in 1 wave(s)
- 2 parallel, 0 sequential
- Ready for execution

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 18:47:14 +05:30
Nuwan a49c133353 docs(12): research phase domain
Phase 12: Attachment Research & Backend Validation
- Backend API contract documented (MusicNotation endpoints)
- MusicNotation model capabilities validated (S3, CarrierWave)
- Legacy AttachmentStore upload flow analyzed
- Integration points identified (chat composer, message display, WebSocket)
- File validation patterns documented (10MB limit, type whitelist)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-02 18:43:20 +05:30
Nuwan 631253d3f7 docs(roadmap): add v1.2 Session Attachments milestone
Add comprehensive roadmap for file attachment feature:
- Update PROJECT.md with v1.2 milestone and requirements
- Create REQUIREMENTS.md with 24 requirements across 7 categories
- Add Phases 12-16 to ROADMAP.md (5 phases, 10 plans)
- Update STATE.md with milestone v1.2 status

Phases:
- Phase 12: Attachment Research & Backend Validation (2 plans)
- Phase 13: File Upload Infrastructure (3 plans)
- Phase 14: Chat Integration & Display (2 plans)
- Phase 15: Real-time Synchronization (1 plan)
- Phase 16: Attachment Finalization (2 plans)

Coverage: 24/24 requirements mapped (100%)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-02 18:38:34 +05:30
Nuwan 961c0e36bb chore: update debug logging and test storage state
Changes:
- .gitignore: Add .run-claude.sh to ignored files
- JKSessionScreen.js: Add "-DEBUG-" prefix to console logs for easier filtering
- user1.json, user2.json: Update test authentication state
- 11-VERIFICATION.md: Add verification document for Phase 11

These are maintenance updates from chat feature development and testing.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-02 17:26:16 +05:30
Nuwan 87d24f6ca1 docs: update handoff with chat pause and profile modal TODO 2026-02-02 17:22:53 +05:30
Nuwan 010cf55302 fix: show alert instead of redirecting to non-existent /client route
When profile guard fails (single-player profile detected):
- Show JavaScript alert explaining the issue
- Leave session cleanly via handleLeaveSession()
- Redirect to dashboard (/) instead of /client (404)

Alert message explains:
- Audio profile not suitable for multi-user sessions
- Need proper audio interface or create private session

TODO: Replace alert() with proper modal dialog component
that offers options like legacy app (create private session,
go to audio settings, cancel).

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-02 10:13:14 +05:30
Nuwan 332ae61ba0 fix: implement legacy profile guard behavior (redirect to home)
Based on legacy app (web/app/assets/javascripts/wizard/gear_utils.js):

When canPlayWithOthers() fails (single-player profile detected):
- Legacy app shows dialog with options:
  * Create private session → redirects to new session
  * Go to audio settings → redirects to /account/audio
  * Cancel → redirects to home

Current implementation (without dialog):
- Reject with error.controlled_location = false
- Redirect to home (/client) when profile check fails
- Prevents user from joining with inadequate audio profile

This matches legacy behavior of kicking user back to home, but
WITHOUT the dialog that explains why or offers alternatives.

TODO: Add JKSessionProfileDialog component with same options as
legacy 'single-player-profile-dialog' for better UX.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-02 10:04:26 +05:30
Nuwan cff2c04732 fix: add AlertCallback alias and proper error in profile guard
Two fixes for built-in audio profile issues:

1. Add JK.AlertCallback as alias for JK.HandleAlertCallback
   - Native client calls default "JK.AlertCallback" before
     SessionSetAlertCallback is registered
   - Now both callback names point to same handler
   - Added logging for alert code 40 (audio profile issues)

2. Provide proper error when guardAgainstSinglePlayerProfile fails
   - Was calling reject() with no parameter (error = undefined)
   - Now creates Error object with message and canPlayResult data
   - Fixes "User profile is not appropriate for session: undefined"

These issues manifest with MacBook built-in mic/speakers when the
profile check fails canPlayWithOthers(), causing tracks to not
display because session guards don't pass.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-02 09:27:16 +05:30
Nuwan 970bbe3eb4 fix: await GetClientID() and add safe navigation for error handling
Two bugs fixed:

1. Missing await for GetClientID() in leaveSessionRest
   - jamClient.GetClientID() returns a Promise
   - Was passed unresolved to deleteParticipant(), causing
     DELETE /api/participants/[object Promise] 404 error
   - Now properly awaited before use

2. Unsafe property access on error object
   - error.controlled_location accessed without null check
   - Changed to error?.controlled_location (optional chaining)
   - Prevents "Cannot read properties of undefined" error

These issues manifested when using MacBook Pro built-in mic/speakers
instead of Scarlet audio interface, likely due to different
initialization timing or missing audio profile causing error paths.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-02 08:42:32 +05:30
Nuwan c4cc80e967 debug: add console logging for WebSocket chat message debugging 2026-02-02 08:02:41 +05:30
Nuwan 5132c83458 fix: pass client_id to exclude sender from WebSocket broadcast
The backend uses client_id to identify the sender and exclude them
from receiving their own message via WebSocket (avoiding duplication
with optimistic update).

Changes:
- rest.js: Add clientId parameter to sendChatMessage
- sessionChatSlice.js: Pass clientId to API call
- JKChatComposer.js: Get server.clientId from context and pass it

This fixes: Messages now broadcast to OTHER users in session, not
just the sender. The sender sees optimistic update immediately, other
users receive via WebSocket.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-01 22:16:01 +05:30
Nuwan 939225a610 fix: correct WebSocket callback signature for chat messages
The WebSocket onmessage handler passes (message, payload) to callbacks,
where payload contains the actual message data. Updated handleChatMessage
to use the second parameter (payload) instead of first (message).

This fixes: Multi-user chat messages now properly received and displayed

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-01 22:03:28 +05:30
Nuwan f3044a29e8 feat: add WebSocket chat message handler for multi-user chat
Enables real-time message delivery between users in the same session:

- Import addMessageFromWebSocket action from sessionChatSlice
- Create handleChatMessage callback to transform Protocol Buffer format
  to Redux format (msg_id → id, sender_id → senderId, etc.)
- Register CHAT_MESSAGE (237) callback when joining session
- Messages now dispatched to Redux when received via WebSocket

This fixes:
- Multi-user message exchange (messages now appear for remote users)
- Badge updates (unread count increments when messages arrive)

Protocol Buffer format (ChatMessage):
  - sender_name, sender_id, msg, msg_id, created_at

Redux format:
  - id, senderId, senderName, message, createdAt, channel, sessionId

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-01 00:21:00 +05:30
Nuwan 99f9d4b898 fix: correct message format handling and add optimistic update params
Two P0 bugs fixed:

1. "Unknown" sender name bug:
   - Root cause: Redux slice expected action.payload.message, but API
     returns message object directly as action.payload
   - Fix: Changed sessionChatSlice.js sendMessage.fulfilled to use
     action.payload instead of action.payload.message

2. First message not appearing bug:
   - Root cause: JKChatComposer wasn't passing optimisticId, userId,
     userName parameters needed for optimistic updates
   - Fix: Added uuid import, useAuth hook, and pass required params
     to sendMessage thunk

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-31 20:31:38 +05:30
Nuwan ec5427b48f wip: update handoff - two P0 bugs fixed, ready for UAT 2026-01-31 20:12:30 +05:30
Nuwan 6dc6c431ed fix(chat): handle user object from API responses
- Updated sendMessage.fulfilled to extract user.name from nested user object
- Updated fetchChatHistory.fulfilled to transform API format to internal format
- API response: { user: { name: "..." }, user_id: "..." }
- Internal format: { senderName: "...", senderId: "..." }
- WebSocket messages already use user_name (unchanged)

Fixes 'Unknown' sender name for messages from API (send + fetch).
2026-01-31 20:12:14 +05:30
Nuwan 2b593cce93 fix(chat): include user object in POST /api/chat response
- Changed create action to render show.rabl view instead of raw model
- Response now includes nested user object with name field
- Matches format returned by GET /api/chat (index action)
- Fixes 'Unknown' sender name issue for sent messages

Follows lobby chat pattern for consistent API response format.
2026-01-31 20:12:11 +05:30
Nuwan d5772ce1d7 wip: chat finalization paused - investigating repeated API requests 2026-01-31 19:42:53 +05:30
Nuwan b2327d77ae docs(11-02): complete UAT & final integration testing plan
Tasks completed: 3/3
- Task 1: UAT checklist prepared (50+ test cases)
- Task 2: User found P0 bug, fixed immediately
- Task 3: Milestone documentation complete

P0 Critical Bug Fixed:
- Chat message submission parameter mismatch (session_id → music_session)
- Single-line fix in jam-ui/src/helpers/rest.js
- Commit: 5b940ae

Milestone v1.1 Status: COMPLETE
- All 11 plans across Phases 6-11 complete
- P0/P1 issues: 1 found, 1 resolved
- Ready for production deployment

SUMMARY: .planning/phases/11-chat-finalization/11-02-SUMMARY.md
2026-01-31 19:22:42 +05:30
Nuwan 5b940ae7f4 fix(11-02): correct chat API parameter name (session_id → music_session)
P0 Critical Bug Fix:
- Frontend was sending session_id but backend expects music_session
- This caused 404 errors when submitting chat messages
- Fixed in sendChatMessage function (jam-ui/src/helpers/rest.js:993)

Root cause: Parameter name mismatch between frontend and backend
- Frontend: body.session_id = sessionId
- Backend: params[:music_session]
- Result: ActiveRecord.find(nil) → 404 error

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-31 19:18:25 +05:30
Nuwan a9178bd68b docs(11-02): prepare UAT test execution
Task 1 complete: UAT checklist prepared, automated tests identified

- UAT checklist: 50+ test cases across 9 categories (already exists)
- Automated tests: 68 unit tests (sessionChatSlice) + 29+ Playwright tests
- Unit tests passing (68/68 for sessionChatSlice)
- Integration tests require backend running (deferred to checkpoint)
- Regression tests identified (Backing Track, JamTrack)

Ready for human verification checkpoint.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-30 16:52:41 +05:30
Nuwan f2ccce86f7 docs(11-02): prepare comprehensive UAT checklist for chat finalization
- Created 11-02-UAT-CHECKLIST.md with 50+ test cases across 9 categories
- Automated test suite: 29+ Playwright tests
- Manual UAT categories: Initialization, Message Display, Composition, Receiving,
  Read/Unread Tracking, Error Handling, Performance, Accessibility, Edge Cases
- Regression checks for Backing Track and JamTrack players
- Test environment requirements documented
- Issue tracking template (P0/P1/P2/P3 severity levels)
2026-01-29 01:04:56 +05:30
Nuwan a401285940 wip: chat finalization paused after plan 11-01 (1/2 complete) 2026-01-27 23:11:18 +05:30
Nuwan a348e27985 docs(11-01): complete error handling & accessibility plan
Tasks completed: 3/3
- Comprehensive error handling and status display
- Accessibility and keyboard navigation
- Polish and edge case handling

SUMMARY: .planning/phases/11-chat-finalization/11-01-SUMMARY.md
2026-01-27 23:08:14 +05:30
Nuwan afcc1349c3 docs(11-01): complete error handling & accessibility plan
Summary of Phase 11 Plan 1 completion:
- 3 tasks completed in 28 minutes
- 7 files modified
- Comprehensive error handling with color-coded displays
- Full accessibility support (ARIA, keyboard navigation, focus management)
- Edge cases validated and handled gracefully
- Production-ready chat with retry functionality

Task commits:
- 6ce747385: feat(11-01): add comprehensive error handling and status display
- d39dcf36f: feat(11-01): add accessibility and keyboard navigation
- 336f88d89: refactor(11-01): polish edge cases and add PropTypes

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-27 23:06:41 +05:30
Nuwan 336f88d89c refactor(11-01): polish edge cases and add PropTypes
Polish edge case handling and add missing PropTypes for textarea ref.

- JKChatComposer: Add PropTypes for textareaRef prop, add defaultProps
- JKChatEmptyState: Update message to match plan spec ("Start the conversation!")
- Verified edge cases: clearSendError works with retry, rapid actions handled, empty states work
- All edge cases from plan verified: disconnection, long messages, rapid toggling, multiple unread

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-27 23:05:53 +05:30
Nuwan d39dcf36fd feat(11-01): add accessibility and keyboard navigation
Add comprehensive ARIA attributes, keyboard shortcuts, and focus management for chat interface.

- JKSessionChatWindow: Add role="dialog", aria-labelledby, Escape key handler, auto-focus textarea
- JKChatComposer: Add aria-label, aria-describedby, aria-invalid, role="alert" for validation
- JKChatHeader: Add id="chat-window-title" for aria-labelledby reference
- JKSessionChatButton: Add aria-label with unread count, aria-pressed state, role="button", tabIndex
- Focus management: Textarea receives focus when window opens (100ms delay for DOM)
- Keyboard navigation: Escape closes window, Tab order preserved, Enter sends message

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-27 23:05:04 +05:30
Nuwan 6ce7473850 feat(11-01): add comprehensive error handling and status display
Add persistent error display with retry button for send failures, WebSocket disconnection banner, and loading/error states for fetch operations.

- Add clearSendError action to sessionChatSlice for retry functionality
- JKChatComposer: Add retry button for sendError, improve error styling (red background)
- JKSessionChatWindow: Add disconnection banner (yellow) when !isConnected
- JKChatMessageList: Add loading spinner during fetch, error display for failed fetch
- Color coding: red for critical errors, yellow for warnings

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-27 23:03:46 +05:30
Nuwan 3a104f1429 docs(11): create phase plan
Phase 11: Chat Finalization
- 2 plans created
- 9 total tasks defined
- Ready for execution

Plans:
- 11-01: Error Handling, Accessibility & Polish (3 tasks)
- 11-02: UAT & Final Integration Testing (3 tasks)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-27 22:58:27 +05:30
Nuwan 0b5848cc05 docs(10-01): complete read/unread status validation plan
Complete Phase 10 Plan 1 with comprehensive integration testing:
- 17 Playwright tests validating unread tracking system
- Badge behavior tests (8): visibility, count display, reset, increment
- localStorage persistence tests (7): save/load, error handling, multi-channel
- E2E workflow tests (2): complete user journeys with state validation
- 94% pass rate (16/17 tests passing when backend running)
- Documents actual vs expected behavior for timestamp-based filtering

Test suite validates Redux state, localStorage persistence, and UI rendering.
All integration tests follow established patterns from Phase 9.

Updates: STATE.md (Phase 10 progress), ROADMAP.md (Plan 10-01 complete)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-27 22:01:58 +05:30
Nuwan ceafe11225 test(10-01): add integration tests for unread badge behavior
Add comprehensive Playwright integration tests for chat unread badge:
- Badge visibility based on count (hidden at 0, visible with count)
- Badge text formatting (1-99, "99+" for 100+)
- Badge reset when window opened
- Badge increment logic (closed window vs different channel)
- Multiple message handling
- Badge state after page reload

Tests validate Redux state, localStorage persistence, and UI rendering.

Related to Phase 10 Plan 1: Read/Unread Status Validation & Testing

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-27 21:59:55 +05:30
Nuwan 3b0277544e docs(10): create phase plan
Phase 10: Read/Unread Status Management
- 1 plan created
- 3 tasks defined (all integration/E2E testing)
- Ready for execution

Tasks:
- Integration tests for unread badge behavior (7+ tests)
- Integration tests for localStorage persistence (6+ tests)
- E2E test for complete unread tracking workflow
2026-01-27 20:04:16 +05:30
Nuwan ae1beab3dc docs(09-02): complete send message integration plan
Tasks completed: 3/3
- Integrate JKChatComposer into JKSessionChatWindow
- Write integration tests for send message flow (7 tests)
- Write integration tests for receive message flow (4 tests)

SUMMARY: .planning/phases/09-message-composition/09-02-SUMMARY.md
2026-01-27 19:50:20 +05:30
Nuwan 984c60c656 test(09-02): add integration tests for receive message flow
- Test WebSocket message display with sender info
- Test message deduplication (sent message not duplicated on WebSocket receive)
- Test auto-scroll to bottom on new message
- Test unread badge increment when window closed
- 4 comprehensive tests for real-time receive scenarios
2026-01-27 19:48:16 +05:30
Nuwan 9eb58bd02b test(09-02): add integration tests for send message flow
- Test send via button click
- Test send via Enter key
- Test Shift+Enter inserts newline without sending
- Test button disabled when empty or over 255 chars
- Test character count and validation message display
- Test error display on send failure
- Test optimistic update behavior
- 7 comprehensive tests for send scenarios
2026-01-27 19:47:50 +05:30
Nuwan b558bfe0c3 feat(09-02): integrate JKChatComposer into chat window
- Added JKChatComposer import and component
- Updated layout with flex container for proper spacing
- Header fixed at top, message list scrollable in middle, composer at bottom
- Complete three-section window structure (header/list/composer)
2026-01-27 19:47:20 +05:30
Nuwan 538cdd0239 docs(09-01): complete message composer UI & validation plan
Tasks completed: 3/3
- Create JKChatComposer component with textarea and send button
- Add keyboard handling for Enter and Shift+Enter
- Add character count validation feedback

SUMMARY: .planning/phases/09-message-composition/09-01-SUMMARY.md
2026-01-27 15:23:48 +05:30
Nuwan d4fc7005d8 feat(09-01): create JKChatComposer with validation and keyboard handling
- Controlled textarea for message input (1-255 chars after trim)
- Character count display (X/255) with color-coded feedback
- Enter to send, Shift+Enter for newline
- Disabled states: disconnected, sending, invalid input
- Validation messages for error states
- Error display for send failures
- React.memo and useCallback optimizations

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-27 15:21:21 +05:30
Nuwan 619e37f505 docs(09): create phase plan for message composition
Phase 9: Message Composition & Sending
- 2 plans created
- 6 total tasks defined
- Ready for execution

Plan 09-01: Message Composer UI & Validation (3 tasks)
- Create JKChatComposer component
- Add keyboard handling (Enter/Shift+Enter)
- Add character count validation

Plan 09-02: Send Message Integration & Real-Time Delivery (3 tasks)
- Integrate composer into chat window
- Write send message integration tests
- Write receive message integration tests
2026-01-27 15:14:32 +05:30
Nuwan c4acebcdeb docs(08-03): complete chat button & unread badge plan
Tasks completed: 3/4
- Create JKSessionChatButton component
- Integrate into JKSessionScreen navigation
- Write integration tests (7 tests)
- SCSS styling (skipped - optional)

SUMMARY: .planning/phases/08-chat-window-ui/08-03-SUMMARY.md

Phase 8 complete - Chat Window UI fully functional
2026-01-27 14:23:00 +05:30
Nuwan 9fd506695d test(08-03): add integration tests for chat button
- Test button visibility in session navigation
- Test badge hidden when unread count = 0
- Test badge shows correct count (1-99)
- Test badge shows "99+" for counts >= 100
- Test button opens chat window
- Test duplicate window prevention
- Test badge resets when window opens
- 7 comprehensive test cases
2026-01-27 14:20:52 +05:30
Nuwan b6e31b3bc2 feat(08-03): integrate chat button into session navigation
- Added JKSessionChatButton import
- Replaced placeholder Chat button with new component
- Passes sessionId prop from Redux state
- Button positioned after Open menu, before Attach button
2026-01-27 14:20:09 +05:30
Nuwan 1230448d96 feat(08-03): create JKSessionChatButton with unread badge
- Displays chat icon from assets
- Badge shows unread count (1-99) or "99+" for 100+
- Badge hidden when count = 0
- Reduced opacity when window already open
- Click handler opens chat window and sets active channel
- useCallback for handleClick optimization
2026-01-27 14:19:25 +05:30
Nuwan 6b687315ce docs(08-02): complete message list & auto-scroll plan
Update project documentation after completing Plan 08-02:

SUMMARY.md:
- Created 8 new files (utilities, components, tests)
- Modified 2 files (JKSessionChatWindow, package.json)
- 77 chat-related tests passing
- Auto-scroll logic validated with TDD
- Ready for Plan 08-03 (Chat Button & Unread Badge)

STATE.md:
- Update current position: Plan 08-02 complete, ready for 08-03
- Progress: 60% (Phase 8: 2/3 plans complete)
- Add accumulated context from Phase 8 Plan 2
- Document timestamp formatting patterns
- Document auto-scroll behavior and state machine
- Note testing library installation (@testing-library/react@12)

ROADMAP.md:
- Mark Plan 08-02 as complete (2026-01-27)
- Update Phase 8 progress: 2/3 plans complete

Total commits for Plan 08-02: 8 commits
- Task 1 (formatTimestamp TDD): 2 commits (RED + GREEN)
- Task 2 (JKChatMessage): 1 commit
- Task 3 (loading/empty states): 1 commit
- Task 4 (JKChatMessageList TDD): 2 commits (RED + GREEN)
- Task 5 (integration): 1 commit
- Metadata: 1 commit (this)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-27 14:09:37 +05:30
Nuwan 6df9356b61 feat(08-02): integrate message list into chat window
Replace placeholder content with JKChatMessageList component:
- Import JKChatMessageList
- Remove placeholder div with text
- JKChatMessageList handles its own styling (flex: 1, padding, scroll)
- Update component documentation

Chat window now displays:
- Header with channel name and close button (fixed top)
- Message list with auto-scroll (scrollable, flex: 1)
- Loading spinner when fetching history
- Empty state when no messages
- Individual messages with avatars and timestamps

Layout follows flexbox pattern with header fixed and message list
filling remaining space with independent scrolling.

Ready for Plan 8.3 (Chat Button & Unread Badge).

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-27 14:07:42 +05:30
Nuwan 07779a9fa8 feat(08-02): implement JKChatMessageList with auto-scroll
GREEN phase: Create message list component with:
- Redux integration (activeChannel, messages, fetchStatus selectors)
- Auto-scroll logic with scroll state management
- Scroll to bottom on mount and new messages
- Disable auto-scroll when user scrolls up
- Re-enable auto-scroll when user scrolls to bottom (50px threshold)
- 300ms debounce for scroll detection
- Loading state (JKChatLoadingSpinner)
- Empty state (JKChatEmptyState)
- Message rendering (JKChatMessage components)

Auto-scroll behavior:
- isUserScrolling state tracks manual scrolling
- scrollToBottom helper with smooth scrolling
- isAtBottom detects bottom position (50px threshold)
- handleScroll debounces scroll events (300ms)
- Cleanup timeout on unmount prevents memory leaks

Mock Element.prototype.scrollTo in tests (not available in JSDOM).

All 3 tests passing:
- Empty state display
- Loading spinner display
- Message rendering

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-27 14:07:12 +05:30
Nuwan 41e6a82c5d test(08-02): add failing tests for JKChatMessageList
RED phase: Create test file with 3 test cases:
- Shows empty state when no messages
- Shows loading spinner when fetching
- Renders messages when available

Install @testing-library/react@12 and @testing-library/jest-dom@5
(compatible with React 16).

Create setupTests.js for jest-dom matchers.

Tests fail as expected (component not implemented yet).

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-27 14:06:19 +05:30
Nuwan 2056629a04 feat(08-02): create loading and empty state components
Create two stateless components for chat UI states:

1. JKChatLoadingSpinner:
   - Displays spinner from reactstrap
   - Shows "Loading messages..." text
   - Used when fetchStatus is 'loading'

2. JKChatEmptyState:
   - Shows chat icon and encouraging message
   - Used when message list is empty
   - Centered layout with friendly copy

Both components are simple, stateless, and require no props.
Inline styles used for MVP (SCSS styling deferred to Plan 8.3).

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-27 14:05:06 +05:30