# core-midtrans-cifo - Technical Specification

**Author:** BMad
**Date:** 2025-11-25
**Project Level:** Quick-Flow (2 Stories)
**Change Type:** UX Enhancement + Bug Fix
**Development Context:** Brownfield - Payment Flow Improvements

---

## Context

### Available Documents

**Loaded Documents:**
- ✅ **Problem-Solution Analysis** (`problem-solution-2025-11-25.md`) - Comprehensive problem analysis by Dr. Quinn identifying 3 interconnected payment flow issues with systematic root cause analysis and 15 evaluated solutions
- ✅ **Project Codebase** - Existing React + TypeScript + Midtrans integration

**Project Type:** Brownfield - Existing functional payment application

**Key Context:**
- Target users: Non-tech-savvy customers (ibu-ibu awam)
- Platform: Mobile-first web application
- Payment Gateway: Midtrans (1 VA per transaction constraint)
- Current Issues: Duplicate VA generation, poor post-payment UX, inadequate error handling

### Project Stack

**Frontend Stack:**
- **React** 19.1.1 - Latest React with modern hooks and concurrent features
- **TypeScript** 5.9.3 - Type-safe development
- **Vite** 7.1.7 - Fast build tool and dev server
- **React Router DOM** 7.9.5 - Client-side routing
- **TailwindCSS** 4.1.17 - Utility-first CSS framework
- **Framer Motion** 12.23.24 - Animation library
- **React Hook Form** 7.66.0 - Form state management
- **TanStack React Query** 5.90.7 - Server state management and data fetching
- **Axios** 1.13.2 - HTTP client

**Backend Stack:**
- **Express** 5.1.0 - Node.js web framework
- **Midtrans Client** 1.4.3 - Official Midtrans SDK for payment processing
- **CORS** 2.8.5 - Cross-origin resource sharing
- **dotenv** 17.2.3 - Environment variable management

**Development Tools:**
- **ESLint** 9.36.0 - Code linting
- **Prettier** 3.6.2 - Code formatting
- **TypeScript ESLint** 8.45.0 - TypeScript-specific linting rules

**Project Type:** Vite + React + TypeScript SPA with Express backend

### Existing Codebase Structure

**Directory Organization:**
```
src/
├── features/     (16 feature modules) - Feature-based architecture
├── pages/        (6 pages) - Route-level components
├── components/   (3 shared components) - Reusable UI components
├── services/     (API services) - Backend communication layer
├── lib/          (utilities) - Helper functions and utilities
└── app/          (app config) - Application configuration
```

**Architecture Pattern:** Feature-based modular architecture
- Each feature is self-contained with its own components, hooks, and logic
- Shared components in `/components` for cross-feature reusability
- Centralized API services in `/services`
- Utility functions in `/lib`

**Styling Approach:** TailwindCSS utility classes
- Responsive mobile-first design
- Custom design system via `tailwind.config.ts`

**State Management:**
- React Query for server state
- React Hook Form for form state
- React hooks (useState, useEffect) for local component state

---

## The Change

### Problem Statement

**Core Problem:** Mobile-first payment application untuk non-tech-savvy users (ibu-ibu awam) mengalami critical UX failures dan poor state management yang menyebabkan:

1. **Duplicate VA Generation** - Users click generate VA button multiple times during 3-5 second delay, triggering HTTP 409 errors with technical error messages
2. **Post-Payment Confusion** - After successful payment, users are redirected to status page with no clear next steps, causing them to press back button which triggers invalid transaction states
3. **Poor Error Handling** - HTTP errors (409, 404) displayed as technical messages; invalid states show "Rp 0" instead of helpful recovery options

**Business Impact:**
- Abandoned transactions → lost revenue
- High support ticket volume
- User frustration and distrust
- Poor mobile UX for primary user demographic

**Root Causes Identified:**
1. Lack of defensive UX design patterns (no loading states, no button disable)
2. Poor React lifecycle management (useEffect re-triggering on navigation)
3. Missing error handling framework (no user-friendly messages, no recovery paths)

### Proposed Solution

**Phase 1: Quick Wins Bundle** - Implement 5 high-impact, low-risk solutions organized into 2 user stories:

**Story 1: Prevent Duplicate VA Generation & Improve Feedback**
- Solution #1: Button State Management - Disable button during processing
- Solution #2: Request Debouncing - 500ms debounce on VA generation
- Solution #3: User-Friendly Error Messages - Map HTTP codes to bahasa Indonesia
- Solution #4: Loading Overlay - Full-screen overlay with clear messaging

**Story 2: Improve Post-Payment UX**
- Solution #5: Auto-Redirect After Success - 5-second countdown with clear CTA

**Expected Impact:** Solves 70-80% of payment flow issues with minimal risk

### Scope

**In Scope:**

✅ **Story 1: Prevent Duplicate VA Generation & Improve Feedback**
1. Implement button disable/enable logic on VA generation button
2. Add loading spinner to button during processing
3. Implement 500ms debounce on VA generation function
4. Create full-screen loading overlay component
5. Map HTTP 409 → "Kode pembayaran Anda sudah dibuat! Klik di sini untuk melihat"
6. Map HTTP 404 → "Terjadi kesalahan. Silakan coba lagi"
7. Add "Coba Lagi" recovery button on error states
8. Add "Lihat Kode Pembayaran" button on 409 errors

