refactor: Simplify notification UI and improve UX

##  UI/UX Improvements

### Channels Page

**Changes:**
1.  Removed "Active/Inactive" badge (redundant with color)
2.  Renamed "Built-in Channels" → "Channels"
3.  Moved "Built-in" badge inline with title
4.  Removed redundant "Subscribe" toggle for push
5.  Unified "Enable/Disable" toggle for all channels
6.  Auto-subscribe when enabling push channel

**Layout:**
- Title + Built-in badge (inline)
- Description
- Enable/Disable toggle + Configure button
- Green icon when enabled, gray when disabled

**Addon Channels:**
- Will show "Addon" badge instead of "Built-in"
- Same consistent layout

### Events Page

**Changes:**
1.  Removed event-level toggle (too dense)
2.  Cleaner header layout
3.  Focus on per-channel toggles only

**Logic:**
- Each event can enable/disable specific channels
- Channel-level toggle (Channels page) = global on/off
- Per-event toggle (Events page) = event-specific on/off
- Both must be enabled for notification to send

### Expected Behavior

**Channel Toggle (Channels Page):**
- Disables/enables channel globally
- Affects all events
- Stored in `woonoow_email_notifications_enabled`
- Stored in `woonoow_push_notifications_enabled`

**Per-Event Channel Toggle (Events Page):**
- Enables/disables channel for specific event
- Stored in `woonoow_notification_settings`
- Independent per event

**Notification Sending Logic:**
```
if (channel_globally_enabled && event_channel_enabled) {
  send_notification();
}
```

---

**UI is now cleaner and more intuitive!** 
This commit is contained in:
dwindown
2025-11-11 15:29:03 +07:00
parent bd30f6e7cb
commit 0cc19fb2e7
2 changed files with 17 additions and 47 deletions

View File

@@ -180,8 +180,8 @@ export default function NotificationChannels() {
</div>
</SettingsCard>
{/* Built-in Channels */}
<SettingsCard title={__('Built-in Channels')} description={__('Channels included with WooNooW')}>
{/* All Channels */}
<SettingsCard title={__('Channels')} description={__('Manage notification delivery channels')}>
<div className="space-y-4">
{builtinChannels.map((channel: NotificationChannel) => (
<div key={channel.id} className="flex flex-col sm:flex-row sm:items-center gap-4 p-4 rounded-lg border bg-card">
@@ -192,19 +192,11 @@ export default function NotificationChannels() {
<div className="flex-1 min-w-0">
<div className="flex items-center gap-2 mb-2">
<h3 className="font-medium">{channel.label}</h3>
</div>
<div className="flex flex-wrap items-center gap-2 mb-2">
<Badge variant="secondary" className="text-xs">
{__('Built-in')}
</Badge>
<Badge
variant={channel.enabled ? 'default' : 'secondary'}
className={`text-xs ${channel.enabled ? 'bg-green-500 hover:bg-green-600' : ''}`}
>
{channel.enabled ? __('Active') : __('Inactive')}
</Badge>
</div>
<p className="text-sm text-muted-foreground mt-1">
<p className="text-sm text-muted-foreground">
{channel.id === 'email' &&
__('Email notifications powered by WooCommerce. Configure templates and SMTP settings.')}
{channel.id === 'push' &&
@@ -222,6 +214,10 @@ export default function NotificationChannels() {
checked={channel.enabled}
onCheckedChange={(checked) => {
toggleChannelMutation.mutate({ channelId: channel.id, enabled: checked });
// If enabling push, also subscribe
if (channel.id === 'push' && checked && pushSupported && !pushSubscribed) {
subscribeToPush.mutate();
}
}}
disabled={toggleChannelMutation.isPending}
/>
@@ -239,24 +235,7 @@ export default function NotificationChannels() {
<Settings className="h-4 w-4 sm:mr-2" />
<span className="sm:inline">{__('Configure')}</span>
</Button>
{channel.id === 'push' && pushSupported && (
<div className="flex items-center justify-between sm:justify-start gap-2 p-2 sm:p-0 rounded-lg sm:rounded-none border sm:border-0">
<span className="text-sm text-muted-foreground">
{pushSubscribed ? __('Subscribed') : __('Not subscribed')}
</span>
<Switch
checked={pushSubscribed}
onCheckedChange={(checked) => {
if (checked) {
subscribeToPush.mutate();
} else {
unsubscribeFromPush.mutate();
}
}}
disabled={subscribeToPush.isPending || unsubscribeFromPush.isPending}
/>
</div>
)}
{channel.id === 'push' && !pushSupported && (
<Badge variant="destructive" className="text-xs w-full sm:w-auto justify-center">
{__('Not Supported')}

View File

@@ -130,12 +130,9 @@ export default function NotificationEvents() {
<div className="space-y-6">
{orderEvents.map((event: NotificationEvent) => (
<div key={event.id} className="pb-6 border-b last:border-0">
<div className="flex items-start justify-between mb-4">
<div className="flex-1">
<h3 className="font-medium text-sm">{event.label}</h3>
<p className="text-xs text-muted-foreground mt-1">{event.description}</p>
</div>
<Switch checked={event.enabled} disabled />
<div className="mb-4">
<h3 className="font-medium text-sm">{event.label}</h3>
<p className="text-xs text-muted-foreground mt-1">{event.description}</p>
</div>
{/* Channel Selection */}
@@ -193,12 +190,9 @@ export default function NotificationEvents() {
<div className="space-y-6">
{productEvents.map((event: NotificationEvent) => (
<div key={event.id} className="pb-6 border-b last:border-0">
<div className="flex items-start justify-between mb-4">
<div className="flex-1">
<h3 className="font-medium text-sm">{event.label}</h3>
<p className="text-xs text-muted-foreground mt-1">{event.description}</p>
</div>
<Switch checked={event.enabled} disabled />
<div className="mb-4">
<h3 className="font-medium text-sm">{event.label}</h3>
<p className="text-xs text-muted-foreground mt-1">{event.description}</p>
</div>
<div className="space-y-3">
@@ -255,12 +249,9 @@ export default function NotificationEvents() {
<div className="space-y-6">
{customerEvents.map((event: NotificationEvent) => (
<div key={event.id} className="pb-6 border-b last:border-0">
<div className="flex items-start justify-between mb-4">
<div className="flex-1">
<h3 className="font-medium text-sm">{event.label}</h3>
<p className="text-xs text-muted-foreground mt-1">{event.description}</p>
</div>
<Switch checked={event.enabled} disabled />
<div className="mb-4">
<h3 className="font-medium text-sm">{event.label}</h3>
<p className="text-xs text-muted-foreground mt-1">{event.description}</p>
</div>
<div className="space-y-3">