diff --git a/src/app/(dashboard)/page.tsx b/src/app/(dashboard)/page.tsx
index 1887796..12e6310 100644
--- a/src/app/(dashboard)/page.tsx
+++ b/src/app/(dashboard)/page.tsx
@@ -1,11 +1,37 @@
'use client'
-import { useState, useEffect } from 'react'
+import { useState, useMemo } from 'react'
import { RefreshCw, Grid, List, Filter } from 'lucide-react'
import KPICards from '@/components/dashboard/KPICards'
import DeviceGrid from '@/components/dashboard/DeviceGrid'
import AlertsFeed from '@/components/dashboard/AlertsFeed'
+import { useSelectedClient } from '@/components/providers/SelectedClientProvider'
import { cn } from '@/lib/utils'
+import { trpc } from '@/lib/trpc-client'
+
+type DeviceForGrid = {
+ id: string
+ nombre: string
+ tipo: string
+ estado: string
+ ip?: string | null
+ sistemaOperativo?: string | null
+ lastSeen?: Date | null
+ cpuUsage?: number | null
+ ramUsage?: number | null
+ cliente?: { nombre: string }
+}
+
+type DashboardAlert = {
+ id: string
+ severidad: 'INFO' | 'WARNING' | 'CRITICAL'
+ estado: 'ACTIVA' | 'RECONOCIDA' | 'RESUELTA'
+ titulo: string
+ mensaje: string
+ createdAt: Date
+ dispositivo: { nombre: string }
+ cliente: { nombre: string }
+}
// Mock data - en produccion vendria de la API
const mockStats = {
@@ -142,18 +168,100 @@ const mockAlerts = [
},
]
+const DEVICES_LIMIT = 12
+
export default function DashboardPage() {
const [viewMode, setViewMode] = useState<'grid' | 'list'>('grid')
- const [isRefreshing, setIsRefreshing] = useState(false)
- const [stats, setStats] = useState(mockStats)
- const [devices, setDevices] = useState(mockDevices)
- const [alerts, setAlerts] = useState(mockAlerts)
+ const utils = trpc.useUtils()
+ const { selectedClientId } = useSelectedClient()
+ const clienteId = selectedClientId ?? undefined
+
+ const statsQuery = trpc.clientes.dashboardStats.useQuery(
+ { clienteId },
+ { refetchOnWindowFocus: false }
+ )
+ const stats = statsQuery.data ?? mockStats
+
+ const alertsQuery = trpc.alertas.list.useQuery(
+ { page: 1, limit: 25, clienteId },
+ { refetchOnWindowFocus: false }
+ )
+ const alerts: DashboardAlert[] = useMemo(() => {
+ const list = alertsQuery.data?.alertas ?? []
+ return list.map((a) => ({
+ id: a.id,
+ severidad: a.severidad,
+ estado: a.estado,
+ titulo: a.titulo,
+ mensaje: a.mensaje,
+ createdAt: a.createdAt instanceof Date ? a.createdAt : new Date(a.createdAt),
+ dispositivo: a.dispositivo ? { nombre: a.dispositivo.nombre } : { nombre: '—' },
+ cliente: { nombre: a.cliente.nombre },
+ }))
+ }, [alertsQuery.data])
+
+ const acknowledgeMutation = trpc.alertas.reconocer.useMutation({
+ onSuccess: () => {
+ utils.alertas.list.invalidate()
+ utils.clientes.dashboardStats.invalidate()
+ },
+ })
+ const resolveMutation = trpc.alertas.resolver.useMutation({
+ onSuccess: () => {
+ utils.alertas.list.invalidate()
+ utils.clientes.dashboardStats.invalidate()
+ },
+ })
+
+ const equiposQuery = trpc.equipos.list.useQuery(
+ { page: 1, limit: DEVICES_LIMIT, clienteId },
+ { refetchOnWindowFocus: false }
+ )
+ const redQuery = trpc.red.list.useQuery(
+ { page: 1, limit: DEVICES_LIMIT, clienteId },
+ { refetchOnWindowFocus: false }
+ )
+ const celularesQuery = trpc.celulares.list.useQuery(
+ { page: 1, limit: DEVICES_LIMIT, clienteId },
+ { refetchOnWindowFocus: false }
+ )
+
+ const devices: DeviceForGrid[] = useMemo(() => {
+ const eq = equiposQuery.data?.dispositivos ?? []
+ const rd = redQuery.data?.dispositivos ?? []
+ const cel = celularesQuery.data?.dispositivos ?? []
+ const all = [...eq, ...rd, ...cel]
+ return all.map((d) => ({
+ id: d.id,
+ nombre: d.nombre,
+ tipo: d.tipo,
+ estado: d.estado,
+ ip: d.ip ?? null,
+ sistemaOperativo: d.sistemaOperativo ?? null,
+ lastSeen: d.lastSeen ?? null,
+ cpuUsage: d.cpuUsage ?? null,
+ ramUsage: d.ramUsage ?? null,
+ cliente: d.cliente ? { nombre: d.cliente.nombre } : undefined,
+ }))
+ }, [equiposQuery.data, redQuery.data, celularesQuery.data])
+
+ const devicesLoading =
+ equiposQuery.isLoading || redQuery.isLoading || celularesQuery.isLoading
+ const isRefreshing =
+ statsQuery.isFetching ||
+ alertsQuery.isFetching ||
+ equiposQuery.isFetching ||
+ redQuery.isFetching ||
+ celularesQuery.isFetching
const handleRefresh = async () => {
- setIsRefreshing(true)
- // TODO: Recargar datos de la API
- await new Promise((resolve) => setTimeout(resolve, 1000))
- setIsRefreshing(false)
+ await Promise.all([
+ statsQuery.refetch(),
+ alertsQuery.refetch(),
+ equiposQuery.refetch(),
+ redQuery.refetch(),
+ celularesQuery.refetch(),
+ ])
}
const handleDeviceAction = (deviceId: string, action: string) => {
@@ -162,17 +270,11 @@ export default function DashboardPage() {
}
const handleAcknowledgeAlert = (alertId: string) => {
- setAlerts((prev) =>
- prev.map((a) => (a.id === alertId ? { ...a, estado: 'RECONOCIDA' as const } : a))
- )
- // TODO: Llamar API
+ acknowledgeMutation.mutate({ id: alertId })
}
const handleResolveAlert = (alertId: string) => {
- setAlerts((prev) =>
- prev.map((a) => (a.id === alertId ? { ...a, estado: 'RESUELTA' as const } : a))
- )
- // TODO: Llamar API
+ resolveMutation.mutate({ id: alertId })
}
return (
@@ -232,20 +334,37 @@ export default function DashboardPage() {
-