✅ **Story 2: Improve Post-Payment UX**
1. Implement 5-second countdown timer on payment success page
2. Add "Anda akan diarahkan ke dashboard dalam X detik..." message
3. Add "Kembali Sekarang" button for impatient users
4. Implement auto-redirect logic to dashboard/home after countdown

✅ **Cross-Story Requirements**
1. Mobile-first responsive design (primary focus)
2. Bahasa Indonesia for all user-facing text
3. Consistent with existing TailwindCSS design system
4. Accessible (keyboard navigation, screen reader friendly)

**Out of Scope:**

❌ **Phase 2 Solutions** (future work):
- Navigation guards (useEffect cleanup)
- Modal-based success page
- Progressive loading states
- Transaction state machine
- Idempotency key implementation

❌ **Backend Changes:**
- Midtrans API modifications
- Database schema changes
- Backend validation logic

❌ **Complete Redesign:**
- Single-page payment flow
- Optimistic UI patterns
- Guided tour/onboarding

---

## Implementation Details

### Source Tree Changes

**Files to CREATE:**

1. **`src/components/LoadingOverlay.tsx`** - NEW
   - Full-screen loading overlay component
   - Props: `isLoading: boolean`, `message: string`
   - Semi-transparent backdrop with centered spinner and message

2. **`src/components/CountdownRedirect.tsx`** - NEW
   - Countdown timer component for auto-redirect
   - Props: `seconds: number`, `onComplete: () => void`, `destination: string`
   - Display countdown with "Kembali Sekarang" button

3. **`src/lib/errorMessages.ts`** - NEW
   - Error message mapping utility
   - Function: `mapErrorToUserMessage(error: AxiosError): string`
   - Maps HTTP status codes to user-friendly Indonesian messages

4. **`src/lib/debounce.ts`** - NEW
   - Debounce utility function
   - Function: `debounce<T>(func: T, delay: number): T`
   - Generic debounce implementation for click handlers

**Files to MODIFY:**

1. **`src/features/payment/components/PaymentMethodSelector.tsx`** (or equivalent)
   - ADD: Button disable logic (disabled state during VA generation)
   - ADD: Loading spinner on button
   - ADD: Debounce wrapper on generateVA handler
   - ADD: LoadingOverlay integration
   - MODIFY: Error handling to use mapErrorToUserMessage

2. **`src/features/payment/pages/PaymentSuccessPage.tsx`** (or equivalent)
   - ADD: CountdownRedirect component
   - ADD: Auto-redirect logic after 5 seconds
   - MODIFY: Layout to include countdown timer and CTA button

