# 🎨 Horizon Domain Data Display Enricher

> Enriquecedor genérico de dados de domínios para display - Transforma dados brutos de entidades em objetos enriquecidos para UI

## 📋 Índice
1. [Visão Geral](#visão-geral)
2. [Instalação](#instalação)
3. [Uso Básico](#uso-básico)
4. [API Completa](#api-completa)
5. [Formatadores](#formatadores)
6. [Templates](#templates)
7. [Exemplos Práticos](#exemplos-práticos)
8. [Migração](#migração)
9. [Estrutura do Pacote](#estrutura-do-pacote)

---

## 🎯 Visão Geral

O **Horizon Domain Data Display Enricher** é uma biblioteca genérica para transformar dados brutos de qualquer domínio (Property, Broker, User, etc.) em objetos enriquecidos com metadados, formatação e informações adicionais para facilitar a exibição no frontend.

### Principais Características

- ✅ **Genérico**: Funciona com qualquer tipo de domínio
- ✅ **Formatação Automática**: Suporta currency, date, area, distance, percent, count
- ✅ **Templates Inteligentes**: Processamento de pluralização e substituições
- ✅ **Type-Safe**: Escrito em TypeScript com tipos completos
- ✅ **Extensível**: Permite customização via opções
- ✅ **Retrocompatível**: Mantém compatibilidade com API antiga

### Transformação Exemplo

```typescript
// ENTRADA (dados brutos)
{
  valor: 1500000,
  dormitorios: 3
}

// SAÍDA (dados enriquecidos)
{
  valor: {
    value: 1500000,
    label: "Valor",
    type: "Number",
    format: "currency",
    valueLabel: "R$ 1.500.000,00",
    composedLabel: "R$ 1.500.000,00"
  },
  dormitorios: {
    value: 3,
    label: "Dormitórios",
    type: "Number",
    format: "count",
    valueLabel: "3",
    composedLabel: "3 dormitórios"
  }
}
```

---

## 📦 Instalação

### Como Pacote NPM (Futuro)

```bash
npm install @horizon/domain-data-display-enricher
# ou
yarn add @horizon/domain-data-display-enricher
# ou
pnpm add @horizon/domain-data-display-enricher
```

### Uso Local (Atual)

```typescript
import { enrichDomainDataForDisplay } from '@/modules/horizon-platform-toolkit';
```

---

## 🚀 Uso Básico

### 1. Exemplo Simples

```typescript
import { enrichDomainDataForDisplay } from '@horizon/domain-data-display-enricher';

// Dados brutos do domínio
const propertyData = {
  title: "Apartamento 3 quartos",
  price: 750000,
  area: 120,
  rooms: 3
};

// Metadados do schema
const metadata = [
  {
    key: "title",
    label: "Título",
    type: "String"
  },
  {
    key: "price",
    label: "Preço",
    type: "Number",
    format: "currency",
    unit: "BRL"
  },
  {
    key: "area",
    label: "Área",
    type: "Number",
    format: "area",
    unit: "m2"
  },
  {
    key: "rooms",
    label: "Quartos",
    type: "Number",
    format: "count",
    composedLabel: "{{value}} quarto{{p:s}}"
  }
];

// Enriquecer dados
const enrichedData = enrichDomainDataForDisplay({
  data: propertyData,
  metadata: metadata
});

console.log(enrichedData.price.valueLabel); // "R$ 750.000,00"
console.log(enrichedData.area.valueLabel); // "120 m²"
console.log(enrichedData.rooms.composedLabel); // "3 quartos"
```

### 2. Com Opções Avançadas

```typescript
const enrichedData = enrichDomainDataForDisplay({
  data: myData,
  metadata: myMetadata,
  locale: 'en-US',
  currency: 'USD',
  getIcon: (iconName) => IconLibrary.get(iconName)
});
```

---

## 📚 API Completa

### Função Principal

#### `enrichDomainDataForDisplay(options: EnrichmentOptions)`

Enriquece dados de domínio com metadados para display.

**Parâmetros:**

```typescript
interface EnrichmentOptions {
  data: Record<string, any>;      // Dados brutos
  metadata: FieldMetadata[];      // Metadados dos campos
  locale?: string;                // Locale (default: 'pt-BR')
  currency?: string;              // Moeda padrão (default: 'BRL')
  getIcon?: (name: string) => any; // Função para obter ícones
}
```

**Retorno:**
```typescript
Record<string, EnrichedField | any>
```

### Tipos

#### `FieldMetadata`

```typescript
interface FieldMetadata {
  key: string;                  // Chave do campo
  label?: string;               // Label para UI
  type?: string;                // Tipo do dado
  format?: string;              // Formato de exibição
  unit?: string;                // Unidade de medida
  categories?: string[];        // Categorias
  composedLabel?: string;       // Template de composição
  icon?: string;                // Ícone direto
  iconName?: string;            // Nome do ícone
  validation?: any;             // Regras de validação
  [key: string]: any;          // Campos adicionais
}
```

#### `EnrichedField`

```typescript
interface EnrichedField extends FieldMetadata {
  value: any;                   // Valor original
  valueLabel?: string;          // Valor formatado
  composedLabel?: string;       // Label composto processado
  icon?: any;                   // Ícone resolvido
}
```

---

## 🎨 Formatadores

### Formatadores Disponíveis

| Format | Descrição | Exemplo |
|--------|-----------|---------|
| `currency` | Valores monetários | 1500 → "R$ 1.500,00" |
| `date` | Datas | "2025-08-07" → "7 de agosto de 2025" |
| `area` | Áreas | 100 → "100 m²" |
| `distance` | Distâncias | 150 → "150m" |
| `percent` | Porcentagens | 15 → "15%" |
| `count` | Contagem | 3 → "3" |
| `year` | Anos | 2025 → "2025" |

### Uso Direto dos Formatadores

```typescript
import { formatters } from '@horizon/domain-data-display-enricher';

// Moeda
formatters.currency(1500.50, 'BRL', 'pt-BR'); // "R$ 1.500,50"
formatters.currency(1500.50, 'USD', 'en-US'); // "$1,500.50"

// Data
formatters.date(new Date('2025-08-07'), 'pt-BR'); // "7 de agosto de 2025"

// Área
formatters.area(120, 'm2'); // "120 m²"
formatters.area(50, 'hectares'); // "50 hectares"

// Distância
formatters.distance(150, 'm'); // "150m"
formatters.distance(5, 'km'); // "5km"

// Porcentagem
formatters.percent(15); // "15%"
formatters.percent(0.15); // "15.00%"
```

---

## 📝 Templates

### Sistema de Templates

O sistema suporta templates com substituições dinâmicas:

| Placeholder | Descrição | Exemplo |
|-------------|-----------|---------|
| `{{value}}` | Valor bruto | 3 → "3" |
| `{{valueLabel}}` | Valor formatado | 3 → "3" |
| `{{p:texto}}` | Texto no plural | 1 → "", 2 → "texto" |
| `{{s:texto}}` | Texto no singular | 1 → "texto", 2 → "" |

### Exemplos de Templates

```typescript
// Pluralização
"{{value}} quarto{{p:s}}"
// 1 → "1 quarto"
// 3 → "3 quartos"

// Singular condicional
"{{s:Apenas }}{{value}} vaga{{p:s}}"
// 1 → "Apenas 1 vaga"
// 2 → "2 vagas"

// Com valor formatado
"Total: {{valueLabel}}"
// 1500 com format: currency → "Total: R$ 1.500,00"
```

### Uso do Processador de Templates

```typescript
import { templateProcessor } from '@horizon/domain-data-display-enricher';

const result = templateProcessor(
  "{{value}} item{{p:s}} - {{valueLabel}}",
  3,
  "R$ 30,00"
);
// "3 items - R$ 30,00"
```

---

## 💡 Exemplos Práticos

### Exemplo 1: Sistema de Imóveis

```typescript
const propertyData = {
  reference: "APT-001",
  type: "Apartamento",
  price: 850000,
  rent: 3500,
  area: 150,
  rooms: 3,
  bathrooms: 2,
  garage: 2,
  condo_fee: 800,
  distance_beach: 200,
  furnished: true,
  features: ["Piscina", "Academia", "Playground"]
};

const propertyMetadata = [
  { key: "reference", label: "Referência", type: "String" },
  { key: "type", label: "Tipo", type: "String" },
  { 
    key: "price", 
    label: "Valor de Venda",
    type: "Number",
    format: "currency",
    unit: "BRL",
    categories: ["valores", "principais"]
  },
  {
    key: "rent",
    label: "Valor de Aluguel",
    type: "Number",
    format: "currency",
    unit: "BRL",
    composedLabel: "{{valueLabel}}/mês"
  },
  {
    key: "area",
    label: "Área",
    type: "Number",
    format: "area",
    unit: "m2",
    iconName: "area"
  },
  {
    key: "rooms",
    label: "Dormitórios",
    type: "Number",
    format: "count",
    composedLabel: "{{value}} dormitório{{p:s}}",
    iconName: "bedroom"
  },
  {
    key: "bathrooms",
    label: "Banheiros",
    type: "Number",
    format: "count",
    composedLabel: "{{value}} banheiro{{p:s}}",
    iconName: "bathroom"
  },
  {
    key: "garage",
    label: "Vagas",
    type: "Number",
    format: "count",
    composedLabel: "{{value}} vaga{{p:s}}",
    iconName: "garage"
  },
  {
    key: "distance_beach",
    label: "Distância da Praia",
    type: "Number",
    format: "distance",
    unit: "m",
    composedLabel: "{{valueLabel}} da praia"
  },
  {
    key: "furnished",
    label: "Mobiliado",
    type: "Boolean"
  },
  {
    key: "features",
    label: "Características",
    type: "Array"
  }
];

const enriched = enrichDomainDataForDisplay({
  data: propertyData,
  metadata: propertyMetadata,
  getIcon: (name) => `icon-${name}` // Mock icon function
});

// Resultados
console.log(enriched.price.valueLabel);        // "R$ 850.000,00"
console.log(enriched.rent.composedLabel);      // "R$ 3.500,00/mês"
console.log(enriched.area.valueLabel);         // "150 m²"
console.log(enriched.rooms.composedLabel);     // "3 dormitórios"
console.log(enriched.bathrooms.composedLabel); // "2 banheiros"
console.log(enriched.garage.composedLabel);    // "2 vagas"
console.log(enriched.distance_beach.composedLabel); // "200m da praia"
console.log(enriched.furnished.valueLabel);    // "Sim"
```

### Exemplo 2: Sistema de Usuários

```typescript
const userData = {
  name: "João Silva",
  age: 28,
  salary: 5500,
  hire_date: "2023-03-15",
  performance: 0.92,
  active: true,
  skills: ["JavaScript", "TypeScript", "React"]
};

const userMetadata = [
  { key: "name", label: "Nome", type: "String" },
  { key: "age", label: "Idade", type: "Number", format: "count" },
  {
    key: "salary",
    label: "Salário",
    type: "Number",
    format: "currency",
    unit: "BRL"
  },
  {
    key: "hire_date",
    label: "Data de Contratação",
    type: "String",
    format: "date"
  },
  {
    key: "performance",
    label: "Performance",
    type: "Number",
    format: "percent"
  },
  { key: "active", label: "Ativo", type: "Boolean" },
  { key: "skills", label: "Habilidades", type: "Array" }
];

const enrichedUser = enrichDomainDataForDisplay({
  data: userData,
  metadata: userMetadata
});

console.log(enrichedUser.salary.valueLabel);     // "R$ 5.500,00"
console.log(enrichedUser.hire_date.valueLabel);  // "15 de março de 2023"
console.log(enrichedUser.performance.valueLabel); // "92.00%"
console.log(enrichedUser.active.valueLabel);     // "Sim"
```

---

## 🔄 Migração

### Da API Antiga para a Nova

```typescript
// ANTES (API antiga)
import { EnrichFieldsWithMetadata } from 'caminho/antigo';

const result = EnrichFieldsWithMetadata({
  data: myData,
  metadata: myMetadata
});

// DEPOIS (API nova)
import { enrichDomainDataForDisplay } from '@horizon/domain-data-display-enricher';

const result = enrichDomainDataForDisplay({
  data: myData,
  metadata: myMetadata
});
```

### Compatibilidade

A função `EnrichFieldsWithMetadata` ainda está disponível para retrocompatibilidade:

```typescript
import { EnrichFieldsWithMetadata } from '@horizon/domain-data-display-enricher';

// Funciona como antes (mas está deprecated)
const result = EnrichFieldsWithMetadata({ data, metadata });
```

---

## 📂 Estrutura do Pacote

```
horizon-domain-data-display-enricher/
├── src/
│   ├── index.ts              # Arquivo principal
│   ├── types.ts              # Definições de tipos
│   ├── formatters.ts         # Funções de formatação
│   ├── templates.ts          # Processador de templates
│   └── enricher.ts           # Lógica de enriquecimento
├── tests/
│   ├── index.test.ts         # Testes principais
│   ├── formatters.test.ts    # Testes dos formatadores
│   └── templates.test.ts     # Testes de templates
├── docs/
│   └── README.md             # Esta documentação
├── package.json
├── tsconfig.json
└── README.md
```

---

## 🔧 Configuração para NPM

### package.json Sugerido

```json
{
  "name": "@horizon/domain-data-display-enricher",
  "version": "1.0.0",
  "description": "Generic domain data enricher for display - Transform raw entity data into enriched UI objects",
  "main": "dist/index.js",
  "module": "dist/index.mjs",
  "types": "dist/index.d.ts",
  "files": [
    "dist",
    "README.md"
  ],
  "scripts": {
    "build": "tsup src/index.ts --format cjs,esm --dts",
    "test": "vitest",
    "test:coverage": "vitest run --coverage"
  },
  "keywords": [
    "horizon",
    "enricher",
    "formatter",
    "display",
    "ui",
    "metadata",
    "transform"
  ],
  "author": "Horizon Platform",
  "license": "MIT",
  "dependencies": {
    "date-fns": "^2.30.0"
  },
  "devDependencies": {
    "@types/node": "^20.0.0",
    "tsup": "^8.0.0",
    "typescript": "^5.0.0",
    "vitest": "^1.0.0"
  },
  "peerDependencies": {
    "date-fns": ">=2.0.0"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/horizon-platform/domain-data-display-enricher"
  }
}
```

### tsconfig.json Sugerido

```json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "lib": ["ES2020"],
    "declaration": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "moduleResolution": "node"
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist", "tests"]
}
```

---

## 🚀 Publicação no NPM

### Passos para Publicar

1. **Criar repositório separado**
```bash
git init horizon-domain-data-display-enricher
cd horizon-domain-data-display-enricher
```

2. **Copiar arquivos necessários**
- Copiar o código de `/src/_modules/horizon-platform-toolkit/packages/horizon-domain-data-display-enricher/`
- Adaptar imports (remover dependências locais)
- Adicionar package.json e tsconfig.json

3. **Instalar dependências**
```bash
pnpm install
```

4. **Rodar testes**
```bash
pnpm test
```

5. **Build**
```bash
pnpm build
```

6. **Publicar**
```bash
npm login
npm publish --access public
```

---

## 📝 Notas de Implementação

### Dependências Externas

Atualmente o código tem algumas dependências que precisam ser resolvidas:

1. **getIcon**: Função para obter ícones
   - Solução: Tornar opcional via options

2. **date-fns**: Formatação de datas
   - Solução: Já está como dependência

3. **horizon-fields-metadata.json**: Metadados centralizados
   - Solução: Remover dependência, tornar configurável

### Ajustes Necessários

Para tornar o pacote totalmente independente:

1. Remover import de `src/core/ui/icons`
2. Remover import de `horizon-fields-metadata.json`
3. Tornar unitListModel configurável
4. Adicionar mais opções de configuração

---

## 📄 Licença

MIT

---

## 🤝 Contribuindo

Contribuições são bem-vindas! Por favor, abra uma issue ou pull request.

---

## 📧 Suporte

Para suporte, abra uma issue no GitHub ou entre em contato com a equipe Horizon.

---

*Desenvolvido com ❤️ pela equipe Horizon Platform*