feat(GRO-106): portal Communication tab — real backend #398

Merged
groombook-engineer[bot] merged 7 commits from feat/GRO-106-portal-communication-real into dev 2026-05-14 16:07:33 +00:00

7 Commits

Author SHA1 Message Date
Chris Farhood e873f11e4f fix(GRO-1241): test and guard scrollIntoView in MessagesPage 2026-05-14 15:46:31 +00:00
Chris Farhood aae11c0c4d fix(GRO-1241): remove unused readOnly and senderName in Communication.tsx
- Rename readOnly to _readOnly in MessageThread destructuring
  (satisfies ESLint no-unused-vars rule)
- Remove unused senderName variable in messages map

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-14 15:26:03 +00:00
Chris Farhood 537b5cb0b3 fix(GRO-1241): resolve all CI failures from QA review
1. **Remove duplicate staffReadAt** in `packages/db/src/schema.ts`
   (TS1117 duplicate identifier — merge conflict artifact)

2. **Add count to db index exports** in `packages/db/src/index.ts`
   (`count` from drizzle-orm was used in conversations.ts but not exported)

3. **Use dev version of conversations.ts** (no type errors, sql\`count(*)\`)
   — PR branch version had incompatible type errors (staff.businessId,
   count, optedOutAt fields not in schema)

4. **Remove duplicate conversationsRouter import** in `apps/api/src/index.ts`

All 289 tests pass, 0 lint errors.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-14 14:46:52 +00:00
Chris Farhood d60200f8a7 fix(GRO-1241): remove duplicate staffReadAt + add count mock
- Remove duplicate staffReadAt column in conversations table schema
  (merge conflict artifact — TS1117 duplicate definition)
- Add count mock to conversations.test.ts mock @groombook/db export
  (PR switched from sql\`count(*)\` to Drizzle count() without updating mock)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-14 14:30:58 +00:00
Chris Farhood c4978be280 feat(GRO-106): staff messages page
- Adds staff conversations API (GET /api/conversations, GET /api/conversations/:id/messages, POST /api/conversations/:id/messages) with auth scoping and cross-tenant protection
- Adds staffReadAt column to conversations table for unread tracking
- Adds staff Messages page with two-column inbox layout (thread list + conversation view + composer)
- Adds Messages entry to staff sidebar navigation
- Includes tests for the MessagesPage component

Part of GRO-106 (SMS/MMS integration) Phase 1.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-14 12:41:35 +00:00
Chris Farhood f43e566dbd fix(GRO-1215): resolve ESLint error, cursor pagination, and UAT playbook gaps
- Add and() + lt() imports from @groombook/db
- Apply businessId to conversation WHERE clause for cross-tenant isolation
  (GET /portal/conversation: clientId AND businessId both scoped)
- Fix cursor pagination: apply lt(messages.createdAt, cursorMsg.createdAt)
  to the cursor WHERE clause so pages actually paginate
- Add UAT_PLAYBOOK.md §4.9.1 Communication tab test cases:
  TC-APP-4.9.6 message history with conversation
  TC-APP-4.9.7 empty state (no conversation yet)
  TC-APP-4.9.8 composer disabled with tooltip
  TC-APP-4.9.9 cross-tenant isolation

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-14 12:40:06 +00:00
Chris Farhood 9c9568b80c feat(GRO-106): portal Communication tab — real backend
- Added GET /portal/conversation and GET /portal/conversation/messages endpoints
- Created Communication.api.ts with typed fetchers and React hooks
- Rewired Communication.tsx to use real API, removed mock data
- Added composer-disabled bar with "Reply from your phone" tooltip
- Added conversation route tests to portal.test.ts

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-14 12:40:06 +00:00