freshyo/apps/admin-web/src/routes/dashboard.coupons.$id.edit.tsx
2026-09-06 23:05:20 +05:30

126 lines
4 KiB
TypeScript

import React from 'react'
import { createFileRoute } from '@tanstack/react-router'
import { AppContainer, p as MyText } from 'web-components'
import CouponForm from '../components/CouponForm'
import { trpc } from '@/lib/trpc-client'
import { ErrorToast } from '@/services/toaster'
import dayjs from 'dayjs'
// Ported from common-ui/shared-types (CreateCouponPayload) — @packages/shared
// does not export it, so the shape is copied here to keep behavior identical.
interface CreateCouponPayload {
couponCodes: string[],
discountPercent?: number,
flatDiscount?: number,
minOrder?: number,
maxValue?: number,
validTill?: string,
maxLimitForUser?: number,
isApplyForAll: boolean,
isUserBased: boolean,
targetUsers?: number[],
productIds?: number[],
skuIds?: number[],
applicableUsers?: number[],
applicableProducts?: number[],
exclusiveApply?: boolean
}
export const Route = createFileRoute('/dashboard/coupons/$id/edit')({
component: EditCoupon,
})
function EditCoupon() {
const { id } = Route.useParams()
const couponId = parseInt(id as string)
const { data: coupon, isLoading, refetch } = trpc.admin.coupon.getById.useQuery({ id: couponId })
const { refetch: refetchCoupons } = trpc.admin.coupon.getAll.useInfiniteQuery(
{ limit: 20, search: '' },
{
enabled: false,
getNextPageParam: (lastPage) => lastPage.nextCursor,
}
)
const { refetch: refetchReservedCoupons } = trpc.admin.coupon.getReservedCoupons.useInfiniteQuery(
{ limit: 20, search: '' },
{
enabled: false,
getNextPageParam: (lastPage) => lastPage.nextCursor,
}
)
const updateCoupon = trpc.admin.coupon.update.useMutation()
const handleUpdateCoupon = (values: CreateCouponPayload & { isReservedCoupon?: boolean }) => {
// Transform targetUsers array to targetUser for backend compatibility
const { targetUsers, ...rest } = values
const updates = {
...rest,
targetUser: targetUsers?.[0] || undefined,
}
// For flat discounts, send the discount value as maxValue too
if (updates.flatDiscount !== undefined) {
updates.maxValue = updates.flatDiscount
}
updateCoupon.mutate({ id: couponId, updates }, {
onSuccess: async () => {
await refetch()
await refetchCoupons()
await refetchReservedCoupons()
window.alert('Success: Coupon updated successfully')
window.history.back()
},
onError: (error: any) => {
ErrorToast(error.message || 'Failed to update coupon')
},
})
}
if (isLoading) {
return (
<AppContainer>
<div className="flex flex-1 flex-col items-center justify-center">
<MyText>Loading...</MyText>
</div>
</AppContainer>
)
}
if (!coupon) {
return (
<AppContainer>
<div className="flex flex-1 flex-col items-center justify-center">
<MyText>Coupon not found</MyText>
</div>
</AppContainer>
)
}
// Transform coupon data for form (targetUser to targetUsers array)
const initialValues: Partial<CreateCouponPayload & { isReservedCoupon?: boolean }> = {
couponCodes: coupon.couponCode ? [coupon.couponCode] : [''],
isUserBased: coupon.isUserBased,
isApplyForAll: coupon.isApplyForAll,
targetUsers: coupon.targetUser ? [coupon.targetUser.id] : [],
discountPercent: coupon.discountPercent ? parseFloat(coupon.discountPercent) : undefined,
flatDiscount: coupon.flatDiscount ? parseFloat(coupon.flatDiscount) : undefined,
minOrder: coupon.minOrder ? parseFloat(coupon.minOrder) : undefined,
maxValue: coupon.maxValue ? parseFloat(coupon.maxValue) : undefined,
validTill: coupon.validTill ? dayjs(coupon.validTill).format('YYYY-MM-DD') : undefined,
maxLimitForUser: coupon.maxLimitForUser || undefined,
skuIds: coupon.skuIds,
isReservedCoupon: false, // Normal coupons
}
return (
<AppContainer>
<CouponForm
initialValues={initialValues}
onSubmit={handleUpdateCoupon}
isLoading={updateCoupon.isPending}
/>
</AppContainer>
)
}