diff --git a/src/app/api/trpc/[trpc]/route.ts b/src/app/api/trpc/[trpc]/route.ts new file mode 100644 index 0000000..09a829e --- /dev/null +++ b/src/app/api/trpc/[trpc]/route.ts @@ -0,0 +1,13 @@ +import { fetchRequestHandler } from '@trpc/server/adapters/fetch' +import { appRouter } from '@/server/trpc/routers' +import { createContext } from '@/server/trpc/trpc' + +const handler = (request: Request) => + fetchRequestHandler({ + endpoint: '/api/trpc', + req: request, + router: appRouter, + createContext: () => createContext(), + }) + +export { handler as GET, handler as POST } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index af7b17f..c4d1888 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,6 +1,7 @@ import type { Metadata } from 'next' import { Inter } from 'next/font/google' import './globals.css' +import TrpcProvider from '@/components/providers/TrpcProvider' const inter = Inter({ subsets: ['latin'] }) @@ -20,7 +21,7 @@ export default function RootLayout({ return ( - {children} + {children} ) diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx new file mode 100644 index 0000000..f0dcc60 --- /dev/null +++ b/src/app/login/page.tsx @@ -0,0 +1,105 @@ +'use client' + +import { useState, useEffect } from 'react' +import { useRouter } from 'next/navigation' +import { trpc } from '@/lib/trpc-client' + +export default function LoginPage() { + const router = useRouter() + const [email, setEmail] = useState('') + const [password, setPassword] = useState('') + const [error, setError] = useState(null) + + const meQuery = trpc.auth.me.useQuery(undefined, { retry: false }) + useEffect(() => { + if (meQuery.data) router.push('/') + }, [meQuery.data, router]) + + const loginMutation = trpc.auth.login.useMutation({ + onSuccess: () => { + router.push('/') + router.refresh() + }, + onError: (err) => { + setError(err.message ?? 'Credenciales inválidas') + }, + }) + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault() + setError(null) + loginMutation.mutate({ email, password }) + } + + if (meQuery.isLoading) { + return ( +
+
Cargando...
+
+ ) + } + if (meQuery.data) return null + + return ( +
+
+
+

MSP Monitor

+

Iniciar sesión

+
+ +
+ {error && ( +
+ {error} +
+ )} + +
+ + setEmail(e.target.value)} + required + autoComplete="email" + className="input w-full" + placeholder="admin@example.com" + /> +
+ +
+ + setPassword(e.target.value)} + required + autoComplete="current-password" + className="input w-full" + /> +
+ + +
+ + {/*

+ Por defecto: admin@example.com / Admin123! +

+ */} +
+
+ ) +} diff --git a/src/lib/trpc-client.ts b/src/lib/trpc-client.ts new file mode 100644 index 0000000..0c20035 --- /dev/null +++ b/src/lib/trpc-client.ts @@ -0,0 +1,4 @@ +import { createTRPCReact } from '@trpc/react-query' +import type { AppRouter } from '@/server/trpc/routers' + +export const trpc = createTRPCReact()