refactor: use shared settings components, fix sections

- Use NotificationToggleList and BellIcon from @ciphera-net/ui
- Remove duplicated inline SVG icons and toggle code
- Remove double card borders from content areas
- Remove broken Ciphera Account external links
- Add dedicated Security section (Trusted Devices, Security Activity)
- Bump @ciphera-net/ui to ^0.0.89
This commit is contained in:
Usman Baig
2026-03-06 00:20:08 +01:00
parent 48cf9a1f62
commit 7865b41722
3 changed files with 34 additions and 94 deletions

View File

@@ -3,7 +3,8 @@
import { useState, useEffect } from 'react'
import Link from 'next/link'
import { SettingsModal, type SettingsSection } from '@ciphera-net/ui'
import { UserIcon, LockIcon, ChevronRightIcon } from '@ciphera-net/ui'
import { UserIcon, LockIcon, BellIcon, ChevronRightIcon } from '@ciphera-net/ui'
import { NotificationToggleList, type NotificationOption } from '@ciphera-net/ui'
import ProfileSettings from '@/components/settings/ProfileSettings'
import TrustedDevicesCard from '@/components/settings/TrustedDevicesCard'
import SecurityActivityCard from '@/components/settings/SecurityActivityCard'
@@ -11,19 +12,9 @@ import { useSettingsModal } from '@/lib/settings-modal-context'
import { useAuth } from '@/lib/auth/context'
import { updateUserPreferences } from '@/lib/api/user'
// Inline SVG icons not available in ciphera-ui
function BellIcon({ className }: { className?: string }) {
return (
<svg className={className} xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9" />
<path d="M13.73 21a2 2 0 0 1-3.46 0" />
</svg>
)
}
// --- Security Alerts ---
const SECURITY_ALERT_OPTIONS = [
const SECURITY_ALERT_OPTIONS: NotificationOption[] = [
{ key: 'login_alerts', label: 'Login Activity', description: 'New device sign-ins and suspicious login attempts.' },
{ key: 'password_alerts', label: 'Password Changes', description: 'Password changes and session revocations.' },
{ key: 'two_factor_alerts', label: 'Two-Factor Authentication', description: '2FA enabled/disabled and recovery code changes.' },
@@ -64,55 +55,14 @@ function SecurityAlertsCard() {
}
return (
<div className="bg-white dark:bg-neutral-900 rounded-2xl border border-neutral-200 dark:border-neutral-800 p-6 shadow-sm">
<div className="flex items-center gap-3 mb-6">
<div className="p-2 rounded-lg bg-brand-orange/10">
<BellIcon className="w-5 h-5 text-brand-orange" />
</div>
<div>
<h2 className="text-lg font-semibold text-neutral-900 dark:text-white">Security Alerts</h2>
<p className="text-sm text-neutral-500">Choose which security events trigger email alerts</p>
</div>
</div>
<div className="space-y-4">
{SECURITY_ALERT_OPTIONS.map((item) => (
<div
key={item.key}
className={`flex items-center justify-between p-4 border rounded-xl transition-all duration-200 ${
emailNotifications[item.key]
? 'bg-orange-50 dark:bg-brand-orange/10 border-brand-orange shadow-sm'
: 'bg-white dark:bg-neutral-900 border-neutral-200 dark:border-neutral-800'
}`}
>
<div className="space-y-0.5">
<span className={`block text-sm font-medium transition-colors duration-200 ${
emailNotifications[item.key] ? 'text-brand-orange' : 'text-neutral-900 dark:text-white'
}`}>
{item.label}
</span>
<span className={`block text-xs transition-colors duration-200 ${
emailNotifications[item.key] ? 'text-brand-orange/80' : 'text-neutral-500 dark:text-neutral-400'
}`}>
{item.description}
</span>
</div>
<button
onClick={() => handleToggle(item.key)}
className={`relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none ${
emailNotifications[item.key] ? 'bg-brand-orange' : 'bg-neutral-200 dark:bg-neutral-700'
}`}
>
<span
className={`pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out ${
emailNotifications[item.key] ? 'translate-x-5' : 'translate-x-0'
}`}
/>
</button>
</div>
))}
</div>
</div>
<NotificationToggleList
title="Security Alerts"
description="Choose which security events trigger email alerts"
icon={<BellIcon className="w-5 h-5 text-brand-orange" />}
options={SECURITY_ALERT_OPTIONS}
values={emailNotifications}
onToggle={handleToggle}
/>
)
}
@@ -120,21 +70,14 @@ function SecurityAlertsCard() {
function NotificationCenterPlaceholder() {
return (
<div className="bg-white dark:bg-neutral-900 rounded-2xl border border-neutral-200 dark:border-neutral-800 p-8 shadow-sm">
<div className="text-center max-w-md mx-auto">
<BellIcon className="w-12 h-12 text-neutral-300 mx-auto mb-4" />
<h3 className="text-lg font-medium text-neutral-900 dark:text-white mb-2">Notification Center</h3>
<p className="text-sm text-neutral-500 mb-4">
View and manage all your notifications in one place.
</p>
<Link
href="/notifications"
className="inline-flex items-center gap-2 px-4 py-2 bg-brand-orange text-white rounded-lg hover:bg-brand-orange/90 transition-colors"
>
Open Notification Center
<ChevronRightIcon className="w-4 h-4" />
</Link>
</div>
<div className="text-center max-w-md mx-auto py-8">
<BellIcon className="w-12 h-12 text-neutral-300 mx-auto mb-4" />
<h3 className="text-lg font-medium text-neutral-900 dark:text-white mb-2">Notification Center</h3>
<p className="text-sm text-neutral-500 mb-4">View and manage all your notifications in one place.</p>
<Link href="/notifications" className="inline-flex items-center gap-2 px-4 py-2 bg-brand-orange text-white rounded-lg hover:bg-brand-orange/90 transition-colors">
Open Notification Center
<ChevronRightIcon className="w-4 h-4" />
</Link>
</div>
)
}
@@ -157,6 +100,16 @@ export default function SettingsModalWrapper() {
{ id: 'preferences', label: 'Preferences', content: <ProfileSettings activeTab="preferences" /> },
],
},
{
id: 'security-section',
label: 'Security',
description: 'Devices and activity',
icon: LockIcon,
items: [
{ id: 'devices', label: 'Trusted Devices', content: <TrustedDevicesCard /> },
{ id: 'activity', label: 'Security Activity', content: <SecurityActivityCard /> },
],
},
{
id: 'notifications',
label: 'Notifications',
@@ -167,19 +120,6 @@ export default function SettingsModalWrapper() {
{ id: 'center', label: 'Notification Center', content: <NotificationCenterPlaceholder /> },
],
},
{
id: 'account',
label: 'Ciphera Account',
description: 'Security, 2FA, and sessions',
icon: LockIcon,
items: [
{ id: 'auth-profile', label: 'Profile & Personal Info', href: 'https://auth.ciphera.net/settings', external: true },
{ id: 'auth-security', label: 'Security & 2FA', href: 'https://auth.ciphera.net/settings?tab=security', external: true },
{ id: 'auth-sessions', label: 'Active Sessions', href: 'https://auth.ciphera.net/settings?tab=sessions', external: true },
{ id: 'devices', label: 'Trusted Devices', content: <TrustedDevicesCard /> },
{ id: 'activity', label: 'Security Activity', content: <SecurityActivityCard /> },
],
},
]
return <SettingsModal open={isOpen} onClose={closeSettings} sections={sections} />

