fix
This commit is contained in:
@@ -41,6 +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'
|
||||
|
||||
const emptyRow = {
|
||||
user: undefined,
|
||||
@@ -48,11 +49,6 @@ const emptyRow = {
|
||||
scheduled_for: undefined
|
||||
}
|
||||
|
||||
type Item = {
|
||||
course: Enrollment['course']
|
||||
quantity: number
|
||||
}
|
||||
|
||||
const formSchemaAssigned = formSchema.extend({
|
||||
coupon: z
|
||||
.object({
|
||||
@@ -68,7 +64,7 @@ type Schema = z.infer<typeof formSchemaAssigned>
|
||||
type AssignedProps = {
|
||||
onSubmit: (value: any) => void | Promise<void>
|
||||
courses: Promise<{ hits: Course[] }>
|
||||
enrollments: object[]
|
||||
enrollments: Enrollment[]
|
||||
coupon?: object
|
||||
}
|
||||
|
||||
@@ -84,10 +80,14 @@ export function Assigned({
|
||||
resolver: zodResolver(formSchemaAssigned),
|
||||
defaultValues: {
|
||||
coupon: couponInit,
|
||||
enrollments: enrollments?.map((e: any) => ({
|
||||
...e,
|
||||
scheduled_for: e.scheduled_for ? new Date(e.scheduled_for) : undefined
|
||||
})) || [emptyRow]
|
||||
enrollments: enrollments.length
|
||||
? enrollments.map((e: any) => ({
|
||||
...e,
|
||||
scheduled_for: e.scheduled_for
|
||||
? new Date(e.scheduled_for)
|
||||
: undefined
|
||||
}))
|
||||
: [emptyRow]
|
||||
}
|
||||
})
|
||||
|
||||
@@ -113,7 +113,7 @@ export function Assigned({
|
||||
return hits
|
||||
}
|
||||
|
||||
const onSubmit_ = async ({ enrollments }: Schema) => {
|
||||
const onSubmit_ = async ({ enrollments, coupon }: Schema) => {
|
||||
const items = Object.values(
|
||||
enrollments.reduce<Record<string, Item>>((acc, e) => {
|
||||
const id = e.course.id
|
||||
@@ -124,7 +124,7 @@ export function Assigned({
|
||||
return acc
|
||||
}, {})
|
||||
)
|
||||
await onSubmit({ enrollments, items })
|
||||
await onSubmit({ enrollments, items, coupon })
|
||||
wizard('payment')
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ 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 { Discount, applyDiscount, type Coupon } from './discount'
|
||||
import { currency } from './utils'
|
||||
import { useWizard } from '@/components/wizard'
|
||||
|
||||
@@ -41,13 +41,6 @@ const emptyRow = {
|
||||
course: undefined
|
||||
}
|
||||
|
||||
type BulkProps = {
|
||||
onSubmit: (value: any) => void | Promise<void>
|
||||
courses: Promise<{ hits: Course[] }>
|
||||
items?: object[]
|
||||
coupon?: object
|
||||
}
|
||||
|
||||
const item = z.object({
|
||||
course: z
|
||||
.object(
|
||||
@@ -76,17 +69,26 @@ const formSchema = z.object({
|
||||
|
||||
type Schema = z.infer<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: itemInit,
|
||||
items: itemsInit,
|
||||
coupon: couponInit
|
||||
}: BulkProps) {
|
||||
const wizard = useWizard()
|
||||
const form = useForm({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
items: itemInit || [emptyRow],
|
||||
items: itemsInit?.length ? itemsInit : [emptyRow],
|
||||
coupon: couponInit
|
||||
}
|
||||
})
|
||||
@@ -117,8 +119,22 @@ export function Bulk({
|
||||
0
|
||||
)
|
||||
|
||||
const onSubmit_ = async (data: Schema) => {
|
||||
await onSubmit(data)
|
||||
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: [] })
|
||||
wizard('payment')
|
||||
}
|
||||
|
||||
@@ -403,11 +419,11 @@ export function Summary({ subtotal, coupon, setValue }: SummaryProps) {
|
||||
) : (
|
||||
<Discount
|
||||
disabled={subtotal === 0}
|
||||
onChange={({ sk, discount_amount, discount_type }) => {
|
||||
onChange={(coupon) => {
|
||||
setValue('coupon', {
|
||||
code: sk,
|
||||
amount: discount_amount,
|
||||
type: discount_type
|
||||
// code: sk,
|
||||
// amount: discount_amount,
|
||||
// type: discount_type
|
||||
})
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -21,17 +21,23 @@ import {
|
||||
FormMessage
|
||||
} from '@repo/ui/components/ui/form'
|
||||
|
||||
export const formSchema = z.object({
|
||||
const formSchema = z.object({
|
||||
coupon: z.string().min(3, { error: 'Digite um cupom válido' }).trim()
|
||||
})
|
||||
|
||||
export type Schema = z.infer<typeof formSchema>
|
||||
type Schema = z.infer<typeof formSchema>
|
||||
|
||||
export type Coupon = {
|
||||
code: string
|
||||
amount: number
|
||||
type: 'FIXED' | 'PERCENT'
|
||||
}
|
||||
|
||||
interface DiscountProps extends Omit<
|
||||
ButtonHTMLAttributes<HTMLButtonElement>,
|
||||
'onChange'
|
||||
> {
|
||||
onChange?: (value: any) => void
|
||||
onChange?: (value: Coupon) => void
|
||||
disabled?: boolean
|
||||
}
|
||||
|
||||
@@ -56,7 +62,17 @@ export function Discount({ onChange, ...props }: DiscountProps) {
|
||||
if (!r.ok) {
|
||||
return setError('coupon', { message: 'Cupom inválido' })
|
||||
}
|
||||
onChange?.(await r.json())
|
||||
const {
|
||||
sk: code,
|
||||
discount_amount: amount,
|
||||
discount_type: type
|
||||
} = (await r.json()) as {
|
||||
sk: string
|
||||
discount_amount: number
|
||||
discount_type: 'FIXED' | 'PERCENT'
|
||||
}
|
||||
|
||||
onChange?.({ code, amount, type })
|
||||
|
||||
reset()
|
||||
set(false)
|
||||
|
||||
@@ -1,63 +1,87 @@
|
||||
import { useForm, Controller, useWatch } from 'react-hook-form'
|
||||
import { useForm, Controller, useWatch, type Control } from 'react-hook-form'
|
||||
import { PatternFormat } from 'react-number-format'
|
||||
import { zodResolver } from '@hookform/resolvers/zod'
|
||||
import { ErrorMessage } from '@hookform/error-message'
|
||||
import z from 'zod'
|
||||
import { ArrowRightIcon } from 'lucide-react'
|
||||
import { ArrowRightIcon, CircleQuestionMarkIcon } from 'lucide-react'
|
||||
|
||||
import { Button } from '@repo/ui/components/ui/button'
|
||||
import { Kbd } from '@repo/ui/components/ui/kbd'
|
||||
import { Label } from '@repo/ui/components/ui/label'
|
||||
import { RadioGroup, RadioGroupItem } from '@repo/ui/components/ui/radio-group'
|
||||
import { Separator } from '@repo/ui/components/ui/separator'
|
||||
|
||||
import { Checkbox } from '@repo/ui/components/ui/checkbox'
|
||||
import { Input } from '@repo/ui/components/ui/input'
|
||||
import { Card, CardContent } from '@repo/ui/components/ui/card'
|
||||
import {
|
||||
HoverCard,
|
||||
HoverCardContent,
|
||||
HoverCardTrigger
|
||||
} from '@repo/ui/components/ui/hover-card'
|
||||
import {
|
||||
Field,
|
||||
FieldDescription,
|
||||
FieldGroup,
|
||||
FieldLabel,
|
||||
FieldLegend,
|
||||
FieldSeparator,
|
||||
FieldSet
|
||||
} from '@repo/ui/components/ui/field'
|
||||
import { Input } from '@repo/ui/components/ui/input'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue
|
||||
} from '@repo/ui/components/ui/select'
|
||||
import { Textarea } from '@repo/ui/components/ui/textarea'
|
||||
NativeSelect,
|
||||
NativeSelectOption
|
||||
} from '@repo/ui/components/ui/native-select'
|
||||
|
||||
import { useWizard } from '@/components/wizard'
|
||||
import { Card, CardContent } from '@repo/ui/components/ui/card'
|
||||
|
||||
const formSchema = z.object({
|
||||
payment_method: z.enum(['PIX', 'BANK_SLIP', 'CREDIT_CARD'], {
|
||||
error: 'Escolha uma forma de pagamento'
|
||||
})
|
||||
const creditCard = z.object({
|
||||
holder_name: z.string().min(1),
|
||||
number: z.string().min(13).max(19),
|
||||
exp_month: z.string().min(2),
|
||||
exp_year: z.string().min(4),
|
||||
cvv: z.string().min(3).max(4)
|
||||
})
|
||||
|
||||
const formSchema = z.discriminatedUnion(
|
||||
'payment_method',
|
||||
[
|
||||
z.object({
|
||||
payment_method: z.literal('PIX')
|
||||
}),
|
||||
z.object({
|
||||
payment_method: z.literal('BANK_SLIP')
|
||||
}),
|
||||
z.object({
|
||||
payment_method: z.literal('CREDIT_CARD'),
|
||||
credit_card: creditCard
|
||||
})
|
||||
],
|
||||
{ error: 'Escolha uma forma de pagamento' }
|
||||
)
|
||||
|
||||
type Schema = z.infer<typeof formSchema>
|
||||
|
||||
export type CreditCard = z.infer<typeof creditCard>
|
||||
|
||||
type PaymentProps = {
|
||||
onSubmit: (value: any) => void | Promise<void>
|
||||
defaultValues?: object
|
||||
payment_method?: 'PIX' | 'BANK_SLIP' | 'CREDIT_CARD'
|
||||
credit_card?: CreditCard
|
||||
}
|
||||
|
||||
export function Payment({ onSubmit, defaultValues }: PaymentProps) {
|
||||
export function Payment({
|
||||
onSubmit,
|
||||
payment_method: paymentMethodInit,
|
||||
credit_card: creditCardInit = undefined
|
||||
}: PaymentProps) {
|
||||
const wizard = useWizard()
|
||||
const { control, handleSubmit } = useForm<Schema>({
|
||||
defaultValues: {
|
||||
payment_method: '' as any,
|
||||
...defaultValues
|
||||
payment_method: paymentMethodInit,
|
||||
credit_card: creditCardInit
|
||||
},
|
||||
resolver: zodResolver(formSchema)
|
||||
})
|
||||
const paymentMethod = useWatch({ control, name: 'payment_method' })
|
||||
|
||||
const onSubmit_ = async (data: Schema) => {
|
||||
await onSubmit(data)
|
||||
await onSubmit({ credit_card: undefined, ...data })
|
||||
wizard('review')
|
||||
}
|
||||
|
||||
@@ -72,10 +96,9 @@ export function Payment({ onSubmit, defaultValues }: PaymentProps) {
|
||||
value={value}
|
||||
onValueChange={onChange}
|
||||
className="lg:flex gap-3
|
||||
*:p-5 *:border *:rounded-xl *:flex-1
|
||||
*:cursor-pointer *:bg-accent/25
|
||||
*:has-[button[data-state=checked]]:bg-accent
|
||||
"
|
||||
*:p-5 *:border *:rounded-xl *:flex-1
|
||||
*:cursor-pointer *:bg-accent/25
|
||||
*:has-[button[data-state=checked]]:bg-accent"
|
||||
>
|
||||
<Label>
|
||||
<RadioGroupItem value="PIX" />
|
||||
@@ -104,7 +127,9 @@ export function Payment({ onSubmit, defaultValues }: PaymentProps) {
|
||||
)}
|
||||
/>
|
||||
|
||||
{paymentMethod === 'CREDIT_CARD' ? <CreditCard /> : null}
|
||||
{paymentMethod === 'CREDIT_CARD' ? (
|
||||
<CreditCard control={control} />
|
||||
) : null}
|
||||
|
||||
<Separator />
|
||||
|
||||
@@ -114,6 +139,7 @@ export function Payment({ onSubmit, defaultValues }: PaymentProps) {
|
||||
variant="link"
|
||||
className="text-black dark:text-white"
|
||||
onClick={() => wizard('cart')}
|
||||
tabIndex={-1}
|
||||
>
|
||||
Voltar
|
||||
</Button>
|
||||
@@ -125,72 +151,159 @@ export function Payment({ onSubmit, defaultValues }: PaymentProps) {
|
||||
)
|
||||
}
|
||||
|
||||
export function CreditCard() {
|
||||
export function CreditCard({ control }: { control: Control<Schema> }) {
|
||||
const currentYear = new Date().getFullYear()
|
||||
const years = Array.from({ length: 10 }, (_, i) => currentYear + i)
|
||||
|
||||
return (
|
||||
<Card className="lg:max-w-md">
|
||||
<Card className="lg:w-1/2">
|
||||
<CardContent>
|
||||
<FieldGroup>
|
||||
<FieldSet>
|
||||
<FieldGroup>
|
||||
<Field>
|
||||
<FieldLabel htmlFor="checkout-7j9-card-number-uw1">
|
||||
Número do cartão
|
||||
</FieldLabel>
|
||||
<Input id="checkout-7j9-card-number-uw1" required />
|
||||
</Field>
|
||||
<Controller
|
||||
control={control}
|
||||
name="credit_card.number"
|
||||
render={({
|
||||
field: { onChange, ref, ...field },
|
||||
fieldState
|
||||
}) => (
|
||||
<Field data-invalid={fieldState.invalid}>
|
||||
<FieldLabel htmlFor={field.name}>
|
||||
Número do cartão
|
||||
</FieldLabel>
|
||||
<PatternFormat
|
||||
id={field.name}
|
||||
format="#### #### #### ####"
|
||||
mask="_"
|
||||
placeholder="•••• •••• •••• ••••"
|
||||
customInput={Input}
|
||||
getInputRef={ref}
|
||||
aria-invalid={fieldState.invalid}
|
||||
onValueChange={({ value }) => {
|
||||
onChange(value)
|
||||
}}
|
||||
{...field}
|
||||
/>
|
||||
</Field>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Field>
|
||||
<FieldLabel htmlFor="checkout-7j9-card-name-43j">
|
||||
Nome do titular
|
||||
</FieldLabel>
|
||||
<Input required />
|
||||
</Field>
|
||||
<Controller
|
||||
control={control}
|
||||
name="credit_card.holder_name"
|
||||
defaultValue=""
|
||||
render={({ field, fieldState }) => (
|
||||
<Field data-invalid={fieldState.invalid}>
|
||||
<FieldLabel htmlFor={field.name}>
|
||||
Nome do titular
|
||||
</FieldLabel>
|
||||
<Input
|
||||
id={field.name}
|
||||
aria-invalid={fieldState.invalid}
|
||||
{...field}
|
||||
/>
|
||||
</Field>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<Field>
|
||||
<FieldLabel htmlFor="checkout-exp-month-ts6">Mês</FieldLabel>
|
||||
<Select defaultValue="">
|
||||
<SelectTrigger id="checkout-exp-month-ts6">
|
||||
<SelectValue placeholder="MM" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="01">01</SelectItem>
|
||||
<SelectItem value="02">02</SelectItem>
|
||||
<SelectItem value="03">03</SelectItem>
|
||||
<SelectItem value="04">04</SelectItem>
|
||||
<SelectItem value="05">05</SelectItem>
|
||||
<SelectItem value="06">06</SelectItem>
|
||||
<SelectItem value="07">07</SelectItem>
|
||||
<SelectItem value="08">08</SelectItem>
|
||||
<SelectItem value="09">09</SelectItem>
|
||||
<SelectItem value="10">10</SelectItem>
|
||||
<SelectItem value="11">11</SelectItem>
|
||||
<SelectItem value="12">12</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</Field>
|
||||
<Field>
|
||||
<FieldLabel htmlFor="checkout-7j9-exp-year-f59">
|
||||
Ano
|
||||
</FieldLabel>
|
||||
<Select defaultValue="">
|
||||
<SelectTrigger id="checkout-7j9-exp-year-f59">
|
||||
<SelectValue placeholder="AAAA" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="2024">2024</SelectItem>
|
||||
<SelectItem value="2025">2025</SelectItem>
|
||||
<SelectItem value="2026">2026</SelectItem>
|
||||
<SelectItem value="2027">2027</SelectItem>
|
||||
<SelectItem value="2028">2028</SelectItem>
|
||||
<SelectItem value="2029">2029</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</Field>
|
||||
<Field>
|
||||
<FieldLabel htmlFor="checkout-7j9-cvv">CVC</FieldLabel>
|
||||
<Input id="checkout-7j9-cvv" placeholder="123" required />
|
||||
</Field>
|
||||
<Controller
|
||||
control={control}
|
||||
name="credit_card.exp_month"
|
||||
defaultValue=""
|
||||
render={({ field, fieldState }) => (
|
||||
<Field data-invalid={fieldState.invalid}>
|
||||
<FieldLabel htmlFor={field.name}>Mês</FieldLabel>
|
||||
<NativeSelect
|
||||
id={field.name}
|
||||
value={field.value}
|
||||
onChange={field.onChange}
|
||||
aria-invalid={fieldState.invalid}
|
||||
>
|
||||
<NativeSelectOption value="" disabled>
|
||||
Selecione
|
||||
</NativeSelectOption>
|
||||
|
||||
{Array.from({ length: 12 }, (_, i) => {
|
||||
const v = String(i + 1).padStart(2, '0')
|
||||
return (
|
||||
<NativeSelectOption key={v} value={v}>
|
||||
{v}
|
||||
</NativeSelectOption>
|
||||
)
|
||||
})}
|
||||
</NativeSelect>
|
||||
</Field>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Controller
|
||||
control={control}
|
||||
name="credit_card.exp_year"
|
||||
defaultValue=""
|
||||
render={({ field, fieldState }) => (
|
||||
<Field data-invalid={fieldState.invalid}>
|
||||
<FieldLabel htmlFor={field.name}>Ano</FieldLabel>
|
||||
<NativeSelect
|
||||
id={field.name}
|
||||
value={field.value}
|
||||
onChange={field.onChange}
|
||||
aria-invalid={fieldState.invalid}
|
||||
>
|
||||
<NativeSelectOption value="" disabled>
|
||||
Selecione
|
||||
</NativeSelectOption>
|
||||
|
||||
{years.map((year) => (
|
||||
<NativeSelectOption key={year} value={String(year)}>
|
||||
{year}
|
||||
</NativeSelectOption>
|
||||
))}
|
||||
</NativeSelect>
|
||||
</Field>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Controller
|
||||
control={control}
|
||||
name="credit_card.cvv"
|
||||
defaultValue=""
|
||||
render={({ field, fieldState }) => (
|
||||
<Field data-invalid={fieldState.invalid}>
|
||||
<FieldLabel htmlFor={field.name}>
|
||||
CVC
|
||||
<HoverCard openDelay={0}>
|
||||
<HoverCardTrigger asChild>
|
||||
<button type="button" tabIndex={-1}>
|
||||
<CircleQuestionMarkIcon className="size-4 text-muted-foreground" />
|
||||
</button>
|
||||
</HoverCardTrigger>
|
||||
<HoverCardContent
|
||||
align="end"
|
||||
className="text-sm space-y-1.5 lg:w-78"
|
||||
>
|
||||
<p>
|
||||
O <Kbd>CVC</Kbd> é o código de segurança do cartão
|
||||
de crédito.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Ele fica no verso do cartão e geralmente possui{' '}
|
||||
<Kbd>3 dígitos</Kbd> (ou <Kbd>4 dígitos</Kbd> na
|
||||
frente, no caso do American Express).
|
||||
</p>
|
||||
</HoverCardContent>
|
||||
</HoverCard>
|
||||
</FieldLabel>
|
||||
<Input
|
||||
id={field.name}
|
||||
aria-invalid={fieldState.invalid}
|
||||
{...field}
|
||||
/>
|
||||
</Field>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</FieldGroup>
|
||||
</FieldSet>
|
||||
|
||||
@@ -13,10 +13,11 @@ import {
|
||||
|
||||
import { useWizard } from '@/components/wizard'
|
||||
|
||||
import { type WizardState } from './route'
|
||||
import { applyDiscount } from './discount'
|
||||
|
||||
type ReviewProps = {
|
||||
state: any
|
||||
state: WizardState
|
||||
}
|
||||
|
||||
export function Review({ state }: ReviewProps) {
|
||||
@@ -35,6 +36,8 @@ export function Review({ state }: ReviewProps) {
|
||||
: 0
|
||||
const total = subtotal > 0 ? subtotal + discount : 0
|
||||
|
||||
console.log(state)
|
||||
|
||||
return (
|
||||
<>
|
||||
<Table>
|
||||
@@ -98,6 +101,7 @@ export function Review({ state }: ReviewProps) {
|
||||
variant="link"
|
||||
className="text-black dark:text-white"
|
||||
onClick={() => wizard('payment')}
|
||||
tabIndex={-1}
|
||||
>
|
||||
Voltar
|
||||
</Button>
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { Route } from './+types/route'
|
||||
|
||||
import { useState } from 'react'
|
||||
import { Link } from 'react-router'
|
||||
import { useLocalStorageState, useMount, useToggle } from 'ahooks'
|
||||
import { useLocalStorageState, useMount } from 'ahooks'
|
||||
import { BookSearchIcon, CircleCheckBigIcon, WalletIcon } from 'lucide-react'
|
||||
|
||||
import {
|
||||
@@ -24,32 +24,35 @@ import { Switch } from '@repo/ui/components/ui/switch'
|
||||
import { createSearch } from '@repo/util/meili'
|
||||
import { cloudflareContext } from '@repo/auth/context'
|
||||
import { Label } from '@repo/ui/components/ui/label'
|
||||
import { Skeleton } from '@repo/ui/components/skeleton'
|
||||
|
||||
import { Wizard, WizardStep } from '@/components/wizard'
|
||||
import { Step, StepItem, StepSeparator } from '@/components/step'
|
||||
import type { Course } from '../_.$orgid.enrollments.add/data'
|
||||
import type { Course, Enrollment } from '../_.$orgid.enrollments.add/data'
|
||||
import { Assigned } from './assigned'
|
||||
import { Bulk } from './bulk'
|
||||
import { Payment } from './payment'
|
||||
import { Bulk, type Item } from './bulk'
|
||||
import { Payment, type CreditCard } from './payment'
|
||||
import { Review } from './review'
|
||||
import { Skeleton } from '@repo/ui/components/skeleton'
|
||||
import type { Coupon } from './discount'
|
||||
|
||||
type WizardState = {
|
||||
export type WizardState = {
|
||||
index: number
|
||||
kind: 'bulk' | 'assigned'
|
||||
items?: object[]
|
||||
coupon?: object
|
||||
enrollments?: object[]
|
||||
payment?: any
|
||||
items: Item[]
|
||||
enrollments: Enrollment[]
|
||||
coupon?: Coupon
|
||||
payment_method?: 'PIX' | 'BANK_SLIP' | 'CREDIT_CARD'
|
||||
credit_card?: CreditCard
|
||||
}
|
||||
|
||||
const emptyWizard: WizardState = {
|
||||
index: 0,
|
||||
kind: 'bulk',
|
||||
items: undefined,
|
||||
items: [],
|
||||
enrollments: [],
|
||||
coupon: undefined,
|
||||
enrollments: undefined,
|
||||
payment: undefined
|
||||
payment_method: undefined,
|
||||
credit_card: undefined
|
||||
}
|
||||
|
||||
export function meta({}: Route.MetaArgs) {
|
||||
@@ -61,7 +64,7 @@ export async function loader({ context }: Route.LoaderArgs) {
|
||||
const courses = createSearch<Course>({
|
||||
index: 'saladeaula_courses',
|
||||
sort: ['created_at:desc'],
|
||||
filter: 'unlisted NOT EXISTS',
|
||||
filter: 'unlisted = false',
|
||||
hitsPerPage: 100,
|
||||
env: cloudflare.env
|
||||
})
|
||||
@@ -167,12 +170,13 @@ export default function Route({
|
||||
o curso ou deixar isso para depois.
|
||||
</p>
|
||||
</div>
|
||||
{/* Toggle button x*/}
|
||||
<Switch
|
||||
checked={kind === 'assigned'}
|
||||
onCheckedChange={() =>
|
||||
onCheckedChange={(checked) =>
|
||||
setState((prev) => ({
|
||||
...(prev ?? emptyWizard),
|
||||
kind: kind === 'bulk' ? 'assigned' : 'bulk'
|
||||
kind: checked ? 'assigned' : 'bulk'
|
||||
}))
|
||||
}
|
||||
className="cursor-pointer"
|
||||
@@ -189,11 +193,12 @@ export default function Route({
|
||||
{/* Payment */}
|
||||
<WizardStep name="payment">
|
||||
<Payment
|
||||
defaultValues={state.payment}
|
||||
payment_method={state.payment_method}
|
||||
credit_card={state.credit_card}
|
||||
onSubmit={(data: any) => {
|
||||
setState((prev) => ({
|
||||
...(prev ?? emptyWizard),
|
||||
payment: data
|
||||
...data
|
||||
}))
|
||||
}}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user