summaryrefslogtreecommitdiff
path: root/src/components/newsletter-form.tsx
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>
  );
};