136 lines
3.4 KiB
TypeScript
136 lines
3.4 KiB
TypeScript
'use client'
|
|
|
|
import { useEffect, useState } from 'react'
|
|
import { useRouter } from 'next/navigation'
|
|
import Sidebar from '@/components/layout/Sidebar'
|
|
import Header from '@/components/layout/Header'
|
|
import { SelectedClientProvider, useSelectedClient } from '@/components/providers/SelectedClientProvider'
|
|
import { trpc } from '@/lib/trpc-client'
|
|
|
|
export default function DashboardLayout({
|
|
children,
|
|
}: {
|
|
children: React.ReactNode
|
|
}) {
|
|
const router = useRouter()
|
|
|
|
const meQuery = trpc.auth.me.useQuery(undefined, {
|
|
retry: false,
|
|
staleTime: 60 * 1000,
|
|
})
|
|
const logoutMutation = trpc.auth.logout.useMutation({
|
|
onSuccess: () => {
|
|
window.location.href = '/login'
|
|
},
|
|
})
|
|
|
|
useEffect(() => {
|
|
if (meQuery.isError) {
|
|
router.push('/login')
|
|
}
|
|
}, [meQuery.isError, router])
|
|
|
|
const handleLogout = () => {
|
|
logoutMutation.mutate()
|
|
}
|
|
|
|
if (meQuery.isLoading || meQuery.isError) {
|
|
return (
|
|
<div className="flex h-screen bg-dark-500 items-center justify-center">
|
|
<div className="text-gray-400">Cargando...</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const user = meQuery.data
|
|
if (!user) return null
|
|
|
|
return (
|
|
<DashboardContent user={user} onLogout={handleLogout}>
|
|
{children}
|
|
</DashboardContent>
|
|
)
|
|
}
|
|
|
|
function DashboardContent({
|
|
user,
|
|
onLogout,
|
|
children,
|
|
}: {
|
|
user: { nombre: string; email: string; rol: string }
|
|
onLogout: () => void
|
|
children: React.ReactNode
|
|
}) {
|
|
return (
|
|
<SelectedClientProvider>
|
|
<DashboardContentInner user={user} onLogout={onLogout}>
|
|
{children}
|
|
</DashboardContentInner>
|
|
</SelectedClientProvider>
|
|
)
|
|
}
|
|
|
|
function DashboardContentInner({
|
|
user,
|
|
onLogout,
|
|
children,
|
|
}: {
|
|
user: { nombre: string; email: string; rol: string }
|
|
onLogout: () => void
|
|
children: React.ReactNode
|
|
}) {
|
|
const { selectedClientId } = useSelectedClient()
|
|
const clienteId = selectedClientId ?? undefined
|
|
|
|
const activeAlertsCountQuery = trpc.alertas.conteoActivas.useQuery(
|
|
{ clienteId },
|
|
{ refetchOnWindowFocus: true, staleTime: 30 * 1000 }
|
|
)
|
|
const activeAlertsCount = activeAlertsCountQuery.data?.total ?? 0
|
|
|
|
const devicesCountQuery = trpc.equipos.list.useQuery(
|
|
{ clienteId, page: 1, limit: 1 },
|
|
{ refetchOnWindowFocus: true, staleTime: 30 * 1000 }
|
|
)
|
|
const devicesCount = devicesCountQuery.data?.pagination?.total ?? 0
|
|
|
|
const clientsQuery = trpc.clientes.list.useQuery(
|
|
{ limit: 100 },
|
|
{ staleTime: 60 * 1000 }
|
|
)
|
|
const clients = (clientsQuery.data?.clientes ?? []).map((c) => ({
|
|
id: c.id,
|
|
nombre: c.nombre,
|
|
codigo: c.codigo,
|
|
}))
|
|
|
|
const [sidebarOpen, setSidebarOpen] = useState(false)
|
|
|
|
return (
|
|
<div className="flex h-screen bg-dark-500">
|
|
<Sidebar
|
|
activeAlertsCount={activeAlertsCount}
|
|
devicesCount={devicesCount}
|
|
open={sidebarOpen}
|
|
onClose={() => setSidebarOpen(false)}
|
|
/>
|
|
<div className="ml-0 md:ml-[260px] flex min-w-0 flex-1 flex-col overflow-hidden transition-[margin] duration-200">
|
|
<Header
|
|
user={{
|
|
nombre: user.nombre,
|
|
email: user.email,
|
|
rol: user.rol,
|
|
}}
|
|
onLogout={onLogout}
|
|
clients={clients}
|
|
showAllClientsOption={user.rol === 'SUPER_ADMIN'}
|
|
onOpenSidebar={() => setSidebarOpen(true)}
|
|
/>
|
|
<main className="flex-1 overflow-y-auto p-4 sm:p-6">
|
|
{children}
|
|
</main>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|