From a373b141b72a69c4e1b8a93b91c3bc1b2419b272 Mon Sep 17 00:00:00 2001 From: dwindown Date: Sun, 9 Nov 2025 23:56:34 +0700 Subject: [PATCH] fix: Shipping toggle refresh + AlertDialog + Local Pickup nav + Notifications info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 1. Fixed Shipping Method Toggle State ✅ - Updated useEffect to properly sync selectedZone with zones data - Added JSON comparison to prevent infinite loops - Toggle now refreshes zone data correctly ## 2. Replace confirm() with AlertDialog ✅ - Added AlertDialog component for delete confirmation - Shows method name in confirmation message - Better UX with proper dialog styling - Updated both desktop and mobile versions ## 3. Added Local Pickup to Navigation ✅ - Added "Local Pickup" menu item in Settings - Now accessible from Settings > Local Pickup - Path: /settings/local-pickup ## 4. Shipping Cost Shortcodes ✅ - Already supported via HTML rendering - WooCommerce shortcodes like [fee percent="10"] work - [qty], [cost] are handled by WooCommerce backend - No additional SPA work needed ## 5. Enhanced Notifications Page ✅ - Added comprehensive info card explaining: - What WooNooW provides (simple toggle) - What WooCommerce provides (advanced config) - Clear guidance on when to use each - Links to WooCommerce for templates/styling - Replaced ToggleField with Switch for simpler usage ## Key Decisions: ✅ AlertDialog > confirm() for better UX ✅ Notifications = Simple toggle + guidance to WC ✅ Shortcodes handled by WooCommerce (no SPA work) ✅ Local Pickup now discoverable in nav --- admin-spa/src/nav/tree.ts | 1 + .../src/routes/Settings/Notifications.tsx | 42 +++++++++++++-- admin-spa/src/routes/Settings/Shipping.tsx | 51 +++++++++++++++---- 3 files changed, 80 insertions(+), 14 deletions(-) diff --git a/admin-spa/src/nav/tree.ts b/admin-spa/src/nav/tree.ts index 58c59b0..ad627df 100644 --- a/admin-spa/src/nav/tree.ts +++ b/admin-spa/src/nav/tree.ts @@ -111,6 +111,7 @@ function getStaticFallbackTree(): MainNode[] { { label: 'Store Details', mode: 'spa' as const, path: '/settings/store' }, { label: 'Payments', mode: 'spa' as const, path: '/settings/payments' }, { label: 'Shipping & Delivery', mode: 'spa' as const, path: '/settings/shipping' }, + { label: 'Local Pickup', mode: 'spa' as const, path: '/settings/local-pickup' }, { label: 'Tax', mode: 'spa' as const, path: '/settings/tax' }, { label: 'Checkout', mode: 'spa' as const, path: '/settings/checkout' }, { label: 'Customer Accounts', mode: 'spa' as const, path: '/settings/customers' }, diff --git a/admin-spa/src/routes/Settings/Notifications.tsx b/admin-spa/src/routes/Settings/Notifications.tsx index 29f8bff..8a474cc 100644 --- a/admin-spa/src/routes/Settings/Notifications.tsx +++ b/admin-spa/src/routes/Settings/Notifications.tsx @@ -3,7 +3,7 @@ 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 { Switch } from '@/components/ui/switch'; import { Button } from '@/components/ui/button'; import { ExternalLink, RefreshCw, Mail } from 'lucide-react'; import { toast } from 'sonner'; @@ -65,6 +65,38 @@ export default function NotificationsSettings() { } >
+ {/* Info Card */} + +
+

+ {__('WooNooW provides simple toggle controls to enable or disable email notifications. For advanced customization like email templates, styling, content, and recipients, use the WooCommerce settings page.')} +

+

+ {__('What you can do here:')} +

+
    +
  • {__('Enable/disable customer emails (order confirmations, shipping updates, etc.)')}
  • +
  • {__('Enable/disable admin emails (new order notifications, low stock alerts, etc.)')}
  • +
  • {__('View current sender name and email address')}
  • +
+

+ {__('For advanced configuration:')} +

