feat(client): magic link sign-in
Signed-off-by: Noa Virellia <noa@requiem.garden>
This commit is contained in:
@@ -2,6 +2,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
import { createRootRoute, Outlet } from '@tanstack/react-router';
|
||||
import { TanStackRouterDevtools } from '@tanstack/react-router-devtools';
|
||||
import { ThemeProvider } from '@/components/theme-provider';
|
||||
import { Toaster } from '@/components/ui/sonner';
|
||||
import '@/index.css';
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
@@ -15,6 +16,7 @@ function RootLayout() {
|
||||
</QueryClientProvider>
|
||||
</ThemeProvider>
|
||||
<TanStackRouterDevtools />
|
||||
<Toaster position="top-right" />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,15 +1,34 @@
|
||||
import { createFileRoute } from '@tanstack/react-router';
|
||||
import { createFileRoute, Navigate } from '@tanstack/react-router';
|
||||
import { zodValidator } from '@tanstack/zod-adapter';
|
||||
import z from 'zod';
|
||||
import { LoginForm } from '@/components/login-form';
|
||||
import { useValidateMagicLink } from '@/hooks/data/useValidateMagicLink';
|
||||
import { setToken } from '@/lib/token';
|
||||
|
||||
const loginMagicLinkReceiverSchema = z.object({
|
||||
ticket: z.string().optional(),
|
||||
});
|
||||
|
||||
export const Route = createFileRoute('/login')({
|
||||
component: RouteComponent,
|
||||
validateSearch: zodValidator(loginMagicLinkReceiverSchema),
|
||||
});
|
||||
|
||||
function ReceiveMagicLinkComponent() {
|
||||
const { ticket } = Route.useSearch();
|
||||
const { data } = useValidateMagicLink(ticket!);
|
||||
|
||||
setToken(data.data.jwt_token);
|
||||
|
||||
return <Navigate to="/" />;
|
||||
}
|
||||
|
||||
function RouteComponent() {
|
||||
const { ticket } = Route.useSearch();
|
||||
return (
|
||||
<div className="bg-background flex min-h-svh flex-col items-center justify-center gap-6 p-6 md:p-10">
|
||||
<div className="w-full max-w-sm">
|
||||
<LoginForm />
|
||||
{ticket === undefined ? <LoginForm /> : <ReceiveMagicLinkComponent />}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
33
client/src/routes/magicLinkSent.tsx
Normal file
33
client/src/routes/magicLinkSent.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import { createFileRoute, Navigate } from '@tanstack/react-router';
|
||||
import { zodValidator } from '@tanstack/zod-adapter';
|
||||
import z from 'zod';
|
||||
import NixOSLogo from '@/assets/nixos.svg?react';
|
||||
|
||||
const paramsSchema = z.object({
|
||||
email: z.string().optional(),
|
||||
});
|
||||
|
||||
export const Route = createFileRoute('/magicLinkSent')({
|
||||
component: RouteComponent,
|
||||
validateSearch: zodValidator(paramsSchema),
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
const { email } = Route.useSearch();
|
||||
return email !== undefined
|
||||
? (
|
||||
<div className="
|
||||
bg-background flex min-h-svh flex-row items-center justify-center gap-6 p-6 md:p-10"
|
||||
>
|
||||
<NixOSLogo className="size-12" />
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="mx-2 inline-block h-6 w-px bg-current opacity-40"
|
||||
/>
|
||||
登录链接已发送至
|
||||
{' '}
|
||||
{email}
|
||||
</div>
|
||||
)
|
||||
: <Navigate to="/login" />;
|
||||
}
|
||||
Reference in New Issue
Block a user