import { useEffect, useState } from 'react' import { useForm } from 'react-hook-form' import { zodResolver } from '@hookform/resolvers/zod' import { useTranslation } from 'react-i18next' import { toast } from 'sonner' import { getCurrencyDisplay, getCurrencyLabel } from '@/lib/currency' import { addTimeToDate } from '@/lib/time' import { Button } from '@/components/ui/button' import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, } from '@/components/ui/form' import { Input } from '@/components/ui/input' import { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, } from '@/components/ui/sheet' import { DateTimePicker } from '@/components/datetime-picker' import { createRedemption, updateRedemption, getRedemption } from '../api' import { SUCCESS_MESSAGES } from '../constants' import { getRedemptionFormSchema, type RedemptionFormValues, REDEMPTION_FORM_DEFAULT_VALUES, transformFormDataToPayload, transformRedemptionToFormDefaults, } from '../lib' import { type Redemption } from '../types' import { useRedemptions } from './redemptions-provider' type RedemptionsMutateDrawerProps = { open: boolean onOpenChange: (open: boolean) => void currentRow?: Redemption } export function RedemptionsMutateDrawer({ open, onOpenChange, currentRow, }: RedemptionsMutateDrawerProps) { const { t } = useTranslation() const isUpdate = !!currentRow const { triggerRefresh } = useRedemptions() const [isSubmitting, setIsSubmitting] = useState(false) const form = useForm({ resolver: zodResolver(getRedemptionFormSchema(t)), defaultValues: REDEMPTION_FORM_DEFAULT_VALUES, }) // Load existing data when updating useEffect(() => { if (open && isUpdate && currentRow) { // For update, fetch fresh data getRedemption(currentRow.id).then((result) => { if (result.success && result.data) { form.reset(transformRedemptionToFormDefaults(result.data)) } }) } else if (open && !isUpdate) { // For create, reset to defaults form.reset(REDEMPTION_FORM_DEFAULT_VALUES) } }, [open, isUpdate, currentRow, form]) const onSubmit = async (data: RedemptionFormValues) => { setIsSubmitting(true) try { const basePayload = transformFormDataToPayload(data) if (isUpdate && currentRow) { const result = await updateRedemption({ ...basePayload, id: currentRow.id, }) if (result.success) { toast.success(t(SUCCESS_MESSAGES.REDEMPTION_UPDATED)) onOpenChange(false) triggerRefresh() } } else { // Create mode const result = await createRedemption(basePayload) if (result.success) { const count = result.data?.length || 0 toast.success( count > 1 ? t('Successfully created {{count}} redemption codes', { count, }) : t(SUCCESS_MESSAGES.REDEMPTION_CREATED) ) onOpenChange(false) triggerRefresh() } } } finally { setIsSubmitting(false) } } const handleSetExpiry = (months: number, days: number, hours: number) => { const newDate = addTimeToDate(months, days, hours) form.setValue('expired_time', newDate) } const { meta: currencyMeta } = getCurrencyDisplay() const currencyLabel = getCurrencyLabel() const tokensOnly = currencyMeta.kind === 'tokens' const quotaLabel = t('Quota ({{currency}})', { currency: currencyLabel }) const quotaPlaceholder = tokensOnly ? t('Enter quota in tokens') : t('Enter quota in {{currency}}', { currency: currencyLabel }) return ( { onOpenChange(v) if (!v) { form.reset() } }} > {isUpdate ? t('Update Redemption Code') : t('Create Redemption Code')} {isUpdate ? t('Update the redemption code by providing necessary info.') : t( 'Add new redemption code(s) by providing necessary info.' )}{' '} {t('Click save when you're done.')}
( {t('Name')} {t('Name for this redemption code (1-20 characters)')} )} /> ( {quotaLabel} field.onChange(parseFloat(e.target.value) || 0) } /> {tokensOnly ? t('Enter the quota amount in tokens') : t('Enter the quota amount in {{currency}}', { currency: currencyLabel, })} )} /> ( {t('Expiration Time')}
{t('Leave empty for never expires')}
)} /> {!isUpdate && ( ( {t('Quantity')} field.onChange(parseInt(e.target.value, 10) || 1) } /> {t('Create multiple redemption codes at once (1-100)')} )} /> )}
) }