# Transaction History Flow

# Flow: Transaction History

**Document:** LLD-003
**Version:** 1.0
**Date:** 2026-02-21
**Author:** Frontend Architect (AI Agent)
**Status:** Draft
**Scope:** Transaction list rendering, filtering, pagination, transaction detail view, receipt download, and dispute initiation

---

## 1. Overview

The transaction history view provides users with a chronological list of all their financial transactions (remittances and QR payments). The list supports filtering by type and status, date-based grouping, infinite scroll pagination, and drill-down to transaction detail with receipt download.

**Key capabilities:**
- Paginated transaction list (20 per page, max 50)
- Filter by type: All, Remittance, QR Payment
- Filter by status: Processing, Completed, Failed
- Date grouping: I dag, I gar, Denne uken, Eldre
- Transaction detail view with exchange rate info
- Receipt download (JSON receipt)
- Complaint/dispute initiation via `/complaints`

---

## 2. Transaction List Load + Filter + Detail View

### 2.1 Sequence Diagram

```mermaid
sequenceDiagram
    actor User
    participant App as Drop App<br/>(/transactions)
    participant API as Drop API
    participant DB as Database

    User->>App: Navigate to /transactions
    App->>App: useAuth() — verify authenticated

    App->>API: GET /api/transactions?page=1&limit=20
    API->>API: JWT verification (cookie/Bearer)
    API->>DB: SELECT transactions WHERE user_id = ?<br/>ORDER BY created_at DESC LIMIT 20
    API-->>App: { data: [...], pagination: { page: 1, limit: 20, total: N } }

    App->>App: groupByDate(transactions)<br/>→ "I dag", "I gar", "Denne uken", "Eldre"
    App->>App: Render grouped transaction list

    User->>App: Tap filter "Overforinger"
    App->>API: GET /api/transactions?type=remittance&limit=50
    API->>DB: SELECT WHERE type = 'remittance'
    API-->>App: { data: [...filtered...] }
    App->>App: Re-group and render

    User->>App: Scroll to bottom (infinite scroll)
    App->>API: GET /api/transactions?page=2&limit=20&type=remittance
    API-->>App: { data: [...more...], pagination: { page: 2 } }
    App->>App: Append to list, re-group

    User->>App: Tap transaction row
    App->>API: GET /api/transactions/{id}
    API->>DB: SELECT transaction with exchange_rate info
    API-->>App: { data: { ...fullDetails } }
    App->>App: Show transaction detail modal/page

    User->>App: Tap "Last ned kvittering"
    App->>API: GET /api/transactions/{id}/receipt
    API-->>App: { data: { receipt } }
    App->>App: Download/display receipt

    User->>App: Tap "Klag" (dispute)
    App->>App: Navigate to /complaints<br/>with transaction context
```

---

## 3. Transaction List Components

### 3.1 Component Diagram

```mermaid
graph TD
    subgraph "Transaction History Page"
        PageHeader["PageHeader<br/>Back button + 'Transaksjonshistorikk' title"]
        FilterTabs["FilterTabs<br/>(Tabs component)"]
        TransactionList["TransactionList<br/>(scrollable area)"]
        LoadMore["LoadMore Trigger<br/>(infinite scroll sentinel)"]
    end

    subgraph "Filter Tabs"
        TabAll["Alle<br/>(all types)"]
        TabRemittance["Overforinger<br/>(type=remittance)"]
        TabQR["QR-betalinger<br/>(type=qr_payment)"]
    end

    subgraph "Transaction List Items"
        DateGroup["DateGroupHeader<br/>('I DAG', 'I GAR', etc.)"]
        TransactionCard["TransactionCard"]
    end

    subgraph "Transaction Card"
        TxIcon["TypeIcon<br/>(ArrowUpRight, ScanLine, Clock)"]
        TxInfo["TxInfo<br/>(name, type label)"]
        TxAmount["TxAmount<br/>(amount + status badge)"]
    end

    subgraph "Transaction Detail"
        DetailHeader["DetailHeader<br/>(back + title)"]
        DetailSummary["DetailSummary<br/>(type, status, date)"]
        AmountBreakdown["AmountBreakdown<br/>(send, receive, rate, fee)"]
        RecipientInfo["RecipientInfo<br/>(name, country, bank)"]
        ReceiptButton["ReceiptButton<br/>('Last ned kvittering')"]
        DisputeButton["DisputeButton<br/>('Klag')"]
    end

    FilterTabs --> TabAll
    FilterTabs --> TabRemittance
    FilterTabs --> TabQR

    TransactionList --> DateGroup
    DateGroup --> TransactionCard
    TransactionCard --> TxIcon
    TransactionCard --> TxInfo
    TransactionCard --> TxAmount

    TransactionCard -->|tap| DetailHeader
    DetailHeader --> DetailSummary
    DetailSummary --> AmountBreakdown
    AmountBreakdown --> RecipientInfo
    RecipientInfo --> ReceiptButton
    RecipientInfo --> DisputeButton
```

