Lovable

Integração via API REST

Migre de CSV estático para dados em tempo real consumindo a API REST do eKyte, com proxy seguro via Serverless Function.

Quando fazer: depois que o dashboard estiver estável e você quiser dados em tempo real, sem exportar CSV manualmente. Requer deploy em plataforma que suporte Serverless Functions (Vercel, Netlify, Railway etc.).

Princípios de segurança

A chave da API nunca é exposta no browser. A arquitetura segue o padrão de proxy seguro via Serverless Function:

Browser (frontend)  →  /api/tasks (proxy interno)  →  api.ekyte.com
  • A chave fica armazenada como variável de ambiente no servidor (EKYTE_API_KEY).
  • O frontend chama apenas o proxy interno (/api/tasks).
  • O proxy (Serverless Function) faz a chamada real à API do eKyte.

Onde obter a chave da API

No painel do eKyte, vá em:

Minha Empresa → Data Driven → Token de acesso
Tela do eKyte mostrando Data Driven > Token de acesso

O token exibido deve ser usado como valor da variável de ambiente:

EKYTE_API_KEY=seu-token-aqui

A chave deve ser tratada como credencial sensível e nunca pode ser exposta no frontend ou commitada no repositório.


Passo 1 — Subir o projeto Lovable para o GitHub

O Lovable se integra diretamente com o GitHub — não é preciso usar terminal nem comandos git.

  1. Crie uma conta no GitHub caso ainda não tenha.
  2. No Lovable, clique no menu do projeto e selecione GitHub.
Menu do Lovable mostrando opção GitHub
  1. Com a conta vinculada, conecte-a ao projeto. O Lovable cria automaticamente um repositório no seu perfil do GitHub e sincroniza o código.
Tela de conexão do Lovable ao GitHub

A partir daqui, qualquer alteração feita no Lovable é refletida automaticamente no repositório.


Passo 2 — Clonar o projeto na plataforma de hospedagem

Importe o repositório do GitHub na plataforma escolhida:

PlataformaComo clonar
Vercel"Add New… → Project" → importar do GitHub
Netlify"Add new site → Import an existing project"
Railway"New Project → Deploy from GitHub repo"
Heroku"New → Create new app" → conectar ao GitHub na aba Deploy
AWS Amplify"Host a web app → Connect a Git provider"
Dockergit clone do repositório no host
Tela de importação de projeto na Vercel Projeto importado aguardando primeiro deploy

Aguarde o primeiro deploy concluir (mesmo que falhe por falta da chave — isso é esperado neste momento).


Passo 3 — Configurar a variável de ambiente

Com o projeto já clonado na plataforma, abra-o no painel e adicione:

  • Nome: EKYTE_API_KEY
  • Valor: sua chave
  • Ambiente: Production (e Preview/Staging, se desejar)

Atenção: nunca use prefixo VITE_ para esta variável — isso a exporia no bundle do browser.

PlataformaLocalização
VercelSettings → Environment Variables
NetlifySite settings → Environment variables
RailwayVariables → New Variable
HerokuSettings → Config Vars
AWS AmplifyEnvironment variables
Dockerarquivo .env ou docker-compose.yml
Tela de Environment Variables na Vercel Variável EKYTE_API_KEY configurada na plataforma

Passo 4 — Fazer redeploy

Variáveis de ambiente só passam a valer no próximo build/deploy — adicioná-las não atualiza o deploy atual.

PlataformaComo forçar redeploy
VercelDeployments → menu ⋯ do último deploy → "Redeploy"
NetlifyDeploys → "Trigger deploy → Deploy site"
RailwayDeployments → "Redeploy"
HerokuDeploy → "Deploy Branch"
AWS AmplifyApp → menu do branch → "Redeploy this version"
Dockerdocker compose up -d --build
Lista de deployments na Vercel com menu de opções Opção Redeploy destacada no menu

Passo 5 — Verificar o deploy

