feat: add Node.js/Express API with real data from Desk CRM

-  API completa em /api com TypeScript
-  Google Calendar integration (pessoal + profissional)
-  Queries diretas à BD: tasks, leads, projectos, billing, pipeline
-  Endpoints: /api/dashboard, /api/monitor, /api/health
-  Vite proxy configurado (/api → localhost:3001)
-  App.tsx usa /api/dashboard (não mais dados mock)
-  Migração completa do PHP (index.php + monitor.php)
-  CHANGELOG.md criado para tracking
-  Scripts npm: dev (paralelo), dev:api, dev:ui, start

Dependencies:
- express, cors, mysql2, googleapis
- concurrently, tsx (dev)

Breaking: PHP backend será descontinuado
See: CHANGELOG.md, api/README.md

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-04 03:26:24 +00:00
parent 6d7280566e
commit a766f3a765
13 changed files with 935 additions and 5 deletions

100
api/routes/dashboard.ts Normal file
View File

@@ -0,0 +1,100 @@
/**
* Dashboard API Route
* GET /api/dashboard
* @author Descomplicar® | @link descomplicar.pt | @copyright 2026
*/
import { Router } from 'express'
import type { Request, Response } from 'express'
import * as dashboardService from '../services/dashboard.js'
import * as calendarService from '../services/calendar.js'
const router = Router()
router.get('/', async (req: Request, res: Response) => {
try {
// Date info
const now = new Date()
const diasSemana = ['Domingo', 'Segunda-feira', 'Terça-feira', 'Quarta-feira', 'Quinta-feira', 'Sexta-feira', 'Sábado']
const meses = ['', 'Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro']
const data_formatada = `${diasSemana[now.getDay()]}, ${now.getDate()} de ${meses[now.getMonth() + 1]} de ${now.getFullYear()}`
const is_monday = now.getDay() === 1
// Parallel queries for performance
const [
urgente,
alta,
vencidas,
em_testes,
esta_semana,
monday_mood,
tickets,
contactar,
followup,
proposta,
projectos,
timesheet,
billing_360,
pipeline,
eventos_hoje,
eventos_semana
] = await Promise.all([
dashboardService.getUrgenteTasks(),
dashboardService.getAltaTasks(),
dashboardService.getVencidasTasks(),
dashboardService.getEmTestesTasks(),
dashboardService.getEstaSemana(),
dashboardService.getMondayMood(),
dashboardService.getTickets(),
dashboardService.getContactarLeads(),
dashboardService.getFollowupLeads(),
dashboardService.getPropostaLeads(),
dashboardService.getProjectos(),
dashboardService.getTimesheet(),
dashboardService.getBilling360(),
dashboardService.getPipeline(),
calendarService.getTodayEvents(),
calendarService.getWeekEvents()
])
// Calculate totals
const total_tarefas = urgente.length + alta.length
const total_leads = contactar.length + proposta.length + followup.length
// Build response matching React component format
const response = {
data_formatada,
is_monday,
eventos_hoje,
eventos_semana,
monday_mood,
urgente,
alta,
vencidas,
em_testes,
esta_semana,
tickets,
proposta,
contactar,
followup,
projectos,
billing_360,
resumo: {
tarefas: total_tarefas,
tickets: tickets.length,
projectos: projectos.length,
leads: total_leads,
horas: timesheet.horas,
horas_pct: timesheet.horas_pct,
pipeline_valor: pipeline.pipeline_valor
}
}
res.json(response)
} catch (error) {
console.error('Dashboard API error:', error)
res.status(500).json({ error: 'Internal server error' })
}
})
export default router