---

## 4. Filter Options

### 4.1 Filter Options Table

| Filter | API Parameter | Value | Label (Norwegian) | Default |
|--------|--------------|-------|--------------------|---------|
| All transactions | (none) | — | Alle | Yes |
| Remittances only | `type` | `remittance` | Overforinger | No |
| QR payments only | `type` | `qr_payment` | QR-betalinger | No |
| Processing status | `status` | `processing` | Behandles | No |
| Completed status | `status` | `completed` | Fulfort | No |
| Failed status | `status` | `failed` | Mislykket | No |

### 4.2 Pagination Parameters

| Parameter | Type | Default | Min | Max | Description |
|-----------|------|---------|-----|-----|-------------|
| `page` | int | 1 | 1 | — | Page number |
| `limit` | int | 20 | 1 | 50 | Items per page |

---

## 5. Transaction Status Display Mapping

| Status | Label (Norwegian) | Color | Icon | Background |
|--------|--------------------|-------|------|------------|
| `completed` | Fulfort | `#0B6E35` (green) | ArrowUpRight / ScanLine | `#F8FAFC` |
| `processing` | Behandles | `#D4A017` (gold) | Clock | `#FEF3C7` |
| `failed` | Mislykket | `#EF4444` (red) | X | `#FEF2F2` |

### 5.1 Transaction Type Icons

| Type | Icon | Color | Description |
|------|------|-------|-------------|
| `remittance` (sent) | ArrowUpRight | `#0B6E35` | Outgoing international transfer |
| `qr_payment` | ScanLine | `#0B6E35` | QR code payment to merchant |
| `remittance` (processing) | Clock | `#D4A017` | Transfer in progress |

### 5.2 Amount Display

| Condition | Format | Color | Example |
|-----------|--------|-------|---------|
| Outgoing (sent) | `-{amount} kr` | `#0F172A` (dark) | -2 000 kr |
| Incoming (received) | `+{amount} kr` | `#10B981` (green) | +5 000 kr |
| Processing | `-{amount} kr` | `#0F172A` (dark) | -3 000 kr |

---

## 6. Date Grouping Logic

The `groupByDate()` function categorizes transactions into temporal groups:

| Group | Label | Condition |
|-------|-------|-----------|
| Today | I DAG | `createdAt` is today |
| Yesterday | I GAR | `createdAt` is yesterday |
| This Week | DENNE UKEN | `createdAt` is within current week (Mon-Sun) |
| Older | Date string (e.g., "12. OKT") | All older transactions, grouped by date |

---

## 7. Transaction Detail View

### 7.1 Remittance Detail Fields

| Field | Source | Example |
|-------|--------|---------|
| Transaction ID | `data.id` | tx_rem_a1b2c3d4e5f6g7h8 |
| Type | `data.type` | Overforing |
| Status | `data.status` | Fullfort |
| Send Amount | `data.sendAmount` + `data.sendCurrency` | 2 000 NOK |
| Receive Amount | `data.receiveAmount` + `data.receiveCurrency` | 23 400 RSD |
| Exchange Rate | `data.exchangeRate` | 1 NOK = 11.70 RSD |
| Fee | `data.fee` | 10.00 NOK (0.5%) |
| Total Cost | `data.total` | 2 010 NOK |
| Recipient | `data.recipientName` | Mama Jasmina |
| Destination | `data.recipientCountry` | Serbia |
| Created | `data.createdAt` | 21. feb 2026 kl. 14:32 |
| Completed | `data.completedAt` | 21. feb 2026 kl. 14:35 |

### 7.2 QR Payment Detail Fields

