import { Fragment } from 'react' import { ArrowRightIcon, MinusIcon, PlusIcon, Trash2Icon, XIcon } from 'lucide-react' import { useForm, useFieldArray, Controller, useWatch, type UseFormSetValue } from 'react-hook-form' import { ErrorMessage } from '@hookform/error-message' import { zodResolver } from '@hookform/resolvers/zod' import { z } from 'zod' import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput } from '@repo/ui/components/ui/input-group' import { Form } from '@repo/ui/components/ui/form' import { Button } from '@repo/ui/components/ui/button' import { Separator } from '@repo/ui/components/ui/separator' import { Spinner } from '@repo/ui/components/ui/spinner' import { Kbd } from '@repo/ui/components/ui/kbd' import { Abbr } from '@repo/ui/components/abbr' import { Cell } from '../_.$orgid.enrollments.add/route' import { CoursePicker } from '../_.$orgid.enrollments.add/course-picker' import { MAX_ITEMS, type Course } from '../_.$orgid.enrollments.add/data' import { Discount, applyDiscount } from './discount' import { currency } from './utils' import { useWizard } from '@/components/wizard' const emptyRow = { course: undefined } type BulkProps = { onSubmit: (value: any) => void | Promise courses: Promise<{ hits: Course[] }> items?: object[] coupon?: object } const item = z.object({ course: z .object( { id: z.string(), name: z.string(), access_period: z.number(), unit_price: z.number() }, { error: 'Escolha um curso' } ) .required(), quantity: z.number().min(1) }) const formSchema = z.object({ items: z.array(item).min(1).max(MAX_ITEMS), coupon: z .object({ code: z.string(), type: z.enum(['FIXED', 'PERCENT']), amount: z.number().positive() }) .optional() }) type Schema = z.infer export function Bulk({ courses, onSubmit, items: itemInit, coupon: couponInit }: BulkProps) { const wizard = useWizard() const form = useForm({ resolver: zodResolver(formSchema), defaultValues: { items: itemInit || [emptyRow], coupon: couponInit } }) const { formState, control, handleSubmit, register, setValue, getValues, setFocus } = form const { fields, remove, append } = useFieldArray({ control, name: 'items' }) const items = useWatch({ control, name: 'items' }) const coupon = useWatch({ control, name: 'coupon' }) const subtotal = items.reduce( (acc, { course, quantity }) => acc + (course?.unit_price || 0) * (Number.isFinite(quantity) && quantity > 0 ? quantity : 1), 0 ) const onSubmit_ = async (data: Schema) => { await onSubmit(data) wizard('payment') } return (
{/* Header */} <> Curso Quantidade Valor unit. Total {/**/} {/* Rows */} {fields.map((field, index) => { const item = items?.[index] || { course: {}, quantity: 1 } const { course, quantity } = item return ( {/* Separator only for mobile */} {index >= 1 &&
} {/* Course */} (
(

{message}

)} />
)} /> {/* Quantity */} Qtd. { const value = Number(e.target.value) if (!value || value < 1) { setValue(`items.${index}.quantity`, 1) } } })} /> { const quantity = getValues(`items.${index}.quantity`) || 1 setValue( `items.${index}.quantity`, Math.max(1, quantity - 1) ) }} > { const quantity = getValues(`items.${index}.quantity`) || 1 setValue(`items.${index}.quantity`, quantity + 1) }} > {/* Unit price */} Valor unit. {/* Total */} Total 0 ? quantity : 1) )} /> {/* Action */}
) })} {/* Add button */}
) } type SummaryProps = { subtotal: number coupon?: { code: string type: 'FIXED' | 'PERCENT' amount: number } setValue: UseFormSetValue } export function Summary({ subtotal, coupon, setValue }: SummaryProps) { const discount = coupon ? applyDiscount(subtotal, coupon.amount, coupon.type) * -1 : 0 const total = subtotal > 0 ? subtotal + discount : 0 return ( <> {/* Subtotal */} <>
Subtotal
Subtotal {/* Discount */} <>
{coupon ? ( Descontos {coupon.code} ) : ( <>Cupom )}
{coupon ? <>Descontos : <>Cupom} {coupon ? ( { setValue('coupon', undefined) }} > ) : ( { setValue('coupon', { code: sk, amount: discount_amount, type: discount_type }) }} /> )} {/* Total */} <>
Total
Total ) }