Files
saladeaula.digital/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.buy/discount.tsx
2025-12-24 01:40:07 -03:00

136 lines
3.7 KiB
TypeScript

import type { InputHTMLAttributes } 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<
InputHTMLAttributes<HTMLInputElement>,
'value' | 'onChange'
> {
onChange?: (value: any) => void
}
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>
)
}