import React, { useState } from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useNavigate } from 'react-router-dom'; import { __ } from '@/lib/i18n'; import { CouponsApi, type Coupon } from '@/lib/api/coupons'; import { showErrorToast, showSuccessToast, getPageLoadErrorMessage } from '@/lib/errorHandling'; import { ErrorCard } from '@/components/ErrorCard'; import { LoadingState } from '@/components/LoadingState'; import { Card } from '@/components/ui/card'; import { Input } from '@/components/ui/input'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Checkbox } from '@/components/ui/checkbox'; import { Badge } from '@/components/ui/badge'; import { Trash2, RefreshCw, Edit, Tag } from 'lucide-react'; import { useFABConfig } from '@/hooks/useFABConfig'; export default function CouponsIndex() { const navigate = useNavigate(); const queryClient = useQueryClient(); const [page, setPage] = useState(1); const [search, setSearch] = useState(''); const [discountType, setDiscountType] = useState(''); const [selectedIds, setSelectedIds] = useState([]); // Configure FAB to navigate to new coupon page useFABConfig('navigate', '/coupons/new'); // Fetch coupons const { data, isLoading, isError, error, refetch } = useQuery({ queryKey: ['coupons', page, search, discountType], queryFn: () => CouponsApi.list({ page, per_page: 20, search, discount_type: discountType }), }); // Delete mutation const deleteMutation = useMutation({ mutationFn: (id: number) => CouponsApi.delete(id, false), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['coupons'] }); showSuccessToast(__('Coupon deleted successfully')); setSelectedIds([]); }, onError: (error) => { showErrorToast(error); }, }); // Bulk delete const handleBulkDelete = async () => { if (!confirm(__('Are you sure you want to delete the selected coupons?'))) return; for (const id of selectedIds) { await deleteMutation.mutateAsync(id); } }; // Toggle selection const toggleSelection = (id: number) => { setSelectedIds(prev => prev.includes(id) ? prev.filter(i => i !== id) : [...prev, id] ); }; // Toggle all const toggleAll = () => { if (selectedIds.length === data?.coupons.length) { setSelectedIds([]); } else { setSelectedIds(data?.coupons.map(c => c.id) || []); } }; // Format discount type const formatDiscountType = (type: string) => { const types: Record = { 'percent': __('Percentage'), 'fixed_cart': __('Fixed Cart'), 'fixed_product': __('Fixed Product'), }; return types[type] || type; }; // Format amount const formatAmount = (coupon: Coupon) => { if (coupon.discount_type === 'percent') { return `${coupon.amount}%`; } return `Rp${coupon.amount.toLocaleString('id-ID')}`; }; if (isLoading) { return ; } if (isError) { return ( refetch()} /> ); } const coupons = data?.coupons || []; const hasActiveFilters = search || discountType; return (
{/* Toolbar */}
{/* Left: Bulk Actions */}
{/* Delete - Show only when items selected */} {selectedIds.length > 0 && ( )} {/* Refresh - Always visible (REQUIRED per SOP) */}
{/* Right: Filters */}
{/* Discount Type Filter */} {/* Search */} setSearch(e.target.value)} className="w-[200px]" /> {/* Reset Filters - Text link style per SOP */} {hasActiveFilters && ( )}
{/* Desktop Table */}
{coupons.length === 0 ? ( ) : ( coupons.map((coupon) => ( )) )}
0} onCheckedChange={toggleAll} /> {__('Code')} {__('Type')} {__('Amount')} {__('Usage')} {__('Expires')} {__('Actions')}
{hasActiveFilters ? __('No coupons found matching your filters') : __('No coupons yet')} {!hasActiveFilters && (

{__('Create your first coupon to get started')}

)}
toggleSelection(coupon.id)} />
{coupon.code}
{coupon.description && (
{coupon.description}
)}
{formatDiscountType(coupon.discount_type)} {formatAmount(coupon)}
{coupon.usage_count} / {coupon.usage_limit || '∞'}
{coupon.date_expires ? (
{new Date(coupon.date_expires).toLocaleDateString('id-ID')}
) : (
{__('No expiry')}
)}
{/* Mobile Cards */}
{coupons.length === 0 ? ( {hasActiveFilters ? __('No coupons found matching your filters') : __('No coupons yet')} {!hasActiveFilters && (

{__('Create your first coupon to get started')}

)}
) : ( coupons.map((coupon) => (
toggleSelection(coupon.id)} />
{coupon.code}
{formatDiscountType(coupon.discount_type)}
{formatAmount(coupon)}
{coupon.description && (

{coupon.description}

)}
{__('Usage')}: {coupon.usage_count} / {coupon.usage_limit || '∞'}
{coupon.date_expires && (
{__('Expires')}: {new Date(coupon.date_expires).toLocaleDateString('id-ID')}
)}
)) )}
{/* Pagination */} {data && data.total_pages > 1 && (
{__('Page')} {page} {__('of')} {data.total_pages}
)}
); }