add zustard
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Fragment } from 'react'
|
||||
import { Fragment, useEffect } from 'react'
|
||||
import {
|
||||
Trash2Icon,
|
||||
PlusIcon,
|
||||
@@ -10,6 +10,7 @@ import { useParams } from 'react-router'
|
||||
import { ErrorMessage } from '@hookform/error-message'
|
||||
import { zodResolver } from '@hookform/resolvers/zod'
|
||||
import { z } from 'zod'
|
||||
import { DateTime } from 'luxon'
|
||||
|
||||
import { Form } from '@repo/ui/components/ui/form'
|
||||
import {
|
||||
@@ -30,7 +31,6 @@ import {
|
||||
import {
|
||||
MAX_ITEMS,
|
||||
formSchema,
|
||||
type Enrollment,
|
||||
type Course,
|
||||
type User
|
||||
} from '../_.$orgid.enrollments.add/data'
|
||||
@@ -41,7 +41,7 @@ import { UserPicker } from '../_.$orgid.enrollments.add/user-picker'
|
||||
import { Summary } from './bulk'
|
||||
import { currency } from './utils'
|
||||
import { useWizard } from '@/components/wizard'
|
||||
import type { Item } from './bulk'
|
||||
import { useWizardStore } from './store'
|
||||
|
||||
const emptyRow = {
|
||||
user: undefined,
|
||||
@@ -49,42 +49,24 @@ const emptyRow = {
|
||||
scheduled_for: undefined
|
||||
}
|
||||
|
||||
const formSchemaAssigned = formSchema.extend({
|
||||
coupon: z
|
||||
.object({
|
||||
code: z.string(),
|
||||
type: z.enum(['FIXED', 'PERCENT']),
|
||||
amount: z.number().positive()
|
||||
})
|
||||
.optional()
|
||||
})
|
||||
|
||||
type Schema = z.infer<typeof formSchemaAssigned>
|
||||
type Schema = z.infer<typeof formSchema>
|
||||
|
||||
type AssignedProps = {
|
||||
onSubmit: (value: any) => void | Promise<void>
|
||||
courses: Promise<{ hits: Course[] }>
|
||||
enrollments: Enrollment[]
|
||||
coupon?: object
|
||||
}
|
||||
|
||||
export function Assigned({
|
||||
courses,
|
||||
onSubmit,
|
||||
enrollments,
|
||||
coupon: couponInit
|
||||
}: AssignedProps) {
|
||||
export function Assigned({ courses }: AssignedProps) {
|
||||
const wizard = useWizard()
|
||||
const { orgid } = useParams()
|
||||
const { update, ...state } = useWizardStore()
|
||||
const form = useForm({
|
||||
resolver: zodResolver(formSchemaAssigned),
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
coupon: couponInit,
|
||||
enrollments: enrollments.length
|
||||
? enrollments.map((e: any) => ({
|
||||
enrollments: state.enrollments.length
|
||||
? state.enrollments.map((e: any) => ({
|
||||
...e,
|
||||
scheduled_for: e.scheduled_for
|
||||
? new Date(e.scheduled_for)
|
||||
? DateTime.fromISO(e.scheduled_for, { zone: 'local' }).toJSDate()
|
||||
: undefined
|
||||
}))
|
||||
: [emptyRow]
|
||||
@@ -96,15 +78,10 @@ export function Assigned({
|
||||
control,
|
||||
name: 'enrollments'
|
||||
})
|
||||
const items = useWatch({
|
||||
const enrollments = useWatch({
|
||||
control,
|
||||
name: 'enrollments'
|
||||
})
|
||||
const coupon = useWatch({ control, name: 'coupon' })
|
||||
const subtotal = items.reduce(
|
||||
(acc, { course }) => acc + (course?.unit_price || 0),
|
||||
0
|
||||
)
|
||||
|
||||
const onSearch = async (search: string) => {
|
||||
const params = new URLSearchParams({ q: search })
|
||||
@@ -113,24 +90,22 @@ export function Assigned({
|
||||
return hits
|
||||
}
|
||||
|
||||
const onSubmit_ = async ({ enrollments, coupon }: Schema) => {
|
||||
const items = Object.values(
|
||||
enrollments.reduce<Record<string, Item>>((acc, e) => {
|
||||
const id = e.course.id
|
||||
|
||||
acc[id] ??= { course: e.course, quantity: 0 }
|
||||
acc[id].quantity++
|
||||
|
||||
return acc
|
||||
}, {})
|
||||
)
|
||||
await onSubmit({ enrollments, items, coupon })
|
||||
const onSubmit = async ({ enrollments }: Schema) => {
|
||||
update({ enrollments })
|
||||
wizard('payment')
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const parsed = formSchema.safeParse({ enrollments })
|
||||
|
||||
if (parsed.success) {
|
||||
update(parsed.data)
|
||||
}
|
||||
}, [enrollments])
|
||||
|
||||
return (
|
||||
<Form {...form}>
|
||||
<form onSubmit={handleSubmit(onSubmit_)} className="space-y-4">
|
||||
<form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
|
||||
<div className="grid w-full gap-3 lg:grid-cols-[3fr_3fr_2fr_2fr_auto]">
|
||||
{/* Header */}
|
||||
<>
|
||||
@@ -166,7 +141,9 @@ export function Assigned({
|
||||
|
||||
{/* Rows */}
|
||||
{fields.map((field, index) => {
|
||||
const { unit_price } = items?.[index]?.course || { unit_price: 0 }
|
||||
const { unit_price } = enrollments?.[index]?.course || {
|
||||
unit_price: 0
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment key={field.id}>
|
||||
@@ -281,7 +258,7 @@ export function Assigned({
|
||||
</div>
|
||||
|
||||
{/* Summary */}
|
||||
<Summary {...{ subtotal, coupon, setValue }} />
|
||||
<Summary />
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
|
||||
Reference in New Issue
Block a user