source: chapterx-frontend/src/components/notifications/NotificationDropdown.tsx@ acf690c

main
Last change on this file since acf690c was b62cefc, checked in by kikisrbinoska <srbinoskakristina07@…>, 4 months ago

Added frontend and imporoved AI Suggestions service

  • Property mode set to 100644
File size: 3.6 KB
Line 
1import React from 'react'
2import { useNavigate } from 'react-router-dom'
3import { Heart, MessageCircle, Users, Bell, Settings, Check } from 'lucide-react'
4import { useNotificationStore } from '../../store/notificationStore'
5import { NotificationType } from '../../types'
6
7const typeIcon = (type: NotificationType) => {
8 const props = { size: 14 }
9 switch (type) {
10 case 'like': return <Heart {...props} className="text-rose-400" />
11 case 'comment': return <MessageCircle {...props} className="text-blue-400" />
12 case 'collaboration': return <Users {...props} className="text-violet-400" />
13 case 'follow': return <Bell {...props} className="text-amber-400" />
14 case 'system': return <Settings {...props} className="text-slate-400" />
15 default: return <Bell {...props} className="text-slate-400" />
16 }
17}
18
19function timeAgo(dateStr: string): string {
20 const diff = Date.now() - new Date(dateStr).getTime()
21 const mins = Math.floor(diff / 60000)
22 if (mins < 1) return 'just now'
23 if (mins < 60) return `${mins}m ago`
24 const hrs = Math.floor(mins / 60)
25 if (hrs < 24) return `${hrs}h ago`
26 return `${Math.floor(hrs / 24)}d ago`
27}
28
29interface Props {
30 onClose: () => void
31}
32
33export const NotificationDropdown: React.FC<Props> = ({ onClose }) => {
34 const navigate = useNavigate()
35 const { notifications, markAllRead, markRead } = useNotificationStore()
36 const recent = notifications.slice(0, 5)
37
38 return (
39 <div className="absolute right-0 top-full mt-2 w-80 bg-slate-900 border border-slate-700 rounded-2xl shadow-2xl z-50 overflow-hidden">
40 <div className="flex items-center justify-between px-4 py-3 border-b border-slate-700">
41 <span className="text-sm font-semibold text-white">Notifications</span>
42 <button
43 onClick={markAllRead}
44 className="text-xs text-indigo-400 hover:text-indigo-300 flex items-center gap-1 transition-colors"
45 >
46 <Check size={12} />
47 Mark all read
48 </button>
49 </div>
50 <div className="divide-y divide-slate-800">
51 {recent.length === 0 ? (
52 <div className="px-4 py-8 text-center text-slate-500 text-sm">
53 No notifications yet
54 </div>
55 ) : (
56 recent.map(n => (
57 <div
58 key={n.notification_id}
59 className={`flex gap-3 px-4 py-3 cursor-pointer transition-colors ${
60 !n.is_read ? 'bg-indigo-500/5 hover:bg-indigo-500/10' : 'hover:bg-slate-800'
61 }`}
62 onClick={() => {
63 markRead(n.notification_id)
64 if (n.link) { navigate(n.link); onClose() }
65 }}
66 >
67 <div className="mt-0.5 w-6 h-6 rounded-full bg-slate-800 flex items-center justify-center flex-shrink-0">
68 {typeIcon(n.type)}
69 </div>
70 <div className="flex-1 min-w-0">
71 <p className="text-xs font-medium text-white">{n.title}</p>
72 <p className="text-xs text-slate-400 line-clamp-2">{n.message}</p>
73 <p className="text-xs text-slate-600 mt-0.5">{timeAgo(n.created_at)}</p>
74 </div>
75 {!n.is_read && (
76 <div className="w-2 h-2 rounded-full bg-indigo-400 flex-shrink-0 mt-1.5" />
77 )}
78 </div>
79 ))
80 )}
81 </div>
82 <div className="border-t border-slate-700 p-2">
83 <button
84 onClick={() => { navigate('/notifications'); onClose() }}
85 className="w-full text-center text-xs text-indigo-400 hover:text-indigo-300 py-1.5 rounded-lg hover:bg-slate-800 transition-colors"
86 >
87 View all notifications
88 </button>
89 </div>
90 </div>
91 )
92}
Note: See TracBrowser for help on using the repository browser.