# Displays & Formatters

## Definition

A **Display** encapsulates **reusable, UI-only display logic**.

In this codebase, we distinguish between **Formatters** (Stateless Logic) and **Display Objects** (Rich Value Objects).

### 1. Formatters (The "Mouth")
Formatters are pure, stateless utilities. They are the "Experts" on how to transform a raw value into a primitive string/number.
- **Usage:** Used by `ViewDataBuilders` (Server) and `ViewModels` (Client).
- **Output:** MUST return primitive values only (`string`, `number`, `boolean`, `null`).
- **Uncle Bob says:** "Data structures (ViewData) should not have behavior. Keep logic in stateless utilities."

### 2. Display Objects (The "Rich API")
Display Objects are logic-rich **Value Objects** that live only on the client. They wrap data and provide multiple ways to look at it.
- **Usage:** Used by `ViewModels` (Client) to provide a rich API to the UI.
- **Output:** Can return complex objects or variants.
- **Uncle Bob says:** "Objects expose behavior, not data. Use them to hide the complexity of the UI."

---

## Responsibilities

A Display/Formatter MAY:
- format values (money, dates, durations)
- handle deterministic localization (mapping stable codes to labels)
- encapsulate UI display conventions

A Display/Formatter MUST:
- be deterministic
- be side-effect free
- be implemented as a **class** with static methods (Formatters) or as immutable classes (Display Objects)

---

## Restrictions

A Display/Formatter MUST NOT:
- contain business logic (e.g., "Team is full if count > 10")
- enforce domain invariants
- perform validation
- **be serialized** (only their primitive outputs are stored in `ViewData`)
- call `Intl.*` or `toLocale*` (unless explicitly marked for client-only ViewModels)

---

## Relationship to ViewData and ViewModels

### The "Primitive Compact" (Server-Side)
`ViewDataBuilders` MUST use **Formatters** to produce flat, serializable `ViewData`.
- **Rule:** `ViewData` properties assigned from a Display/Formatter MUST be primitives.
- **Reason:** Ensures `ViewData` remains a "dumb" JSON structure for SSR.

### The "Rich API" (Client-Side)
`ViewModels` MAY use **Display Objects** to provide interactive formatting.
- **Rule:** `ViewModels` can return `Display Object` instances to the UI.
- **Reason:** Allows the UI to access multiple variants (e.g., `date.short`, `date.relative`) without re-fetching data.

---

## Summary of the Flow

```mermaid
graph TD
    DTO[Raw DTO] -->|ViewDataBuilder| VD[ViewData]
    subgraph "Server: The Formatter Compact"
    VD -->|Uses| F[Stateless Formatter]
    F -->|Returns| S[Primitive string/number]
    end
    
    VD -->|SSR Boundary| T[Template]
    
    subgraph "Client: The DisplayObject Richness"
    T -->|Props| CW[ClientWrapper]
    CW -->|new| VM[ViewModel]
    VM -->|Wraps| DO[Rich Display Object]
    DO -->|Provides| R[Rich API: .time, .relative, .date]
    end
```

## Final Rule: Where does logic live?

1. **Is it a business rule?** (e.g., "Can join?") → **ViewModel**.
2. **Is it a formatting rule?** (e.g., "How to show date?") → **Formatter/Display**.
3. **Is it for SEO/SSR?** → **ViewDataBuilder** (using a Formatter).
4. **Is it for interaction?** → **ViewModel** (using a Display Object).