Após o redeploy, confirme que:

  1. A aplicação está acessível.
  2. A variável EKYTE_API_KEY foi configurada corretamente.
  3. O endpoint /api/tasks responde sem expor a chave.
  4. Acesse a URL da aplicação indicada no painel da plataforma:
Painel da Vercel mostrando a URL do deploy em produção
  1. Acesse no navegador: <url>/api/tasks
Resposta do endpoint /api/tasks no navegador
  1. Se tudo estiver correto, cole o prompt de API (§ abaixo) no Lovable.

Especificação da API eKyte

Endpoints

AmbienteURL base
Produçãohttps://api.ekyte.com/v1.1/tasks

Parâmetros obrigatórios

ParâmetroDescriçãoFormatoExemplo
apiKeyChave de autenticaçãoString(gerenciado pelo proxy)
createdFromData inicialYYYY-MM-DD2022-01-15
statusFiltro de status0, 1 ou omitir0 = ativas, 1 = concluídas
pageNúmero da páginaInteger1 (começa em 1)

Exemplo de chamada

https://api.ekyte.com/v1.1/tasks?apiKey={KEY}&createdFrom=2022-01-15&status=0&page=1

Serverless Function (proxy seguro)

Arquivo padrão: api/tasks.ts (criado na raiz do projeto)

PlataformaCaminho
Vercel / Netlifyapi/tasks.ts
Next.jspages/api/tasks.ts ou app/api/tasks/route.ts
Express / Nodeserver/routes/tasks.js

Responsabilidades da função:

  1. Receber requisições do frontend (?page=X).
  2. Ler EKYTE_API_KEY de process.env.
  3. Validar que a chave existe.
  4. Fazer a requisição à API do eKyte.
  5. Retornar os dados ao frontend.
  6. Configurar CORS adequadamente.

Prompt de migração para API REST

# Prompt: Dashboard eKyte via API REST

## Contexto
Substituir leitura do `tarefas.csv` pelo consumo da API REST do eKyte.
Projeto hospedado na Vercel.

- Frontend/proxy: <url>.vercel.app  ##INSERIR AQUI URL
- Serverless Function: <url>.vercel.app/api/tasks  ##INSERIR AQUI URL

---

## Segurança (obrigatório)

1. Criar `/api/tasks.ts` como Vercel Serverless Function — a chave **nunca** sai do servidor
2. Chave via `process.env.EKYTE_API_KEY` (Settings → Environment Variables) — sem hardcode, sem fallback, sem prefixo `VITE_`
3. `.env` no `.gitignore`
4. Frontend chama apenas `/api/tasks?page=X`
5. Configurar CORS na função
6. Se a chave estiver ausente → `HTTP 500` com `{ "error": "EKYTE_API_KEY não configurada" }` → frontend exibe mensagem clara

---

## API eKyte

GET https://api.ekyte.com/v1.1/tasks?apiKey={KEY}&createdFrom=2022-01-15&status=0&page={N}

**Paginação:** buscar todas as páginas automaticamente; detectar fim por array vazio, `hasMore=false` ou total atingido; máximo 3 requests paralelos.

**Retry:** backoff exponencial em 429/5xx — esperas 1s, 2s, 4s (máx 3 tentativas); exibir "Aguardando..." durante backoff.

---

## UX

- Progresso: `"Carregando página X de Y..."`
- Botão "Atualizar dados"
- Offline: mensagem + botão "Tentar novamente"

---

## Pipeline de dados (ordem obrigatória)

[API eKyte] → [Serverless /api/tasks] → [Frontend]
  → [Camada 1: Envelope Resolver]
  → [Camada 2: Task Canonical Mapper]
  → [Camada 3: Validação + Telemetria]
  → [Camada 4: Agregações/KPIs]
  → [Gráficos e UI]

> **Regra absoluta:** nenhum gráfico, KPI ou componente acessa o payload bruto. Tudo usa exclusivamente o `TaskCanonical`.

---

## Schema real da API

