Desenvolvedores
src_
components_
RegisterForm.jsx

O código a seguir implementa um formulário de registro com validação de dados e integração com a API para criar um novo aluno. Vamos passar por cada parte do código com uma explicação detalhada e incluir emojis para tornar a leitura mais envolvente 😄.

Importações 📦

O código começa com as importações necessárias:

'use client'
import React from 'react'
import { useRouter } from 'next/navigation'
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { z } from 'zod'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import InputCpf from '@/components/InputCpf'
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import BackgroundVideo from '@/components/BackgroundVideo'
import { toast } from 'sonner'
  • useForm e zodResolver são usados para gerenciar a validação do formulário de forma eficiente.
  • z é utilizado para definir o esquema de validação dos dados.
  • Componentes como Button, Input e Card são usados para construir a interface de usuário.

Definição do Esquema de Validação 📋

Aqui, usamos o zod para definir o esquema de validação dos dados do formulário:

const formSchema = z.object({
  fullName: z.string().min(3, { message: 'Nome completo deve ter pelo menos 3 caracteres.' }),
  email: z.string().email({ message: 'Email inválido' }),
  cpf: z.string().min(11, { message: 'CPF inválido.' }),
  password: z.string().min(6, { message: 'Senha deve ter pelo menos 6 caracteres.' }),
})
  • fullName deve ter pelo menos 3 caracteres.
  • email precisa ser um email válido.
  • cpf deve ter no mínimo 11 caracteres.
  • password precisa ter pelo menos 6 caracteres.

Inicialização do Formulário 📝

A seguir, inicializamos o formulário com o useForm e passamos o esquema de validação para ele:

const form = useForm({
  resolver: zodResolver(formSchema),
  defaultValues: {
    fullName: '',
    email: '',
    cpf: '',
    password: '',
  },
})

Aqui estamos configurando o formulário com valores iniciais vazios para todos os campos.

Função de Submissão 🔄

Quando o formulário é enviado, o onSubmit é chamado para enviar os dados para a API:

const onSubmit = async (values) => {
  try {
    const apiUrl = process.env.NEXT_PUBLIC_SERVER_URL
    const response = await fetch(`${apiUrl}/api/alunos`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        nomeCompleto: values.fullName,
        email: values.email,
        cpf: values.cpf,
        password: values.password,
      }),
    })
 
    if (!response.ok) {
      throw new Error('Erro ao registrar o aluno')
    }
 
    const data = await response.json()
 
    toast('Conta criada com sucesso!', {
      description: <span style={{ color: '#d1d5db' }}>Faça seu login agora</span>,
      style: {
        backgroundColor: '#15803d',
        color: 'white',
      },
    })
 
    router.push('/login')
  } catch (error) {
    console.error('Erro:', error)
  }
}

Aqui, o código faz uma requisição POST para o backend com os dados do aluno e, se a requisição for bem-sucedida, exibe uma mensagem de sucesso.

Estrutura do Formulário 💻

A interface de usuário é construída com componentes reutilizáveis para criar os campos do formulário:

return (
  <div className="relative w-full h-screen overflow-y-auto bg-background">
    <BackgroundVideo />
    <div className="relative z-10 min-h-screen py-8 flex flex-col items-center justify-center">
      <Card className="p-8 rounded-lg shadow-lg max-w-md w-full mx-4">
        <CardHeader>
          <CardTitle>Registrar</CardTitle>
          <CardDescription>Bem-vindo, crie sua conta de aluno abaixo</CardDescription>
        </CardHeader>
        <CardContent>
          <Form {...form}>
            <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
              <FormField
                control={form.control}
                name="fullName"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>
                      Nome Completo <span className="text-red-500">*</span>
                    </FormLabel>
                    <FormControl>
                      <Input placeholder="Digite seu nome" {...field} />
                    </FormControl>
                    <FormMessage />
                  </FormItem>
                )}
              />
              <FormField
                control={form.control}
                name="email"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>
                      Email <span className="text-red-500">*</span>
                    </FormLabel>
                    <FormControl>
                      <Input type="email" placeholder="email@exemplo.com" {...field} />
                    </FormControl>
                    <FormMessage />
                  </FormItem>
                )}
              />
              <FormField
                control={form.control}
                name="cpf"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>
                      CPF <span className="text-red-500">*</span>
                    </FormLabel>
                    <FormControl>
                      <InputCpf control={form.control} name="cpf" />
                    </FormControl>
                    <FormDescription>
                      É fundamental seu nome completo e CPF estarem corretos para gerarmos seus
                      certificados
                    </FormDescription>
                    <FormMessage />
                  </FormItem>
                )}
              />
              <FormField
                control={form.control}
                name="password"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>
                      Senha <span className="text-red-500">*</span>
                    </FormLabel>
                    <FormControl>
                      <Input type="password" placeholder="Digite sua senha" {...field} />
                    </FormControl>
                    <FormMessage />
                  </FormItem>
                )}
              />
              <div className="flex justify-center">
                <Button type="submit">Registrar</Button>
              </div>
            </form>
          </Form>
        </CardContent>
      </Card>
      <div className="text-balance text-center mt-4 text-xs text-muted-foreground [&_a]:underline [&_a]:underline-offset-4 [&_a]:hover:text-primary ">
        Ao clicar em continuar, você concorda com nossos <br></br>
        <a href="#">Termos de Serviço</a> e <a href="#"> Política de Privacidade</a>.
      </div>
    </div>
  </div>
)

