d0b4baf5aa
* feat: add customer-facing appointment notes (GRO-106) - Migration 0014: add customer_notes column to appointments - Schema update: add customerNotes field to appointments table - Factory update: include customerNotes in buildAppointment - Portal route: PATCH /api/portal/appointments/:id/notes - Ownership validation via impersonation session - Future-only validation (no edits after start) - 500 character limit - Register portal router in index.ts Co-Authored-By: Paperclip <noreply@paperclip.ing> * Fix confirmationToken leak and add unit tests for portal notes endpoint - Return only id, customerNotes, updatedAt instead of full appointment row - Add comprehensive unit tests covering auth, ownership, time-gating, and validation - Fix: confirmationToken no longer returned to portal session Co-Authored-By: Paperclip <noreply@paperclip.ing> * feat: add customer notes UI to portal and staff views (GRO-178) - Add customerNotes field to Appointment type - Add read-only customer notes display in staff appointment detail modal - Add customer notes textarea with save, char counter (500 max), and disabled state - Wire up PATCH /api/portal/appointments/:id/notes in portal UI - Update mockData with customerNotes field Co-Authored-By: Paperclip <noreply@paperclip.ing> * fix: address QA review feedback - null check and portal route auth - Add null check after db.update().returning() in portal notes endpoint - Move portal router registration before auth middleware so clients can access it - Remove unused ENDED_SESSION variable from test file Co-Authored-By: Paperclip <noreply@paperclip.ing> * fix(portal): address QA review - isUpcoming time parsing and session header - Fixed parseTimeTo24Hour to handle 12-hour AM/PM format correctly - Added X-Impersonation-Session-Id header to CustomerNotesSection fetch - Added comprehensive tests for CustomerNotesSection and time parsing - Fixed TypeScript strict null checks for parseTimeTo24Hour Fixes QA review issues: - isUpcoming() now correctly parses 12-hour time format - CustomerNotesSection sends session ID header for auth - Added unit tests for new UI component Co-Authored-By: Paperclip <noreply@paperclip.ing> * fix: thread sessionId as prop instead of sessionStorage CustomerNotesSection was reading sessionStorage for the impersonation session ID, but CustomerPortal stores it in React state. Pass sessionId as a prop through AppointmentsSection and AppointmentCard instead. Also update tests to pass sessionId prop and add test for null sessionId case. Co-Authored-By: Paperclip <noreply@paperclip.ing> --------- Co-authored-by: Scrubs McBarkley <scrubs@groombook.app> Co-authored-by: Paperclip <noreply@paperclip.ing> Co-authored-by: groombook-cto[bot] <269737991+groombook-cto[bot]@users.noreply.github.com>