- Create frontend/app/utils/exchange.ts with shared formatting functions
- Update exchange/page.tsx to use shared formatEur
- Update trades/page.tsx to use shared formatEur and getTradeStatusDisplay
- Update admin/trades/page.tsx to use shared formatEur and getTradeStatusDisplay
- SatsDisplay was already extracted (confirmed it's in components/SatsDisplay.tsx)
The agreed_price depends on trade direction (buy/sell) and must be
calculated on the frontend. Returning a buy-side-only agreed_price
from the API was misleading and unused.
Frontend already calculates the direction-aware price correctly.
- Updated auth-context.tsx to use new exchange permissions
(CREATE_EXCHANGE, VIEW_OWN_EXCHANGES, etc.) instead of old
appointment permissions (BOOK_APPOINTMENT, etc.)
- Updated exchange/page.tsx, trades/page.tsx, admin/trades/page.tsx
to use correct permission constants
- Updated profile/page.test.tsx mock permissions
- Updated admin/availability/page.tsx to use constants.exchange
instead of constants.booking
- Added /api/exchange/slots endpoint to return available slots
for a date, filtering out already booked slots
- Fixed E2E tests:
- exchange.spec.ts: Wait for button to be enabled before clicking
- permissions.spec.ts: Use more specific heading selector
- price-history.spec.ts: Expect /exchange redirect for regular users
New /admin/trades page for managing exchange trades:
- Upcoming trades tab with user contact info
- History tab with status/user search filters
- Complete/No-show/Cancel actions for admin
- Trade details: direction, amounts, rates, premium
Update navigation:
- Admin home redirects to /admin/trades
- Regular user home redirects to /exchange
- Header shows 'Trades' for admin
- Create /admin/random-jobs/page.tsx with outcomes table
- Add 'admin-random-jobs' to PageId type in Header
- Add 'Random Jobs' nav item to ADMIN_NAV_ITEMS
- Display: ID, Job ID, Triggered By, Value, Duration, Status, Created At
- Uses VIEW_AUDIT permission
- Replaced borderColor with full border property in dayCardActive
- Replaced borderColor with full border property in dayCardSource
- Replaced borderColor with full border property in dayCardTarget
- Prevents React warning about mixing shorthand and non-shorthand properties
- Fixes console error when using 'Clear all' button on availability page
- Created formatTimeString() utility to properly parse time strings
- Replaced all .slice(0, 5) calls with proper time formatting
- Handles both 'HH:MM:SS' and 'HH:MM' formats safely
- More robust than string slicing
- Created getDateRange() function in utils/date.ts
- Replaced getBookableDates() and getDateRange() duplicates
- Both booking and availability pages now use shared function
- Function accepts minAdvanceDays and maxAdvanceDays as parameters
- TIME_OPTIONS is now computed at module level, not inside component
- generateTimeOptions now accepts slotDurationMinutes as parameter
- Prevents unnecessary recomputation on every render
- Standardized all error handling to use ternary pattern
- Changed if/else blocks to ternary operators for consistency
- Updated booking, appointments, and admin appointments pages
- Created frontend/app/utils/appointment.ts with getStatusDisplay()
- Supports context-aware text (isOwnView parameter)
- Updated both appointments pages to use shared utility
- Created frontend/app/utils/date.ts with formatDate, formatTime, formatDateTime, formatDisplayDate
- Created frontend/e2e/helpers/date.ts with formatDateLocal, getTomorrowDateStr
- Updated all frontend pages and e2e tests to use shared utilities
- Removed duplicate date formatting code from 6 files
- Added pagination with page/per_page query params
- Fixed N+1 query by using eager-loaded user relationship
- Removed unused _get_user_email helper function
- Updated frontend to handle paginated response
- Regenerated API types
Add check to both user and admin cancel endpoints to reject
cancellation of appointments whose slot_start is in the past.
This matches the spec requirement that cancellations can only
happen 'before the appointment'.
Added tests for both user and admin cancel endpoints.
Also includes frontend styling updates.
- Use data-testid attributes to target specific day cards in availability tests
- Wait for networkidle before interacting with page elements
- Set up PUT and GET response listeners before triggering actions
- Add retry logic for availability API in booking tests
- Fix appointments test to handle multiple 'Booked' elements with .first()
- Increase parallel workers to 12 for faster test execution