blob: 7dd0cc0b51024df86da25c591024f5cad07af3eb (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
'use client';
import { useAction } from 'next-safe-action/hooks';
import { Button } from '@/components/ui/button';
import {
Form,
FormControl,
FormField,
FormItem,
FormMessage,
} from '@/components/ui/form';
import { Input } from '@/components/ui/input';
import type { Newsletter } from '@/lib/validators';
import { NewsletterSchema } from '@/lib/validators';
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import { Alert, AlertTitle } from '@/components/ui/alert';
import { subscribeUser } from '@/app/(home)/actions';
import { Icons } from '@/components/icons/icons';
export const NewsletterForm = () => {
const form = useForm({
resolver: zodResolver(NewsletterSchema),
defaultValues: {
email: '',
},
});
const { execute, result, status } = useAction(subscribeUser);
const onSubmit = (values: Newsletter) => {
execute(values);
};
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className='flex-1 space-y-4'>
<div className='flex h-full min-h-10 overflow-hidden rounded-md border bg-muted p-0'>
<div className='flex-1'>
<FormField
control={form.control}
name='email'
render={({ field }) => (
<FormItem className='group h-full'>
<FormControl className='h-full group-has-[p]:pt-3'>
<Input
{...field}
disabled={status === 'executing'}
placeholder='Email address'
type='email'
className='h-full rounded-md rounded-r-none border-none px-4 shadow-none focus-visible:ring-0 focus-visible:ring-offset-0'
/>
</FormControl>
<FormMessage className='ml-4 pb-2 text-xs' />
</FormItem>
)}
/>
</div>
<Button
disabled={status === 'executing'}
type='submit'
size='icon'
className='group size-auto w-15 rounded-md rounded-l-none px-3'
>
{status === 'executing' ? (
<Icons.spinner className='size-4 animate-spin' />
) : (
<Icons.send className='group-hover:-rotate-45 size-4 transition-transform' />
)}
</Button>
</div>
{status === 'hasSucceeded' && (
<Alert className='border-emerald-500/15 bg-emerald-500/15 p-3 px-3 py-2 text-emerald-500 has-[>svg]:gap-x-1.5'>
<Icons.success size={16} />
<AlertTitle className='mb-0 leading-normal'>
{result.data?.message ?? "Hmm... Our server didn't respond."}
</AlertTitle>
</Alert>
)}
{result.serverError && (
<Alert className='border-destructive/15 bg-destructive/15 p-3 px-3 py-2 text-destructive has-[>svg]:gap-x-1.5 dark:border-destructive dark:bg-destructive dark:text-destructive-foreground'>
<Icons.warning className='size-4' />
<AlertTitle className='mb-0 leading-normal'>
{result.serverError}
</AlertTitle>
</Alert>
)}
</form>
</Form>
);
};
|