This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

29 1 0

Clone this repository

https://tangled.org/arthr.me/ub https://tangled.org/did:plc:yv6uthcnhuwzfjz2rratednu
git@tangled.org:arthr.me/ub git@tangled.org:did:plc:yv6uthcnhuwzfjz2rratednu

For self-hosted knots, clone URLs may differ based on your setup.



README.md

ub / flowpay#

Sistema full-stack para distribuição automática e monitoramento em tempo real de atendimentos da central de relacionamento da FlowPay.

Demo:


O Problema#

A FlowPay organiza sua central de atendimento em três times:

Time Assunto
Time Cartões Solicitações contendo "cartão"
Time Empréstimos Solicitações contendo "empréstimo"
Time Outros Assuntos Todos os demais assuntos

Regras de distribuição:

  • Cada atendente atende no máximo 3 clientes simultaneamente
  • Se todos os atendentes de um time estiverem ocupados, o atendimento entra na fila de espera
  • Quando um atendente finaliza um atendimento, o próximo da fila é atribuído automaticamente
  • Ao cadastrar ou reativar um atendente, os clientes em espera do seu time são atribuídos imediatamente

Arquitetura#

flowpay/
├── apps/
│   ├── api/          # REST API — Hono + Cloudflare Workers + D1
│   └── web/          # Dashboard — React + Vite + Cloudflare Pages
└── packages/
    └── types/        # Interfaces TypeScript compartilhadas

Backend: Worker Hono no edge do Cloudflare. Toda a lógica de distribuição e enfileiramento roda aqui, com persistência em D1 (SQLite).

Frontend: SPA React servida pelo Cloudflare Pages. Consulta a API a cada 5 segundos para manter o dashboard atualizado em tempo real.


Tech Stack#

Camada Tecnologia
API Hono v4 + Cloudflare Workers
Banco de dados Cloudflare D1 (SQLite)
Validação Zod + @hono/zod-validator
Frontend React 18 + Vite 5
Roteamento React Router v6
Estilo Tailwind CSS v3
Monorepo pnpm workspaces
Testes Vitest
Deploy Wrangler v3

Desenvolvimento Local#

Pré-requisitos#

  • Node.js 18+
  • pnpm 8+

Instalação#

git clone <repo>
cd flowpay
pnpm install

Rodar a API localmente#

# Criar o banco D1 local e aplicar o schema
cd apps/api
wrangler d1 execute flowpay-db --local --file=schema.sql
wrangler d1 execute flowpay-db --local --file=seed.sql

# Iniciar o Worker em modo desenvolvimento
pnpm dev:api
# API disponível em http://localhost:8787

Rodar o frontend localmente#

# Em outro terminal, na raiz do projeto
pnpm dev:web
# Dashboard disponível em http://localhost:5173

O arquivo apps/web/.env.local aponta para http://localhost:8787 por padrão.

Testes#

pnpm test
# 13 testes passando (classificação de assuntos + lógica de distribuição)

API Reference#

Base URL (produção): https://flowpay-api.arthrfrts.workers.dev

Times#

GET /teams#

Retorna os 3 times cadastrados.

[
  { "id": 1, "name": "Time Cartões", "slug": "cartoes" },
  { "id": 2, "name": "Time Empréstimos", "slug": "emprestimos" },
  { "id": 3, "name": "Time Outros Assuntos", "slug": "outros" }
]

Atendentes#

GET /agents#

Lista todos os atendentes com a contagem de atendimentos ativos.

[
  {
    "id": 1,
    "name": "Ana",
    "team_id": 1,
    "active": 1,
    "created_at": "2026-05-19 10:00:00",
    "active_count": 2
  }
]

POST /agents#

Cria um novo atendente. Automaticamente atribui atendimentos em espera do time.

Body:

{ "name": "João", "team_id": 1 }

Resposta: 201 com o atendente criado.

Erros:

  • 400team_id não existe

PUT /agents/:id#

Atualiza dados de um atendente. Ao reativar (active: 1), atribui automaticamente atendimentos em espera do time.

Body (todos os campos opcionais):

{ "name": "João Silva", "team_id": 2, "active": 0 }

Erros:

  • 400 — nenhum campo fornecido
  • 404 — atendente não encontrado

DELETE /agents/:id#

Desativa um atendente (soft delete — active = 0). Atendimentos em curso não são alterados.

Erros:

  • 404 — atendente não encontrado

Atendimentos#

GET /attendances#

Lista atendimentos com filtros opcionais.

Query params:

Param Valores
status waiting, in_progress, completed
team_id ID do time
agent_id ID do atendente
[
  {
    "id": 1,
    "customer_name": "Maria",
    "subject": "Problemas com cartão",
    "team_id": 1,
    "agent_id": 2,
    "status": "in_progress",
    "queue_position": null,
    "created_at": "2026-05-19 10:05:00",
    "started_at": "2026-05-19 10:05:01",
    "completed_at": null
  }
]

POST /attendances#

Cria um novo atendimento e aciona a distribuição automática.

Body:

{ "customer_name": "Carlos", "subject": "Contratação de empréstimo" }

Lógica de classificação:

  • Assunto contém "cartão" ou "cartao" (case-insensitive) → Time Cartões
  • Assunto contém "empréstimo" ou "emprestimo" (case-insensitive) → Time Empréstimos
  • Demais → Time Outros Assuntos

Resposta: 201

{
  "attendance": {
    /* objeto Attendance */
  },
  "assigned": true,
  "team": { "id": 1, "name": "Time Cartões", "slug": "cartoes" }
}

O campo assigned: true indica atribuição imediata a um atendente; false indica que entrou na fila de espera.

POST /attendances/:id/complete#

Finaliza um atendimento em andamento. Automaticamente promove o próximo da fila para o atendente que ficou livre.

Erros:

  • 404 — atendimento não encontrado
  • 400 — atendimento não está com status in_progress

Dashboard#

GET /dashboard#

Retorna o estado agregado para o dashboard em tempo real.

{
  "teams": [
    {
      "id": 1,
      "name": "Time Cartões",
      "slug": "cartoes",
      "queue_count": 2,
      "in_progress_count": 6,
      "agents": [
        {
          "id": 1,
          "name": "Ana",
          "team_id": 1,
          "active": 1,
          "active_count": 3,
          "capacity": 3
        }
      ]
    }
  ],
  "totals": {
    "waiting": 4,
    "in_progress": 9,
    "completed_today": 27
  }
}

Deploy#

API (Cloudflare Workers)#

cd apps/api

# Autenticar (primeira vez)
wrangler login

# Criar banco D1
wrangler d1 create flowpay-db

# Aplicar schema e seed
wrangler d1 execute flowpay-db --remote --file=schema.sql
wrangler d1 execute flowpay-db --remote --file=seed.sql

# Deploy
wrangler deploy

Frontend (Cloudflare Pages)#

cd apps/web

# Build com a URL da API em produção
VITE_API_URL=https://flowpay-api.arthrfrts.workers.dev pnpm build

# Deploy
wrangler pages deploy dist --project-name flowpay-web

Estrutura do Banco de Dados#

-- Times (pré-cadastrados via seed)
teams: id, name, slug

-- Atendentes
agents: id, name, team_id, active, created_at

-- Atendimentos
attendances:
  id, customer_name, subject,
  team_id, agent_id,
  status (waiting | in_progress | completed),
  queue_position,
  created_at, started_at, completed_at