81 lines
2.7 KiB
TypeScript
81 lines
2.7 KiB
TypeScript
import type { TurnstileInstance } from '@marsidev/react-turnstile';
|
|
import { Turnstile } from '@marsidev/react-turnstile';
|
|
import { useNavigate } from '@tanstack/react-router';
|
|
import { useRef, useState } from 'react';
|
|
import { toast } from 'sonner';
|
|
import NixOSLogo from '@/assets/nixos.svg?react';
|
|
import { Button } from '@/components/ui/button';
|
|
import {
|
|
Field,
|
|
FieldGroup,
|
|
FieldLabel,
|
|
} from '@/components/ui/field';
|
|
import { Input } from '@/components/ui/input';
|
|
import { useGetMagicLink } from '@/hooks/data/useGetMagicLink';
|
|
import { cn } from '@/lib/utils';
|
|
|
|
export function LoginForm({
|
|
className,
|
|
...props
|
|
}: React.ComponentProps<'div'>) {
|
|
const formRef = useRef<HTMLFormElement>(null);
|
|
const turnstileRef = useRef<TurnstileInstance>(null);
|
|
const [token, setToken] = useState<string | null>(null);
|
|
const { mutateAsync, isPending } = useGetMagicLink();
|
|
const navigate = useNavigate();
|
|
|
|
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
|
|
event.preventDefault();
|
|
const formData = new FormData(formRef.current!);
|
|
const email = formData.get('email')! as string;
|
|
mutateAsync({ email, turnstile_token: token! }).then(() => {
|
|
void navigate({ to: '/magicLinkSent', search: { email } });
|
|
}).catch((error) => {
|
|
console.error(error);
|
|
toast.error('请求登录链接失败');
|
|
turnstileRef.current?.reset();
|
|
});
|
|
};
|
|
|
|
return (
|
|
<div className={cn('flex flex-col gap-6', className)} {...props}>
|
|
<form ref={formRef} onSubmit={handleSubmit}>
|
|
<FieldGroup>
|
|
<div className="flex flex-col items-center gap-2 text-center">
|
|
<div className="flex size-8 items-center justify-center rounded-md">
|
|
<NixOSLogo className="size-6" />
|
|
</div>
|
|
<span className="sr-only">Nix CN Meetup #2</span>
|
|
<h1 className="text-xl font-bold">欢迎来到 Nix CN Meetup #2</h1>
|
|
</div>
|
|
<Field>
|
|
<FieldLabel htmlFor="email">参会登记Email</FieldLabel>
|
|
<Input
|
|
id="email"
|
|
name="email"
|
|
type="email"
|
|
placeholder="edolstra@gmail.com"
|
|
required
|
|
/>
|
|
</Field>
|
|
<Field>
|
|
<Button type="submit" disabled={token === null || isPending}>
|
|
{token === null ? '等待 Turnstile' : isPending ? '发送中...' : '发送登录链接'}
|
|
</Button>
|
|
</Field>
|
|
</FieldGroup>
|
|
</form>
|
|
<Turnstile
|
|
ref={turnstileRef}
|
|
siteKey="0x4AAAAAACI5pu-lNWFc6Wu1"
|
|
options={{
|
|
refreshExpired: 'auto',
|
|
}}
|
|
onSuccess={(token) => {
|
|
setToken(token);
|
|
}}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|