| Grupo | Campos |
|---|---|
| Identificação | `id`, `title`, `description` |
| Status | `situation` (campo primário) |
| Prioridade | `priority`, `priorityGroup` |
| Datas | `creationDate`, `originalDueDate`, `currentDueDate`, `resolvedDate` |
| Esforço | `estimatedTime`, `actualTime` (minutos) |
| Responsáveis | `executor`, `createdBy`, `coExecutor` (string ou `{name, email}`) |
| Fluxo | `phase`, `phases`, `phaseStartDate`, `phaseDueDate` |
| Organização | `workspace`, `project`, `squad`, `channel`, `media` |
| Financeiro | `manualBudget`, `totalEstimatedHourlyRate`, `totalAccomplishedHourlyRate` |

---

## TaskCanonical (TypeScript)

interface TaskCanonical {
  id: string
  title: string
  description: string
  status: 'Ativa' | 'Concluída' | 'Cancelada' | 'unknown'
  prioridade: 'Urgente' | 'Alta' | 'Média' | 'Baixa' | 'Não definida'
  dataCriacao: Date | null
  dataPrazoOriginal: Date | null
  dataPrazoAtual: Date | null
  dataConclusao: Date | null
  esforcoEstimadoMin: number
  esforcoRealMin: number
  responsaveis: string[]
  etapaAtual: string
  workspace: string
  project: string
  squad: string
  orcamento: number
  taxaEstimada: number
  taxaRealizada: number
  _camposAusentes: string[]
  _fallbacksAplicados: string[]
}

---

## Camada 1 — Envelope Resolver

Detectar o array real nesta ordem:

1. `payload` (se array)
2. `payload.data`
3. `payload.data.items`
4. `payload.data.tasks`
5. `payload.data.results`
6. `payload.items`
7. `payload.tasks`
8. `payload.results`
9. `payload.response?.data`

Se nenhum for array → lançar erro estruturado logando o payload bruto.

---

## Camada 2 — Task Canonical Mapper

**`status`** (fonte: `situation`):

| Valores raw | Canônico |
|---|---|
| done, concluido, finalizado, resolved, completed | `'Concluída'` |
| cancelled, cancelado, canceled | `'Cancelada'` |
| active, ativo, open, aberto, in_progress | `'Ativa'` |
| qualquer outro | `'Ativa'` |
| ausente/null | `'unknown'` + registrar |

**`prioridade`** (fonte: `priority`, fallback `priorityGroup`):

| Valor | Canônico |
|---|---|
| 1 / urgent / urgente | `'Urgente'` |
| 2 / high / alta | `'Alta'` |
| 3 / medium / média / normal | `'Média'` |
| 4 / low / baixa | `'Baixa'` |
| ausente | `'Não definida'` + registrar |

---

## Camada 3 — Validação + Telemetria

- `status` 100% `'unknown'` → modo diagnóstico (não renderizar gráficos)
- `esforço` 100% zero → aviso "Dados de esforço indisponíveis"
- `responsaveis` 100% vazios → aviso "Responsáveis não identificados"
- Modo diagnóstico exibe sumário na UI em vez de gráficos zerados

---

## Camada 4 — KPIs (somente `TaskCanonical[]`)

| KPI | Lógica |
| --- | --- |
| Taxa de conclusão | `Concluídas / total * 100` |
| Throughput | Concluídas com `dataConclusao !== null`, agrupadas por semana/mês |
| Esforço total/médio | `esforcoRealMin` (realizado), `esforcoEstimadoMin` (planejado); exibir em horas (÷60) |
| Atraso | `status !== 'Concluída' && dataPrazoAtual < now` |
| Distribuição por etapa | Agrupar por `etapaAtual` |
| Heatmap executor × etapa | Cruzar `responsaveis[0]` com `etapaAtual` |
| Financeiro | Somar `orcamento`, `taxaEstimada`, `taxaRealizada`; usar `?? 0` em todos |
Esta página foi útil?