import { create } from 'zustand' import { persist } from 'zustand/middleware' import type { PaymentMethod } from '@repo/ui/routes/orders/data' import type { Enrollment } from '../_.$orgid.enrollments.add/data' import type { Item } from './bulk' import { applyDiscount, type Coupon } from './discount' import { calcInterest, type CreditCard } from './payment' import type { Address } from './review' export type WizardState = { index: number kind: 'bulk' | 'assigned' items: Item[] enrollments: Enrollment[] coupon?: Coupon installments?: number payment_method?: PaymentMethod credit_card?: CreditCard address?: Address } type Summary = { subtotal: number discount: number interest_amount: number total: number } export type WizardStore = WizardState & { setIndex: (index: number) => void setKind: (kind: 'bulk' | 'assigned') => void update: (data: Partial) => void reset: () => void summary: () => Summary } const emptyWizard: WizardState = { index: 0, kind: 'bulk', items: [], enrollments: [], address: undefined, coupon: undefined, installments: undefined, payment_method: undefined, credit_card: undefined } export const useWizardStore = create()( persist( (set, get) => ({ ...emptyWizard, setIndex: (index) => set({ index }), setKind: (kind) => set({ kind }), summary: () => { const { items, coupon, credit_card, installments } = get() const subtotal = items.reduce( (acc, { course, quantity }) => acc + (course.unit_price || 0) * (Number.isFinite(quantity) && quantity > 0 ? quantity : 1), 0 ) const discount = coupon ? applyDiscount(subtotal, coupon.amount, coupon.type) * -1 : 0 const total = subtotal > 0 ? subtotal + discount : 0 const interest_amount = credit_card && typeof installments === 'number' && installments > 1 ? calcInterest(total, installments) - total : 0 return { subtotal, discount, interest_amount, total: total + interest_amount } }, update: (data) => set((state) => { if (data.enrollments) { const items = Object.values( data.enrollments.reduce>( (acc, { course }) => { const { id } = course acc[id] ??= { course, quantity: 0 } acc[id].quantity++ return acc }, {} ) ) return { ...state, ...data, items } } if (data.items) { const items = Object.values( data.items.reduce>((acc, item) => { const id = item.course.id if (!acc[id]) { acc[id] = { ...item } } else { acc[id].quantity += item.quantity } return acc }, {}) ) return { ...state, ...data, items, enrollments: [] } } return { ...state, ...data } }), reset: () => set({ ...emptyWizard }) }), { name: 'wizard_cart' } ) )