diff --git a/admin-spa/src/App.tsx b/admin-spa/src/App.tsx
index 3450949..2676a5f 100644
--- a/admin-spa/src/App.tsx
+++ b/admin-spa/src/App.tsx
@@ -202,6 +202,7 @@ import SettingsCustomers from '@/routes/Settings/Customers';
import SettingsLocalPickup from '@/routes/Settings/LocalPickup';
import SettingsNotifications from '@/routes/Settings/Notifications';
import StaffNotifications from '@/routes/Settings/Notifications/Staff';
+import CustomerNotifications from '@/routes/Settings/Notifications/Customer';
import SettingsDeveloper from '@/routes/Settings/Developer';
import MorePage from '@/routes/More';
@@ -490,6 +491,7 @@ function AppRoutes() {
} />
} />
} />
+ } />
} />
} />
diff --git a/admin-spa/src/routes/Settings/Notifications/Customer.tsx b/admin-spa/src/routes/Settings/Notifications/Customer.tsx
new file mode 100644
index 0000000..388efab
--- /dev/null
+++ b/admin-spa/src/routes/Settings/Notifications/Customer.tsx
@@ -0,0 +1,49 @@
+import React, { useState } from 'react';
+import { Link } from 'react-router-dom';
+import { SettingsLayout } from '../components/SettingsLayout';
+import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
+import { Button } from '@/components/ui/button';
+import { __ } from '@/lib/i18n';
+import { ChevronLeft } from 'lucide-react';
+import CustomerChannels from './Customer/Channels';
+import CustomerEvents from './Customer/Events';
+import NotificationTemplates from './Templates';
+
+export default function CustomerNotifications() {
+ const [activeTab, setActiveTab] = useState('channels');
+
+ return (
+
+
+
+ {__('Back to Notifications')}
+
+
+ }
+ >
+
+
+ {__('Channels')}
+ {__('Events')}
+ {__('Templates')}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/admin-spa/src/routes/Settings/Notifications/Customer/Channels.tsx b/admin-spa/src/routes/Settings/Notifications/Customer/Channels.tsx
new file mode 100644
index 0000000..d7bcba2
--- /dev/null
+++ b/admin-spa/src/routes/Settings/Notifications/Customer/Channels.tsx
@@ -0,0 +1,160 @@
+import React from 'react';
+import { useQuery } from '@tanstack/react-query';
+import { api } from '@/lib/api';
+import { SettingsCard } from '../../components/SettingsCard';
+import { Badge } from '@/components/ui/badge';
+import { Button } from '@/components/ui/button';
+import { Alert, AlertDescription } from '@/components/ui/alert';
+import { RefreshCw, Mail, Bell, MessageSquare, Info } from 'lucide-react';
+import { __ } from '@/lib/i18n';
+
+interface NotificationChannel {
+ id: string;
+ label: string;
+ icon: string;
+ enabled: boolean;
+ builtin?: boolean;
+ addon?: string;
+}
+
+export default function CustomerChannels() {
+ // Fetch channels
+ const { data: channels, isLoading } = useQuery({
+ queryKey: ['notification-channels'],
+ queryFn: () => api.get('/notifications/channels'),
+ });
+
+ const getChannelIcon = (channelId: string) => {
+ switch (channelId) {
+ case 'email':
+ return ;
+ case 'push':
+ return ;
+ case 'sms':
+ return ;
+ default:
+ return ;
+ }
+ };
+
+ if (isLoading) {
+ return (
+
+
+
+ );
+ }
+
+ const builtinChannels = (channels || []).filter((c: NotificationChannel) => c.builtin);
+
+ return (
+
+
+
+
+ {__('Customer notifications are sent based on order status, account activities, and customer preferences. Customers can manage their notification preferences from their account page.')}
+
+
+
+
+
+ {/* Email Channel */}
+
+
+
+
+
+
+
{__('Email')}
+
+ {__('Built-in')}
+
+
+ {__('Active')}
+
+
+
+ {__('Transactional emails sent to customers for order updates, account activities, and more.')}
+
+
+ {__('Powered by WordPress email system')}
+
+
+
+
+ {/* Push Notifications */}
+
+
+
+
+
+
+
{__('Push Notifications')}
+
+ {__('Built-in')}
+
+
+ {__('Requires opt-in')}
+
+
+
+ {__('Browser push notifications for real-time order updates. Customers must enable push notifications in their account.')}
+
+
+ {__('Customer-controlled from their account preferences')}
+
+
+
+
+ {/* SMS Channel (Coming Soon) */}
+
+
+
+
+
+
+
{__('SMS Notifications')}
+
+ {__('Addon')}
+
+
+ {__('Coming Soon')}
+
+
+
+ {__('Send SMS notifications for critical order updates and delivery notifications.')}
+
+
+ {__('Install SMS Addon')}
+
+
+
+
+
+
+
+
+
+ {__('Customers can manage their notification preferences from:')}
+
+
+ {__('My Account → Notification Preferences')}
+ {__('Unsubscribe links in emails')}
+ {__('Browser push notification settings')}
+
+
+
+ {__('Note: Transactional emails (order confirmations, shipping updates) cannot be disabled by customers as they are required for order fulfillment.')}
+
+
+
+
+
+ );
+}
diff --git a/admin-spa/src/routes/Settings/Notifications/Customer/Events.tsx b/admin-spa/src/routes/Settings/Notifications/Customer/Events.tsx
new file mode 100644
index 0000000..1130bcd
--- /dev/null
+++ b/admin-spa/src/routes/Settings/Notifications/Customer/Events.tsx
@@ -0,0 +1,175 @@
+import React from 'react';
+import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
+import { api } from '@/lib/api';
+import { SettingsCard } from '../../components/SettingsCard';
+import { Switch } from '@/components/ui/switch';
+import { Button } from '@/components/ui/button';
+import { Badge } from '@/components/ui/badge';
+import { RefreshCw, Mail, MessageCircle, Send, Bell } from 'lucide-react';
+import { toast } from 'sonner';
+import { __ } from '@/lib/i18n';
+
+interface NotificationEvent {
+ id: string;
+ label: string;
+ description: string;
+ category: string;
+ enabled: boolean;
+ channels: {
+ [channelId: string]: {
+ enabled: boolean;
+ recipient: 'admin' | 'customer' | 'both';
+ };
+ };
+}
+
+interface NotificationChannel {
+ id: string;
+ label: string;
+ icon: string;
+ enabled: boolean;
+ builtin?: boolean;
+ addon?: string;
+}
+
+export default function CustomerEvents() {
+ const queryClient = useQueryClient();
+
+ // Fetch customer events
+ const { data: eventsData, isLoading: eventsLoading } = useQuery({
+ queryKey: ['notification-customer-events'],
+ queryFn: () => api.get('/notifications/customer/events'),
+ });
+
+ // Fetch channels
+ const { data: channels, isLoading: channelsLoading } = useQuery({
+ queryKey: ['notification-channels'],
+ queryFn: () => api.get('/notifications/channels'),
+ });
+
+ // Update event mutation
+ const updateMutation = useMutation({
+ mutationFn: async ({ eventId, channelId, enabled, recipient }: any) => {
+ return api.post('/notifications/events/update', {
+ eventId,
+ channelId,
+ enabled,
+ recipient,
+ });
+ },
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: ['notification-customer-events'] });
+ toast.success(__('Event settings updated'));
+ },
+ onError: (error: any) => {
+ toast.error(error?.message || __('Failed to update event'));
+ },
+ });
+
+ const getChannelIcon = (channelId: string) => {
+ switch (channelId) {
+ case 'email':
+ return ;
+ case 'push':
+ return ;
+ case 'whatsapp':
+ return ;
+ case 'telegram':
+ return ;
+ default:
+ return ;
+ }
+ };
+
+ const handleToggle = (eventId: string, channelId: string, currentEnabled: boolean, recipient: string) => {
+ updateMutation.mutate({
+ eventId,
+ channelId,
+ enabled: !currentEnabled,
+ recipient,
+ });
+ };
+
+ if (eventsLoading || channelsLoading) {
+ return (
+
+
+
+ );
+ }
+
+ const events = eventsData || {};
+ const enabledChannels = (channels || []).filter((c: NotificationChannel) => c.enabled);
+
+ return (
+
+ {Object.entries(events).map(([category, categoryEvents]: [string, any]) => (
+
+
+ {(categoryEvents as NotificationEvent[]).map((event) => (
+
+
+
+
{event.label}
+
{event.description}
+
+
+
+
+ {enabledChannels.map((channel: NotificationChannel) => {
+ const channelSettings = event.channels[channel.id];
+ const isEnabled = channelSettings?.enabled || false;
+ const recipient = channelSettings?.recipient || 'customer';
+
+ return (
+
+
+
+ {getChannelIcon(channel.id)}
+
+
+
+ {channel.label}
+ {channel.builtin && (
+
+ {__('Built-in')}
+
+ )}
+
+
+ {__('Recipient')}: {recipient}
+
+
+
+
handleToggle(event.id, channel.id, isEnabled, recipient)}
+ disabled={updateMutation.isPending}
+ />
+
+ );
+ })}
+
+
+ ))}
+
+
+ ))}
+
+ {Object.keys(events).length === 0 && (
+
+
+ {__('Customer notification events will appear here once configured.')}
+
+
+ )}
+
+ );
+}