Aqui é onde a UI é renderizada, incluindo o fundo com o BackgroundVideo, o card de formulário, e o botão de submissão.

Código Completo 📝

'use client'
import React from 'react'
import { useRouter } from 'next/navigation'
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { z } from 'zod'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import InputCpf from '@/components/InputCpf'
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import BackgroundVideo from '@/components/BackgroundVideo'
import { toast } from 'sonner'
 
const formSchema = z.object({
  fullName: z.string().min(3, { message: 'Nome completo deve ter pelo menos 3 caracteres.' }),
  email: z.string().email({ message: 'Email inválido' }),
  cpf: z.string().min(11, { message: 'CPF inválido.' }),
  password: z.string().min(6, { message: 'Senha deve ter pelo menos 6 caracteres.' }),
})
 
const RegisterForm = () => {
  const router = useRouter()
 
  const form = useForm({
    resolver: zodResolver(formSchema),
    defaultValues: {
      fullName: '',
      email: '',
      cpf: '',
      password: '',
    },
  })
 
  const onSubmit = async (values) => {
    try {
      const apiUrl = process.env.NEXT_PUBLIC_SERVER_URL
      const response = await fetch(`${apiUrl}/api/alunos`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          nomeCompleto: values.fullName,
          email: values.email,
          cpf: values.cpf,
          password: values.password,
        }),
      })
 
      if (!response.ok) {
        throw new Error('Erro ao registrar o aluno')
      }
 
      const data = await response.json()
 
      toast('Conta criada com sucesso!', {
        description: <span style={{ color: '#d1d5db' }}>Faça seu login agora</span>,
        style: {
          backgroundColor: '#15803d',
          color: 'white',
        },
      })
 
      router.push('/login')
    } catch (error) {
      console.error('Erro:', error)
    }
  }
 
  return (
    <div className="relative w-full h-screen overflow-y-auto bg-background">
      <BackgroundVideo />
      <div className="relative z-10 min-h-screen py-8 flex flex-col items-center justify-center">
        <Card className="p-8 rounded-lg shadow-lg max-w-md w-full mx-4">
          <CardHeader>
            <CardTitle>Registrar</CardTitle>
            <CardDescription>Bem-vindo, crie sua conta de aluno abaixo</CardDescription>
          </CardHeader>
          <CardContent>
            <Form {...form}>
              <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
                <FormField
                  control={form.control}
                  name="fullName"
                  render={({ field }) => (
                    <FormItem>
                      <FormLabel>
                        Nome Completo <span className="text-red-500">*</span>
                      </FormLabel>
                      <FormControl>
                        <Input placeholder="Digite seu nome" {...field} />
                      </FormControl>
                      <FormMessage />
                    </FormItem>
                  )}
                />
                <FormField
                  control={form.control}
                  name="email"
                  render={({ field }) => (
                    <FormItem>
                      <FormLabel>
                        Email <span className="text-red-500">*</span>
                      </FormLabel>
                      <FormControl>
                        <Input type="email" placeholder="email@exemplo.com" {...field} />
                      </FormControl>
                      <FormMessage />
                    </FormItem>
                  )}
                />
                <FormField
                  control={form.control}
                  name="cpf"
                  render={({ field }) => (
                    <FormItem>
                      <FormLabel>
                        CPF <span className="text-red-500">*</span>
                      </FormLabel>
                      <FormControl>
                        <InputCpf control={form.control} name="cpf" />
                      </FormControl>
                      <FormDescription>
                        É fundamental seu nome completo e CPF estarem corretos para gerarmos seus
                        certificados
                      </FormDescription>
                      <FormMessage />
                    </FormItem>
                  )}
                />
                <FormField
                  control={form.control}
                  name="password"
                  render={({ field }) => (
                    <FormItem>
                      <FormLabel>
                        Senha <span className="text-red-500">*</span>
                      </FormLabel>
                      <FormControl>
                        <Input type="password" placeholder="Digite sua senha" {...field} />
                      </FormControl>
                      <FormMessage />
                    </FormItem>
                  )}
                />
                <div className="flex justify-center">
                  <Button type="submit">Registrar</Button>
                </div>
              </form>
            </Form>
          </CardContent>
        </Card>
        <div className="text-balance text-center mt-4 text-xs text-muted-foreground [&_a]:underline [&_a]:underline-offset-4 [&_a]:hover:text-primary ">
          Ao clicar em continuar, você concorda com nossos <br></br>
          <a href="#">Termos de Serviço</a> e <a href="#"> Política de Privacidade</a>.
        </div>
      </div>
    </div>
  )
}
 
export default RegisterForm