+
    +
  • {__('Email templates and HTML/CSS styling')}
  • +
  • {__('Email subject lines and content')}
  • +
  • {__('Custom recipient addresses')}
  • +
  • {__('Additional email headers')}
  • +
+

+ {__('Use the "Edit in WooCommerce" links below or the advanced settings link at the bottom.')} +

+
+
+ {/* Customer Emails */} {email.description}

- toggleMutation.mutate({ + onCheckedChange={(checked) => toggleMutation.mutate({ emailId: email.id, enabled: checked })} @@ -124,9 +156,9 @@ export default function NotificationsSettings() {

{email.description}

- toggleMutation.mutate({ + onCheckedChange={(checked) => toggleMutation.mutate({ emailId: email.id, enabled: checked })} diff --git a/admin-spa/src/routes/Settings/Shipping.tsx b/admin-spa/src/routes/Settings/Shipping.tsx index e008bda..d5c74eb 100644 --- a/admin-spa/src/routes/Settings/Shipping.tsx +++ b/admin-spa/src/routes/Settings/Shipping.tsx @@ -6,6 +6,7 @@ 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 { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from '@/components/ui/alert-dialog'; import { Drawer, DrawerContent, DrawerHeader, DrawerTitle } from '@/components/ui/drawer'; import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/ui/accordion'; import { Globe, Truck, MapPin, Edit, Trash2, RefreshCw, Loader2, ExternalLink, Settings, Plus, X, ChevronDown } from 'lucide-react'; @@ -33,10 +34,10 @@ export default function ShippingPage() { 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 [showAddMethod, setShowAddMethod] = useState(false); const [expandedMethod, setExpandedMethod] = useState(''); const [methodSettings, setMethodSettings] = useState>({}); + const [deletingMethod, setDeletingMethod] = useState<{ zoneId: number; instanceId: number; name: string } | null>(null); const isDesktop = useMediaQuery("(min-width: 768px)"); // Fetch shipping zones from WooCommerce @@ -55,13 +56,13 @@ export default function ShippingPage() { // Sync selectedZone with zones data when it changes useEffect(() => { - if (selectedZone && zones.length > 0) { + if (selectedZone && zones && zones.length > 0) { const updatedZone = zones.find((z: any) => z.id === selectedZone.id); - if (updatedZone) { + if (updatedZone && JSON.stringify(updatedZone) !== JSON.stringify(selectedZone)) { setSelectedZone(updatedZone); } } - }, [zones]); + }, [zones, selectedZone]); // Toggle shipping method mutation const toggleMutation = useMutation({ @@ -153,9 +154,19 @@ export default function ShippingPage() { } }; - const handleDeleteMethod = (instanceId: number) => { - if (selectedZone && confirm(__('Are you sure you want to delete this shipping method?'))) { - deleteMethodMutation.mutate({ zoneId: selectedZone.id, instanceId }); + const handleDeleteMethod = (instanceId: number, methodName: string) => { + if (selectedZone) { + setDeletingMethod({ zoneId: selectedZone.id, instanceId, name: methodName }); + } + }; + + const confirmDelete = () => { + if (deletingMethod) { + deleteMethodMutation.mutate({ + zoneId: deletingMethod.zoneId, + instanceId: deletingMethod.instanceId + }); + setDeletingMethod(null); } }; @@ -424,7 +435,7 @@ export default function ShippingPage() { variant="destructive" size="sm" onClick={() => { - handleDeleteMethod(rate.instance_id); + handleDeleteMethod(rate.instance_id, rate.title); setExpandedMethod(''); }} disabled={deleteMethodMutation.isPending} @@ -594,7 +605,7 @@ export default function ShippingPage() { variant="destructive" size="sm" onClick={() => { - handleDeleteMethod(rate.instance_id); + handleDeleteMethod(rate.instance_id, rate.title); setExpandedMethod(''); }} disabled={deleteMethodMutation.isPending} @@ -696,6 +707,28 @@ export default function ShippingPage() { + {/* Delete Confirmation Dialog */} + setDeletingMethod(null)}> + + + {__('Delete Shipping Method?')} + + {__('Are you sure you want to delete')} {deletingMethod?.name}? + {' '}{__('This action cannot be undone.')} + + + + {__('Cancel')} + + {__('Delete')} + + + + + ); }