WAGERBABE DOCS
All Stories
7-6-3-cash-out-uiReadyEpic 7.6

Story 7.6.3: Cash Out UI

Status: ready-for-dev

Tasks

  • **Task 1: Create CashOutButton Component** (AC: #1, #2, #3)
    • 1.1: Create `/client/src/components/betting/cash-out-button.tsx` file
    • 1.2: Define TypeScript interfaces (CashOutOffer, CashOutButtonProps)
    • 1.3: Implement useEffect polling hook for 5-second updates
    • 1.4: Add GET `/api/v1/betting/cash-out/{betId}/offer` API call
    • 1.5: Implement conditional rendering (only show if available)
    • 1.6: Add profit/loss calculation and color logic (green/red)
    • 1.7: Style button with yellow background, proper spacing, mobile touch targets
    • 1.8: Add click handler to open confirmation modal
    • 1.9: Add loading state indicator for value updates
    • 1.10: Handle polling cleanup on unmount and when modal opens
  • **Task 2: Create CashOutConfirmModal Component** (AC: #4, #5)
    • 2.1: Create `/client/src/components/betting/cash-out-confirm-modal.tsx` file
    • 2.2: Use shadcn/ui Dialog component as base
    • 2.3: Add props interface (value, stake, profitLoss, onConfirm, onCancel, isLoading)
    • 2.4: Display original stake in modal body
    • 2.5: Display cash out value prominently (large, bold font)
    • 2.6: Display profit/loss with green/red coloring and border separator
    • 2.7: Add Cancel button (outline variant, disabled during loading)
    • 2.8: Add Confirm button with loading spinner (Loader2 icon)
    • 2.9: Prevent modal close during execution (disable onOpenChange when loading)
    • 2.10: Ensure responsive layout for mobile devices
  • **Task 3: Implement Cash Out Execution Logic** (AC: #5, #6)
    • 3.1: Create executeCashOut async function in CashOutButton
    • 3.2: Add POST `/api/v1/betting/cash-out/{betId}/execute` API call
    • 3.3: Send accepted_value and offer_timestamp in request body
    • 3.4: Add isExecuting state to manage button/modal loading
    • 3.5: Handle success response (show toast, refresh bet list)
    • 3.6: Handle error responses (show specific error messages)
    • 3.7: Handle odds_changed scenario (update offer with new_value)
    • 3.8: Close modal only after success or cancellation
    • 3.9: Add timeout handling for long-running requests
    • 3.10: Cleanup polling interval after successful cash out
  • **Task 4: Add Toast Notifications** (AC: #6)
    • 4.1: Import toast utility from shadcn/ui or react-hot-toast
    • 4.2: Implement success toast with formatted cash out amount
    • 4.3: Show updated balance in success toast (e.g., "New balance: $123.45")
    • 4.4: Implement error toast for failed cash outs
    • 4.5: Add specific error messages for each CashOutResult type:
    • 4.5.1: EXPIRED - "Cash out offer expired. Refreshing..."
    • 4.5.2: ODDS_CHANGED - "Odds have changed. New value: $X.XX"
    • 4.5.3: ALREADY_SETTLED - "This bet has already been settled"
    • 4.5.4: ERROR - Generic error message with retry suggestion
    • 4.6: Add toast auto-dismiss timeout (3-5 seconds)
    • 4.7: Ensure toast positioning doesn't interfere with bet list
  • **Task 5: Integrate with Bet List** (AC: #1, #3, #6)
    • 5.1: Locate existing bet list component (e.g., `/client/src/components/betting/bet-history.tsx`)
    • 5.2: Import CashOutButton component
    • 5.3: Add CashOutButton to each active bet row/card
    • 5.4: Pass betId and stake props to CashOutButton
    • 5.5: Ensure button placement doesn't disrupt bet card layout
    • 5.6: Add callback to refresh bet list after successful cash out
    • 5.7: Test bet status update after cash out (PENDING → CASHED_OUT)
    • 5.8: Verify button disappears after bet is cashed out
    • 5.9: Test responsive layout on mobile (stacked vs. inline)
    • 5.10: Add loading skeleton while bet list fetches
  • **Task 6: Error Handling & Edge Cases** (AC: #3, #6)
    • 6.1: Handle network failures during offer fetch (show last known value)
    • 6.2: Handle 401 Unauthorized (redirect to login)
    • 6.3: Handle 404 Not Found (bet doesn't exist)
    • 6.4: Handle 400 Bad Request (validation error)
    • 6.5: Handle 500 Server Error (generic error message)
    • 6.6: Add retry logic for transient failures (exponential backoff)
    • 6.7: Handle race condition (bet settled while modal open)
    • 6.8: Validate offer hasn't expired before showing modal
    • 6.9: Handle market suspension (show "Cash Out Unavailable" message)
    • 6.10: Test with slow network (3G throttling)
  • **Task 7: Mobile Optimization** (AC: #1, #4)
    • 7.1: Test button touch targets (minimum 44px × 44px)
    • 7.2: Test modal on small screens (320px width)
    • 7.3: Ensure modal doesn't overflow viewport
    • 7.4: Add proper viewport meta tag if missing
    • 7.5: Test scroll behavior when modal is open (prevent body scroll)
    • 7.6: Test button wrapping on narrow screens
    • 7.7: Optimize font sizes for mobile readability
    • 7.8: Test with iOS Safari and Android Chrome
    • 7.9: Add touch-friendly spacing between buttons
    • 7.10: Test landscape orientation on mobile devices
  • **Task 8: Testing & Validation** (AC: All)
    • 8.1: Test cash out button appears only on eligible bets
    • 8.2: Test 5-second polling updates cash out value
    • 8.3: Test profit/loss colors (green for positive, red for negative)
    • 8.4: Test confirmation modal displays correct values
    • 8.5: Test successful cash out updates balance and bet status
    • 8.6: Test error scenarios (expired, odds changed, already settled)
    • 8.7: Test modal cannot be closed during execution
    • 8.8: Test polling stops when modal is open
    • 8.9: Test responsive design on mobile and desktop
    • 8.10: Verify accessibility (keyboard navigation, screen reader)

Progress

Tasks0/8
Acceptance Criteria0
Total Tasks8