'use client'; import { useState, useEffect } from 'react'; import { useRouter } from 'next/navigation'; import Link from 'next/link'; import { useTranslation } from '@/lib/i18n'; import { useAuthStore } from '@/lib/store'; import { notificationApi, Notification } from '@/lib/api'; export default function NotificationsPage() { const router = useRouter(); const { t } = useTranslation(); const { user } = useAuthStore(); const [notifications, setNotifications] = useState([]); const [loading, setLoading] = useState(true); const [page, setPage] = useState(1); const [total, setTotal] = useState(0); const [unreadCount, setUnreadCount] = useState(0); const [filter, setFilter] = useState<'all' | 'unread'>('all'); const pageSize = 20; // Redirect if not logged in useEffect(() => { if (!user) { router.push('/login?redirect=/notifications'); } }, [user, router]); // Fetch notifications useEffect(() => { if (!user) return; const fetchNotifications = async () => { setLoading(true); try { const response = await notificationApi.getNotifications( page, pageSize, filter === 'unread' ); setNotifications(response.notifications); setTotal(response.total); setUnreadCount(response.unread_count); } catch (error) { console.error('Failed to fetch notifications:', error); } finally { setLoading(false); } }; fetchNotifications(); }, [user, page, filter]); // Mark as read and navigate const handleNotificationClick = async (notification: Notification) => { if (!notification.is_read) { try { await notificationApi.markAsRead([notification.id]); setNotifications(prev => prev.map(n => n.id === notification.id ? { ...n, is_read: true } : n) ); setUnreadCount(prev => Math.max(0, prev - 1)); } catch (error) { console.error('Failed to mark as read:', error); } } if (notification.link) { router.push(notification.link); } }; // Mark all as read const handleMarkAllRead = async () => { try { await notificationApi.markAllAsRead(); setNotifications(prev => prev.map(n => ({ ...n, is_read: true }))); setUnreadCount(0); } catch (error) { console.error('Failed to mark all as read:', error); } }; // Delete notification const handleDelete = async (e: React.MouseEvent, notificationId: number) => { e.stopPropagation(); try { await notificationApi.deleteNotification(notificationId); setNotifications(prev => prev.filter(n => n.id !== notificationId)); setTotal(prev => prev - 1); } catch (error) { console.error('Failed to delete notification:', error); } }; // Format time const formatTime = (dateString: string) => { const date = new Date(dateString); const now = new Date(); const diffMs = now.getTime() - date.getTime(); const diffMins = Math.floor(diffMs / 60000); const diffHours = Math.floor(diffMins / 60); const diffDays = Math.floor(diffHours / 24); if (diffMins < 1) return '방금 전'; if (diffMins < 60) return `${diffMins}분 전`; if (diffHours < 24) return `${diffHours}시간 전`; if (diffDays < 7) return `${diffDays}일 전`; return date.toLocaleDateString('ko-KR', { year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit' }); }; // Get notification icon const getNotificationIcon = (type: string) => { switch (type) { case 'vehicle_recommended': return '🚗'; case 'shipping_update': return '🚚'; case 'withdrawal_processed': return '💰'; case 'referral_reward': return '🎁'; case 'dealer_approved': return '✅'; case 'dealer_rejected': return '❌'; case 'share_purchased': return '🎉'; case 'system': return '📢'; default: return '🔔'; } }; // Get notification type label const getTypeLabel = (type: string) => { switch (type) { case 'vehicle_recommended': return '차량 추천'; case 'shipping_update': return '배송 업데이트'; case 'withdrawal_processed': return '출금 처리'; case 'referral_reward': return '레퍼럴 보상'; case 'dealer_approved': return '딜러 승인'; case 'dealer_rejected': return '딜러 거부'; case 'share_purchased': return '공유 판매'; case 'system': return '시스템 알림'; default: return '알림'; } }; const totalPages = Math.ceil(total / pageSize); if (!user) { return null; } return (
{/* Header */}

{t.notifications || '알림'}

{unreadCount > 0 ? ( 읽지 않은 알림 {unreadCount}개 ) : ( '모든 알림을 확인했습니다' )}

{unreadCount > 0 && ( )}
{/* Filter Tabs */}
{/* Notification List */}
{loading ? (

알림을 불러오는 중...

) : notifications.length === 0 ? (
🔔

{filter === 'unread' ? '읽지 않은 알림이 없습니다' : '알림이 없습니다'}

) : (
{notifications.map((notification) => (
handleNotificationClick(notification)} className={`p-4 hover:bg-gray-50 cursor-pointer transition ${ !notification.is_read ? 'bg-blue-50' : '' }`} >
{/* Icon */}
{getNotificationIcon(notification.notification_type)}
{/* Content */}
{getTypeLabel(notification.notification_type)} {!notification.is_read && ( )}

{notification.title}

{notification.message}

{formatTime(notification.created_at)}

{/* Actions */}
))}
)}
{/* Pagination */} {totalPages > 1 && (
{page} / {totalPages}
)} {/* Back Link */}
← 홈으로 돌아가기
); }