import React, { useState } from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { api } from '@/lib/api'; import { SettingsLayout } from './components/SettingsLayout'; import { SettingsCard } from './components/SettingsCard'; import { ToggleField } from './components/ToggleField'; import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Drawer, DrawerContent, DrawerHeader, DrawerTitle } from '@/components/ui/drawer'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Globe, Truck, MapPin, Edit, Trash2, RefreshCw, Loader2, ExternalLink, Settings, Plus, X } from 'lucide-react'; import { toast } from 'sonner'; import { __ } from '@/lib/i18n'; import { useMediaQuery } from '@/hooks/use-media-query'; interface ShippingRate { id: string; name: string; price: string; condition?: string; transitTime?: string; } interface ShippingZone { id: string; name: string; regions: string; rates: ShippingRate[]; } export default function ShippingPage() { const queryClient = useQueryClient(); const wcAdminUrl = (window as any).WNW_CONFIG?.wpAdminUrl || '/wp-admin'; const [togglingMethod, setTogglingMethod] = useState(null); const [selectedZone, setSelectedZone] = useState(null); const [isModalOpen, setIsModalOpen] = useState(false); const [activeTab, setActiveTab] = useState('methods'); const [showAddMethod, setShowAddMethod] = useState(false); const isDesktop = useMediaQuery("(min-width: 768px)"); // Fetch shipping zones from WooCommerce const { data: zones = [], isLoading, refetch } = useQuery({ queryKey: ['shipping-zones'], queryFn: () => api.get('/settings/shipping/zones'), staleTime: 5 * 60 * 1000, // 5 minutes }); // Fetch available shipping methods const { data: availableMethods = [] } = useQuery({ queryKey: ['available-shipping-methods'], queryFn: () => api.get('/settings/shipping/methods/available'), enabled: showAddMethod, }); // Toggle shipping method mutation const toggleMutation = useMutation({ mutationFn: async ({ zoneId, instanceId, enabled }: { zoneId: number; instanceId: number; enabled: boolean }) => { return api.post(`/settings/shipping/zones/${zoneId}/methods/${instanceId}/toggle`, { enabled }); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['shipping-zones'] }); toast.success(__('Shipping method updated successfully')); }, onError: (error: any) => { toast.error(error?.message || __('Failed to update shipping method')); }, onSettled: () => { setTogglingMethod(null); }, }); // Add shipping method mutation const addMethodMutation = useMutation({ mutationFn: async ({ zoneId, methodId }: { zoneId: number; methodId: string }) => { return api.post(`/settings/shipping/zones/${zoneId}/methods`, { method_id: methodId }); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['shipping-zones'] }); toast.success(__('Shipping method added successfully')); setShowAddMethod(false); }, onError: (error: any) => { toast.error(error?.message || __('Failed to add shipping method')); }, }); // Delete shipping method mutation const deleteMethodMutation = useMutation({ mutationFn: async ({ zoneId, instanceId }: { zoneId: number; instanceId: number }) => { return api.delete(`/settings/shipping/zones/${zoneId}/methods/${instanceId}`); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['shipping-zones'] }); toast.success(__('Shipping method deleted successfully')); }, onError: (error: any) => { toast.error(error?.message || __('Failed to delete shipping method')); }, }); const handleToggle = (zoneId: number, instanceId: number, enabled: boolean) => { setTogglingMethod(`${zoneId}-${instanceId}`); toggleMutation.mutate({ zoneId, instanceId, enabled }); }; const handleAddMethod = (methodId: string) => { if (selectedZone) { addMethodMutation.mutate({ zoneId: selectedZone.id, methodId }); } }; const handleDeleteMethod = (instanceId: number) => { if (selectedZone && confirm(__('Are you sure you want to delete this shipping method?'))) { deleteMethodMutation.mutate({ zoneId: selectedZone.id, instanceId }); } }; if (isLoading) { return (
); } return ( refetch()} disabled={isLoading} > {__('Refresh')} } > {/* Shipping Zones */} {zones.length === 0 ? (

{__('No shipping zones configured yet.')}

) : (
{zones.map((zone: any) => (

{zone.name}

{zone.regions}

{zone.rates.length} {zone.rates.length === 1 ? 'method' : 'methods'}

{/* Shipping Rates */}
{zone.rates?.map((rate: any) => (
{rate.transitTime && ( • {rate.transitTime} )} {rate.condition && ( • {rate.condition} )}
handleToggle(zone.id, rate.instance_id, checked)} disabled={togglingMethod === `${zone.id}-${rate.instance_id}`} />
))}
))}
)}
{/* Help Card */}

💡 {__('Shipping tips')}

  • • {__('Offer free shipping for orders above a certain amount to increase average order value')}
  • • {__('Provide multiple shipping options to give customers flexibility')}
  • • {__('Set realistic delivery estimates to manage customer expectations')}
  • • {__('Configure detailed shipping settings in WooCommerce for full control')}
{/* Settings Modal/Drawer */} {selectedZone && ( isDesktop ? ( {selectedZone.name}

{selectedZone.regions}

{__('Shipping Methods')} {__('Zone Details')}
{/* Add Method Button */} {/* Methods List */}
{selectedZone.rates?.map((rate: any) => (
{__('Cost')}:{' '}
{rate.enabled ? __('Active') : __('Inactive')}
))}

{__('Zone Name')}

{selectedZone.name}

{__('Regions')}

{selectedZone.regions}

{__('Zone Order')}

{selectedZone.order}

{__('Priority in shipping calculations')}

{__('To edit zone name, regions, or order, use WooCommerce.')}

) : ( {selectedZone.name}

{selectedZone.regions}

{/* Zone Summary */}

{__('Zone Order')}

{__('Priority in shipping calculations')}

{selectedZone.order}
{/* Shipping Methods */}

{__('Shipping Methods')}

{selectedZone.rates?.length} {selectedZone.rates?.length === 1 ? 'method' : 'methods'}
{selectedZone.rates?.map((rate: any) => (
{__('Cost')}:{' '}
{rate.enabled ? __('Active') : __('Inactive')}
))}
) )} {/* Add Method Dialog */} {__('Add Shipping Method')}

{__('Select a shipping method to add to this zone:')}

{availableMethods.map((method: any) => ( ))}
); }