import React, { useState } from 'react'; import { useShippingRates, useSaveShippingRate, useDeleteShippingRate, } from '@/hooks/useShippingRates'; import { useBulkApplyRegionRate } from '@/hooks/useRegions'; import { useRegions } from '@/hooks/useRegions'; import { RateTable } from './RateTable'; import { RateForm } from './RateForm'; import { CSVImportExport } from './CSVImportExport'; import { LocationDrillDown } from './LocationDrillDown'; import { RegionManager } from './RegionManager'; import type { Province } from '@/types/address.types'; import type { Region, ShippingRate, LocationType } from '@/types/shipping.types'; interface ShippingRateManagerProps { provinces: Province[]; } type Tab = 'by_location' | 'by_region' | 'manage_regions'; // ---- Bulk-apply panel ------------------------------------------------------- // interface BulkApplyPanelProps { region: Region; provinces: Province[]; onDone: () => void; } const BulkApplyPanel: React.FC = ({ region, provinces, onDone }) => { const { mutate: bulkApply, isPending } = useBulkApplyRegionRate(); const [result, setResult] = useState<{ inserted: number; updated: number } | null>(null); const provinceMap = React.useMemo(() => { const m: Record = {}; provinces.forEach((p) => (m[p.code] = p.name)); return m; }, [provinces]); const handleSave = (rateData: Partial) => { bulkApply( { regionCode: region.region_code, rate: rateData }, { onSuccess: (res) => { setResult(res); }, } ); }; if (result) { return (

Applied successfully!

Created {result.inserted} rules and updated{' '} {result.updated} existing rules for{' '} {region.province_codes.length} provinces/cities in region{' '} {region.region_name}.

Applied provinces/cities:{' '} {region.province_codes.map((c) => provinceMap[c] || c).join(', ')}

); } return (

This rate will apply to all {region.province_codes.length} provinces/cities in region{' '} {region.region_name} as province-level rules. Existing province rules will be updated.

); }; // ---- Tab: By Region --------------------------------------------------------- // interface ByRegionTabProps { provinces: Province[]; } const ByRegionTab: React.FC = ({ provinces }) => { const { data: regions = [], isLoading: loadingRegions } = useRegions(); const [selectedRegion, setSelectedRegion] = useState(null); const [showBulkApply, setShowBulkApply] = useState(false); const [editingRate, setEditingRate] = useState(null); const [showRateForm, setShowRateForm] = useState(false); const { data: rates = [], isLoading: loadingRates, refetch: refetchRates } = useShippingRates( selectedRegion ? 'region' : undefined, selectedRegion?.region_code ); const { mutate: saveRate, isPending: isSaving } = useSaveShippingRate(); const { mutate: deleteRate, isPending: isDeleting } = useDeleteShippingRate(); const handleSaveRate = (rateData: Partial) => { saveRate(rateData, { onSuccess: () => { setShowRateForm(false); setEditingRate(null); refetchRates(); }, }); }; return (
{/* Region selector */}
{loadingRegions && Loading...}
{!selectedRegion && (

Select a region to view and manage region shipping rates.

)} {selectedRegion && ( <>
{showBulkApply && ( setShowBulkApply(false)} /> )} {showRateForm && !showBulkApply && ( { setShowRateForm(false); setEditingRate(null); }} isSaving={isSaving} /> )} { setEditingRate(r); setShowRateForm(true); setShowBulkApply(false); }} onDelete={(id) => { if (confirm('Delete this shipping rate?')) { deleteRate(id, { onSuccess: () => refetchRates() }); } }} isDeleting={isDeleting} /> )}
); }; // ---- Tab: By Location ------------------------------------------------------- // interface ByLocationTabProps { provinces: Province[]; } const ByLocationTab: React.FC = ({ provinces }) => { const [selectedProvince, setSelectedProvince] = useState(''); const [selectedDistrict, setSelectedDistrict] = useState(''); const [selectedWard, setSelectedWard] = useState(''); const [editingRate, setEditingRate] = useState(null); const [showForm, setShowForm] = useState(false); const locationType: LocationType | undefined = selectedWard ? 'ward' : selectedDistrict ? 'district' : selectedProvince ? 'province' : undefined; const locationCode = selectedWard || selectedDistrict || selectedProvince || undefined; const { data: rates = [], isLoading, refetch } = useShippingRates(locationType, locationCode); const { mutate: saveRate, isPending: isSaving } = useSaveShippingRate(); const { mutate: deleteRate, isPending: isDeleting } = useDeleteShippingRate(); const handleSave = (rateData: Partial) => { saveRate(rateData, { onSuccess: () => { setShowForm(false); setEditingRate(null); refetch(); }, }); }; return (
{ setSelectedProvince(v); setSelectedDistrict(''); setSelectedWard(''); }} onDistrictChange={(v) => { setSelectedDistrict(v); setSelectedWard(''); }} onWardChange={setSelectedWard} />
{showForm && ( { setShowForm(false); setEditingRate(null); }} isSaving={isSaving} /> )} {locationCode ? ( { setEditingRate(r); setShowForm(true); }} onDelete={(id) => { if (confirm('Delete this shipping rate?')) { deleteRate(id, { onSuccess: () => refetch() }); } }} isDeleting={isDeleting} /> ) : (

Please select a location to view and manage shipping rates.

)}
); }; // ---- Main component --------------------------------------------------------- // const tabStyle = (active: boolean): React.CSSProperties => ({ padding: '8px 20px', border: 'none', borderBottom: active ? '3px solid #2271b1' : '3px solid transparent', background: 'none', cursor: 'pointer', fontWeight: active ? 600 : 400, color: active ? '#2271b1' : '#1d2327', fontSize: '14px', transition: 'all 0.15s', }); export const ShippingRateManager: React.FC = ({ provinces }) => { const [tab, setTab] = useState('by_location'); return (

Shipping rate management

{/* Tab bar */}
{tab === 'by_location' && } {tab === 'by_region' && } {tab === 'manage_regions' && }
); };