3. **`src/features/payment/hooks/useGenerateVA.ts`** (or create if doesn't exist)
   - ADD: Loading state management
   - ADD: Error state with user-friendly messages
   - ADD: Button disable logic
   - MODIFY: Error handling to use mapErrorToUserMessage

**Files to ADD TESTS:**

1. **`src/components/__tests__/LoadingOverlay.test.tsx`** - CREATE
2. **`src/components/__tests__/CountdownRedirect.test.tsx`** - CREATE
3. **`src/lib/__tests__/errorMessages.test.ts`** - CREATE
4. **`src/lib/__tests__/debounce.test.ts`** - CREATE

### Technical Approach

**1. Button State Management (Solution #1)**

**Approach:** Use React state to track loading status and disable button during API call

```typescript
const [isGenerating, setIsGenerating] = useState(false);

const handleGenerateVA = async () => {
  setIsGenerating(true);
  try {
    await generateVAAPI();
  } finally {
    setIsGenerating(false);
  }
};

<button disabled={isGenerating}>
  {isGenerating ? <Spinner /> : 'Generate VA'}
</button>
```

**Why:** Simple, effective, uses existing React patterns

---

**2. Request Debouncing (Solution #2)**

**Approach:** Wrap VA generation handler with debounce utility (500ms delay)

```typescript
import { debounce } from '@/lib/debounce';

const debouncedGenerateVA = useMemo(
  () => debounce(handleGenerateVA, 500),
  []
);
```

**Why:** Prevents rapid successive clicks, complements button disable

---

**3. User-Friendly Error Messages (Solution #3)**

**Approach:** Create error mapping utility that translates HTTP codes to Indonesian

```typescript
// src/lib/errorMessages.ts
export const mapErrorToUserMessage = (error: AxiosError): string => {
  if (error.response?.status === 409) {
    return "Kode pembayaran Anda sudah dibuat! Klik di sini untuk melihat";
  }
  if (error.response?.status === 404) {
    return "Terjadi kesalahan. Silakan coba lagi";
  }
  return "Terjadi kesalahan. Silakan coba lagi";
};
```

**Why:** Centralized error handling, easy to maintain and extend

---

**4. Loading Overlay (Solution #4)**

**Approach:** Create reusable LoadingOverlay component with Framer Motion animations

```typescript
// src/components/LoadingOverlay.tsx
export const LoadingOverlay = ({ isLoading, message }) => {
  if (!isLoading) return null;
  
  return (
    <motion.div
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      className="fixed inset-0 bg-black/50 flex items-center justify-center z-50"
    >
      <div className="bg-white p-6 rounded-lg">
        <Spinner />
        <p>{message}</p>
      </div>
    </motion.div>
  );
};
```

**Why:** Prevents interaction during processing, clear visual feedback

---

**5. Auto-Redirect After Success (Solution #5)**

**Approach:** Use countdown timer with useEffect and setTimeout

```typescript
// src/components/CountdownRedirect.tsx
export const CountdownRedirect = ({ seconds, onComplete, destination }) => {
  const [countdown, setCountdown] = useState(seconds);
  
  useEffect(() => {
    if (countdown === 0) {
      onComplete();
      return;
    }
    
    const timer = setTimeout(() => {
      setCountdown(c => c - 1);
    }, 1000);
    
    return () => clearTimeout(timer);
  }, [countdown, onComplete]);
  
  return (
    <div>
      <p>Anda akan diarahkan ke {destination} dalam {countdown} detik...</p>
      <button onClick={onComplete}>Kembali Sekarang</button>
    </div>
  );
};
```

**Why:** Clear user guidance, option for impatient users, prevents back button confusion

### Existing Patterns to Follow

**React Patterns:**
- Functional components with hooks (no class components)
- Custom hooks for reusable logic (e.g., `useGenerateVA`)
- TypeScript for type safety
- Props interfaces defined with `interface` keyword

**Styling Patterns:**
- TailwindCSS utility classes
- Responsive design with mobile-first breakpoints (`sm:`, `md:`, `lg:`)
- Custom colors and spacing from `tailwind.config.ts`
- Framer Motion for animations (already in use)

**State Management Patterns:**
- React Query for API calls and server state
- React Hook Form for form state
- Local useState for component-specific state

**Error Handling Patterns:**
- Try-catch blocks for async operations
- Error states in components
- User-friendly error messages (to be improved by this change)

**File Naming Conventions:**
- PascalCase for components: `LoadingOverlay.tsx`
- camelCase for utilities: `errorMessages.ts`
- Test files: `ComponentName.test.tsx`

### Integration Points

**1. Midtrans API Integration**
- **Location:** `src/services/midtrans.ts` (or similar)
- **Integration:** VA generation API call
- **Changes:** Wrap with loading state, error handling, debounce

**2. React Query Integration**
- **Usage:** Manage VA generation API state
- **Pattern:** Use `useMutation` for VA generation
- **Changes:** Add onMutate (loading), onError (error messages), onSuccess (redirect)

**3. React Router Integration**
- **Usage:** Navigate to success page, auto-redirect after payment
- **Pattern:** Use `useNavigate` hook
- **Changes:** Implement programmatic navigation in CountdownRedirect

**4. TailwindCSS Design System**
- **Integration:** All new components use Tailwind classes
- **Consistency:** Match existing color scheme, spacing, typography
- **Responsive:** Mobile-first breakpoints

**5. Framer Motion Animations**
- **Usage:** LoadingOverlay fade-in animation
- **Pattern:** `motion.div` with initial/animate props
- **Consistency:** Match existing animation timing and easing

---

## Development Context

### Relevant Existing Code

**Payment Feature Module:**
- **Location:** `src/features/payment/` (assumed based on feature-based architecture)
- **Components:** PaymentMethodSelector, PaymentSuccessPage (names may vary)
- **Hooks:** Likely has custom hooks for payment logic
- **Services:** API calls to Midtrans via backend

**Reference Patterns:**
- Check existing components in `src/components/` for styling patterns
- Review existing API calls in `src/services/` for error handling patterns
- Look at existing hooks for state management patterns

**Key Files to Review Before Implementation:**
1. Payment method selection component (where VA generation button lives)
2. Payment success/status page component
3. Existing API service layer for Midtrans calls
4. Existing error handling utilities (if any)

### Dependencies

**Framework/Libraries:**

**Production Dependencies (Already Installed):**
- `react@19.1.1` - Core React library
- `react-dom@19.1.1` - React DOM rendering
- `react-router-dom@7.9.5` - Routing
- `@tanstack/react-query@5.90.7` - Server state management
- `axios@1.13.2` - HTTP client
- `framer-motion@12.23.24` - Animations
- `tailwindcss@4.1.17` - Styling
- `clsx@2.1.1` - Conditional class names
- `tailwind-merge@3.3.1` - Merge Tailwind classes

**Development Dependencies (Already Installed):**
- `typescript@5.9.3` - TypeScript compiler
- `vite@7.1.7` - Build tool
- `eslint@9.36.0` - Linting
- `prettier@3.6.2` - Code formatting

**No New Dependencies Required** - All solutions use existing stack

### Internal Modules

**Modules to Create:**
- `@/components/LoadingOverlay` - Loading overlay component
- `@/components/CountdownRedirect` - Countdown redirect component
- `@/lib/errorMessages` - Error message mapping utility
- `@/lib/debounce` - Debounce utility function

**Modules to Import:**
- `@/services/midtrans` (or equivalent) - Midtrans API service
- `react-router-dom` - useNavigate hook
- `@tanstack/react-query` - useMutation hook
- `framer-motion` - motion components
- `clsx` or `tailwind-merge` - Conditional styling

### Configuration Changes

**No Configuration Changes Required**

All solutions work within existing configuration:
- ✅ No new environment variables
- ✅ No Vite config changes
- ✅ No TailwindCSS config changes
- ✅ No ESLint/Prettier config changes
- ✅ No package.json changes (no new dependencies)

### Existing Conventions (Brownfield)

**Code Style:**
- **TypeScript:** Strict mode enabled
- **Quotes:** Single quotes (based on Prettier config)
- **Semicolons:** Yes (TypeScript default)
- **Indentation:** 2 spaces
- **Line Length:** 80-100 characters (Prettier default)

**Component Patterns:**
- Functional components with TypeScript interfaces for props
- Named exports preferred
- Props interface named `ComponentNameProps`

**Import Organization:**
- React imports first
- Third-party libraries second
- Internal imports last
- Absolute imports using `@/` alias

**Error Handling:**
- Try-catch for async operations
- Error boundaries for component errors (if implemented)
- User-friendly error messages (to be improved)

**Testing:**
- Test files co-located with components in `__tests__/` folder
- File naming: `ComponentName.test.tsx`
- Framework: Likely Vitest (Vite's test framework) or Jest

### Test Framework & Standards

**Test Framework:** Vitest (recommended for Vite projects) or Jest

**Test File Patterns:**
- Location: `src/components/__tests__/` or `src/lib/__tests__/`
- Naming: `ComponentName.test.tsx` or `utilityName.test.ts`
- Structure: Describe blocks for component/function, it blocks for test cases

**Testing Strategy:**
- Unit tests for utilities (`debounce`, `errorMessages`)
- Component tests for UI components (`LoadingOverlay`, `CountdownRedirect`)
- Integration tests for payment flow (optional, recommended)

**Coverage Requirements:**
- Aim for 80%+ coverage on new code
- All utility functions must have tests
- All new components must have basic render tests

---

## Implementation Stack

**Runtime Environment:**
- Node.js 20.x (recommended for Express 5.x)
- Browser: Modern browsers with ES2020+ support

**Frontend Stack:**
- React 19.1.1
- TypeScript 5.9.3
- Vite 7.1.7
- TailwindCSS 4.1.17
- Framer Motion 12.23.24
- React Router DOM 7.9.5
- TanStack React Query 5.90.7
- Axios 1.13.2

**Backend Stack:**
- Express 5.1.0
- Midtrans Client 1.4.3

**Development Tools:**
- ESLint 9.36.0
- Prettier 3.6.2
- TypeScript ESLint 8.45.0

**Testing:**
- Vitest (recommended) or Jest
- React Testing Library (for component tests)

---

## Technical Details

### Story 1: Prevent Duplicate VA Generation & Improve Feedback

**Technical Implementation Details:**

**1. Button Disable Logic**
- State variable: `isGenerating: boolean`
- Set to `true` on button click, `false` on API response (success or error)
- Button `disabled` attribute bound to `isGenerating`
- Visual feedback: Show spinner when `isGenerating === true`

**2. Debounce Implementation**
- Debounce delay: 500ms
- Implementation: Custom debounce utility using setTimeout
- Applied to: VA generation click handler
- Edge case: Clear timeout on component unmount

**3. Error Message Mapping**
- HTTP 409 → "Kode pembayaran Anda sudah dibuat! Klik di sini untuk melihat"
- HTTP 404 → "Terjadi kesalahan. Silakan coba lagi"
- HTTP 500 → "Terjadi kesalahan server. Silakan coba lagi nanti"
- Network error → "Tidak dapat terhubung ke server. Periksa koneksi internet Anda"
- Default → "Terjadi kesalahan. Silakan coba lagi"

**4. Loading Overlay**
- Z-index: 50 (above all content)
- Backdrop: Semi-transparent black (`bg-black/50`)
- Content: White card with spinner and message
- Animation: Fade in (200ms) using Framer Motion
- Message: "Sedang membuat kode pembayaran..."
- Accessibility: Focus trap, ESC key to cancel (optional)

**5. Recovery Buttons**
- "Coba Lagi" button on all errors → Retry VA generation
- "Lihat Kode Pembayaran" button on 409 error → Navigate to existing VA view
- "Kembali" button on errors → Navigate back to payment method selection

### Story 2: Improve Post-Payment UX

**Technical Implementation Details:**

**1. Countdown Timer**
- Initial value: 5 seconds
- Update interval: 1 second (1000ms)
- Implementation: useEffect with setTimeout
- Cleanup: Clear timeout on unmount
- Display format: "Anda akan diarahkan ke dashboard dalam {X} detik..."

**2. Auto-Redirect**
- Trigger: When countdown reaches 0
- Destination: Dashboard or home page (configurable)
- Method: `useNavigate()` from react-router-dom
- Fallback: Manual "Kembali Sekarang" button

**3. Manual Redirect Button**
- Label: "Kembali Sekarang"
- Action: Immediately navigate to destination (skip countdown)
- Styling: Primary button style (prominent, easy to find)
- Position: Below countdown message

**Performance Considerations:**
- Debounce prevents excessive API calls
- Loading overlay prevents UI interaction during processing
- Countdown timer uses single setTimeout (not setInterval) for better performance

**Security Considerations:**
- No sensitive data in error messages
- Error messages don't reveal system internals
- Rate limiting handled by backend (out of scope)

**Accessibility Considerations:**
- Loading overlay has proper ARIA labels
- Countdown timer announced by screen readers
- Buttons have clear labels and keyboard navigation
- Focus management during loading states

---

## Development Setup

**Prerequisites:**
- Node.js 20.x installed
- npm or yarn package manager
- Git for version control

**Initial Setup (if not already done):**

```bash
# 1. Clone repository (if not already cloned)
git clone <repository-url>
cd core-midtrans-cifo

# 2. Install dependencies
npm install

# 3. Set up environment variables
cp .env.example .env
# Edit .env with your Midtrans credentials

# 4. Start development server
npm run dev

# 5. Start backend server (in separate terminal)
npm run server
```

**Development Workflow:**

```bash
# Start Vite dev server (frontend)
npm run dev
# Access at http://localhost:5173

# Start Express server (backend)
npm run server
# Access at http://localhost:3000 (or configured port)

# Run linter
npm run lint

# Run tests (when implemented)
npm test

# Build for production
npm run build

# Preview production build
npm run preview
```

**Environment Variables Required:**
- `VITE_MIDTRANS_CLIENT_KEY` - Midtrans client key
- `MIDTRANS_SERVER_KEY` - Midtrans server key (backend)
- `MIDTRANS_IS_PRODUCTION` - true/false for sandbox vs production

---

## Implementation Guide

### Setup Steps

**Pre-Implementation Checklist:**

1. ✅ Create feature branch
   ```bash
   git checkout -b feature/payment-ux-improvements
   ```

2. ✅ Verify development environment running
   - Frontend dev server: `npm run dev`
   - Backend server: `npm run server`
   - Both running without errors

3. ✅ Review existing payment flow code
   - Locate payment method selection component
   - Locate payment success page component
   - Locate Midtrans API service layer
   - Understand current error handling

4. ✅ Set up test environment (if not already)
   - Install Vitest or Jest
   - Configure test runner
   - Create test file structure

### Implementation Steps

**Story 1: Prevent Duplicate VA Generation & Improve Feedback**

**Phase 1: Create Utility Functions (30 minutes)**

1. Create `src/lib/debounce.ts`
   - Implement generic debounce function
   - Add TypeScript types
   - Write unit tests

2. Create `src/lib/errorMessages.ts`
   - Implement error mapping function
   - Map all HTTP status codes
   - Add recovery action suggestions
   - Write unit tests

**Phase 2: Create UI Components (1 hour)**

3. Create `src/components/LoadingOverlay.tsx`
   - Implement overlay with backdrop
   - Add Framer Motion animations
   - Add spinner and message
   - Make responsive for mobile
   - Write component tests

**Phase 3: Modify Payment Method Component (1.5 hours)**

4. Locate and modify payment method selection component
   - Add `isGenerating` state
   - Wrap VA generation handler with debounce
   - Add button disable logic
   - Add loading spinner to button
   - Integrate LoadingOverlay
   - Update error handling to use `mapErrorToUserMessage`
   - Add recovery buttons based on error type

**Phase 4: Testing & Refinement (1 hour)**

5. Manual testing
   - Test duplicate click prevention
   - Test loading overlay display
   - Test error messages for different error types
   - Test recovery buttons
   - Test on mobile devices

6. Fix any issues found during testing

**Story 2: Improve Post-Payment UX**

**Phase 1: Create Countdown Component (45 minutes)**

1. Create `src/components/CountdownRedirect.tsx`
   - Implement countdown timer with useEffect
   - Add auto-redirect logic
   - Add manual redirect button
   - Make responsive for mobile
   - Write component tests

**Phase 2: Modify Payment Success Page (45 minutes)**

2. Locate and modify payment success page component
   - Integrate CountdownRedirect component
   - Configure redirect destination
   - Update layout for mobile-first
   - Add clear success messaging

**Phase 3: Testing & Refinement (30 minutes)**

3. Manual testing
   - Test countdown timer accuracy
   - Test auto-redirect functionality
   - Test manual redirect button
   - Test on mobile devices
   - Verify no back button issues

4. Fix any issues found during testing

### Testing Strategy

**Unit Tests:**

1. **`debounce.test.ts`**
   - Test debounce delays function execution
   - Test multiple rapid calls only execute once
   - Test cleanup on unmount

2. **`errorMessages.test.ts`**
   - Test HTTP 409 maps to correct message
   - Test HTTP 404 maps to correct message
   - Test default error message
   - Test network error message

**Component Tests:**

3. **`LoadingOverlay.test.tsx`**
   - Test renders when isLoading=true
   - Test doesn't render when isLoading=false
   - Test displays correct message
   - Test animation

4. **`CountdownRedirect.test.tsx`**
   - Test countdown decrements every second
   - Test onComplete called when countdown reaches 0
   - Test manual redirect button works
   - Test cleanup on unmount

**Integration Tests (Recommended):**

5. **Payment Flow Integration Test**
   - Test full VA generation flow with loading states
   - Test error handling and recovery
   - Test success flow with auto-redirect

**Manual Testing Checklist:**

- [ ] Click VA generation button multiple times rapidly → Only one request sent
- [ ] Loading overlay appears during VA generation
- [ ] Error 409 shows user-friendly message with "Lihat Kode" button
- [ ] Error 404 shows user-friendly message with "Coba Lagi" button
- [ ] Payment success page shows countdown timer
- [ ] Auto-redirect works after 5 seconds
- [ ] Manual "Kembali Sekarang" button works immediately
- [ ] All flows work on mobile devices (Chrome, Safari)
- [ ] All text is in Bahasa Indonesia
- [ ] Keyboard navigation works
- [ ] Screen reader announces loading states and countdown

### Acceptance Criteria

**Story 1: Prevent Duplicate VA Generation & Improve Feedback**

**AC1: Button Disable During Processing**
- GIVEN user clicks "Generate VA" button
- WHEN API request is in progress
- THEN button is disabled and shows loading spinner
- AND user cannot click button again
- AND loading overlay appears with message "Sedang membuat kode pembayaran..."

**AC2: Debounce Prevents Rapid Clicks**
- GIVEN user clicks "Generate VA" button multiple times within 500ms
- WHEN debounce is active
- THEN only one API request is sent
- AND subsequent clicks within 500ms are ignored

**AC3: User-Friendly Error Messages**
- GIVEN VA generation fails with HTTP 409
- WHEN error is displayed to user
- THEN message shows "Kode pembayaran Anda sudah dibuat! Klik di sini untuk melihat"
- AND "Lihat Kode Pembayaran" button is displayed
- AND clicking button navigates to existing VA view

**AC4: Error Recovery Options**
- GIVEN VA generation fails with any error
- WHEN error is displayed to user
- THEN "Coba Lagi" button is displayed
- AND clicking button retries VA generation
- AND "Kembali" button is displayed
- AND clicking button returns to payment method selection

**AC5: Loading Overlay Prevents Interaction**
- GIVEN VA generation is in progress
- WHEN loading overlay is displayed
- THEN user cannot interact with page content
- AND overlay shows clear message in Bahasa Indonesia
- AND overlay is responsive on mobile devices

**Story 2: Improve Post-Payment UX**

**AC6: Countdown Timer Display**
- GIVEN user completes payment successfully
- WHEN payment success page loads
- THEN countdown timer shows "Anda akan diarahkan ke dashboard dalam 5 detik..."
- AND countdown decrements every second (5, 4, 3, 2, 1)
- AND timer is visible and readable on mobile devices

**AC7: Auto-Redirect After Countdown**
- GIVEN countdown timer reaches 0
- WHEN timer completes
- THEN user is automatically redirected to dashboard/home page
- AND redirect happens smoothly without errors

**AC8: Manual Redirect Button**
- GIVEN countdown timer is active
- WHEN user clicks "Kembali Sekarang" button
- THEN user is immediately redirected to dashboard/home page
- AND countdown is cancelled

**AC9: Mobile-First Responsive Design**
- GIVEN user accesses payment flow on mobile device
- WHEN any new UI element is displayed
- THEN all elements are properly sized and positioned for mobile
- AND all text is readable without zooming
- AND all buttons are easily tappable (minimum 44x44px)

**AC10: Bahasa Indonesia Throughout**
- GIVEN user interacts with any new UI element
- WHEN text is displayed
- THEN all text is in Bahasa Indonesia
- AND language is appropriate for non-tech-savvy users (ibu-ibu awam)
- AND no technical jargon is used

---

## Developer Resources

### File Paths Reference

**New Files to Create:**
- `src/components/LoadingOverlay.tsx`
- `src/components/CountdownRedirect.tsx`
- `src/lib/errorMessages.ts`
- `src/lib/debounce.ts`
- `src/components/__tests__/LoadingOverlay.test.tsx`
- `src/components/__tests__/CountdownRedirect.test.tsx`
- `src/lib/__tests__/errorMessages.test.ts`
- `src/lib/__tests__/debounce.test.ts`

**Existing Files to Modify:**
- `src/features/payment/components/PaymentMethodSelector.tsx` (or equivalent)
- `src/features/payment/pages/PaymentSuccessPage.tsx` (or equivalent)
- `src/features/payment/hooks/useGenerateVA.ts` (or create if doesn't exist)

**Configuration Files (No Changes):**
- `package.json` - No new dependencies
- `vite.config.ts` - No changes
- `tailwind.config.ts` - No changes
- `tsconfig.json` - No changes

### Key Code Locations

**Payment Feature Module:**
- **Location:** `src/features/payment/` (assumed)
- **Key Components:**
  - Payment method selection component (contains VA generation button)
  - Payment success/status page component
- **Key Hooks:**
  - VA generation hook (may need to create)
- **Key Services:**
  - Midtrans API service (`src/services/midtrans.ts` or similar)

**Shared Components:**
- **Location:** `src/components/`
- **New Components:**
  - LoadingOverlay
  - CountdownRedirect

**Utilities:**
- **Location:** `src/lib/`
- **New Utilities:**
  - errorMessages
  - debounce

**Important Functions to Locate:**
1. VA generation API call function
2. Payment success navigation logic
3. Error handling in payment flow
4. Existing loading state management (if any)

### Testing Locations

**Unit Tests:**
- `src/lib/__tests__/` - Utility function tests
  - `debounce.test.ts`
  - `errorMessages.test.ts`

**Component Tests:**
- `src/components/__tests__/` - Component tests
  - `LoadingOverlay.test.tsx`
  - `CountdownRedirect.test.tsx`

**Integration Tests (Recommended):**
- `src/features/payment/__tests__/` - Payment flow integration tests
  - `PaymentFlow.integration.test.tsx`

**Test Configuration:**
- `vitest.config.ts` or `jest.config.js` (if exists)
- Test setup file (if exists)

### Documentation to Update

**Code Documentation:**
- [ ] Add JSDoc comments to all new functions and components
- [ ] Add inline comments for complex logic (debounce, countdown timer)
- [ ] Add TypeScript interfaces with descriptions

**Project Documentation:**
- [ ] Update `README.md` with new features (optional)
- [ ] Update API documentation if error responses changed (unlikely)
- [ ] Add this tech-spec to `docs/` folder for future reference

**User Documentation (Optional):**
- [ ] Update user guide with new payment flow behavior
- [ ] Update FAQ with error message explanations
- [ ] Create internal documentation for support team

---

## UX/UI Considerations

**UI Components Affected:**

**Story 1:**
1. **VA Generation Button**
   - MODIFY: Add disabled state styling
   - MODIFY: Add loading spinner
   - ENSURE: Button remains accessible (keyboard, screen reader)

2. **Loading Overlay** (NEW)
   - CREATE: Full-screen overlay component
   - DESIGN: Semi-transparent backdrop, centered content
   - ANIMATION: Fade in/out with Framer Motion
   - MOBILE: Full viewport coverage, readable text

3. **Error Display** (MODIFY)
   - MODIFY: Replace technical errors with user-friendly messages
   - ADD: Recovery action buttons
   - DESIGN: Clear, non-threatening, helpful tone

**Story 2:**
1. **Payment Success Page**
   - ADD: Countdown timer component
   - ADD: Manual redirect button
   - MODIFY: Layout to accommodate new elements
   - MOBILE: Ensure all elements visible without scrolling

**UX Flow Changes:**

**Current Flow:**
1. User selects payment method
2. User clicks "Generate VA"
3. (3-5 second delay with no feedback)
4. VA displayed OR error shown
5. After payment: Success page with no clear next step
6. User presses back → Invalid state

**New Flow:**
1. User selects payment method
2. User clicks "Generate VA"
3. **Button disables, loading overlay appears**
4. **"Sedang membuat kode pembayaran..." message shown**
5. VA displayed OR **user-friendly error with recovery options**
6. After payment: Success page with **countdown timer**
7. **Auto-redirect after 5 seconds** OR **user clicks "Kembali Sekarang"**
8. User lands on dashboard (no back button confusion)

**Visual/Interaction Patterns:**

**Loading States:**
- Spinner: Use existing spinner component or create simple CSS spinner
- Color: Match primary brand color
- Size: Appropriate for mobile (not too small)
- Animation: Smooth, not distracting

**Error States:**
- Color: Warning yellow or soft red (not harsh)
- Icon: Information icon (not scary error icon)
- Tone: Helpful, not blaming user
- Actions: Clear buttons with action verbs

**Success States:**
- Color: Success green
- Icon: Checkmark
- Tone: Positive, reassuring
- Actions: Clear next step

**Responsive Design:**
- Mobile-first: Design for 320px width minimum
- Breakpoints: Use TailwindCSS defaults (sm: 640px, md: 768px, lg: 1024px)
- Touch targets: Minimum 44x44px for buttons
- Text size: Minimum 16px for body text (prevents zoom on iOS)

**Accessibility:**

**Keyboard Navigation:**
- All interactive elements focusable
- Logical tab order
- Visible focus indicators
- ESC key to dismiss overlay (optional)

**Screen Reader:**
- ARIA labels for loading states
- ARIA live regions for countdown timer
- Descriptive button labels
- Alt text for icons

**Color Contrast:**
- WCAG AA compliance minimum
- Text on overlay readable
- Error messages high contrast

**User Feedback:**

**Loading Feedback:**
- Visual: Spinner + overlay
- Text: Clear message in Bahasa Indonesia
- Duration: Show immediately, hide on response

**Error Feedback:**
- Visual: Error message + icon
- Text: User-friendly explanation + recovery action
- Persistence: Stay until user takes action

**Success Feedback:**
- Visual: Success message + checkmark
- Text: Countdown timer with destination
- Action: Auto-redirect + manual option

---

## Testing Approach

**Test Framework:** Vitest (recommended for Vite) or Jest

**Testing Pyramid:**
- 70% Unit Tests (utilities, hooks)
- 20% Component Tests (UI components)
- 10% Integration Tests (full flows)

**Unit Tests:**

1. **`debounce.test.ts`**
   ```typescript
   describe('debounce', () => {
     it('delays function execution', () => {
       // Test implementation
     });
     
     it('only executes once for multiple rapid calls', () => {
       // Test implementation
     });
     
     it('clears timeout on cleanup', () => {
       // Test implementation
     });
   });
   ```

2. **`errorMessages.test.ts`**
   ```typescript
   describe('mapErrorToUserMessage', () => {
     it('maps HTTP 409 to user-friendly message', () => {
       // Test implementation
     });
     
     it('maps HTTP 404 to user-friendly message', () => {
       // Test implementation
     });
     
     it('returns default message for unknown errors', () => {
       // Test implementation
     });
   });
   ```

**Component Tests:**

3. **`LoadingOverlay.test.tsx`**
   ```typescript
   describe('LoadingOverlay', () => {
     it('renders when isLoading is true', () => {
       // Test implementation
     });
     
     it('does not render when isLoading is false', () => {
       // Test implementation
     });
     
     it('displays the provided message', () => {
       // Test implementation
     });
   });
   ```

4. **`CountdownRedirect.test.tsx`**
   ```typescript
   describe('CountdownRedirect', () => {
     it('decrements countdown every second', () => {
       // Test implementation with fake timers
     });
     
     it('calls onComplete when countdown reaches 0', () => {
       // Test implementation
     });
     
     it('redirects immediately when button clicked', () => {
       // Test implementation
     });
   });
   ```

**Integration Tests (Recommended):**

5. **Payment Flow Integration Test**
   ```typescript
   describe('Payment Flow', () => {
     it('prevents duplicate VA generation', () => {
       // Test full flow with multiple clicks
     });
     
     it('shows user-friendly error on 409', () => {
       // Test error handling
     });
     
     it('auto-redirects after payment success', () => {
       // Test success flow
     });
   });
   ```

**Coverage Goals:**
- Overall: 80%+
- New utilities: 100%
- New components: 90%+
- Modified components: 80%+

**Manual Testing Checklist:**
- [ ] Desktop Chrome
- [ ] Desktop Firefox
- [ ] Desktop Safari
- [ ] Mobile Chrome (Android)
- [ ] Mobile Safari (iOS)
- [ ] Tablet (iPad)
- [ ] Slow 3G network simulation
- [ ] Offline scenario
- [ ] Keyboard-only navigation
- [ ] Screen reader (NVDA/JAWS/VoiceOver)

---

## Deployment Strategy

### Deployment Steps

**Pre-Deployment:**

1. **Code Review**
   - Create pull request from feature branch
   - Request review from team lead
   - Address all review comments
   - Ensure all tests pass

2. **QA Testing**
   - Deploy to staging environment
   - QA team tests all acceptance criteria
   - Fix any bugs found
   - Re-test until all criteria pass

3. **Merge to Main**
   ```bash
   git checkout main
   git merge feature/payment-ux-improvements
   git push origin main
   ```

**Deployment to Production:**

4. **Build Production Bundle**
   ```bash
   npm run build
   ```

5. **Deploy Frontend**
   - Upload `dist/` folder to hosting (Vercel, Netlify, or custom server)
   - Verify environment variables are set
   - Test production build locally with `npm run preview`

6. **Deploy Backend (if changes)**
   - No backend changes in Phase 1
   - Backend deployment not required

7. **Verify Deployment**
   - Test VA generation on production
   - Test error scenarios
   - Test payment success flow
   - Monitor for errors

**Post-Deployment:**

8. **Monitor**
   - Watch error logs for 24 hours
   - Monitor user behavior analytics
   - Check support ticket volume
   - Gather user feedback

9. **Iterate**
   - Address any issues found
   - Plan Phase 2 improvements based on data

### Rollback Plan

**If Critical Issues Found:**

1. **Immediate Rollback**
   ```bash
   # Revert to previous commit
   git revert HEAD
   git push origin main
   
   # Rebuild and redeploy
   npm run build
   # Deploy dist/ folder
   ```

2. **Verify Rollback**
   - Test that old behavior is restored
   - Confirm no errors in logs
   - Notify users if necessary

3. **Post-Mortem**
   - Identify what went wrong
   - Fix issues in feature branch
   - Re-test thoroughly
   - Re-deploy when ready

**Rollback Triggers:**
- Critical bug preventing payments
- Widespread errors (>5% of transactions)
- Security vulnerability discovered
- Performance degradation (>2s load time increase)

### Monitoring

**Metrics to Monitor:**

**User Behavior:**
- VA generation success rate (target: >95%)
- Error rate (target: <5%)
- Payment completion rate (target: increase by 10%+)
- Time on payment success page (target: decrease by 50%)
- Back button usage after payment (target: decrease by 80%)

**Technical Metrics:**
- API response time (target: <3 seconds)
- Frontend load time (target: <2 seconds)
- Error logs (target: <1% error rate)
- 409 error frequency (target: near zero)

**Business Metrics:**
- Abandoned transaction rate (target: decrease by 20%+)
- Support ticket volume (target: decrease by 30%+)
- User satisfaction score (target: increase)

**Monitoring Tools:**
- Google Analytics for user behavior
- Sentry or similar for error tracking
- Server logs for API monitoring
- User feedback surveys

**Alert Thresholds:**
- Error rate >10% → Immediate alert
- API response time >5s → Warning alert
- Payment success rate <90% → Critical alert

---

**End of Technical Specification**

This tech-spec provides a comprehensive guide for implementing Phase 1 Quick Wins Bundle (2 stories, 5 solutions) to improve payment flow UX for non-tech-savvy users in a brownfield Midtrans payment application.
