Commit 1e2e278b authored by Wellton Quirino's avatar Wellton Quirino

feat: improving pages admin routes

parent 4f7e1d0b
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
"@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-label": "^2.1.0", "@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-popover": "^1.1.1", "@radix-ui/react-popover": "^1.1.1",
"@radix-ui/react-radio-group": "^1.2.1",
"@radix-ui/react-select": "^2.1.1", "@radix-ui/react-select": "^2.1.1",
"@radix-ui/react-separator": "^1.1.0", "@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-slot": "^1.1.0",
...@@ -1804,6 +1805,81 @@ ...@@ -1804,6 +1805,81 @@
} }
} }
}, },
"node_modules/@radix-ui/react-radio-group": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.2.1.tgz",
"integrity": "sha512-kdbv54g4vfRjja9DNWPMxKvXblzqbpEC8kspEkZ6dVP7kQksGCn+iZHkcCz2nb00+lPdRvxrqy4WrvvV1cNqrQ==",
"dependencies": {
"@radix-ui/primitive": "1.1.0",
"@radix-ui/react-compose-refs": "1.1.0",
"@radix-ui/react-context": "1.1.1",
"@radix-ui/react-direction": "1.1.0",
"@radix-ui/react-presence": "1.1.1",
"@radix-ui/react-primitive": "2.0.0",
"@radix-ui/react-roving-focus": "1.1.0",
"@radix-ui/react-use-controllable-state": "1.1.0",
"@radix-ui/react-use-previous": "1.1.0",
"@radix-ui/react-use-size": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-roving-focus": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz",
"integrity": "sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA==",
"dependencies": {
"@radix-ui/primitive": "1.1.0",
"@radix-ui/react-collection": "1.1.0",
"@radix-ui/react-compose-refs": "1.1.0",
"@radix-ui/react-context": "1.1.0",
"@radix-ui/react-direction": "1.1.0",
"@radix-ui/react-id": "1.1.0",
"@radix-ui/react-primitive": "2.0.0",
"@radix-ui/react-use-callback-ref": "1.1.0",
"@radix-ui/react-use-controllable-state": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-context": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz",
"integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-select": { "node_modules/@radix-ui/react-select": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.1.1.tgz", "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.1.1.tgz",
......
import { api } from '@/lib/axios'
export type CategoriesProps = {
id: string
name: string
}
export async function getCategories() {
const categories = await api.get<CategoriesProps[]>('/categories')
return categories
}
...@@ -29,7 +29,8 @@ export default function Home() { ...@@ -29,7 +29,8 @@ export default function Home() {
label="O que você quer aprender hoje?" label="O que você quer aprender hoje?"
variant="standard" variant="standard"
type="text" type="text"
className="w-full #fafafa" className="w-full"
themeColor="#fafafa"
/> />
<Search size={24} /> <Search size={24} />
</div> </div>
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
import { AreasProps, deleteArea, editArea, getAreasId } from '@/api/areas' import { AreasProps, deleteArea, editArea, getAreasId } from '@/api/areas'
import BreadcrumbComponent from '@/components/breadcrumb-component' import BreadcrumbComponent from '@/components/breadcrumb-component'
import InputFile from '@/components/input-file' import InputFile from '@/components/input-file'
import { LoadingSpinIcon } from '@/components/loading-spin-icon'
import ModalDialog from '@/components/modal-dialog' import ModalDialog from '@/components/modal-dialog'
import { AlertDialog, AlertDialogTrigger } from '@/components/ui/alert-dialog' import { AlertDialog, AlertDialogTrigger } from '@/components/ui/alert-dialog'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
...@@ -24,8 +25,8 @@ export default function AreaId() { ...@@ -24,8 +25,8 @@ export default function AreaId() {
const queryClient = useQueryClient() const queryClient = useQueryClient()
const { data: area, isLoading, isPending } = useQuery({ const { data: area, isLoading } = useQuery({
queryKey: ['area'], queryKey: ['area', params.id],
queryFn: () => getAreasId(params.id), queryFn: () => getAreasId(params.id),
enabled: !!params.id, enabled: !!params.id,
}) })
...@@ -60,14 +61,13 @@ export default function AreaId() { ...@@ -60,14 +61,13 @@ export default function AreaId() {
mutationDelete.mutate(params.id) mutationDelete.mutate(params.id)
} }
if (isLoading) {
if(isLoading) { return (
console.log('isloading') <div className="flex w-full h-[500px] items-center justify-center">
return <span>isLoading TEST...</span> <LoadingSpinIcon />
} <span>Loading...</span>
if(isPending) { </div>
console.log('isPeding') )
return <span>isPending TEST...</span>
} }
return ( return (
...@@ -76,7 +76,13 @@ export default function AreaId() { ...@@ -76,7 +76,13 @@ export default function AreaId() {
<form onSubmit={handleSubmit(onSubmit)}> <form onSubmit={handleSubmit(onSubmit)}>
<div className="flex items-center gap-6"> <div className="flex items-center gap-6">
<h1 className="text-3xl font-bold">Editar Área</h1> <h1 className="text-3xl font-bold">Editar Área</h1>
<Button variant="secondary" type='submit' className="uppercase rounded-sm"> <Button
variant="secondary"
type="submit"
className="uppercase rounded-sm"
disabled={isLoading}
>
{mutationEdit.isPending && <LoadingSpinIcon />}
Salvar e publicar Salvar e publicar
</Button> </Button>
<AlertDialog> <AlertDialog>
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
import { AreasProps, createAreas } from '@/api/areas' import { AreasProps, createAreas } from '@/api/areas'
import InputFile from '@/components/input-file' import InputFile from '@/components/input-file'
import { LoadingSpinIcon } from '@/components/loading-spin-icon'
import { StyledInputs } from '@/components/mui/styled-inputs' import { StyledInputs } from '@/components/mui/styled-inputs'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { TextField } from '@mui/material' import { TextField } from '@mui/material'
...@@ -39,6 +40,7 @@ export default function Area() { ...@@ -39,6 +40,7 @@ export default function Area() {
<div className="flex items-center gap-6"> <div className="flex items-center gap-6">
<h1 className="text-3xl font-bold">Criar Área</h1> <h1 className="text-3xl font-bold">Criar Área</h1>
<Button variant="secondary" className="uppercase rounded-sm"> <Button variant="secondary" className="uppercase rounded-sm">
{mutation.isPending && <LoadingSpinIcon />}
Salvar e publicar Salvar e publicar
</Button> </Button>
</div> </div>
......
...@@ -29,7 +29,7 @@ export default function EditCourse() { ...@@ -29,7 +29,7 @@ export default function EditCourse() {
<section className="container py-10"> <section className="container py-10">
<form> <form>
<div className="flex items-center gap-6"> <div className="flex items-center gap-6">
<h1 className="text-green-700 text-3xl font-bold">Editar curso</h1> <h1 className="text-3xl font-bold">Editar curso</h1>
{/* <Button variant="third" className="uppercase"> {/* <Button variant="third" className="uppercase">
Salvar como rascunho Salvar como rascunho
</Button> */} </Button> */}
...@@ -50,9 +50,20 @@ export default function EditCourse() { ...@@ -50,9 +50,20 @@ export default function EditCourse() {
Informações sobre o curso Informações sobre o curso
</h6> </h6>
<InputMui label="Nome do curso" variant="standard" type="text" /> <InputMui
label="Nome do curso"
variant="standard"
type="text"
themeColor="#26AAA7"
/>
<InputMui type="text" variant="standard" label="Área" select> <InputMui
type="text"
variant="standard"
label="Área"
select
themeColor="#26AAA7"
>
{options.map((option) => ( {options.map((option) => (
<MenuItem key={option.value} value={option.value}> <MenuItem key={option.value} value={option.value}>
{option.label} {option.label}
...@@ -66,12 +77,14 @@ export default function EditCourse() { ...@@ -66,12 +77,14 @@ export default function EditCourse() {
type="text" type="text"
multiline multiline
rows={4} rows={4}
themeColor="#26AAA7"
/> />
<InputMui <InputMui
label="Nome dos(as) Professores(as):" label="Nome dos(as) Professores(as):"
variant="standard" variant="standard"
type="text" type="text"
themeColor="#26AAA7"
/> />
<div className="flex justify-between flex-wrap gap-6"> <div className="flex justify-between flex-wrap gap-6">
...@@ -119,7 +132,7 @@ export default function EditCourse() { ...@@ -119,7 +132,7 @@ export default function EditCourse() {
<Button <Button
variant={'ghost'} variant={'ghost'}
className={cn( className={cn(
'lg:w-[450px] justify-start text-left font-normal border-b rounded-none pl-0', 'lg:w-[450px] justify-start text-left font-normal border-b rounded-none pl-0 border-green-400',
!date && 'text-muted-foreground', !date && 'text-muted-foreground',
)} )}
> >
...@@ -159,7 +172,7 @@ export default function EditCourse() { ...@@ -159,7 +172,7 @@ export default function EditCourse() {
<Button <Button
variant={'ghost'} variant={'ghost'}
className={cn( className={cn(
'lg:w-[450px] justify-start text-left font-normal border-b rounded-none pl-0', 'lg:w-[450px] justify-start text-left font-normal border-b rounded-none pl-0 border-green-400',
!date && 'text-muted-foreground', !date && 'text-muted-foreground',
)} )}
> >
...@@ -189,7 +202,12 @@ export default function EditCourse() { ...@@ -189,7 +202,12 @@ export default function EditCourse() {
<h6 className="text-xl text-purple-100 mb-4">Módulos</h6> <h6 className="text-xl text-purple-100 mb-4">Módulos</h6>
<div className="flex flex-col p-4 gap-6 border border-gray-100"> <div className="flex flex-col p-4 gap-6 border border-gray-100">
<InputMui label="Título" variant="standard" type="text" /> <InputMui
label="Título"
variant="standard"
type="text"
themeColor="#26AAA7"
/>
<InputMui <InputMui
label="Descrição" label="Descrição"
...@@ -197,6 +215,7 @@ export default function EditCourse() { ...@@ -197,6 +215,7 @@ export default function EditCourse() {
type="text" type="text"
multiline multiline
rows={4} rows={4}
themeColor="#26AAA7"
/> />
</div> </div>
...@@ -207,6 +226,7 @@ export default function EditCourse() { ...@@ -207,6 +226,7 @@ export default function EditCourse() {
<PlusIcon size={20} /> <span>Adicionar Módulo</span> <PlusIcon size={20} /> <span>Adicionar Módulo</span>
</Button> </Button>
</div> </div>
<div className="w-[380px] pl-6 flex flex-col gap-4"> <div className="w-[380px] pl-6 flex flex-col gap-4">
<h6 className="text-xl text-purple-100 mb-4"> <h6 className="text-xl text-purple-100 mb-4">
Qual o público alvo? Qual o público alvo?
......
'use client' 'use client'
import { InputMui } from '@/components/mui/inputs' import { getAreas } from '@/api/areas'
import { getAudiences } from '@/api/audiences'
import { getCategories } from '@/api/categories'
import InputFile from '@/components/input-file'
import { LoadingSpinIcon } from '@/components/loading-spin-icon'
import { StyledInputs } from '@/components/mui/styled-inputs'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { Calendar } from '@/components/ui/calendar' import { Calendar } from '@/components/ui/calendar'
import { Checkbox } from '@/components/ui/checkbox' import { Checkbox } from '@/components/ui/checkbox'
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
} from '@/components/ui/form'
import { Label } from '@/components/ui/label' import { Label } from '@/components/ui/label'
import { import {
Popover, Popover,
PopoverContent, PopoverContent,
PopoverTrigger, PopoverTrigger,
} from '@/components/ui/popover' } from '@/components/ui/popover'
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'
import { Separator } from '@/components/ui/separator' import { Separator } from '@/components/ui/separator'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
import { MenuItem } from '@mui/material' import { Box, Chip, MenuItem, TextField } from '@mui/material'
import { useQuery } from '@tanstack/react-query'
import { format } from 'date-fns' import { format } from 'date-fns'
import { CalendarIcon, PlusIcon, Trash } from 'lucide-react' import { CalendarIcon, PlusIcon } from 'lucide-react'
import { useState } from 'react' import { useState } from 'react'
import { Controller, useForm } from 'react-hook-form'
import { z } from 'zod'
// type CoursesProps = {
// name: string
// description: string
// desktopBanner: string
// mobileBanner: string
// duration: number
// startDate: Date
// endDate: Date
// professors: string[]
// workload: number
// areaId: string
// audienceId: string
// categoryId: string
// moduleIds: string[]
// }
const options = [ const FormSchema = z.object({
{ label: 'The Godfather', value: 1 }, name: z.string(),
{ label: 'Pulp Fiction', value: 2 }, description: z.string(),
] desktopBanner: z.string(),
mobileBanner: z.string(),
duration: z.number(),
startDate: z.date().optional(),
endDate: z.date().optional(),
professors: z.array(z.string()),
workload: z.number(),
areaId: z.string(),
audienceId: z.string(),
categoryId: z.string(),
moduleIds: z.array(z.string()),
})
export default function Curso() { export default function Curso() {
const [date, setDate] = useState<Date>() const [checkedStart, setCheckedStart] = useState<boolean>(false)
const [checkedEnd, setCheckedEnd] = useState<boolean>(false)
const [dateStart, setDateStart] = useState<Date>()
const [dateEnd, setDateEnd] = useState<Date>()
const [inputValue, setInputValue] = useState<string>('')
// const { form.register, watch, handleSubmit, control } = useForm<CoursesProps>()
const form = useForm<z.infer<typeof FormSchema>>({
// resolver: zodResolver(FormSchema),
defaultValues: {
areaId: '',
professors: [],
},
})
const values = form.watch()
const valueDesktopBanner = values?.desktopBanner?.['0']
const valueMobileBanner = values?.mobileBanner?.['0']
const { data: areas } = useQuery({
queryKey: ['areas'],
queryFn: getAreas,
})
const { data: audiences, isLoading: audiencesLoading } = useQuery({
queryKey: ['audiences'],
queryFn: getAudiences,
})
const { data: categories, isLoading: categoriesLoading } = useQuery({
queryKey: ['categories'],
queryFn: getCategories,
})
function onSubmit(data: z.infer<typeof FormSchema>) {
const body = {
...data,
startDate: dateStart?.toLocaleDateString() || '',
endDate: dateEnd?.toLocaleDateString() || '',
}
console.log(body)
}
function onCheckedStart(checkedStart: boolean) {
setCheckedStart(checkedStart)
}
function onCheckedEnd(checkedEnd: boolean) {
setCheckedEnd(checkedEnd)
}
const handleKeyDown = (event: React.KeyboardEvent) => {
if (event.key === 'Enter' && inputValue.trim()) {
event.preventDefault()
form.setValue('professors', [...values.professors, inputValue.trim()])
setInputValue('')
}
}
const handleDelete = (professorToDelete: string) => {
form.setValue(
'professors',
values.professors.filter((str) => str !== professorToDelete),
)
}
return ( return (
<section className="container py-10"> <section className="container py-10">
<form> <Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)}>
<div className="flex items-center gap-6"> <div className="flex items-center gap-6">
<h1 className="text-green-700 text-3xl font-bold">Criar curso</h1> <h1 className="text-3xl font-bold">Criar curso</h1>
{/* <Button variant="third" className="uppercase"> <Button type="submit" variant="secondary" className="uppercase">
Salvar como rascunho
</Button> */}
<Button variant="secondary" className="uppercase">
Salvar e publicar Salvar e publicar
</Button> </Button>
<Button
variant="ghost"
className="uppercase flex items-center gap-2 text-orange-100 hover:text-orange-100"
>
<span>Apagar curso</span>
<Trash />
</Button>
</div> </div>
<div className="flex w-full mt-10"> <div className="flex w-full mt-10">
<div className="flex-1 flex flex-col border-r border-gray-50 pr-6 space-y-4"> <div className="flex-1 flex flex-col border-r border-gray-50 pr-6 space-y-4">
...@@ -50,52 +148,109 @@ export default function Curso() { ...@@ -50,52 +148,109 @@ export default function Curso() {
Informações sobre o curso Informações sobre o curso
</h6> </h6>
<InputMui label="Nome do curso" variant="standard" type="text" /> <TextField
label="Nome do curso"
variant="standard"
type="text"
{...form.register('name')}
sx={StyledInputs({ color: '#26AAA7' })}
/>
<InputMui type="text" variant="standard" label="Área" select> <TextField
{options.map((option) => ( type="text"
<MenuItem key={option.value} value={option.value}> variant="standard"
{option.label} label="Área"
select
sx={StyledInputs({ color: '#26AAA7' })}
defaultValue={''}
{...form.register('areaId')}
>
<MenuItem value="" className="hidden">
Selecione a área
</MenuItem>
{areas?.data.map((option) => (
<MenuItem key={option.id} value={option.id}>
{option.name}
</MenuItem> </MenuItem>
))} ))}
</InputMui> </TextField>
<InputMui <TextField
label="Descrição do Curso" label="Descrição do Curso"
variant="standard" variant="standard"
type="text" type="text"
multiline multiline
rows={4} rows={4}
sx={StyledInputs({ color: '#26AAA7' })}
{...form.register('description')}
/> />
<InputMui {/* <TextField
label="Nome dos(as) Professores(as):" label="Nome dos(as) Professores(as):"
variant="standard" variant="standard"
type="text" type="text"
sx={StyledInputs({ color: '#26AAA7' })}
{...form.register('professors')}
/> */}
<Controller
control={form.control}
name="professors"
render={({ field }) => (
<Box
sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}
>
<TextField
label="Digite os nomes dos professores e pressione Enter"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
onKeyDown={handleKeyDown}
variant="standard"
sx={StyledInputs({ color: '#26AAA7' })}
/>
<Box sx={{ display: 'flex', gap: 1, flexWrap: 'wrap' }}>
{field.value.map((str, index) => (
<Chip
key={index}
label={str}
onDelete={() => handleDelete(str)}
variant="outlined"
color="secondary"
sx={{ color: 'white' }}
/>
))}
</Box>
</Box>
)}
/> />
<div className="flex justify-between flex-wrap gap-6"> <div className="flex justify-between flex-wrap gap-6 py-6">
<div className="flex flex-col flex-1 mt-6"> <div className="flex flex-col flex-1 mt-6">
<h6 className="text-xl text-purple-100">Banner Desktop</h6> <h6 className="text-xl text-purple-100">Banner Desktop</h6>
<span className="mt-4">Dimensões recomendadas: </span> <span className="mt-4">
Dimensões recomendadas: 1512 x 300
</span>
<span>Formatos aceitos: .png, .jpg</span> <span>Formatos aceitos: .png, .jpg</span>
<Button
variant="third" <InputFile
className="border border-dotted border-green-400 rounded-sm mt-6 mx-auto md:w-[436px]" id="desktopBanner"
> values={valueDesktopBanner}
Adicionar banner label="Adicionar banner"
</Button> {...form.register('desktopBanner')}
/>
</div> </div>
<div className="flex flex-col flex-1 mt-6"> <div className="flex flex-col flex-1 mt-6">
<h6 className="text-xl text-purple-100">Banner Mobile</h6> <h6 className="text-xl text-purple-100">Banner Mobile</h6>
<span className="mt-4">Dimensões recomendadas: </span> <span className="mt-4">
Dimensões recomendadas: 390 x 300
</span>
<span>Formatos aceitos: .png, .jpg</span> <span>Formatos aceitos: .png, .jpg</span>
<Button <InputFile
variant="third" id="mobileBanner"
className="border border-dotted border-green-400 rounded-sm mt-6 mx-auto md:w-[436px]" values={valueMobileBanner}
> label="Adicionar banner"
Adicionar banner {...form.register('mobileBanner')}
</Button> />
</div> </div>
</div> </div>
...@@ -104,7 +259,7 @@ export default function Curso() { ...@@ -104,7 +259,7 @@ export default function Curso() {
<div className="flex flex-col space-y-6"> <div className="flex flex-col space-y-6">
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Checkbox id="start" /> <Checkbox id="start" onCheckedChange={onCheckedStart} />
<label <label
htmlFor="start" htmlFor="start"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
...@@ -112,6 +267,7 @@ export default function Curso() { ...@@ -112,6 +267,7 @@ export default function Curso() {
Definir data de início Definir data de início
</label> </label>
</div> </div>
{checkedStart && (
<div className="flex flex-col"> <div className="flex flex-col">
<Label>Data de início</Label> <Label>Data de início</Label>
<Popover> <Popover>
...@@ -119,12 +275,12 @@ export default function Curso() { ...@@ -119,12 +275,12 @@ export default function Curso() {
<Button <Button
variant={'ghost'} variant={'ghost'}
className={cn( className={cn(
'lg:w-[450px] justify-start text-left font-normal border-b rounded-none pl-0', 'lg:w-[450px] justify-start text-left font-normal border-b rounded-none pl-0 border-green-400',
!date && 'text-muted-foreground', !dateStart && 'text-muted-foreground',
)} )}
> >
{date ? ( {dateStart ? (
format(date, 'dd/MM/yyyy') format(dateStart, 'dd/MM/yyyy')
) : ( ) : (
<span className="text-gray-600">MM/DD/YYYY</span> <span className="text-gray-600">MM/DD/YYYY</span>
)} )}
...@@ -134,17 +290,18 @@ export default function Curso() { ...@@ -134,17 +290,18 @@ export default function Curso() {
<PopoverContent className="w-auto p-0"> <PopoverContent className="w-auto p-0">
<Calendar <Calendar
mode="single" mode="single"
selected={date} selected={dateStart}
onSelect={setDate} onSelect={setDateStart}
initialFocus initialFocus
/> />
</PopoverContent> </PopoverContent>
</Popover> </Popover>
</div> </div>
)}
</div> </div>
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Checkbox id="closure" /> <Checkbox id="end" onCheckedChange={onCheckedEnd} />
<label <label
htmlFor="closure" htmlFor="closure"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
...@@ -152,6 +309,7 @@ export default function Curso() { ...@@ -152,6 +309,7 @@ export default function Curso() {
Definir data de encerramento Definir data de encerramento
</label> </label>
</div> </div>
{checkedEnd && (
<div className="flex flex-col"> <div className="flex flex-col">
<Label>Data de encerramento</Label> <Label>Data de encerramento</Label>
<Popover> <Popover>
...@@ -159,12 +317,12 @@ export default function Curso() { ...@@ -159,12 +317,12 @@ export default function Curso() {
<Button <Button
variant={'ghost'} variant={'ghost'}
className={cn( className={cn(
'lg:w-[450px] justify-start text-left font-normal border-b rounded-none pl-0', 'lg:w-[450px] justify-start text-left font-normal border-b rounded-none pl-0 border-green-400',
!date && 'text-muted-foreground', !dateEnd && 'text-muted-foreground',
)} )}
> >
{date ? ( {dateEnd ? (
format(date, 'dd/MM/yyyy') format(dateEnd, 'dd/MM/yyyy')
) : ( ) : (
<span className="text-gray-600">MM/DD/YYYY</span> <span className="text-gray-600">MM/DD/YYYY</span>
)} )}
...@@ -174,13 +332,15 @@ export default function Curso() { ...@@ -174,13 +332,15 @@ export default function Curso() {
<PopoverContent className="w-auto p-0"> <PopoverContent className="w-auto p-0">
<Calendar <Calendar
mode="single" mode="single"
selected={date} selected={dateEnd}
onSelect={setDate} onSelect={setDateEnd}
initialFocus initialFocus
{...form.register('endDate')}
/> />
</PopoverContent> </PopoverContent>
</Popover> </Popover>
</div> </div>
)}
</div> </div>
</div> </div>
...@@ -189,14 +349,20 @@ export default function Curso() { ...@@ -189,14 +349,20 @@ export default function Curso() {
<h6 className="text-xl text-purple-100 mb-4">Módulos</h6> <h6 className="text-xl text-purple-100 mb-4">Módulos</h6>
<div className="flex flex-col p-4 gap-6 border border-gray-100"> <div className="flex flex-col p-4 gap-6 border border-gray-100">
<InputMui label="Título" variant="standard" type="text" /> <TextField
label="Título"
variant="standard"
type="text"
sx={StyledInputs({ color: '#26AAA7' })}
/>
<InputMui <TextField
label="Descrição" label="Descrição"
variant="standard" variant="standard"
type="text" type="text"
multiline multiline
rows={4} rows={4}
sx={StyledInputs({ color: '#26AAA7' })}
/> />
</div> </div>
...@@ -211,66 +377,73 @@ export default function Curso() { ...@@ -211,66 +377,73 @@ export default function Curso() {
<h6 className="text-xl text-purple-100 mb-4"> <h6 className="text-xl text-purple-100 mb-4">
Qual o público alvo? Qual o público alvo?
</h6> </h6>
{audiencesLoading && <LoadingSpinIcon className="ml-10" />}
<div className="flex items-center gap-2 ml-4"> <div className="flex items-center gap-2 ml-4">
<Checkbox id="terms" /> <FormField
<label control={form.control}
htmlFor="terms" name="audienceId"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" render={({ field }) => (
> <FormControl>
Estudante <RadioGroup
</label> onValueChange={field.onChange}
</div> defaultValue={field.value}
<div className="flex items-center gap-2 ml-4"> className="flex flex-col space-y-4"
<Checkbox id="terms" />
<label
htmlFor="terms"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
> >
Profissionais {audiences?.data.map((audience) => (
</label> <FormItem
</div> className="flex items-center space-x-3 space-y-0"
<div className="flex items-center gap-2 ml-4"> key={audience.id}
<Checkbox id="terms" />
<label
htmlFor="terms"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
> >
Empresas <FormControl>
</label> <RadioGroupItem value={audience.id} />
</FormControl>
<FormLabel className="font-normal">
{audience.name}
</FormLabel>
</FormItem>
))}
</RadioGroup>
</FormControl>
)}
/>
</div> </div>
<h6 className="text-xl text-purple-100 my-4"> <h6 className="text-xl text-purple-100 my-4">
Qual o tipo de curso? Qual o tipo de curso?
</h6> </h6>
{categoriesLoading && <LoadingSpinIcon className="ml-10" />}
<div className="flex items-center gap-2 ml-4"> <div className="flex items-center gap-2 ml-4">
<Checkbox id="terms" /> <FormField
<label control={form.control}
htmlFor="terms" name="categoryId"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" render={({ field }) => (
> <FormControl>
Curso rápido <RadioGroup
</label> onValueChange={field.onChange}
</div> defaultValue={field.value}
<div className="flex items-center gap-2 ml-4"> className="flex flex-col space-y-4"
<Checkbox id="terms" />
<label
htmlFor="terms"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
> >
Curso de aprofundamento {categories?.data.map((category) => (
</label> <FormItem
</div> className="flex items-center space-x-3 space-y-0"
<div className="flex items-center gap-2 ml-4"> key={category.id}
<Checkbox id="terms" />
<label
htmlFor="terms"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
> >
Curso Corporativo <FormControl>
</label> <RadioGroupItem value={category.id} />
</FormControl>
<FormLabel className="font-normal">
{category.name}
</FormLabel>
</FormItem>
))}
</RadioGroup>
</FormControl>
)}
/>
</div> </div>
</div> </div>
</div> </div>
</form> </form>
</Form>
</section> </section>
) )
} }
...@@ -115,6 +115,7 @@ export default function Admin() { ...@@ -115,6 +115,7 @@ export default function Admin() {
type="text" type="text"
variant="standard" variant="standard"
className="w-full" className="w-full"
themeColor="#fafafa"
/> />
<Search size={24} className="-ml-6" /> <Search size={24} className="-ml-6" />
</div> </div>
......
import { cn } from '@/lib/utils'
type SpinProps = {
className?: React.HTMLProps<HTMLElement>['className']
}
export function LoadingSpinIcon({ className }: SpinProps) {
return (
<svg
className={cn('animate-spin -ml-1 mr-3 h-5 w-5 text-white', className)}
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
></circle>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
)
}
import { import {
AlertDialogAction,
AlertDialogCancel, AlertDialogCancel,
AlertDialogContent, AlertDialogContent,
AlertDialogDescription, AlertDialogDescription,
...@@ -7,6 +6,7 @@ import { ...@@ -7,6 +6,7 @@ import {
AlertDialogHeader, AlertDialogHeader,
AlertDialogTitle, AlertDialogTitle,
} from './ui/alert-dialog' } from './ui/alert-dialog'
import { Button } from './ui/button'
type AlertDialogProps = { type AlertDialogProps = {
title: string title: string
...@@ -27,7 +27,13 @@ export default function ModalDialog({ ...@@ -27,7 +27,13 @@ export default function ModalDialog({
</AlertDialogHeader> </AlertDialogHeader>
<AlertDialogFooter> <AlertDialogFooter>
<AlertDialogCancel>Cancelar</AlertDialogCancel> <AlertDialogCancel>Cancelar</AlertDialogCancel>
<AlertDialogAction onClick={handleClick}>Continue</AlertDialogAction> <Button
onClick={handleClick}
variant="outline"
className="text-gray-50 bg-red-500 hover:bg-red-500/80"
>
Continue
</Button>
</AlertDialogFooter> </AlertDialogFooter>
</AlertDialogContent> </AlertDialogContent>
) )
......
...@@ -7,6 +7,7 @@ import { ReactNode } from 'react' ...@@ -7,6 +7,7 @@ import { ReactNode } from 'react'
type InputMuiProps = TextFieldProps & { type InputMuiProps = TextFieldProps & {
label: string label: string
variant: 'standard' | 'filled' | 'outlined' variant: 'standard' | 'filled' | 'outlined'
themeColor?: string
children?: ReactNode children?: ReactNode
} }
...@@ -14,11 +15,12 @@ export function InputMui({ ...@@ -14,11 +15,12 @@ export function InputMui({
label, label,
variant, variant,
children, children,
themeColor = '#fafafa',
...props ...props
}: InputMuiProps) { }: InputMuiProps) {
const themeConfig = useThemeClient() const themeConfig = useThemeClient()
const color = themeConfig === 'dark' ? '#fafafa' : '#3C3C3C' const color = themeConfig === 'dark' ? themeColor : '#3C3C3C'
return ( return (
<TextField <TextField
...@@ -44,10 +46,10 @@ export function InputMui({ ...@@ -44,10 +46,10 @@ export function InputMui({
color: `${color}`, color: `${color}`,
}, },
'& input': { '& input': {
color: `${color}`, color: `#fafafa`,
}, },
'& .MuiInputBase-input': { '& .MuiInputBase-input': {
color: `${color}`, color: `#fafafa`,
}, },
'& .MuiInput-underline:before': { '& .MuiInput-underline:before': {
borderBottomColor: color, borderBottomColor: color,
......
"use client"
import * as React from "react"
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"
import { Circle } from "lucide-react"
import { cn } from "@/lib/utils"
const RadioGroup = React.forwardRef<
React.ElementRef<typeof RadioGroupPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>
>(({ className, ...props }, ref) => {
return (
<RadioGroupPrimitive.Root
className={cn("grid gap-2", className)}
{...props}
ref={ref}
/>
)
})
RadioGroup.displayName = RadioGroupPrimitive.Root.displayName
const RadioGroupItem = React.forwardRef<
React.ElementRef<typeof RadioGroupPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>
>(({ className, ...props }, ref) => {
return (
<RadioGroupPrimitive.Item
ref={ref}
className={cn(
"aspect-square h-4 w-4 rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
className
)}
{...props}
>
<RadioGroupPrimitive.Indicator className="flex items-center justify-center">
<Circle className="h-2.5 w-2.5 fill-current text-current" />
</RadioGroupPrimitive.Indicator>
</RadioGroupPrimitive.Item>
)
})
RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName
export { RadioGroup, RadioGroupItem }
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