8
package-lock.json generated
View File

@@ -8,7 +8,7 @@
"name": "pulse-frontend",
"version": "0.13.0-alpha",
"dependencies": {
"@ciphera-net/ui": "^0.0.88",
"@ciphera-net/ui": "^0.0.89",
"@ducanh2912/next-pwa": "^10.2.9",
"@radix-ui/react-icons": "^1.3.0",
"@simplewebauthn/browser": "^13.2.2",
@@ -1665,9 +1665,9 @@
}
},
"node_modules/@ciphera-net/ui": {
"version": "0.0.88",
"resolved": "https://npm.pkg.github.com/download/@ciphera-net/ui/0.0.88/70285ac19f9349fd13b4cbedf59612bc9c6ecc7e",
"integrity": "sha512-YMfrK8NVfFyS/KqvlnFSm3EmeCnIc5Wb4gO//qqyIt7d1lFGgsQJfQ0xOHoo0oQq0STywdnXPOwaTUWJeUIdMA==",
"version": "0.0.89",
"resolved": "https://npm.pkg.github.com/download/@ciphera-net/ui/0.0.89/2c528b440d3984e20a524be8a1d458df0aa8597e",
"integrity": "sha512-Ax4EMJCbWeEaCkoQqFCbl28QE5TnS0OY2nPNQiLVdLcG3xyiAgGL7MPpewo1RAUOrYm1/cr3F4Z3iiX7VAeSMA==",
"dependencies": {
"@radix-ui/react-icons": "^1.3.0",
"clsx": "^2.1.0",

View File

@@ -12,7 +12,7 @@
"test:watch": "vitest"
},
"dependencies": {
"@ciphera-net/ui": "^0.0.88",
"@ciphera-net/ui": "^0.0.89",
"@ducanh2912/next-pwa": "^10.2.9",
"@radix-ui/react-icons": "^1.3.0",
"@simplewebauthn/browser": "^13.2.2",