refactor: improve code quality
Signed-off-by: Noa Virellia <noa@requiem.garden>
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useEvents } from '@/hooks/data/useEvents';
|
||||
import { Button } from '../../ui/button';
|
||||
import { DialogTrigger } from '../../ui/dialog';
|
||||
@@ -10,22 +11,28 @@ import { EventGridView } from './event-grid.view';
|
||||
export function EventGridContainer() {
|
||||
const { data, isLoading } = useEvents();
|
||||
|
||||
const events = useMemo(() => {
|
||||
return data?.pages.flatMap(page => page.data ?? []).map(toEventInfo) ?? [];
|
||||
}, [data]);
|
||||
|
||||
return (
|
||||
isLoading
|
||||
? <EventGridSkeleton />
|
||||
: (
|
||||
<EventGridView
|
||||
events={data.pages.flatMap(page => page.data ?? []).map(toEventInfo)}
|
||||
events={events}
|
||||
footer={(eventInfo) => {
|
||||
const Container = eventInfo.requireKyc ? KycDialogContainer : EventJoinDialogContainer;
|
||||
|
||||
return (
|
||||
<Container event={eventInfo}>
|
||||
{eventInfo.isJoined ? (
|
||||
{eventInfo.isJoined
|
||||
? (
|
||||
<Button className="w-full" disabled>
|
||||
已加入
|
||||
</Button>
|
||||
) : (
|
||||
)
|
||||
: (
|
||||
<DialogTrigger asChild>
|
||||
<Button className="w-full">加入活动</Button>
|
||||
</DialogTrigger>
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
import type { TurnstileInstance } from '@marsidev/react-turnstile';
|
||||
import type { AuthorizeSearchParams } from '@/routes/authorize';
|
||||
import { Turnstile } from '@marsidev/react-turnstile';
|
||||
import { useForm } from '@tanstack/react-form';
|
||||
import { useNavigate } from '@tanstack/react-router';
|
||||
import { Loader2 } from 'lucide-react';
|
||||
import { useRef, useState } from 'react';
|
||||
import { toast } from 'sonner';
|
||||
import z from 'zod';
|
||||
import NixOSLogo from '@/assets/nixos.svg?react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
Field,
|
||||
FieldError,
|
||||
FieldGroup,
|
||||
FieldLabel,
|
||||
} from '@/components/ui/field';
|
||||
@@ -23,29 +26,43 @@ export function LoginForm({
|
||||
}: React.ComponentProps<'div'> & {
|
||||
oauthParams: AuthorizeSearchParams;
|
||||
}) {
|
||||
const formRef = useRef<HTMLFormElement>(null);
|
||||
const turnstileRef = useRef<TurnstileInstance>(null);
|
||||
const [token, setToken] = useState<string | null>(import.meta.env.DEV ? 'turnstile_token' : 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({ body: { email, turnstile_token: token!, ...oauthParams } }).then(() => {
|
||||
void navigate({ to: '/magicLinkSent', search: { email } });
|
||||
}).catch((error) => {
|
||||
const form = useForm({
|
||||
defaultValues: {
|
||||
email: '',
|
||||
},
|
||||
validators: {
|
||||
onSubmit: z.object({
|
||||
email: z.string().email('请输入有效的邮箱地址'),
|
||||
}),
|
||||
},
|
||||
onSubmit: async ({ value }) => {
|
||||
try {
|
||||
await mutateAsync({ body: { email: value.email, turnstile_token: token!, ...oauthParams } });
|
||||
await navigate({ to: '/magicLinkSent', search: { email: value.email } });
|
||||
}
|
||||
catch (error) {
|
||||
console.error(error);
|
||||
toast.error('请求登录链接失败');
|
||||
turnstileRef.current?.reset();
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const isLoading = isPending || token === null;
|
||||
return (
|
||||
<div className={cn('flex flex-col gap-6', className)} {...props}>
|
||||
<form ref={formRef} onSubmit={handleSubmit}>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
void form.handleSubmit();
|
||||
}}
|
||||
>
|
||||
<FieldGroup>
|
||||
<div className="flex flex-col items-center gap-2 text-center">
|
||||
<div className="flex size-8 items-center justify-center rounded-md">
|
||||
@@ -54,6 +71,8 @@ export function LoginForm({
|
||||
<span className="sr-only">Nix CN CMS</span>
|
||||
<h1 className="text-xl font-bold">欢迎来到 Nix CN CMS</h1>
|
||||
</div>
|
||||
<form.Field name="email">
|
||||
{field => (
|
||||
<Field>
|
||||
<FieldLabel htmlFor="email">参会登记Email</FieldLabel>
|
||||
<Input
|
||||
@@ -62,8 +81,14 @@ export function LoginForm({
|
||||
type="email"
|
||||
placeholder="edolstra@gmail.com"
|
||||
required
|
||||
value={field.state.value}
|
||||
onBlur={field.handleBlur}
|
||||
onChange={e => field.handleChange(e.target.value)}
|
||||
/>
|
||||
<FieldError errors={field.state.meta.errors} />
|
||||
</Field>
|
||||
)}
|
||||
</form.Field>
|
||||
<Field>
|
||||
<Button type="submit" disabled={isLoading}>
|
||||
{isLoading && <Loader2 className="animate-spin" />}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import type { Query } from '@tanstack/react-query';
|
||||
import type { ClassValue } from 'clsx';
|
||||
// eslint-disable-next-line unicorn/prefer-node-protocol
|
||||
import { Buffer } from 'buffer';
|
||||
@@ -19,15 +18,6 @@ export function utf8ToBase64(utf8: string): string {
|
||||
return Buffer.from(utf8, 'utf-8').toString('base64');
|
||||
}
|
||||
|
||||
export function invalidateBlurry(id: string) {
|
||||
return {
|
||||
predicate: (query: Query<unknown, Error, unknown, readonly unknown[]>) => {
|
||||
const key = query.queryKey[0] as { _id: string };
|
||||
return key?._id === id;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function isInDateRange(start: Date, end: Date, target: Date = new Date()): boolean {
|
||||
const time = target.getTime();
|
||||
return time >= start.getTime() && time <= end.getTime();
|
||||
|
||||
Reference in New Issue
Block a user