From 15f82eee0027ec3099d1dc48cbf09797716162a3 Mon Sep 17 00:00:00 2001 From: Usman Baig Date: Sat, 28 Feb 2026 20:36:53 +0100 Subject: [PATCH] feat: add email notification preferences and update settings page structure --- app/settings/SettingsPageClient.tsx | 146 +++++++++++++++++++++--- components/settings/ProfileSettings.tsx | 1 + package-lock.json | 8 +- package.json | 2 +- 4 files changed, 136 insertions(+), 21 deletions(-) diff --git a/app/settings/SettingsPageClient.tsx b/app/settings/SettingsPageClient.tsx index ee478c6..2269181 100644 --- a/app/settings/SettingsPageClient.tsx +++ b/app/settings/SettingsPageClient.tsx @@ -1,11 +1,12 @@ 'use client' -import { useState } from 'react' +import { useState, useEffect } from 'react' import Link from 'next/link' import { useAuth } from '@/lib/auth/context' import ProfileSettings from '@/components/settings/ProfileSettings' import TrustedDevicesCard from '@/components/settings/TrustedDevicesCard' import SecurityActivityCard from '@/components/settings/SecurityActivityCard' +import { updateUserPreferences } from '@/lib/api/user' import { motion, AnimatePresence } from 'framer-motion' import { UserIcon, @@ -29,15 +30,16 @@ function BellIcon({ className }: { className?: string }) { // --- Types --- type ProfileSubTab = 'profile' | 'security' | 'preferences' +type NotificationSubTab = 'email' | 'center' type ActiveSelection = | { section: 'profile'; subTab: ProfileSubTab } - | { section: 'notifications' } + | { section: 'notifications'; subTab: NotificationSubTab } | { section: 'account' } | { section: 'devices' } | { section: 'activity' } -type ExpandableSection = 'profile' | 'account' +type ExpandableSection = 'profile' | 'notifications' | 'account' // --- Sidebar Components --- @@ -137,6 +139,98 @@ function ExpandableSubItems({ expanded, children }: { expanded: boolean; childre // --- Content Components --- +// Email Notification Preferences Card +const PULSE_NOTIFICATION_OPTIONS = [ + { key: 'security_alerts', label: 'Security Alerts', description: 'Important security events like new logins, password changes, and 2FA updates.' }, +] + +function EmailNotificationPreferencesCard() { + const { user } = useAuth() + const [emailNotifications, setEmailNotifications] = useState>({}) + + useEffect(() => { + if (user?.preferences?.email_notifications) { + setEmailNotifications(user.preferences.email_notifications) + } else { + const defaults = PULSE_NOTIFICATION_OPTIONS.reduce((acc, option) => ({ + ...acc, + [option.key]: true + }), {} as Record) + setEmailNotifications(defaults) + } + }, [user]) + + const handleToggle = async (key: string) => { + const newState = { + ...emailNotifications, + [key]: !emailNotifications[key] + } + setEmailNotifications(newState) + try { + await updateUserPreferences({ + email_notifications: newState as { new_file_received: boolean; file_downloaded: boolean; security_alerts: boolean } + }) + } catch { + setEmailNotifications(prev => ({ + ...prev, + [key]: !prev[key] + })) + } + } + + return ( +
+
+
+ +
+
+

Email Notifications

+

Choose which email notifications you receive

+
+
+ +
+ {PULSE_NOTIFICATION_OPTIONS.map((item) => ( +
+
+ + {item.label} + + + {item.description} + +
+ +
+ ))} +
+
+ ) +} + function AccountManagementCard() { const accountLinks = [ { @@ -234,13 +328,14 @@ function AppSettingsSection() { case 'profile': return case 'notifications': - return ( + if (active.subTab === 'email') return + if (active.subTab === 'center') return (
-

Notification Preferences

+

Notification Center

- Configure which notifications you receive and how you want to be notified. + View and manage all your notifications in one place.

) + return null case 'account': return case 'devices': @@ -306,16 +402,34 @@ function AppSettingsSection() {
- {/* Notifications (flat, no expansion) */} - setActive({ section: 'notifications' })} - icon={BellIcon} - label="Notifications" - description="Email and in-app notifications" - hasChildren={false} - /> + {/* Notifications (expandable) */} +
+ { + toggleSection('notifications') + if (!expanded.has('notifications')) { + selectSubTab({ section: 'notifications', subTab: 'email' }) + } + }} + icon={BellIcon} + label="Notifications" + description="Email and in-app notifications" + /> + + selectSubTab({ section: 'notifications', subTab: 'email' })} + label="Email Preferences" + /> + selectSubTab({ section: 'notifications', subTab: 'center' })} + label="Notification Center" + /> + +
diff --git a/components/settings/ProfileSettings.tsx b/components/settings/ProfileSettings.tsx index d98574b..e1d4e5d 100644 --- a/components/settings/ProfileSettings.tsx +++ b/components/settings/ProfileSettings.tsx @@ -60,6 +60,7 @@ export default function ProfileSettings({ activeTab }: Props = {}) { logout={logout} activeTab={activeTab} hideNav={activeTab !== undefined} + hideNotifications /> ) } diff --git a/package-lock.json b/package-lock.json index 33e3059..87c5d00 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "pulse-frontend", "version": "0.11.1-alpha", "dependencies": { - "@ciphera-net/ui": "^0.0.75", + "@ciphera-net/ui": "^0.0.76", "@ducanh2912/next-pwa": "^10.2.9", "@radix-ui/react-icons": "^1.3.0", "@simplewebauthn/browser": "^13.2.2", @@ -1543,9 +1543,9 @@ } }, "node_modules/@ciphera-net/ui": { - "version": "0.0.75", - "resolved": "https://npm.pkg.github.com/download/@ciphera-net/ui/0.0.75/0a5f40babb9c7a8ae9d067155bc7c05c322ca410", - "integrity": "sha512-t1dPS9sID1qCC8A3bz91dtJX9NwnfqaNhkWJpeLQQDPxg89+HodtoqQ2gZaLv2X0rK1gekh6MRBNwXil1ePxBA==", + "version": "0.0.76", + "resolved": "https://npm.pkg.github.com/download/@ciphera-net/ui/0.0.76/f584def8ea9ac4bccc52abdd281212f2e28959c0", + "integrity": "sha512-Bw7KOSUXQajfMAmgU39XiJGFudxx7Gj7Tnjr2tHHL+2oLOoBuDCNRRIC+A6Uo5WmxDBitw6voipoOfRcFo5XAA==", "dependencies": { "@radix-ui/react-icons": "^1.3.0", "clsx": "^2.1.0", diff --git a/package.json b/package.json index b96bcd0..1184722 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "type-check": "tsc --noEmit" }, "dependencies": { - "@ciphera-net/ui": "^0.0.75", + "@ciphera-net/ui": "^0.0.76", "@ducanh2912/next-pwa": "^10.2.9", "@radix-ui/react-icons": "^1.3.0", "@simplewebauthn/browser": "^13.2.2",