do to formatters

This commit is contained in:
2026-01-24 01:22:43 +01:00
parent 891b3cf0ee
commit 705f9685b5
18 changed files with 361 additions and 760 deletions

View File

@@ -85,9 +85,9 @@ export function TeamsTemplate({ teams, searchQuery, onSearchChange, onTeamClick
<SearchInput value={searchQuery} onChange={onSearchChange} />
</Header>
<TeamLeaderboardPreview
teams={teams}
onTeamClick={onTeamClick}
<TeamLeaderboardPreview
teams={teams}
onTeamClick={onTeamClick}
/>
<TeamGrid teams={teams} onTeamClick={onTeamClick} />
@@ -123,7 +123,7 @@ import { Card, CardHeader, TeamRow } from '@/ui';
export function TeamLeaderboardPreview({ teams, onTeamClick }: Props) {
// App-specific logic: medal colors, ranking, etc.
const getMedalColor = (position: number) => {
const getMedalColor = (position: number) => {
if (position === 0) return 'gold';
if (position === 1) return 'silver';
return 'none';
@@ -133,7 +133,7 @@ export function TeamLeaderboardPreview({ teams, onTeamClick }: Props) {
<Card variant="elevated">
<CardHeader title="Top Teams" />
{teams.map((team, index) => (
<TeamRow
<TeamRow
key={team.id}
name={team.name}
rank={index + 1}
@@ -174,7 +174,7 @@ export function Button({ children, variant = 'primary', onClick }: ButtonProps)
}[variant];
return (
<button
<button
className={`px-4 py-2 rounded-md transition-colors ${classes}`}
onClick={onClick}
>
@@ -224,7 +224,7 @@ Components must only expose props that describe **what** the component is or **h
- **`components/` components**: **MUST NOT** use `className`, `style`, or any prop that accepts raw styling values. They must only use the semantic APIs provided by `ui/`.
- **`templates/`**: Same as `components/`.
## The Display Object Layer
## The Formatter & Display Object Layer
**Purpose**: Reusable formatting and presentation logic
@@ -235,11 +235,13 @@ Components must only expose props that describe **what** the component is or **h
- Value transformations for display
**Rules**:
- **Formatters**: Stateless utilities for server-side primitive output.
- **Display Objects**: Rich Value Objects for client-side interactive APIs.
- Class-based
- Immutable
- Deterministic
- No side effects
- No `Intl.*` or `toLocale*`
- No `Intl.*` or `toLocale*` (unless client-only)
**Usage**:
```typescript
@@ -256,11 +258,15 @@ export class RatingDisplay {
}
}
// In ViewModel Builder
const viewModel = {
rating: RatingDisplay.format(dto.rating),
ratingColor: RatingDisplay.getColor(dto.rating)
// In ViewData Builder (Server)
const viewData = {
rating: RatingDisplay.format(dto.rating), // Primitive string
};
// In ViewModel (Client)
get rating() {
return new RatingDisplay(this.data.rating); // Rich API
}
```
## Dependency Flow
@@ -292,7 +298,7 @@ ui/ (generic primitives)
- **Component**: Understands app concepts (teams, races, leagues)
- **UI**: Generic building blocks (button, card, input)
### When to use Display Objects?
### When to use Formatters/Display Objects?
- When formatting is reusable across multiple ViewModels
- When mapping codes to labels
- When presentation logic needs to be deterministic