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:
85
api/services/monitoring.ts
Normal file
85
api/services/monitoring.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* Monitoring Queries Service
|
||||
* @author Descomplicar® | @link descomplicar.pt | @copyright 2026
|
||||
*/
|
||||
import db from '../db.js'
|
||||
import type { RowDataPacket } from 'mysql2'
|
||||
|
||||
interface MonitoringItem {
|
||||
id: number
|
||||
name: string
|
||||
category: string
|
||||
type: string
|
||||
status: string
|
||||
details: any
|
||||
last_check: string
|
||||
created_at: string
|
||||
updated_at: string
|
||||
}
|
||||
|
||||
interface CategorySummary {
|
||||
category: string
|
||||
total: number
|
||||
ok: number
|
||||
warning: number
|
||||
critical: number
|
||||
}
|
||||
|
||||
export async function getMonitoringData() {
|
||||
// Get all items
|
||||
const [items] = await db.query<RowDataPacket[]>(`
|
||||
SELECT * FROM tbl_eal_monitoring
|
||||
ORDER BY category, name
|
||||
`)
|
||||
|
||||
// Get summary by category
|
||||
const [summary] = await db.query<RowDataPacket[]>(`
|
||||
SELECT
|
||||
category,
|
||||
COUNT(*) as total,
|
||||
SUM(CASE WHEN status IN ('ok','up') THEN 1 ELSE 0 END) as ok,
|
||||
SUM(CASE WHEN status = 'warning' THEN 1 ELSE 0 END) as warning,
|
||||
SUM(CASE WHEN status IN ('failed','down') THEN 1 ELSE 0 END) as critical
|
||||
FROM tbl_eal_monitoring
|
||||
GROUP BY category
|
||||
`)
|
||||
|
||||
// Parse details JSON
|
||||
const itemsParsed = items.map(item => ({
|
||||
...item,
|
||||
details: typeof item.details === 'string' ? JSON.parse(item.details) : item.details
|
||||
}))
|
||||
|
||||
// Organize by category
|
||||
const data: Record<string, MonitoringItem[]> = {}
|
||||
for (const item of itemsParsed) {
|
||||
if (!data[item.category]) {
|
||||
data[item.category] = []
|
||||
}
|
||||
data[item.category].push(item)
|
||||
}
|
||||
|
||||
// Calculate overall status
|
||||
let overall: 'ok' | 'warning' | 'critical' = 'ok'
|
||||
let total_critical = 0
|
||||
let total_warning = 0
|
||||
|
||||
for (const s of summary as CategorySummary[]) {
|
||||
total_critical += s.critical
|
||||
total_warning += s.warning
|
||||
}
|
||||
|
||||
if (total_critical > 0) overall = 'critical'
|
||||
else if (total_warning > 0) overall = 'warning'
|
||||
|
||||
return {
|
||||
items: data,
|
||||
summary,
|
||||
overall,
|
||||
stats: {
|
||||
total_critical,
|
||||
total_warning,
|
||||
total_ok: items.length - total_critical - total_warning
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user