Commit dcf368ee authored by Wellton Quirino's avatar Wellton Quirino

Finishing Frontend

parent f47a9145
......@@ -34,6 +34,7 @@
"lucide-react": "^0.383.0",
"next": "14.2.3",
"next-themes": "^0.3.0",
"nodemailer": "^6.10.0",
"nookies": "^2.5.2",
"react": "^18",
"react-day-picker": "^8.10.1",
......@@ -49,6 +50,7 @@
"@rocketseat/eslint-config": "^2.2.2",
"@types/cookie": "^0.6.0",
"@types/node": "^20",
"@types/nodemailer": "^6.4.17",
"@types/react": "^18",
"@types/react-dom": "^18",
"@types/react-input-mask": "^3.0.5",
......@@ -3873,6 +3875,16 @@
"undici-types": "~5.26.4"
}
},
"node_modules/@types/nodemailer": {
"version": "6.4.17",
"resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.17.tgz",
"integrity": "sha512-I9CCaIp6DTldEg7vyUTZi8+9Vo0hi1/T8gv3C89yk1rSAAzoKQ8H8ki/jBYJSFoH/BisgLP8tkZMlQ91CIquww==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/parse-json": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz",
......@@ -7196,6 +7208,15 @@
"node": "^10 || ^12 || >=14"
}
},
"node_modules/nodemailer": {
"version": "6.10.0",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.10.0.tgz",
"integrity": "sha512-SQ3wZCExjeSatLE/HBaXS5vqUOQk6GtBdIIKxiFdmm01mOQZX/POJkO3SUX1wDiYcwUOJwT23scFSC9fY2H8IA==",
"license": "MIT-0",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/nookies": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/nookies/-/nookies-2.5.2.tgz",
......
......@@ -29,8 +29,6 @@ export default function AreaId() {
} = useForm<AreasProps>()
const router = useRouter()
console.log('🚀 ~ AreaId ~ errors:', errors)
const queryClient = useQueryClient()
const { data: area, isLoading } = useQuery({
......@@ -61,8 +59,6 @@ export default function AreaId() {
const urlDesktop = await handleUpload(desktopBanner)
const urlMobile = await handleUpload(mobileBanner)
console.log(data)
const dataArea = {
...data,
id: params.id,
......
......@@ -23,7 +23,6 @@ const FormSchema = z.object({
export default function Area() {
const [desktopBanner, setDesktopBanner] = useState<File | null>(null)
const [mobileBanner, setMobileBanner] = useState<File | null>(null)
console.log('🚀 ~ Area ~ mobileBanner:', mobileBanner)
const {
register,
......@@ -33,7 +32,6 @@ export default function Area() {
} = useForm<AreasProps>({
resolver: zodResolver(FormSchema),
})
console.log('🚀 ~ Area ~ error:', errors)
const router = useRouter()
const queryClient = useQueryClient()
......
......@@ -59,7 +59,6 @@ export default function AudienceId() {
}
async function onSubmit(data: AudiencesProps) {
console.log('🚀 ~ onSubmit ~ data:', data)
const body = {
id: params.id,
name: data.name,
......
......@@ -280,8 +280,6 @@ export default function Curso() {
return data.url
}
console.log('error: ', form.formState.errors)
if (isLoading) {
return <p>Carregando...</p>
}
......
......@@ -233,8 +233,6 @@ export default function Curso() {
return data.url
}
console.log('error: ', form.formState.errors)
return (
<section className="container py-10">
<BreadcrumbComponent page="Curso" />
......
import { NextResponse } from 'next/server'
import nodemailer from 'nodemailer'
export async function POST(req: Request) {
try {
const { fullname, email, subject, message } = await req.json()
const transporter = nodemailer.createTransport({
host: process.env.EMAIL_HOST,
port: Number(process.env.EMAIL_PORT),
auth: {
user: process.env.EMAIL_USER,
pass: process.env.EMAIL_PASS,
},
})
const mailOptions = {
from: email,
to: process.env.EMAIL_SEVENPRO,
subject: `Nova dúvida de ${fullname}: ${subject}`,
text: message,
html: `<p><strong>Nome:</strong> ${fullname}</p><p><strong>Assunto:</strong> ${subject}</p><p><strong>Mensagem:</strong></p><p>${message}</p>`,
}
await transporter.sendMail(mailOptions)
return NextResponse.json(
{ message: 'E-mail enviado com sucesso!' },
{ status: 200 },
)
} catch (error) {
return NextResponse.json(
{ error: 'Erro ao enviar o e-mail.' },
{ status: 500 },
)
}
}
......@@ -2,15 +2,6 @@ import { s3 } from '@/lib/cloudflare'
import { PutObjectCommand } from '@aws-sdk/client-s3'
import { NextRequest, NextResponse } from 'next/server'
// const s3Client = new S3Client({
// region: 'auto',
// endpoint: process.env.NEXT_PUBLIC_CLOUDFLARE_ACCESS_ENDPOINT,
// credentials: {
// accessKeyId: process.env.NEXT_PUBLIC_CLOUDFLARE_ACCESS_KEY_ID!,
// secretAccessKey: process.env.NEXT_PUBLIC_CLOUDFLARE_SECRET_ACCESS_KEY!,
// },
// })
export async function POST(req: NextRequest) {
const formData = await req.formData()
const file = formData.get('file') as File
......@@ -38,7 +29,6 @@ export async function POST(req: NextRequest) {
return NextResponse.json({ url: fileUrl })
} catch (error) {
console.error(error)
return NextResponse.json({ error: 'Upload failed' }, { status: 500 })
}
}
......@@ -2,9 +2,12 @@
import { InputMui } from '@/components/mui/inputs'
import { Button } from '@/components/ui/button'
import { zodResolver } from '@hookform/resolvers/zod'
import { MenuItem } from '@mui/material'
import { Clock4, Mail, Smartphone } from 'lucide-react'
import { useState } from 'react'
import { useForm } from 'react-hook-form'
import { z } from 'zod'
const matters = [
{
......@@ -25,8 +28,56 @@ const matters = [
},
]
type DataEmail = {
fullname: string
email: string
message: string
subject: string
}
const schema = z
.object({
fullname: z.string().min(5, { message: 'Digite seu nome completo' }),
email: z.string().email({ message: 'E-mail inválido' }),
message: z
.string()
.min(5, { message: 'Mensagem deve ter no mínimo 5 caracteres' }),
subject: z.string().min(2, { message: 'Selecione uma assunto' }),
})
.required()
export default function Contact() {
const { register } = useForm()
const {
register,
handleSubmit,
reset,
formState: { errors },
} = useForm<DataEmail>({
resolver: zodResolver(schema),
})
const [status, setStatus] = useState('')
async function onSubmit(data: DataEmail) {
setStatus('Enviando...')
try {
const response = await fetch('/api/send-email', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
if (response.ok) {
setStatus('E-mail enviado com sucesso!')
reset()
} else {
setStatus('Erro ao enviar o e-mail.')
}
} catch (error) {
setStatus('Erro ao enviar o e-mail.')
}
}
return (
<main className="container flex flex-col justify-center items-center py-20">
......@@ -57,14 +108,30 @@ export default function Contact() {
<h2 className="text-green-800 text-xl md:text-2xl">
Envie uma mensagem
</h2>
<form action="" className="mt-6 flex flex-col gap-6">
<form
onSubmit={handleSubmit(onSubmit)}
className="mt-6 flex flex-col gap-6"
>
<InputMui
type="text"
variant="outlined"
label="Nome completo"
name="full-name"
name="fullname"
register={register}
/>
{errors.fullname?.message && (
<p className="text-red-600">{errors.fullname?.message}</p>
)}
<InputMui
type="text"
variant="outlined"
label="E-mail"
name="email"
register={register}
/>
{errors.email?.message && (
<p className="text-red-600">{errors.email?.message}</p>
)}
<InputMui
type="text"
variant="outlined"
......@@ -74,7 +141,9 @@ export default function Contact() {
name="message"
register={register}
/>
{errors.message?.message && (
<p className="text-red-600">{errors.message?.message}</p>
)}
<InputMui
type="text"
variant="outlined"
......@@ -89,6 +158,9 @@ export default function Contact() {
</MenuItem>
))}
</InputMui>
{errors.subject?.message && (
<p className="text-red-600">{errors.subject?.message}</p>
)}
<div className="flex">
<Button type="submit" className="w-auto">
......@@ -96,6 +168,7 @@ export default function Contact() {
</Button>
</div>
</form>
{status && <p className="mt-4 text-sm text-white">{status}</p>}
</div>
</div>
</main>
......
'use client'
import { getCourses } from '@/api/courses'
import { About } from '@/components/about'
import { BannerCategory } from '@/components/banner-category'
import { Card } from '@/components/card'
import { Differences } from '@/components/differences'
import { NavLinkCategory } from '@/components/nav-link-category'
import { PaginationComponent } from '@/components/pagination-component'
import SearchFilter from '@/components/search-filter'
import { SignUp } from '@/components/sign-up'
import { SkeletonSerachParams } from '@/components/skeleton-serach-params'
import { CoursesCard } from '@/utils/courses-array'
import { formatDate } from '@/utils/formatDate'
import { useQuery } from '@tanstack/react-query'
import { Calendar, Clock4, User } from 'lucide-react'
import { usePathname, useSearchParams } from 'next/navigation'
import { Suspense } from 'react'
export default function Companies() {
const path = usePathname()
const searchParams = useSearchParams()
const category = searchParams.get('area')
const { data: courses, isLoading: coursesLoading } = useQuery({
queryKey: ['courses'],
queryFn: getCourses,
})
const filterCoursesAudience = courses?.data.filter((item) =>
path.toLowerCase().includes(item?.audience?.name.toLowerCase() as string),
)
const filterCoursesAudiencesAndArea = filterCoursesAudience?.filter((area) =>
category?.includes(area?.area?.name.toLowerCase() as string),
)
if (coursesLoading) {
return <p>Carregando...</p>
}
return (
<main>
<Suspense fallback={<SkeletonSerachParams />}>
<BannerCategory />
<NavLinkCategory />
</Suspense>
<SearchFilter />
<div className="grid grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 grid-rows-3 lg:grid-rows-2 gap-4 md:gap-6 p-6">
{CoursesCard.map((course) => (
<div className="flex justify-center" key={course.id}>
<Card.Root link={`/curso/${course.id}`}>
<Card.Image image={course.image.src} width={273} height={365}>
<Card.Title title={course.title} />
</Card.Image>
<Card.Content description={course.hours}>
<Card.Icon icon={Clock4} />
</Card.Content>
<Card.Content description={course.category}>
<Card.Icon icon={User} />
</Card.Content>
<Card.Content description={course.calender}>
<Card.Icon icon={Calendar} />
</Card.Content>
</Card.Root>
</div>
))}
{/* <SearchFilter /> */}
<div className="grid rounded-none grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 grid-rows-3 lg:grid-rows-2 gap-4 md:gap-6 p-6">
{!category &&
filterCoursesAudience &&
filterCoursesAudience.map((course) => (
<div className="flex justify-center" key={course.id}>
<Card.Root link={`/curso/${course.id}`}>
<Card.Image
image={course.mobileBanner as string}
width={273}
height={365}
>
<Card.Title title={course.name} />
</Card.Image>
<Card.Content
description={`${course.workload} hrs / ${course.category?.name}`}
>
<Card.Icon icon={Clock4} />
</Card.Content>
<Card.Content description={course.audience?.name as string}>
<Card.Icon icon={User} />
</Card.Content>
<Card.Content
description={formatDate(course.startDate) as string}
>
<Card.Icon icon={Calendar} />
</Card.Content>
</Card.Root>
</div>
))}
{category &&
filterCoursesAudiencesAndArea &&
filterCoursesAudiencesAndArea.map((course) => (
<div className="flex justify-center" key={course.id}>
<Card.Root link={`/curso/${course.id}`}>
<Card.Image
image={course.mobileBanner as string}
width={273}
height={365}
>
<Card.Title title={course.name} />
</Card.Image>
<Card.Content
description={`${course.workload} hrs / ${course.category?.name}`}
>
<Card.Icon icon={Clock4} />
</Card.Content>
<Card.Content description={course.audience?.name as string}>
<Card.Icon icon={User} />
</Card.Content>
<Card.Content
description={formatDate(course.startDate) as string}
>
<Card.Icon icon={Calendar} />
</Card.Content>
</Card.Root>
</div>
))}
{category && filterCoursesAudiencesAndArea?.length === 0 && (
<p>
Não há cursos para a área <b>{category}</b> com audiência{' '}
<b>{path.replace('/', '')}</b>
</p>
)}
{!category && filterCoursesAudience?.length === 0 && (
<p>
Não há cursos para a audiência <b>{path.replace('/', '')}</b>
</p>
)}
</div>
<div className="my-6">
{/* <div className="my-6">
<PaginationComponent pageIndex={0} totalCount={105} perPage={10} />
</div>
</div> */}
<Differences />
<SignUp />
<About.Root>
......
......@@ -6,8 +6,6 @@ import { BannerCategory } from '@/components/banner-category'
import { Card } from '@/components/card'
import { Differences } from '@/components/differences'
import { NavLinkCategory } from '@/components/nav-link-category'
import { PaginationComponent } from '@/components/pagination-component'
import SearchFilter from '@/components/search-filter'
import { SignUp } from '@/components/sign-up'
import { SkeletonSerachParams } from '@/components/skeleton-serach-params'
import { formatDate } from '@/utils/formatDate'
......@@ -20,86 +18,106 @@ export default function Students() {
const path = usePathname()
const searchParams = useSearchParams()
const category = searchParams.get('area')
console.log("🚀 ~ Students ~ category:", category)
const {
data: courses,
isLoading: coursesLoading,
isError: coursesIsError,
} = useQuery({
const { data: courses, isLoading: coursesLoading } = useQuery({
queryKey: ['courses'],
queryFn: getCourses,
})
const filterCoursesAudience = courses?.data.filter((item) =>
path.toLowerCase().includes(item?.audience?.name.toLowerCase() as string)
const filterCoursesAudience = courses?.data.filter((item) =>
path.toLowerCase().includes(item?.audience?.name.toLowerCase() as string),
)
console.log("🚀 ~ Students ~ filterCoursesAudience:", filterCoursesAudience)
const filterCoursesAudiencesAndArea = filterCoursesAudience?.filter((area) => category?.includes(area?.area?.name.toLowerCase() as string))
console.log("🚀 ~ Students ~ filterCoursesAudiencesAndArea:", filterCoursesAudiencesAndArea)
const filterCoursesAudiencesAndArea = filterCoursesAudience?.filter((area) =>
category?.includes(area?.area?.name.toLowerCase() as string),
)
if (coursesLoading) {
return <p>Carregando...</p>
}
return (
<main>
<Suspense fallback={<SkeletonSerachParams />}>
<BannerCategory />
<NavLinkCategory />
</Suspense>
<SearchFilter />
{/* <SearchFilter /> */}
<div className="grid rounded-none grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 grid-rows-3 lg:grid-rows-2 gap-4 md:gap-6 p-6">
{!category && filterCoursesAudience && filterCoursesAudience.map(course => (
<div className="flex justify-center" key={course.id}>
<Card.Root link={`/curso/${course.id}`}>
<Card.Image image={course.mobileBanner as string} width={273} height={365}>
<Card.Title title={course.name} />
</Card.Image>
<Card.Content description={`${course.workload} hrs / ${course.category?.name}`}>
<Card.Icon icon={Clock4} />
</Card.Content>
<Card.Content description={course.audience?.name as string}>
<Card.Icon icon={User} />
</Card.Content>
<Card.Content description={formatDate(course.startDate) as string}>
<Card.Icon icon={Calendar} />
</Card.Content>
</Card.Root>
</div>
))}
{!category &&
filterCoursesAudience &&
filterCoursesAudience.map((course) => (
<div className="flex justify-center" key={course.id}>
<Card.Root link={`/curso/${course.id}`}>
<Card.Image
image={course.mobileBanner as string}
width={273}
height={365}
>
<Card.Title title={course.name} />
</Card.Image>
<Card.Content
description={`${course.workload} hrs / ${course.category?.name}`}
>
<Card.Icon icon={Clock4} />
</Card.Content>
<Card.Content description={course.audience?.name as string}>
<Card.Icon icon={User} />
</Card.Content>
<Card.Content
description={formatDate(course.startDate) as string}
>
<Card.Icon icon={Calendar} />
</Card.Content>
</Card.Root>
</div>
))}
{category && filterCoursesAudiencesAndArea && filterCoursesAudiencesAndArea.map((course) => (
{category &&
filterCoursesAudiencesAndArea &&
filterCoursesAudiencesAndArea.map((course) => (
<div className="flex justify-center" key={course.id}>
<Card.Root link={`/curso/${course.id}`}>
<Card.Image image={course.mobileBanner as string} width={273} height={365}>
<Card.Image
image={course.mobileBanner as string}
width={273}
height={365}
>
<Card.Title title={course.name} />
</Card.Image>
<Card.Content description={`${course.workload} hrs / ${course.category?.name}`}>
<Card.Content
description={`${course.workload} hrs / ${course.category?.name}`}
>
<Card.Icon icon={Clock4} />
</Card.Content>
<Card.Content description={course.audience?.name as string}>
<Card.Icon icon={User} />
</Card.Content>
<Card.Content description={formatDate(course.startDate) as string}>
<Card.Content
description={formatDate(course.startDate) as string}
>
<Card.Icon icon={Calendar} />
</Card.Content>
</Card.Root>
</div>
))
}
))}
{category && filterCoursesAudiencesAndArea?.length === 0 && (
<p>Não há cursos para a área {category} com audiência {path}</p>
<p>
Não há cursos para a área <b>{category}</b> com audiência{' '}
<b>{path.replace('/', '')}</b>
</p>
)}
{!category && filterCoursesAudience?.length === 0 && (
<p>Não há cursos para a audiência {path}</p>
<p>
Não há cursos para a audiência <b>{path.replace('/', '')}</b>
</p>
)}
</div>
<div className="my-6">
{/* <div className="my-6">
<PaginationComponent pageIndex={0} totalCount={105} perPage={10} />
</div>
</div> */}
<Differences />
<SignUp />
<About.Root>
......
......@@ -31,8 +31,6 @@ export default function Login() {
const { message } = error.response?.data
toast.error(`${message}`)
}
console.log('🚀 ~ onSubmit ~ error aqui:', error)
}
}
......
'use client'
import { getCourses } from '@/api/courses'
import { About } from '@/components/about'
import { BannerCategory } from '@/components/banner-category'
import { Card } from '@/components/card'
import { Differences } from '@/components/differences'
import { NavLinkCategory } from '@/components/nav-link-category'
import { PaginationComponent } from '@/components/pagination-component'
import SearchFilter from '@/components/search-filter'
import { SignUp } from '@/components/sign-up'
import { SkeletonSerachParams } from '@/components/skeleton-serach-params'
import { CoursesCard } from '@/utils/courses-array'
import { formatDate } from '@/utils/formatDate'
import { useQuery } from '@tanstack/react-query'
import { Calendar, Clock4, User } from 'lucide-react'
import { usePathname, useSearchParams } from 'next/navigation'
import { Suspense } from 'react'
export default function Professionals() {
const path = usePathname()
const searchParams = useSearchParams()
const category = searchParams.get('area')
const { data: courses, isLoading: coursesLoading } = useQuery({
queryKey: ['courses'],
queryFn: getCourses,
})
const filterCoursesAudience = courses?.data.filter((item) =>
path.toLowerCase().includes(item?.audience?.name.toLowerCase() as string),
)
const filterCoursesAudiencesAndArea = filterCoursesAudience?.filter((area) =>
category?.includes(area?.area?.name.toLowerCase() as string),
)
if (coursesLoading) {
return <p>Carregando...</p>
}
return (
<main>
<Suspense fallback={<SkeletonSerachParams />}>
<BannerCategory />
<NavLinkCategory />
</Suspense>
<SearchFilter />
<div className="grid grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 grid-rows-3 lg:grid-rows-2 gap-4 md:gap-6 p-6">
{CoursesCard.map((course) => (
<div className="flex justify-center" key={course.id}>
<Card.Root link={`/curso/${course.id}`}>
<Card.Image image={course.image.src} width={273} height={365}>
<Card.Title title={course.title} />
</Card.Image>
<Card.Content description={course.hours}>
<Card.Icon icon={Clock4} />
</Card.Content>
<Card.Content description={course.category}>
<Card.Icon icon={User} />
</Card.Content>
<Card.Content description={course.calender}>
<Card.Icon icon={Calendar} />
</Card.Content>
</Card.Root>
</div>
))}
{/* <SearchFilter /> */}
<div className="grid rounded-none grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 grid-rows-3 lg:grid-rows-2 gap-4 md:gap-6 p-6">
{!category &&
filterCoursesAudience &&
filterCoursesAudience.map((course) => (
<div className="flex justify-center" key={course.id}>
<Card.Root link={`/curso/${course.id}`}>
<Card.Image
image={course.mobileBanner as string}
width={273}
height={365}
>
<Card.Title title={course.name} />
</Card.Image>
<Card.Content
description={`${course.workload} hrs / ${course.category?.name}`}
>
<Card.Icon icon={Clock4} />
</Card.Content>
<Card.Content description={course.audience?.name as string}>
<Card.Icon icon={User} />
</Card.Content>
<Card.Content
description={formatDate(course.startDate) as string}
>
<Card.Icon icon={Calendar} />
</Card.Content>
</Card.Root>
</div>
))}
{category &&
filterCoursesAudiencesAndArea &&
filterCoursesAudiencesAndArea.map((course) => (
<div className="flex justify-center" key={course.id}>
<Card.Root link={`/curso/${course.id}`}>
<Card.Image
image={course.mobileBanner as string}
width={273}
height={365}
>
<Card.Title title={course.name} />
</Card.Image>
<Card.Content
description={`${course.workload} hrs / ${course.category?.name}`}
>
<Card.Icon icon={Clock4} />
</Card.Content>
<Card.Content description={course.audience?.name as string}>
<Card.Icon icon={User} />
</Card.Content>
<Card.Content
description={formatDate(course.startDate) as string}
>
<Card.Icon icon={Calendar} />
</Card.Content>
</Card.Root>
</div>
))}
{category && filterCoursesAudiencesAndArea?.length === 0 && (
<p>
Não há cursos para a área <b>{category}</b> com audiência{' '}
<b>{path.replace('/', '')}</b>
</p>
)}
{!category && filterCoursesAudience?.length === 0 && (
<p>
Não há cursos para a audiência <b>{path.replace('/', '')}</b>
</p>
)}
</div>
<div className="my-6">
{/* <div className="my-6">
<PaginationComponent pageIndex={0} totalCount={105} perPage={10} />
</div>
</div> */}
<Differences />
<SignUp />
<About.Root>
......
......@@ -2,24 +2,69 @@
import { Button } from '@/components/ui/button'
import { Separator } from '@/components/ui/separator'
import { TextField } from '@mui/material'
import { zodResolver } from '@hookform/resolvers/zod'
import Image from 'next/image'
import { SubmitHandler, useForm } from 'react-hook-form'
import { useState } from 'react'
import { useForm } from 'react-hook-form'
import { toast } from 'sonner'
import { z } from 'zod'
import signUpImage from '../../public/images/sign-up.png'
import { StyledInputs } from './mui/styled-inputs'
import { InputMui } from './mui/inputs'
type FormSignUpTypes = {
name: string
fullname: string
email: string
whatsapp: string
interest: string
area: string
course: string
}
const schema = z
.object({
fullname: z.string().min(5, { message: 'Digite seu nome completo' }),
email: z.string().email({ message: 'E-mail inválido' }),
whatsapp: z
.string()
.min(10, { message: 'Digite seu whatsapp com o DDD' })
.max(13, { message: 'Digite apenas o número do seu whatsapp' }),
area: z.string().min(2, { message: 'Informe a área' }),
course: z.string().min(2, { message: 'Informe o curso' }),
})
.required()
export function SignUp() {
const { handleSubmit } = useForm<FormSignUpTypes>()
const {
register,
handleSubmit,
reset,
formState: { errors },
} = useForm<FormSignUpTypes>({
resolver: zodResolver(schema),
})
const [status, setStatus] = useState('')
const onSubmit: SubmitHandler<FormSignUpTypes> = (data) => console.log(data)
async function onSubmit(data: FormSignUpTypes) {
setStatus('Enviando...')
try {
const response = await fetch('/api/send-email', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
if (response.ok) {
toast.success('E-mail enviado com sucesso!')
setStatus('Inscrever')
reset()
} else {
toast.error('Falha ao enviar E-mail!')
setStatus('Inscrever')
}
} catch (error) {
setStatus('Inscrever')
}
}
return (
<section className="w-full bg-gradient-to-r from-green-700 to-green-50 pb-6 md:py-6 md:pb-0">
......@@ -39,42 +84,62 @@ export function SignUp() {
onSubmit={handleSubmit(onSubmit)}
className="w-full md:w-[600px] flex flex-col gap-8 order-4"
>
<TextField
label="Nome"
variant="standard"
<InputMui
type="text"
sx={StyledInputs({ color: '#fafafa' })}
/>
<TextField
label="Whatsapp"
variant="standard"
type="number"
sx={StyledInputs({ color: '#fafafa' })}
label="Nome completo"
name="fullname"
register={register}
/>
<TextField
label="Área de interesse"
{errors.fullname?.message && (
<p className="text-red-600">{errors.fullname?.message}</p>
)}
<InputMui
type="number"
variant="standard"
type="text"
sx={StyledInputs({ color: '#fafafa' })}
label="Whatsapp"
name="whatsapp"
register={register}
/>
<TextField
label="E-mail"
variant="standard"
{errors.whatsapp?.message && (
<p className="text-red-600">{errors.whatsapp?.message}</p>
)}
<InputMui
type="text"
sx={StyledInputs({ color: '#fafafa' })}
variant="standard"
label="Área de interesse"
name="area"
register={register}
/>
<TextField
label="Curso desejado"
{errors.area?.message && (
<p className="text-red-600">{errors.area?.message}</p>
)}
<InputMui
type="text"
variant="standard"
label="E-mail"
name="email"
register={register}
/>
{errors.email?.message && (
<p className="text-red-600">{errors.email?.message}</p>
)}
<InputMui
type="text"
sx={StyledInputs({ color: '#fafafa' })}
variant="standard"
label="Curso desejado"
name="course"
register={register}
/>
{errors.course?.message && (
<p className="text-red-600">{errors.course?.message}</p>
)}
<Button
type="submit"
variant="secondary"
className="uppercase max-w-32 mx-auto md:mb-6"
>
Inscrever
{status || 'Inscrever'}
</Button>
</form>
</div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment