add zustard
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Fragment } from 'react'
|
||||
import { Fragment, useEffect } from 'react'
|
||||
import {
|
||||
ArrowRightIcon,
|
||||
MinusIcon,
|
||||
@@ -36,9 +36,11 @@ import { MAX_ITEMS, type Course } from '../_.$orgid.enrollments.add/data'
|
||||
import { Discount, applyDiscount, type Coupon } from './discount'
|
||||
import { currency } from './utils'
|
||||
import { useWizard } from '@/components/wizard'
|
||||
import { useWizardStore } from './store'
|
||||
|
||||
const emptyRow = {
|
||||
course: undefined
|
||||
course: undefined as any,
|
||||
quantity: 1
|
||||
}
|
||||
|
||||
const item = z.object({
|
||||
@@ -57,39 +59,24 @@ const item = z.object({
|
||||
})
|
||||
|
||||
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()
|
||||
items: z.array(item).min(1).max(MAX_ITEMS)
|
||||
})
|
||||
|
||||
type Schema = z.infer<typeof formSchema>
|
||||
type Schema = z.input<typeof formSchema>
|
||||
|
||||
export type Item = z.infer<typeof item>
|
||||
|
||||
type BulkProps = {
|
||||
onSubmit: (value: any) => void | Promise<void>
|
||||
courses: Promise<{ hits: Course[] }>
|
||||
items: Item[]
|
||||
coupon?: Coupon
|
||||
}
|
||||
|
||||
export function Bulk({
|
||||
courses,
|
||||
onSubmit,
|
||||
items: itemsInit,
|
||||
coupon: couponInit
|
||||
}: BulkProps) {
|
||||
export function Bulk({ courses }: BulkProps) {
|
||||
const wizard = useWizard()
|
||||
const { update, ...state } = useWizardStore()
|
||||
const form = useForm({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
items: itemsInit?.length ? itemsInit : [emptyRow],
|
||||
coupon: couponInit
|
||||
items: state.items.length ? state.items : [emptyRow]
|
||||
}
|
||||
})
|
||||
const {
|
||||
@@ -109,35 +96,20 @@ export function Bulk({
|
||||
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 ({ coupon, ...data }: Schema) => {
|
||||
const items = Object.values(
|
||||
data.items.reduce<Record<string, Item>>((acc, item) => {
|
||||
const id = item.course.id
|
||||
|
||||
if (!acc[id]) {
|
||||
acc[id] = { ...item }
|
||||
} else {
|
||||
acc[id].quantity += item.quantity
|
||||
}
|
||||
|
||||
return acc
|
||||
}, {})
|
||||
)
|
||||
|
||||
await onSubmit({ coupon, items, enrollments: [] })
|
||||
const onSubmit_ = async ({ items }: Schema) => {
|
||||
update({ items })
|
||||
wizard('payment')
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const parsed = formSchema.safeParse({ items })
|
||||
|
||||
if (parsed.success) {
|
||||
update(parsed.data)
|
||||
}
|
||||
}, [items])
|
||||
|
||||
return (
|
||||
<Form {...form}>
|
||||
<form onSubmit={handleSubmit(onSubmit_)} className="space-y-4">
|
||||
@@ -316,7 +288,7 @@ export function Bulk({
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Summary {...{ subtotal, coupon, setValue }} />
|
||||
<Summary />
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
@@ -337,17 +309,9 @@ export function Bulk({
|
||||
)
|
||||
}
|
||||
|
||||
type SummaryProps = {
|
||||
subtotal: number
|
||||
coupon?: Coupon
|
||||
setValue: UseFormSetValue<any>
|
||||
}
|
||||
|
||||
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
|
||||
export function Summary() {
|
||||
const { summary, coupon, update } = useWizardStore()
|
||||
const { total, discount, subtotal } = summary()
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -407,7 +371,7 @@ export function Summary({ subtotal, coupon, setValue }: SummaryProps) {
|
||||
tabIndex={-1}
|
||||
variant="ghost"
|
||||
onClick={() => {
|
||||
setValue('coupon', null)
|
||||
update({ coupon: undefined })
|
||||
}}
|
||||
>
|
||||
<XIcon />
|
||||
@@ -416,7 +380,7 @@ export function Summary({ subtotal, coupon, setValue }: SummaryProps) {
|
||||
<Discount
|
||||
disabled={subtotal === 0}
|
||||
onChange={(coupon) => {
|
||||
setValue('coupon', coupon)
|
||||
update({ coupon })
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user