'use client'; import { useState, useEffect } from 'react'; import { z } from 'zod'; import { zodResolver } from '@hookform/resolvers/zod'; import { useForm } from 'react-hook-form'; import { Save, X, Loader2 } from 'lucide-react'; 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 { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Switch } from '@/components/ui/switch'; import { Textarea } from '@/components/ui/textarea'; import { toast } from '@/components/ui/use-toast'; import { Promotion, PromotionFormData } from '@/lib/types/promotion'; import { fetchClient } from '@/lib/client-service'; // Form schema validation with Zod (same as NewPromotionForm) const formSchema = z.object({ code: z.string() .min(3, 'Code must be at least 3 characters') .max(20, 'Code cannot exceed 20 characters') .regex(/^[A-Za-z0-9]+$/, 'Only letters and numbers are allowed'), discountType: z.enum(['percentage', 'fixed']), discountValue: z.coerce.number() .positive('Discount value must be positive') .refine(val => val <= 100, { message: 'Percentage discount cannot exceed 100%', path: ['discountValue'], // Only validate this rule if discount type is percentage params: { type: 'percentage' }, }), minOrderAmount: z.coerce.number() .min(0, 'Minimum order amount cannot be negative'), maxUsage: z.coerce.number() .nullable() .optional(), isActive: z.boolean().default(true), startDate: z.string().optional(), endDate: z.string().nullable().optional(), description: z.string().max(200, 'Description cannot exceed 200 characters').optional(), }); interface EditPromotionFormProps { promotion: Promotion; onSuccess: () => void; onCancel: () => void; } export default function EditPromotionForm({ promotion, onSuccess, onCancel }: EditPromotionFormProps) { const [isSubmitting, setIsSubmitting] = useState(false); // Format dates from ISO to YYYY-MM-DD for input elements const formatDateForInput = (dateString: string | null) => { if (!dateString) return ''; return new Date(dateString).toISOString().split('T')[0]; }; // Initialize form with promotion values const form = useForm>({ resolver: zodResolver(formSchema), defaultValues: { code: promotion.code, discountType: promotion.discountType, discountValue: promotion.discountValue, minOrderAmount: promotion.minOrderAmount, maxUsage: promotion.maxUsage, isActive: promotion.isActive, description: promotion.description, startDate: formatDateForInput(promotion.startDate), endDate: formatDateForInput(promotion.endDate), }, }); // Form submission handler async function onSubmit(data: z.infer) { setIsSubmitting(true); try { await fetchClient(`/promotions/${promotion._id}`, { method: 'PUT', body: data, }); toast({ title: 'Success', description: 'Promotion updated successfully', }); onSuccess(); } catch (error) { console.error('Error updating promotion:', error); // Error toast is already shown by fetchClient } finally { setIsSubmitting(false); } } return (
( Promotion Code field.onChange(e.target.value.toUpperCase())} /> Enter a unique code for your promotion. Only letters and numbers. )} />
( Discount Type )} /> ( Discount Value {form.watch('discountType') === 'percentage' ? 'Enter a percentage (1-100%)' : 'Enter an amount in £'} )} /> ( Minimum Order Amount (£) Minimum purchase required )} />
( Maximum Usage Count { const value = e.target.value; field.onChange(value === '' ? null : parseInt(value, 10)); }} /> Leave empty for unlimited usage (currently used: {promotion.usageCount} times) )} /> ( Start Date )} /> ( End Date (Optional) { const value = e.target.value; field.onChange(value === '' ? null : value); }} /> Leave empty for no expiration )} />
(
Active Status Enable or disable this promotion
)} /> ( Description (Optional)