feat: Tax route fix + Local Pickup + Email/Notifications settings
## 1. Fixed Tax Settings Route ✅ - Changed /settings/taxes → /settings/tax in nav tree - Now matches App.tsx route - Tax page now loads correctly ## 2. Advanced Local Pickup ✅ Frontend (LocalPickup.tsx): - Add/edit/delete pickup locations - Enable/disable locations - Full address fields (street, city, state, postcode) - Phone number and business hours - Clean modal UI for adding locations Backend (PickupLocationsController.php): - GET /settings/pickup-locations - POST /settings/pickup-locations (create) - POST /settings/pickup-locations/:id (update) - DELETE /settings/pickup-locations/:id - POST /settings/pickup-locations/:id/toggle - Stores in wp_options as array ## 3. Email/Notifications Settings ✅ Frontend (Notifications.tsx): - List all WooCommerce emails - Separate customer vs admin emails - Enable/disable toggle for each email - Show from name/email - Link to WooCommerce for advanced config Backend (EmailController.php): - GET /settings/emails - List all emails - POST /settings/emails/:id/toggle - Enable/disable - Uses WC()->mailer()->get_emails() - Auto-detects recipient type (customer/admin) ## Features: ✅ Simple, non-tech-savvy UI ✅ All CRUD operations ✅ Real-time updates ✅ Links to WooCommerce for advanced settings ✅ Mobile responsive Next: Test all settings pages
This commit is contained in:
228
admin-spa/src/routes/Settings/Notifications.tsx
Normal file
228
admin-spa/src/routes/Settings/Notifications.tsx
Normal file
@@ -0,0 +1,228 @@
|
||||
import React 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 { ExternalLink, RefreshCw, Mail } from 'lucide-react';
|
||||
import { toast } from 'sonner';
|
||||
import { __ } from '@/lib/i18n';
|
||||
|
||||
export default function NotificationsSettings() {
|
||||
const queryClient = useQueryClient();
|
||||
const wcAdminUrl = (window as any).WNW_CONFIG?.wpAdminUrl || '/wp-admin';
|
||||
|
||||
// Fetch email settings
|
||||
const { data: settings, isLoading, refetch } = useQuery({
|
||||
queryKey: ['email-settings'],
|
||||
queryFn: () => api.get('/settings/emails'),
|
||||
});
|
||||
|
||||
// Toggle email mutation
|
||||
const toggleMutation = useMutation({
|
||||
mutationFn: async ({ emailId, enabled }: { emailId: string; enabled: boolean }) => {
|
||||
return api.post(`/settings/emails/${emailId}/toggle`, { enabled });
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['email-settings'] });
|
||||
toast.success(__('Email settings updated'));
|
||||
},
|
||||
onError: (error: any) => {
|
||||
toast.error(error?.message || __('Failed to update email settings'));
|
||||
},
|
||||
});
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<SettingsLayout
|
||||
title={__('Notifications')}
|
||||
description={__('Manage email notifications sent to customers and admins')}
|
||||
>
|
||||
<div className="flex items-center justify-center py-12">
|
||||
<RefreshCw className="h-6 w-6 animate-spin text-muted-foreground" />
|
||||
</div>
|
||||
</SettingsLayout>
|
||||
);
|
||||
}
|
||||
|
||||
const customerEmails = settings?.emails?.filter((e: any) => e.recipient === 'customer') || [];
|
||||
const adminEmails = settings?.emails?.filter((e: any) => e.recipient === 'admin') || [];
|
||||
|
||||
return (
|
||||
<SettingsLayout
|
||||
title={__('Notifications')}
|
||||
description={__('Manage email notifications sent to customers and admins')}
|
||||
action={
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => refetch()}
|
||||
>
|
||||
<RefreshCw className="h-4 w-4 mr-2" />
|
||||
{__('Refresh')}
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
<div className="space-y-6">
|
||||
{/* Customer Emails */}
|
||||
<SettingsCard
|
||||
title={__('Customer Notifications')}
|
||||
description={__('Emails sent to customers about their orders')}
|
||||
>
|
||||
<div className="space-y-4">
|
||||
{customerEmails.map((email: any) => (
|
||||
<div key={email.id} className="flex items-start justify-between py-3 border-b last:border-0">
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<Mail className="h-4 w-4 text-muted-foreground" />
|
||||
<h3 className="font-medium">{email.title}</h3>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground">{email.description}</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<ToggleField
|
||||
checked={email.enabled === 'yes'}
|
||||
onChange={(checked) => toggleMutation.mutate({
|
||||
emailId: email.id,
|
||||
enabled: checked
|
||||
})}
|
||||
disabled={toggleMutation.isPending}
|
||||
/>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
asChild
|
||||
>
|
||||
<a
|
||||
href={`${wcAdminUrl}/admin.php?page=wc-settings&tab=email§ion=${email.id}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<ExternalLink className="h-4 w-4" />
|
||||
</a>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</SettingsCard>
|
||||
|
||||
{/* Admin Emails */}
|
||||
<SettingsCard
|
||||
title={__('Admin Notifications')}
|
||||
description={__('Emails sent to store administrators')}
|
||||
>
|
||||
<div className="space-y-4">
|
||||
{adminEmails.map((email: any) => (
|
||||
<div key={email.id} className="flex items-start justify-between py-3 border-b last:border-0">
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<Mail className="h-4 w-4 text-muted-foreground" />
|
||||
<h3 className="font-medium">{email.title}</h3>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground">{email.description}</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<ToggleField
|
||||
checked={email.enabled === 'yes'}
|
||||
onChange={(checked) => toggleMutation.mutate({
|
||||
emailId: email.id,
|
||||
enabled: checked
|
||||
})}
|
||||
disabled={toggleMutation.isPending}
|
||||
/>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
asChild
|
||||
>
|
||||
<a
|
||||
href={`${wcAdminUrl}/admin.php?page=wc-settings&tab=email§ion=${email.id}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<ExternalLink className="h-4 w-4" />
|
||||
</a>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</SettingsCard>
|
||||
|
||||
{/* Email Sender Settings */}
|
||||
<SettingsCard
|
||||
title={__('Email Sender')}
|
||||
description={__('Configure who emails are sent from')}
|
||||
>
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center justify-between py-2">
|
||||
<div>
|
||||
<p className="font-medium text-sm">{__('From Name')}</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{settings?.from_name || __('Not configured')}
|
||||
</p>
|
||||
</div>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
asChild
|
||||
>
|
||||
<a
|
||||
href={`${wcAdminUrl}/admin.php?page=wc-settings&tab=email`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{__('Change')}
|
||||
</a>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between py-2 border-t">
|
||||
<div>
|
||||
<p className="font-medium text-sm">{__('From Email')}</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{settings?.from_email || __('Not configured')}
|
||||
</p>
|
||||
</div>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
asChild
|
||||
>
|
||||
<a
|
||||
href={`${wcAdminUrl}/admin.php?page=wc-settings&tab=email`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{__('Change')}
|
||||
</a>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</SettingsCard>
|
||||
|
||||
{/* Advanced Settings Link */}
|
||||
<div className="rounded-lg border border-dashed p-6 text-center">
|
||||
<p className="text-sm text-muted-foreground mb-4">
|
||||
{__('For email templates, styling, and advanced configuration, use the WooCommerce settings page')}
|
||||
</p>
|
||||
<Button
|
||||
variant="outline"
|
||||
asChild
|
||||
>
|
||||
<a
|
||||
href={`${wcAdminUrl}/admin.php?page=wc-settings&tab=email`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<ExternalLink className="h-4 w-4 mr-2" />
|
||||
{__('Open Email Settings in WooCommerce')}
|
||||
</a>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</SettingsLayout>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user