import { useState, useEffect } from "react"; import { supabase } from "@/integrations/supabase/client"; import { useToast } from "@/hooks/use-toast"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Switch } from "@/components/ui/switch"; import { Badge } from "@/components/ui/badge"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Plus, Pencil, Trash2, Ticket, RefreshCw, Copy } from "lucide-react"; interface DiscountCode { id: string; code: string; description: string | null; discount_type: string; discount_value: number; min_order_amount: number; max_uses: number | null; current_uses: number; valid_from: string; valid_until: string | null; is_active: boolean; created_at: string; } const DiscountCodesTab = () => { const { toast } = useToast(); const [codes, setCodes] = useState([]); const [loading, setLoading] = useState(true); const [dialogOpen, setDialogOpen] = useState(false); const [editingCode, setEditingCode] = useState(null); const [saving, setSaving] = useState(false); const [formData, setFormData] = useState({ code: "", description: "", discount_type: "percentage", discount_value: "", min_order_amount: "0", max_uses: "", valid_until: "", is_active: true, }); useEffect(() => { fetchCodes(); }, []); const fetchCodes = async () => { setLoading(true); try { const { data, error } = await supabase .from("discount_codes") .select("*") .order("created_at", { ascending: false }); if (error) throw error; setCodes(data || []); } catch (error) { console.error("Failed to fetch discount codes:", error); toast({ title: "Error", description: "Failed to load discount codes.", variant: "destructive", }); } finally { setLoading(false); } }; const resetForm = () => { setFormData({ code: "", description: "", discount_type: "percentage", discount_value: "", min_order_amount: "0", max_uses: "", valid_until: "", is_active: true, }); setEditingCode(null); }; const generateCode = () => { const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; let code = ""; for (let i = 0; i < 8; i++) { code += chars.charAt(Math.floor(Math.random() * chars.length)); } setFormData({ ...formData, code }); }; const openEditDialog = (code: DiscountCode) => { setEditingCode(code); setFormData({ code: code.code, description: code.description || "", discount_type: code.discount_type, discount_value: code.discount_value.toString(), min_order_amount: code.min_order_amount.toString(), max_uses: code.max_uses?.toString() || "", valid_until: code.valid_until ? code.valid_until.split("T")[0] : "", is_active: code.is_active, }); setDialogOpen(true); }; const handleSubmit = async () => { if (!formData.code || !formData.discount_value) { toast({ title: "Validation Error", description: "Code and discount value are required.", variant: "destructive", }); return; } setSaving(true); try { const codeData = { code: formData.code.toUpperCase().trim(), description: formData.description.trim() || null, discount_type: formData.discount_type, discount_value: parseFloat(formData.discount_value), min_order_amount: parseFloat(formData.min_order_amount) || 0, max_uses: formData.max_uses ? parseInt(formData.max_uses) : null, valid_until: formData.valid_until ? new Date(formData.valid_until).toISOString() : null, is_active: formData.is_active, }; if (editingCode) { const { error } = await supabase .from("discount_codes") .update(codeData) .eq("id", editingCode.id); if (error) throw error; toast({ title: "Success", description: "Discount code updated." }); } else { const { error } = await supabase.from("discount_codes").insert(codeData); if (error) throw error; toast({ title: "Success", description: "Discount code created." }); } setDialogOpen(false); resetForm(); fetchCodes(); } catch (error: any) { console.error("Failed to save discount code:", error); toast({ title: "Error", description: error.message || "Failed to save discount code.", variant: "destructive", }); } finally { setSaving(false); } }; const handleDelete = async (id: string) => { if (!confirm("Are you sure you want to delete this discount code?")) return; try { const { error } = await supabase.from("discount_codes").delete().eq("id", id); if (error) throw error; toast({ title: "Success", description: "Discount code deleted." }); fetchCodes(); } catch (error) { console.error("Failed to delete discount code:", error); toast({ title: "Error", description: "Failed to delete discount code.", variant: "destructive", }); } }; const copyCode = (code: string) => { navigator.clipboard.writeText(code); toast({ title: "Copied!", description: `Code "${code}" copied to clipboard.` }); }; const toggleActive = async (code: DiscountCode) => { try { const { error } = await supabase .from("discount_codes") .update({ is_active: !code.is_active }) .eq("id", code.id); if (error) throw error; fetchCodes(); } catch (error) { console.error("Failed to toggle code:", error); } }; const isExpired = (validUntil: string | null) => { if (!validUntil) return false; return new Date(validUntil) < new Date(); }; return ( Discount Codes
{ setDialogOpen(open); if (!open) resetForm(); }}> {editingCode ? "Edit Discount Code" : "Create Discount Code"} {editingCode ? "Update discount code details." : "Create a new discount code for customers."}
setFormData({ ...formData, code: e.target.value.toUpperCase() })} placeholder="SAVE20" className="font-mono" />
setFormData({ ...formData, description: e.target.value })} placeholder="Summer sale discount" />
setFormData({ ...formData, discount_value: e.target.value })} placeholder={formData.discount_type === "percentage" ? "20" : "10.00"} />
setFormData({ ...formData, min_order_amount: e.target.value })} placeholder="0" />
setFormData({ ...formData, max_uses: e.target.value })} placeholder="Unlimited" />
setFormData({ ...formData, valid_until: e.target.value })} />
setFormData({ ...formData, is_active: checked })} />
{loading ? (
Loading...
) : codes.length === 0 ? (

No discount codes yet

) : ( Code Discount Uses Expires Status Actions {codes.map((code) => (
{code.code}
{code.discount_type === "percentage" ? `${code.discount_value}%` : `$${Number(code.discount_value).toFixed(2)}`} {code.current_uses}{code.max_uses ? `/${code.max_uses}` : ""} {code.valid_until ? new Date(code.valid_until).toLocaleDateString() : "Never"} {isExpired(code.valid_until) ? ( Expired ) : ( toggleActive(code)} > {code.is_active ? "Active" : "Inactive"} )}
))}
)}
); }; export default DiscountCodesTab;