通知中心增加通知配置入口
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Bell, Check, Trash2, X } from 'lucide-react';
|
import { Bell, Check, Settings, Trash2, X } from 'lucide-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
@@ -12,11 +12,13 @@ import { Notification } from '@/lib/types';
|
|||||||
interface NotificationPanelProps {
|
interface NotificationPanelProps {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
|
onOpenNotificationSettings?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const NotificationPanel: React.FC<NotificationPanelProps> = ({
|
export const NotificationPanel: React.FC<NotificationPanelProps> = ({
|
||||||
isOpen,
|
isOpen,
|
||||||
onClose,
|
onClose,
|
||||||
|
onOpenNotificationSettings,
|
||||||
}) => {
|
}) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [notifications, setNotifications] = useState<Notification[]>([]);
|
const [notifications, setNotifications] = useState<Notification[]>([]);
|
||||||
@@ -144,6 +146,10 @@ export const NotificationPanel: React.FC<NotificationPanelProps> = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleOpenNotificationSettings = () => {
|
||||||
|
onOpenNotificationSettings?.();
|
||||||
|
};
|
||||||
|
|
||||||
// 打开面板时加载通知
|
// 打开面板时加载通知
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isOpen) {
|
if (isOpen) {
|
||||||
@@ -160,7 +166,7 @@ export const NotificationPanel: React.FC<NotificationPanelProps> = ({
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
{/* 通知面板 */}
|
{/* 通知面板 */}
|
||||||
<div className='fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-full max-w-lg max-h-[80vh] bg-white dark:bg-gray-900 rounded-xl shadow-xl z-[1001] flex flex-col overflow-hidden'>
|
<div className='fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-full max-w-lg min-h-[520px] max-h-[80vh] bg-white dark:bg-gray-900 rounded-xl shadow-xl z-[1001] flex flex-col overflow-hidden max-sm:min-h-[70vh]'>
|
||||||
{/* 标题栏 */}
|
{/* 标题栏 */}
|
||||||
<div className='flex items-center justify-between px-6 py-4 border-b border-gray-200 dark:border-gray-700'>
|
<div className='flex items-center justify-between px-6 py-4 border-b border-gray-200 dark:border-gray-700'>
|
||||||
<div className='flex items-center gap-2'>
|
<div className='flex items-center gap-2'>
|
||||||
@@ -194,13 +200,31 @@ export const NotificationPanel: React.FC<NotificationPanelProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 通知列表 */}
|
{/* 通知列表 */}
|
||||||
<div className='flex-1 overflow-y-auto p-4'>
|
<div className='flex flex-1 flex-col overflow-y-auto p-4'>
|
||||||
|
{onOpenNotificationSettings && (
|
||||||
|
<button
|
||||||
|
type='button'
|
||||||
|
onClick={handleOpenNotificationSettings}
|
||||||
|
className='mb-3 flex w-full items-center gap-2 rounded-lg border border-blue-200 bg-blue-50 px-3 py-2.5 text-left transition-colors hover:bg-blue-100 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:border-blue-800 dark:bg-blue-900/20 dark:hover:bg-blue-900/30 dark:focus:ring-offset-gray-900'
|
||||||
|
>
|
||||||
|
<div className='flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-blue-100 text-blue-600 dark:bg-blue-900/40 dark:text-blue-300'>
|
||||||
|
<Settings className='h-4 w-4' />
|
||||||
|
</div>
|
||||||
|
<span className='min-w-0 flex-1 text-sm text-gray-700 dark:text-gray-200'>
|
||||||
|
开启邮件通知或当前设备浏览器系统通知后,重要更新可在站外提醒您
|
||||||
|
</span>
|
||||||
|
<span className='shrink-0 text-xs font-medium text-blue-700 dark:text-blue-200'>
|
||||||
|
去配置
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<div className='flex items-center justify-center py-12'>
|
<div className='flex items-center justify-center py-12'>
|
||||||
<div className='w-8 h-8 border-4 border-green-500 border-t-transparent rounded-full animate-spin'></div>
|
<div className='w-8 h-8 border-4 border-green-500 border-t-transparent rounded-full animate-spin'></div>
|
||||||
</div>
|
</div>
|
||||||
) : notifications.length === 0 ? (
|
) : notifications.length === 0 ? (
|
||||||
<div className='flex flex-col items-center justify-center py-12 text-gray-500 dark:text-gray-400'>
|
<div className='flex flex-1 flex-col items-center justify-center py-12 text-gray-500 dark:text-gray-400'>
|
||||||
<Bell className='w-12 h-12 mb-3 opacity-30' />
|
<Bell className='w-12 h-12 mb-3 opacity-30' />
|
||||||
<p className='text-sm'>暂无通知</p>
|
<p className='text-sm'>暂无通知</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -995,13 +995,12 @@ export const UserMenu: React.FC = () => {
|
|||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
setPushNotificationsBusy(true);
|
setPushNotificationsBusy(true);
|
||||||
try {
|
try {
|
||||||
let endpoint: string | undefined;
|
|
||||||
const registration =
|
const registration =
|
||||||
'serviceWorker' in navigator
|
'serviceWorker' in navigator
|
||||||
? await navigator.serviceWorker.getRegistration()
|
? await navigator.serviceWorker.getRegistration()
|
||||||
: undefined;
|
: undefined;
|
||||||
const subscription = await registration?.pushManager.getSubscription();
|
const subscription = await registration?.pushManager.getSubscription();
|
||||||
endpoint = subscription?.endpoint;
|
const endpoint = subscription?.endpoint;
|
||||||
await subscription?.unsubscribe();
|
await subscription?.unsubscribe();
|
||||||
await fetch('/api/notifications/push', {
|
await fetch('/api/notifications/push', {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
@@ -5187,6 +5186,11 @@ export const UserMenu: React.FC = () => {
|
|||||||
createPortal(
|
createPortal(
|
||||||
<NotificationPanel
|
<NotificationPanel
|
||||||
isOpen={isNotificationPanelOpen}
|
isOpen={isNotificationPanelOpen}
|
||||||
|
onOpenNotificationSettings={() => {
|
||||||
|
setIsNotificationPanelOpen(false);
|
||||||
|
setIsEmailSettingsOpen(true);
|
||||||
|
void loadEmailSettings();
|
||||||
|
}}
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
setIsNotificationPanelOpen(false);
|
setIsNotificationPanelOpen(false);
|
||||||
// 不需要在这里刷新,NotificationPanel 内部会触发事件
|
// 不需要在这里刷新,NotificationPanel 内部会触发事件
|
||||||
|
|||||||
Reference in New Issue
Block a user