do to formatters
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user