| Field | Source | Example |
|-------|--------|---------|
| Transaction ID | `data.id` | tx_qr_a1b2c3d4e5f6g7h8 |
| Type | `data.type` | QR-betaling |
| Status | `data.status` | Fullfort |
| Amount | `data.amount` | 129 NOK |
| Fee | `data.fee` | 1.29 NOK (1%) |
| Merchant | `data.merchantName` | Ahmetov Kebab |
| Source Account | `data.fromAccount` | DNB |
| Created | `data.createdAt` | 21. feb 2026 kl. 12:15 |

### 7.3 Receipt Endpoint

`GET /api/transactions/{id}/receipt` returns a structured receipt:

```json
{
  "data": {
    "transactionId": "tx_rem_1",
    "date": "2026-02-21T14:32:00.000Z",
    "type": "remittance",
    "amount": 2000,
    "currency": "NOK",
    "fee": 10,
    "exchangeRate": 11.7,
    "receiveAmount": 23400,
    "receiveCurrency": "RSD",
    "recipient": { "name": "Mama Jasmina", "country": "RS" },
    "reference": "tx_rem_1",
    "status": "completed",
    "completedAt": "2026-02-21T14:35:00.000Z"
  }
}
```

---

## 8. Dispute Initiation

Users can initiate a dispute from the transaction detail view by navigating to the complaints page:

| Step | Action |
|------|--------|
| 1 | User taps "Klag" on transaction detail |
| 2 | Navigate to `/complaints` with pre-filled category = "transaction" |
| 3 | User fills subject and description |
| 4 | `POST /api/complaints { category: "transaction", subject, description }` |
| 5 | Confirmation: "Vi behandler klagen din innen 15 virkedager" (Finansavtaleloven 3-53) |

---

## 9. Platform Differences

| Feature | Web (`/transactions`) | Mobile (`history.js`) |
|---------|----------------------|----------------------|
| Filter tabs | Tabs component (Alle, Overforinger, QR-betalinger) | Custom buttons (Alle, Sendinger, QR) |
| Pagination | Infinite scroll with limit=50 | FlatList with pull-to-refresh |
| Transaction detail | Inline expansion or modal | Separate screen (not yet implemented) |
| Receipt download | API call + browser download | Not implemented |
| Dispute link | Navigate to /complaints | Not implemented |
| Date grouping | groupByDate() utility | Same pattern |
| Refresh | Re-fetch on filter change | Pull-to-refresh via RefreshControl |

---

## 10. Accessibility Considerations (WCAG 2.1 AA)

| Requirement | Implementation |
|-------------|---------------|
| List semantics | Transaction list uses semantic list markup |
| Filter announcement | Active filter tab announced to screen readers |
| Amount polarity | Positive/negative amounts use text prefix (+/-) in addition to color |
| Status indication | Status uses both color AND text label (not color alone) |
| Tap targets | Transaction cards are full-width, min 48px height |
| Loading state | Skeleton placeholders shown during initial load |
| Empty state | "Ingen transaksjoner" message when list is empty |
| Keyboard nav | Tab cycles through filters, then transaction items |

---

## 11. Cross-References

- **Transaction list API:** `GET /api/transactions` — See [API Reference](../../backend/API-REFERENCE.md)
- **Transaction detail API:** `GET /api/transactions/{id}` — See [API Reference](../../backend/API-REFERENCE.md)
- **Receipt API:** `GET /api/transactions/{id}/receipt` — See [API Reference](../../backend/API-REFERENCE.md)
- **Complaints API:** `POST /api/complaints` — See [API Reference](../../backend/API-REFERENCE.md)
- **Transaction schema:** `transactions` table — See [Database Schema](../../backend/DATABASE-SCHEMA.md)
- **Component overview:** See [component-overview.md](../hld/component-overview.md)
- **Figma transaction history:** `mockups/figma-make-export/src/app/screens/TransactionHistory.tsx`
- **Web page:** `src/drop-app/src/app/transactions/page.tsx` — See [PAGES.md](../../frontend/PAGES.md)
- **Mobile screen:** `src/drop-mobile/app/history.js` — See [MOBILE-APP.md](../../mobile/MOBILE-APP.md)
- **QR payment flow:** See [flow-qr-payment.md](flow-qr-payment.md)