feat: add financial panel, compact services list, add Syncthing

- New /financial page with sales/expenses cards, monthly bar chart and
  expense distribution pie chart (Recharts)
- New API endpoint GET /api/financial with queries on tblinvoices and
  tblexpenses
- Compact services grid (2-col dots layout) in Monitor page
- Add Syncthing to critical services monitoring
- Add Financeiro nav link to Dashboard, Monitor and Financial headers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-07 22:50:12 +00:00
co-authored by Claude Opus 4.6
parent 86ad4a64be
commit 12e1552d02
7 changed files with 478 additions and 5 deletions
+22 -5
View File
@@ -16,6 +16,7 @@ import {
ArrowLeft,
Activity,
Clock,
TrendingUp,
} from 'lucide-react'
// Types
@@ -264,6 +265,13 @@ export default function Monitor() {
>
<RefreshCw className={`w-5 h-5 text-zinc-400 ${refreshing ? 'animate-spin' : ''}`} />
</motion.button>
<Link
to="/financial"
className="hidden md:flex items-center gap-2 px-4 py-2 rounded-xl bg-white/5 hover:bg-white/10 text-zinc-400 hover:text-white transition-all text-sm"
>
<TrendingUp className="w-4 h-4" />
Financeiro
</Link>
<Link
to="/"
className="flex items-center gap-2 px-4 py-2 rounded-xl bg-white/5 hover:bg-white/10 text-zinc-400 hover:text-white transition-all text-sm"
@@ -301,12 +309,20 @@ export default function Monitor() {
</CategoryCard>
)}
{/* Services */}
{/* Services - Compact Grid */}
{groupedItems.service && (
<CategoryCard title="Serviços Críticos" icon={Wifi} count={groupedItems.service.length}>
{groupedItems.service.map((item) => (
<MonitorItemRow key={item.id} item={item} />
))}
<div className="grid grid-cols-2 gap-x-3 gap-y-1.5">
{groupedItems.service.map((item) => (
<div key={item.id} className="flex items-center gap-2 px-2 py-1.5 rounded-lg hover:bg-white/[0.04] transition-colors">
<div className={`w-2 h-2 rounded-full flex-shrink-0 ${
item.status === 'ok' || item.status === 'up' ? 'bg-emerald-400' :
item.status === 'warning' ? 'bg-amber-400' : 'bg-red-400'
}`} />
<span className="text-sm text-zinc-300 truncate">{item.name}</span>
</div>
))}
</div>
</CategoryCard>
)}
@@ -438,6 +454,7 @@ function getMockData(): MonitorData {
{ id: 521, name: 'Google Docs', category: 'service', status: 'up', details: {}, last_check: '' },
{ id: 549, name: 'MCP Hub', category: 'service', status: 'up', details: {}, last_check: '' },
{ id: 515, name: 'WhatSMS', category: 'service', status: 'up', details: {}, last_check: '' },
{ id: 41594, name: 'Syncthing', category: 'service', status: 'up', details: {}, last_check: '' },
],
site: [
{ id: 15960, name: 'Descomplicar', category: 'site', status: 'up', details: { domain: 'descomplicar.pt', response_time: 0.093 }, last_check: '' },
@@ -470,7 +487,7 @@ function getMockData(): MonitorData {
overall: 'warning',
summary: [
{ category: 'server', total: 6, ok: 6, warning: 0, critical: 0 },
{ category: 'service', total: 10, ok: 10, warning: 0, critical: 0 },
{ category: 'service', total: 11, ok: 11, warning: 0, critical: 0 },
{ category: 'site', total: 7, ok: 6, warning: 0, critical: 1 },
{ category: 'container', total: 1, ok: 0, warning: 1, critical: 0 },
{ category: 'backup', total: 4, ok: 2, warning: 1, critical: 1 },