Commit 89d68af0 authored by Wellton Quirino's avatar Wellton Quirino

Holiday Adjustments

parent 1a435420
import { api } from '@/lib/axios' import { api } from '@/lib/axios'
export type AudiencesNameProps = {
name: string
}
export type AudiencesProps = { export type AudiencesProps = {
id: string id?: string
name: string name: string
} }
export async function createAudiences({ export async function createAudiences({ name }: AudiencesProps) {
name, const audiences = await api.post<AudiencesProps>('/audiences', {
}: AudiencesNameProps) {
const audiences = await api.post<AudiencesNameProps>('/audiences', {
name, name,
}) })
return audiences return audiences
...@@ -27,8 +22,10 @@ export async function getAudienceId(id: string) { ...@@ -27,8 +22,10 @@ export async function getAudienceId(id: string) {
return audiences return audiences
} }
export async function editAudienceId(id: string) { export async function editAudienceId(data: AudiencesProps) {
const audiences = await api.put<AudiencesProps>(`/audiences/${id}`) const audiences = await api.put<AudiencesProps>(`/audiences/${data.id}`, {
name: data.name,
})
return audiences return audiences
} }
......
import { api } from '@/lib/axios' import { api } from '@/lib/axios'
export type CategoriesProps = { export type CategoriesProps = {
id: string id?: string
name: string name: string
} }
export async function createCategories({ name }: CategoriesProps) {
const categories = await api.post<CategoriesProps>('/categories', {
name,
})
return categories
}
export async function getCategories() { export async function getCategories() {
const categories = await api.get<CategoriesProps[]>('/categories') const categories = await api.get<CategoriesProps[]>('/categories')
return categories return categories
} }
export async function getCategoryId(id: string) {
const categories = await api.get<CategoriesProps>(`/categories/${id}`)
return categories
}
export async function editCategoryId(data: CategoriesProps) {
const categories = await api.put<CategoriesProps>(`/categories/${data.id}`, {
name: data.name,
})
return categories
}
export async function deleteCategory(id: string) {
const categories = await api.delete(`/categories/${id}`)
return categories
}
'use client'
import {
AudiencesProps,
deleteAudience,
editAudienceId,
getAudienceId,
} from '@/api/audiences'
import BreadcrumbComponent from '@/components/breadcrumb-component'
import { LoadingSpinIcon } from '@/components/loading-spin-icon'
import ModalDialog from '@/components/modal-dialog'
import { StyledInputs } from '@/components/mui/styled-inputs'
import { AlertDialog, AlertDialogTrigger } from '@/components/ui/alert-dialog'
import { Button } from '@/components/ui/button'
import { TextField } from '@mui/material'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { Trash } from 'lucide-react'
import { useParams, useRouter } from 'next/navigation'
import { useForm } from 'react-hook-form'
import { toast } from 'sonner'
export default function AudienceId() {
const params = useParams<{ id: string }>()
const {
register,
handleSubmit,
formState: { errors },
} = useForm<AudiencesProps>()
const router = useRouter()
const queryClient = useQueryClient()
const { data: audience, isLoading } = useQuery({
queryKey: ['audiences', params.id],
queryFn: () => getAudienceId(params.id),
enabled: !!params.id,
})
const mutationEditAudience = useMutation({
mutationFn: editAudienceId,
onSuccess: () => {
toast.success('Audiência auterada com sucesso!')
queryClient.invalidateQueries({ queryKey: ['audiences'] })
router.push('/admin')
},
})
const mutationDeleteAudience = useMutation({
mutationFn: deleteAudience,
onSuccess: () => {
toast.success('Audiência criada com sucesso!')
queryClient.invalidateQueries({ queryKey: ['audiences'] })
router.push('/admin')
},
})
function handleDeleteAudience() {
mutationDeleteAudience.mutate(params.id)
}
async function onSubmit(data: AudiencesProps) {
console.log('🚀 ~ onSubmit ~ data:', data)
const body = {
id: params.id,
name: data.name,
}
mutationEditAudience.mutateAsync(body)
}
if (isLoading) {
return (
<div className="flex w-full h-[500px] items-center justify-center">
<LoadingSpinIcon />
<span>Loading...</span>
</div>
)
}
return (
<section className="container py-10">
<BreadcrumbComponent page="Audiência" />
<form onSubmit={handleSubmit(onSubmit)}>
<div className="flex items-center gap-6">
<h1 className="text-3xl font-bold">Editar Audiência</h1>
<Button
variant="secondary"
type="submit"
className="uppercase rounded-sm"
disabled={isLoading}
>
{mutationEditAudience.isPending && <LoadingSpinIcon />}
Salvar e publicar
</Button>
<AlertDialog>
<>
<AlertDialogTrigger
className="uppercase flex items-center gap-2 text-orange-100 border-none hover:bg-orange-100/10 hover:text-orange-100 h-10 px-5 rounded-sm"
type="button"
>
<span>Apagar audiência</span>
<Trash />
</AlertDialogTrigger>
<ModalDialog
title="Tem certeza que deseja deletar a audiência?"
description={`Ao clicar em continue você irá deletar a audiência ${audience?.data.name}`}
handleClick={handleDeleteAudience}
/>
</>
</AlertDialog>
</div>
<div className="w-full mt-16">
<TextField
label="Nome da audiência"
type="text"
defaultValue={audience?.data.name}
{...register('name')}
variant="standard"
className="flex"
sx={StyledInputs(
errors.name ? { color: '#dc2626' } : { color: '#26AAA7' },
)}
/>
</div>
</form>
</section>
)
}
'use client'
import { AudiencesProps, createAudiences } from '@/api/audiences'
import BreadcrumbComponent from '@/components/breadcrumb-component'
import { LoadingSpinIcon } from '@/components/loading-spin-icon'
import { StyledInputs } from '@/components/mui/styled-inputs'
import { Button } from '@/components/ui/button'
import { zodResolver } from '@hookform/resolvers/zod'
import { TextField } from '@mui/material'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useRouter } from 'next/navigation'
import { useForm } from 'react-hook-form'
import { toast } from 'sonner'
import { z } from 'zod'
const FormSchema = z.object({
name: z.string().trim().min(3, { message: 'Nome obrigatório' }),
})
export default function Audience() {
const {
register,
handleSubmit,
formState: { errors },
} = useForm<AudiencesProps>({
resolver: zodResolver(FormSchema),
})
const router = useRouter()
const queryClient = useQueryClient()
const mutation = useMutation({
mutationFn: createAudiences,
onSuccess: () => {
toast.success('Audiência criada com sucesso!')
queryClient.invalidateQueries({ queryKey: ['audiences'] })
router.push('/admin')
},
})
async function onSubmit(data: AudiencesProps) {
mutation.mutateAsync(data)
}
return (
<section className="container py-10">
<BreadcrumbComponent page="Audiência" />
<form onSubmit={handleSubmit(onSubmit)}>
<div className="flex items-center gap-6">
<h1 className="text-3xl font-bold">Criar Audiência</h1>
<Button variant="secondary" className="uppercase rounded-sm">
{mutation.isPending && <LoadingSpinIcon />}
Salvar e publicar
</Button>
</div>
<div className="w-full mt-16">
<TextField
label="Nome da audiência"
variant="standard"
type="text"
className="flex"
{...register('name')}
sx={StyledInputs(
errors.name ? { color: '#dc2626' } : { color: '#26AAA7' },
)}
/>
</div>
</form>
</section>
)
}
'use client'
import {
CategoriesProps,
deleteCategory,
editCategoryId,
getCategoryId,
} from '@/api/categories'
import BreadcrumbComponent from '@/components/breadcrumb-component'
import { LoadingSpinIcon } from '@/components/loading-spin-icon'
import ModalDialog from '@/components/modal-dialog'
import { StyledInputs } from '@/components/mui/styled-inputs'
import { AlertDialog, AlertDialogTrigger } from '@/components/ui/alert-dialog'
import { Button } from '@/components/ui/button'
import { TextField } from '@mui/material'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { Trash } from 'lucide-react'
import { useParams, useRouter } from 'next/navigation'
import { useForm } from 'react-hook-form'
import { toast } from 'sonner'
export default function AudienceId() {
const params = useParams<{ id: string }>()
const {
register,
handleSubmit,
formState: { errors },
} = useForm<CategoriesProps>()
const router = useRouter()
const queryClient = useQueryClient()
const { data: categorie, isLoading } = useQuery({
queryKey: ['categories', params.id],
queryFn: () => getCategoryId(params.id),
enabled: !!params.id,
})
const mutationEditAudience = useMutation({
mutationFn: editCategoryId,
onSuccess: () => {
toast.success('Categoria auterada com sucesso!')
queryClient.invalidateQueries({ queryKey: ['categories'] })
router.push('/admin')
},
})
const mutationDeleteAudience = useMutation({
mutationFn: deleteCategory,
onSuccess: () => {
toast.success('Categoria criada com sucesso!')
queryClient.invalidateQueries({ queryKey: ['categories'] })
router.push('/admin')
},
})
function handleDeleteAudience() {
mutationDeleteAudience.mutate(params.id)
}
async function onSubmit(data: CategoriesProps) {
const body = {
id: params.id,
name: data.name,
}
mutationEditAudience.mutateAsync(body)
}
if (isLoading) {
return (
<div className="flex w-full h-[500px] items-center justify-center">
<LoadingSpinIcon />
<span>Loading...</span>
</div>
)
}
return (
<section className="container py-10">
<BreadcrumbComponent page="Categoria" />
<form onSubmit={handleSubmit(onSubmit)}>
<div className="flex items-center gap-6">
<h1 className="text-3xl font-bold">Editar Categoria</h1>
<Button
variant="secondary"
type="submit"
className="uppercase rounded-sm"
disabled={isLoading}
>
{mutationEditAudience.isPending && <LoadingSpinIcon />}
Salvar e publicar
</Button>
<AlertDialog>
<>
<AlertDialogTrigger
className="uppercase flex items-center gap-2 text-orange-100 border-none hover:bg-orange-100/10 hover:text-orange-100 h-10 px-5 rounded-sm"
type="button"
>
<span>Apagar categoria</span>
<Trash />
</AlertDialogTrigger>
<ModalDialog
title="Tem certeza que deseja deletar a categoria?"
description={`Ao clicar em continue você irá deletar a categoria ${categorie?.data.name}`}
handleClick={handleDeleteAudience}
/>
</>
</AlertDialog>
</div>
<div className="w-full mt-16">
<TextField
label="Nome da categoria"
type="text"
defaultValue={categorie?.data.name}
{...register('name')}
variant="standard"
className="flex"
sx={StyledInputs(
errors.name ? { color: '#dc2626' } : { color: '#26AAA7' },
)}
/>
</div>
</form>
</section>
)
}
'use client'
import { CategoriesProps, createCategories } from '@/api/categories'
import BreadcrumbComponent from '@/components/breadcrumb-component'
import { LoadingSpinIcon } from '@/components/loading-spin-icon'
import { StyledInputs } from '@/components/mui/styled-inputs'
import { Button } from '@/components/ui/button'
import { zodResolver } from '@hookform/resolvers/zod'
import { TextField } from '@mui/material'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useRouter } from 'next/navigation'
import { useForm } from 'react-hook-form'
import { toast } from 'sonner'
import { z } from 'zod'
const FormSchema = z.object({
name: z.string().trim().min(3, { message: 'Nome obrigatório' }),
})
export default function Category() {
const {
register,
handleSubmit,
formState: { errors },
} = useForm<CategoriesProps>({
resolver: zodResolver(FormSchema),
})
const router = useRouter()
const queryClient = useQueryClient()
const mutation = useMutation({
mutationFn: createCategories,
onSuccess: () => {
toast.success('Categoria criada com sucesso!')
queryClient.invalidateQueries({ queryKey: ['categories'] })
router.push('/admin')
},
})
async function onSubmit(data: CategoriesProps) {
mutation.mutateAsync(data)
}
return (
<section className="container py-10">
<BreadcrumbComponent page="Categoria" />
<form onSubmit={handleSubmit(onSubmit)}>
<div className="flex items-center gap-6">
<h1 className="text-3xl font-bold">Criar Categoria</h1>
<Button variant="secondary" className="uppercase rounded-sm">
{mutation.isPending && <LoadingSpinIcon />}
Salvar e publicar
</Button>
</div>
<div className="w-full mt-16">
<TextField
label="Nome da categoria"
variant="standard"
type="text"
className="flex"
{...register('name')}
sx={StyledInputs(
errors.name ? { color: '#dc2626' } : { color: '#26AAA7' },
)}
/>
</div>
</form>
</section>
)
}
'use client' 'use client'
import { getAreas } from '@/api/areas' import { getAreas } from '@/api/areas'
import { createAudiences, deleteAudience, editAudienceId, getAudiences } from '@/api/audiences' import { getAudiences } from '@/api/audiences'
import { getCategories } from '@/api/categories'
import { getCourses } from '@/api/courses' import { getCourses } from '@/api/courses'
import { Card } from '@/components/card' import { Card } from '@/components/card'
import ModalInputs from '@/components/modal-inputs'
import { InputMui } from '@/components/mui/inputs' import { InputMui } from '@/components/mui/inputs'
import { AlertDialog, AlertDialogTrigger } from '@/components/ui/alert-dialog'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { AuthContext } from '@/contexts/auth-context' import { AuthContext } from '@/contexts/auth-context'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import { useQuery } from '@tanstack/react-query'
import { Pencil, Search } from 'lucide-react' import { Pencil, Search } from 'lucide-react'
import Link from 'next/link' import Link from 'next/link'
import { useContext, useState } from 'react' import { useContext } from 'react'
import { useForm } from 'react-hook-form' import { useForm } from 'react-hook-form'
import { toast } from 'sonner'
export default function Admin() { export default function Admin() {
const [open, setOpen] = useState<boolean>(false);
const [nameAudience, setNameAudience] = useState('')
const { register } = useForm() const { register } = useForm()
const { user } = useContext(AuthContext) const { user } = useContext(AuthContext)
const queryClient = useQueryClient()
const { const {
data: areas, data: areas,
...@@ -30,6 +26,11 @@ export default function Admin() { ...@@ -30,6 +26,11 @@ export default function Admin() {
isError, isError,
} = useQuery({ queryKey: ['areas'], queryFn: getAreas }) } = useQuery({ queryKey: ['areas'], queryFn: getAreas })
const { data: categories } = useQuery({
queryKey: ['categories'],
queryFn: getCategories,
})
const { data: audiences } = useQuery({ const { data: audiences } = useQuery({
queryKey: ['audiences'], queryKey: ['audiences'],
queryFn: getAudiences, queryFn: getAudiences,
...@@ -40,48 +41,6 @@ export default function Admin() { ...@@ -40,48 +41,6 @@ export default function Admin() {
queryFn: getCourses, queryFn: getCourses,
}) })
const mutationCreateAudience = useMutation({
mutationFn: createAudiences,
onSuccess: () => {
toast.success('Audiência criada com sucesso!')
queryClient.invalidateQueries({ queryKey: ['audiences'] })
},
})
const mutationEditAudience = useMutation({
mutationFn: editAudienceId,
onSuccess: () => {
toast.success('Audiência criada com sucesso!')
queryClient.invalidateQueries({ queryKey: ['audiences'] })
},
})
const mutationDeleteAudience = useMutation({
mutationFn: deleteAudience,
onSuccess: () => {
toast.success('Audiência criada com sucesso!')
queryClient.invalidateQueries({ queryKey: ['audiences'] })
},
})
function handleCreateAudience() {
const body = {
name: nameAudience
}
mutationCreateAudience.mutate(body)
setOpen(false)
}
function handleEditAudience(id: string) {
mutationEditAudience.mutate(id)
setOpen(false)
}
function handleDeleteAudience(id: string) {
mutationDeleteAudience.mutate(id)
setOpen(false)
}
if (isLoading) { if (isLoading) {
return <span>Loading...</span> return <span>Loading...</span>
} }
...@@ -119,73 +78,47 @@ export default function Admin() { ...@@ -119,73 +78,47 @@ export default function Admin() {
<h2 className="text-purple-50 text-2xl mt-10">Audiência</h2> <h2 className="text-purple-50 text-2xl mt-10">Audiência</h2>
<AlertDialog open={open} onOpenChange={setOpen}> <Button className="uppercase mt-6" asChild>
<> <Link href="admin/audience">+ Adicionar novo</Link>
<AlertDialogTrigger
className="flex justify-between w-full"
type="button"
>
<Button className="uppercase mt-6">
+ Adicionar novo
</Button> </Button>
</AlertDialogTrigger>
<ModalInputs
title="Criar"
description="Criar nova audiência"
handleClick={handleCreateAudience}
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setNameAudience(e.target.value)
}
/>
</>
</AlertDialog>
<AlertDialog open={open} onOpenChange={setOpen}> <nav className="my-6">
<nav className="my-6 w-full">
<ul className="space-y-4"> <ul className="space-y-4">
{audiences?.data.map((audience) => ( {audiences?.data.map((audience) => (
<li <li key={audience.id} className="border-b border-green-400">
key={audience.id} <Link
className="border-b border-green-400 py-2 hover:bg-green-400/10" href={`/admin/audience/${audience.id}`}
> className="flex justify-between py-2 hover:bg-green-400/10"
<AlertDialogTrigger
className="flex justify-between w-full"
type="button"
> >
{audience.name} <span>{audience.name}</span>
<Pencil className="text-green-400" /> <Pencil className="text-green-400" />
</AlertDialogTrigger> </Link>
<ModalInputs
title="Editar"
description="Editar nome da audiência"
handleClick={() => handleEditAudience(audience.id)}
value={nameAudience}
handleClickDelete={() => handleDeleteAudience(audience.id)}
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setNameAudience(e.target.value)
}
/>
</li> </li>
))} ))}
</ul> </ul>
</nav> </nav>
</AlertDialog>
{/* <h2 className="text-purple-50 text-2xl mt-10">Banners</h2> <h2 className="text-purple-50 text-2xl mt-10">Categoria</h2>
<Button className="uppercase mt-6" asChild>
<Link href="admin/category">+ Adicionar novo</Link>
</Button>
<nav className="my-6"> <nav className="my-6">
<ul className="space-y-4"> <ul className="space-y-4">
{banners.map((banner) => ( {categories?.data.map((category) => (
<li <li key={category.id} className="border-b border-green-400">
key={banner.title} <Link
className="flex justify-between border-b border-green-400 py-2" href={`/admin/category/${category.id}`}
className="flex justify-between py-2 hover:bg-green-400/10"
> >
<Link href="#">{banner.title}</Link> <span>{category.name}</span>
<Pencil className="text-green-400" /> <Pencil className="text-green-400" />
</Link>
</li> </li>
))} ))}
</ul> </ul>
</nav> */} </nav>
</aside> </aside>
<div className="flex-1 ml-4 pl-6 border-l border-gray-50"> <div className="flex-1 ml-4 pl-6 border-l border-gray-50">
...@@ -217,7 +150,7 @@ export default function Admin() { ...@@ -217,7 +150,7 @@ export default function Admin() {
> >
<div className="border border-gray-100 pb-4 rounded-lg overflow-hidden"> <div className="border border-gray-100 pb-4 rounded-lg overflow-hidden">
<Card.Image <Card.Image
image={course.desktopBanner || ''} image={course.mobileBanner || ''}
width={240} width={240}
height={320} height={320}
> >
......
...@@ -3,10 +3,10 @@ ...@@ -3,10 +3,10 @@
import { InputMui } from '@/components/mui/inputs' import { InputMui } from '@/components/mui/inputs'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { AuthContext } from '@/contexts/auth-context' import { AuthContext } from '@/contexts/auth-context'
import { AxiosError } from 'axios'
import Image from 'next/image' import Image from 'next/image'
import Link from 'next/link' import Link from 'next/link'
// import { useRouter } from 'next/router' import { useRouter } from 'next/navigation'
import { AxiosError } from 'axios'
import { useContext } from 'react' import { useContext } from 'react'
import { useForm } from 'react-hook-form' import { useForm } from 'react-hook-form'
import { toast } from 'sonner' import { toast } from 'sonner'
...@@ -20,12 +20,12 @@ type FormLogin = { ...@@ -20,12 +20,12 @@ type FormLogin = {
export default function Login() { export default function Login() {
const { handleSubmit, register } = useForm<FormLogin>() const { handleSubmit, register } = useForm<FormLogin>()
const { signIn } = useContext(AuthContext) const { signIn } = useContext(AuthContext)
// const router = useRouter() const router = useRouter()
const onSubmit = async (data: FormLogin) => { const onSubmit = async (data: FormLogin) => {
try { try {
await signIn(data) await signIn(data)
// router.push('/admin') router.push('/admin')
} catch (error) { } catch (error) {
if (error instanceof AxiosError) { if (error instanceof AxiosError) {
const { message } = error.response?.data const { message } = error.response?.data
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
import Link, { LinkProps } from 'next/link' import Link, { LinkProps } from 'next/link'
import { useSearchParams } from 'next/navigation' import { usePathname, useSearchParams } from 'next/navigation'
import { Button } from './ui/button' import { Button } from './ui/button'
interface NavLinkProps extends LinkProps { interface NavLinkProps extends LinkProps {
...@@ -23,16 +23,25 @@ interface NavLinkProps extends LinkProps { ...@@ -23,16 +23,25 @@ interface NavLinkProps extends LinkProps {
export function NavLinkSearchParams(props: NavLinkProps) { export function NavLinkSearchParams(props: NavLinkProps) {
const searchParams = useSearchParams() const searchParams = useSearchParams()
const category = searchParams.get('area') const pathname = usePathname()
const path = pathname
const area = searchParams.get('area')
return ( return (
<Button <Button
data-current={category === props.href} data-current={area === props.href}
className={`data-[current=true]:font-semibold rounded-2xl ${props.className}`} className={`data-[current=true]:font-semibold rounded-2xl ${props.className}`}
variant={category === props.href ? 'third' : props.variant} variant={area === props.href ? 'third' : props.variant}
asChild asChild
> >
<Link href={{ query: { area: props.href as string } }}> <Link
href={{
pathname: `${path === '/' ? '/estudantes' : path}`,
query: { area: props.href as string },
}}
>
{props.children} {props.children}
</Link> </Link>
</Button> </Button>
......
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