npm package: @hed-hog/faq
Description: O módulo `@hed-hog/faq` é responsável pela gestão de FAQs (Frequently Asked Questions) multilíngues dentro do sistema HedHog. Ele permite criar, listar, atualizar, consultar e deletar FAQs com suporte a múltiplos idiomas, garantindo que cada pergunta e re
Latest version: 0.0.303

# Módulo @hed-hog/faq

## 1. Visão geral do módulo

O módulo `@hed-hog/faq` é responsável pela gestão de FAQs (Frequently Asked Questions) multilíngues dentro do sistema HedHog. Ele permite criar, listar, atualizar, consultar e deletar FAQs com suporte a múltiplos idiomas, garantindo que cada pergunta e resposta estejam disponíveis em diferentes localidades configuradas.

## 2. Escopo e responsabilidades

- Gerenciar FAQs com suporte a múltiplos idiomas.
- Validar dados de localização para perguntas e respostas.
- Fornecer paginação e busca textual nas FAQs.
- Expor endpoints REST para operações CRUD.
- Controlar acesso via roles específicas para administração.
- Integrar com o serviço de localização para validação e tradução.

## 3. Endpoints

| Método | Path         | Autenticação                     | Descrição                                  |
|--------|--------------|---------------------------------|--------------------------------------------|
| GET    | `/faq`       | Sim (roles `admin`, `admin-faq`) | Lista FAQs paginadas e filtradas por busca. |
| GET    | `/faq/stats` | Sim (roles `admin`, `admin-faq`) | Retorna estatísticas gerais das FAQs.      |
| GET    | `/faq/:id`   | Sim (roles `admin`, `admin-faq`) | Retorna FAQ específica por ID com traduções. |
| POST   | `/faq`       | Sim (roles `admin`, `admin-faq`) | Cria uma nova FAQ com dados multilíngues.  |
| PATCH  | `/faq/:id`   | Sim (roles `admin`, `admin-faq`) | Atualiza FAQ existente parcialmente.        |
| DELETE | `/faq/:id`   | Sim (roles `admin`, `admin-faq`) | Remove FAQ pelo ID.                          |

---

### GET `/faq`

- **Autenticação:** Requer role `admin` ou `admin-faq`.
- **Query Params:**
  - `search` (string, opcional): termo para busca em perguntas e respostas.
  - `take` (number, obrigatório): quantidade de itens por página.
  - `skip` (number, obrigatório): quantidade de itens a pular (offset).
- **Headers:**
  - `Accept-Language`: código do locale para filtrar perguntas/respostas.
- **Resposta:**
  ```json
  {
    "data": [
      {
        "faq_id": 1,
        "locale_id": 2,
        "question": "Pergunta no idioma solicitado",
        "answer": "Resposta no idioma solicitado",
        "available_locales": [
          { "code": "en", "name": "English" },
          { "code": "pt", "name": "Português" }
        ]
      }
    ],
    "total": 100,
    "page": 1,
    "pageSize": 10,
    "prev": null,
    "next": 2,
    "lastPage": 10
  }
  ```
- **Erros comuns:**
  - 400 Bad Request: parâmetros inválidos.
  - 404 Not Found: locale informado não encontrado.

---

### GET `/faq/stats`

- **Autenticação:** Requer role `admin` ou `admin-faq`.
- **Descrição:** Retorna estatísticas gerais, como total de FAQs cadastradas.
- **Resposta:**
  ```json
  {
    "total": 100
  }
  ```

---

### GET `/faq/:id`

- **Autenticação:** Requer role `admin` ou `admin-faq`.
- **Parâmetros:**
  - `id` (number): ID da FAQ.
- **Headers:**
  - `Accept-Language`: código do locale para resposta localizada.
- **Resposta:**
  ```json
  {
    "id": 1,
    "faq_locale": [...],
    "locale": {
      "en": { "question": "Question?", "answer": "Answer." },
      "pt": { "question": "Pergunta?", "answer": "Resposta." }
    }
  }
  ```
- **Erros comuns:**
  - 404 Not Found: FAQ não encontrada.

---

### POST `/faq`

- **Autenticação:** Requer role `admin` ou `admin-faq`.
- **Headers:**
  - `Accept-Language`: código do locale para validação.
- **Body:**
  ```json
  {
    "locale": {
      "en": { "question": "Question?", "answer": "Answer." },
      "pt": { "question": "Pergunta?", "answer": "Resposta." }
    }
  }
  ```
- **Descrição:** Cria uma nova FAQ com traduções.
- **Resposta:** Objeto FAQ criado com dados multilíngues (igual ao GET `/faq/:id`).
- **Erros comuns:**
  - 400 Bad Request: objeto `locale` inválido ou vazio.

---

### PATCH `/faq/:id`

- **Autenticação:** Requer role `admin` ou `admin-faq`.
- **Parâmetros:**
  - `id` (number): ID da FAQ a ser atualizada.
- **Headers:**
  - `Accept-Language`: código do locale para validação.
- **Body:** (parcial)
  ```json
  {
    "locale": {
      "en": { "question": "Updated question?", "answer": "Updated answer." }
    }
  }
  ```
- **Descrição:** Atualiza parcialmente a FAQ, incluindo traduções.
- **Resposta:** Objeto FAQ atualizado (igual ao GET `/faq/:id`).
- **Erros comuns:**
  - 400 Bad Request: dados de localização inválidos.
  - 404 Not Found: FAQ não encontrada.

---

### DELETE `/faq/:id`

- **Autenticação:** Requer role `admin` ou `admin-faq`.
- **Parâmetros:**
  - `id` (number): ID da FAQ a ser removida.
- **Headers:**
  - `Accept-Language`: código do locale para mensagens.
- **Descrição:** Remove FAQ pelo ID.
- **Resposta:** Objeto da FAQ deletada.
- **Erros comuns:**
  - 404 Not Found: FAQ não encontrada.

## 4. Regras de autenticação e autorização

- Todos os endpoints requerem autenticação.
- Acesso restrito a usuários com roles:
  - `admin`
  - `admin-faq` (Administrador de FAQ)
- Roles definidas no arquivo `hedhog/data/role.yaml` com permissões específicas para gerenciamento de FAQs.

## 5. Estruturas de request/response

### FAQDTO (Request Body para criação/atualização)

```ts
{
  locale: {
    [localeCode: string]: {
      question: string;
      answer: string;
    }
  }
}
```

- `locale`: objeto obrigatório que deve conter pelo menos uma chave de idioma com `question` e `answer` como strings não vazias.
- Validação: o objeto `locale` não pode ser vazio, e cada idioma deve conter `question` e `answer` do tipo string.

### Resposta FAQ detalhada

```ts
{
  id: number;
  faq_locale: Array<any>;
  locale: {
    [localeCode: string]: {
      question: string;
      answer: string;
    }
  }
}
```

### Paginação (GET `/faq`)

- Query params: `search` (string opcional), `take` (number obrigatório), `skip` (number obrigatório).
- Resposta inclui:
  - `data`: array de FAQs com traduções no locale solicitado.
  - `total`: total de FAQs encontradas.
  - `page`: página atual.
  - `pageSize`: quantidade de itens por página.
  - `prev`: página anterior ou null.
  - `next`: próxima página ou null.
  - `lastPage`: última página disponível.

## 6. Erros comuns

- **400 Bad Request:** Dados de localização inválidos ou vazios.
- **404 Not Found:** FAQ ou locale não encontrados.
- **401 Unauthorized:** Usuário sem autenticação ou sem roles adequados.
- **500 Internal Server Error:** Erros inesperados no servidor.

## 7. Banco de dados (tabelas YAML)

### Tabela `faq`

- **Finalidade:** Armazenar registros de FAQs.
- **Colunas:**
  - `id` (PK): Identificador único da FAQ.
  - `created_at`: Timestamp de criação (automático).
  - `updated_at`: Timestamp de atualização (automático).
- **Defaults:** `created_at` e `updated_at` gerenciados automaticamente.
- **Nulabilidade:** `id`, `created_at` e `updated_at` não nulos.
- **Integridade:** Chave primária em `id`.
- **Índices:** Índice primário em `id`.

### Tabela `faq_locale`

- **Finalidade:** Armazenar traduções de perguntas e respostas por locale.
- **Colunas:**
  - `faq_id` (FK): Referência para `faq.id`.
  - `locale_id` (FK): Referência para `locale.id`.
  - `question` (locale_varchar, 255): Pergunta traduzida.
  - `answer` (locale_text): Resposta traduzida.
  - `created_at`: Timestamp de criação (automático).
  - `updated_at`: Timestamp de atualização (automático).
- **Defaults:** Timestamps automáticos.
- **Nulabilidade:** `question` e `answer` não nulos para registros válidos.
- **Integridade:** Chave única composta por `[faq_id, locale_id]`.
- **Índices:** Índice único em `[faq_id, locale_id]` para garantir unicidade da tradução por idioma.

## 8. Regras de negócio relevantes

- Cada FAQ deve possuir pelo menos uma tradução válida com `question` e `answer`.
- Traduções são validadas para garantir que sejam objetos com strings não vazias.
- Busca textual é feita no idioma solicitado, com filtro case-insensitive.
- Ao criar ou atualizar, o sistema cria ou atualiza as traduções correspondentes.
- Exclusão remove o FAQ e todas as suas traduções associadas.
- Estatísticas retornam o total de FAQs cadastradas.
- Roles específicas controlam o acesso para garantir segurança.

## 9. Guia rápido de uso (exemplos)

### Listar FAQs com paginação e busca

```http
GET /faq?search=termo&take=10&skip=0
Accept-Language: pt
Authorization: Bearer <token>
```

### Criar nova FAQ

```http
POST /faq
Accept-Language: pt
Authorization: Bearer <token>
Content-Type: application/json

{
  "locale": {
    "en": {
      "question": "What is HedHog?",
      "answer": "HedHog is a modular monorepo system."
    },
    "pt": {
      "question": "O que é HedHog?",
      "answer": "HedHog é um sistema modular monorepo."
    }
  }
}
```

### Atualizar FAQ parcialmente

```http
PATCH /faq/1
Accept-Language: pt
Authorization: Bearer <token>
Content-Type: application/json

{
  "locale": {
    "pt": {
      "question": "Pergunta atualizada?",
      "answer": "Resposta atualizada."
    }
  }
}
```

### Consultar FAQ por ID

```http
GET /faq/1
Accept-Language: en
Authorization: Bearer <token>
```

### Deletar FAQ

```http
DELETE /faq/1
Accept-Language: en
Authorization: Bearer <token>
```

---

Este módulo é fundamental para a gestão multilíngue de FAQs no sistema HedHog, garantindo flexibilidade e controle de acesso rigoroso para administradores.