137 lines
3.7 KiB
TypeScript
137 lines
3.7 KiB
TypeScript
import type { ButtonHTMLAttributes } from 'react'
|
|
import { useRequest, useToggle } from 'ahooks'
|
|
import { useForm } from 'react-hook-form'
|
|
import { zodResolver } from '@hookform/resolvers/zod'
|
|
import { z } from 'zod'
|
|
|
|
import { Button } from '@repo/ui/components/ui/button'
|
|
import { Input } from '@repo/ui/components/ui/input'
|
|
import { Spinner } from '@repo/ui/components/ui/spinner'
|
|
import {
|
|
Popover,
|
|
PopoverContent,
|
|
PopoverTrigger
|
|
} from '@repo/ui/components/ui/popover'
|
|
import {
|
|
Form,
|
|
FormControl,
|
|
FormField,
|
|
FormItem,
|
|
FormLabel,
|
|
FormMessage
|
|
} from '@repo/ui/components/ui/form'
|
|
|
|
export const formSchema = z.object({
|
|
coupon: z.string().min(3, { error: 'Digite um cupom válido' }).trim()
|
|
})
|
|
|
|
export type Schema = z.infer<typeof formSchema>
|
|
|
|
interface DiscountProps extends Omit<
|
|
ButtonHTMLAttributes<HTMLButtonElement>,
|
|
'onChange'
|
|
> {
|
|
onChange?: (value: any) => void
|
|
disabled?: boolean
|
|
}
|
|
|
|
export function Discount({ onChange, ...props }: DiscountProps) {
|
|
const form = useForm({
|
|
resolver: zodResolver(formSchema)
|
|
})
|
|
const [open, { toggle, set }] = useToggle()
|
|
const { runAsync } = useRequest(
|
|
async (coupon) => {
|
|
return await fetch(`/~/api/coupons/${coupon}`, {
|
|
method: 'GET'
|
|
})
|
|
},
|
|
{ manual: true }
|
|
)
|
|
const { handleSubmit, control, formState, setError, reset } = form
|
|
|
|
const onSubmit = async (data: Schema) => {
|
|
const r = await runAsync(data.coupon)
|
|
|
|
if (!r.ok) {
|
|
return setError('coupon', { message: 'Cupom inválido' })
|
|
}
|
|
onChange?.(await r.json())
|
|
|
|
reset()
|
|
set(false)
|
|
}
|
|
|
|
return (
|
|
<Popover open={open} onOpenChange={toggle} modal={true}>
|
|
<PopoverTrigger asChild>
|
|
<Button
|
|
tabIndex={-1}
|
|
variant="outline"
|
|
className="text-xs cursor-pointer h-6 px-2"
|
|
type="button"
|
|
{...props}
|
|
>
|
|
Adicionar
|
|
</Button>
|
|
</PopoverTrigger>
|
|
|
|
<PopoverContent align="end" className="w-82">
|
|
<Form {...form}>
|
|
<form
|
|
onSubmit={async (e) => {
|
|
e.stopPropagation()
|
|
e.preventDefault()
|
|
await handleSubmit(onSubmit)(e)
|
|
}}
|
|
>
|
|
<div className="space-y-2.5">
|
|
<h4 className="leading-none font-medium">Recebeu um cupom?</h4>
|
|
<p className="text-muted-foreground text-sm">
|
|
Aplique seu cupom e tenha acesso aos cursos com descontos
|
|
exclusivos.
|
|
</p>
|
|
|
|
<FormField
|
|
control={control}
|
|
name="coupon"
|
|
defaultValue=""
|
|
render={({ field }) => (
|
|
<FormItem className="grid grid-cols-[20%_auto] gap-1">
|
|
<FormLabel>Cupom</FormLabel>
|
|
<FormControl>
|
|
<Input {...field} />
|
|
</FormControl>
|
|
<FormMessage className="col-start-2 " />
|
|
</FormItem>
|
|
)}
|
|
/>
|
|
|
|
<div className="flex justify-end gap-2.5">
|
|
<Button
|
|
type="button"
|
|
variant="link"
|
|
tabIndex={-1}
|
|
className="cursor-pointer dark:text-white text-black"
|
|
onClick={() => set(false)}
|
|
>
|
|
Cancelar
|
|
</Button>
|
|
|
|
<Button
|
|
type="submit"
|
|
className="cursor-pointer"
|
|
disabled={formState.isSubmitting}
|
|
>
|
|
{formState.isSubmitting && <Spinner />}
|
|
Aplicar
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</Form>
|
|
</PopoverContent>
|
|
</Popover>
|
|
)
|
|
}
|