Skip to content

Commit e58eb1c

Browse files
committed
notification workflow
1 parent 242ef12 commit e58eb1c

File tree

1 file changed

+52
-13
lines changed

1 file changed

+52
-13
lines changed

src/components/NotificationsDropdown.tsx

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
import React from 'react';
32
import { useNavigate } from 'react-router-dom';
43
import {
@@ -24,43 +23,61 @@ import {
2423
import { Button } from '@/components/ui/button';
2524
import { Badge } from '@/components/ui/badge';
2625
import { formatDistanceToNow } from 'date-fns';
26+
import { UserProfile } from '../utils/firebase';
27+
import type { Timestamp } from 'firebase/firestore';
28+
29+
interface Notification {
30+
id: string;
31+
type: 'achievement' | 'emergency' | 'friendRequest' | 'streakMilestone' | string;
32+
message: string;
33+
timestamp: Timestamp;
34+
read: boolean;
35+
senderInfo?: {
36+
id: string;
37+
name: string;
38+
};
39+
}
2740

2841
const NotificationsDropdown: React.FC = () => {
29-
const { notifications, unreadNotifications, refreshUserData } = useAuth();
42+
const { notifications, unreadNotifications, refreshUserData, friends } = useAuth();
3043
const navigate = useNavigate();
44+
const [localNotifications, setLocalNotifications] = React.useState<Notification[]>(notifications);
45+
46+
React.useEffect(() => {
47+
setLocalNotifications(notifications);
48+
}, [notifications]);
3149

32-
const handleAcceptFriendRequest = async (senderId: string) => {
50+
const handleAcceptFriendRequest = async (senderId: string, notificationId: string) => {
3351
const result = await acceptFriendRequest(auth.currentUser?.uid || '', senderId);
3452
if (result) {
3553
toast.success('Friend request accepted');
54+
setLocalNotifications((prev) => prev.filter(n => n.id !== notificationId));
3655
refreshUserData();
3756
} else {
3857
toast.error('Failed to accept friend request');
3958
}
4059
};
4160

42-
const handleDeclineFriendRequest = async (senderId: string) => {
61+
const handleDeclineFriendRequest = async (senderId: string, notificationId: string) => {
4362
const result = await declineFriendRequest(auth.currentUser?.uid || '', senderId);
4463
if (result) {
4564
toast.success('Friend request declined');
65+
setLocalNotifications((prev) => prev.filter(n => n.id !== notificationId));
4666
refreshUserData();
4767
} else {
4868
toast.error('Failed to decline friend request');
4969
}
5070
};
5171

52-
const handleNotificationClick = async (notification: any) => {
72+
const handleNotificationClick = async (notification: Notification) => {
5373
if (!notification.read) {
5474
await markNotificationAsRead(auth.currentUser?.uid || '', notification.id);
5575
}
56-
57-
// Navigate based on notification type
5876
if (notification.type === 'achievement') {
5977
navigate('/achievements');
6078
} else if (notification.type === 'emergency') {
6179
navigate(`/profile?friend=${notification.senderInfo?.id}`);
6280
}
63-
6481
refreshUserData();
6582
};
6683

@@ -96,10 +113,32 @@ const NotificationsDropdown: React.FC = () => {
96113
<DropdownMenuLabel>Notifications</DropdownMenuLabel>
97114
<DropdownMenuSeparator />
98115
<div className="max-h-[400px] overflow-y-auto">
99-
{notifications && notifications.length > 0 ? (
116+
{localNotifications && localNotifications.length > 0 ? (
100117
<DropdownMenuGroup>
101-
{notifications
102-
.sort((a, b) => b.timestamp.toDate() - a.timestamp.toDate())
118+
{localNotifications
119+
.sort((a, b) => {
120+
let aTime: number;
121+
let bTime: number;
122+
if (typeof a.timestamp.toMillis === 'function') {
123+
aTime = a.timestamp.toMillis();
124+
} else if (typeof a.timestamp === 'number') {
125+
aTime = a.timestamp;
126+
} else if (typeof a.timestamp === 'object' && 'seconds' in a.timestamp) {
127+
aTime = (a.timestamp as { seconds: number }).seconds * 1000;
128+
} else {
129+
aTime = Date.now(); // fallback
130+
}
131+
if (typeof b.timestamp.toMillis === 'function') {
132+
bTime = b.timestamp.toMillis();
133+
} else if (typeof b.timestamp === 'number') {
134+
bTime = b.timestamp;
135+
} else if (typeof b.timestamp === 'object' && 'seconds' in b.timestamp) {
136+
bTime = (b.timestamp as { seconds: number }).seconds * 1000;
137+
} else {
138+
bTime = Date.now(); // fallback
139+
}
140+
return bTime - aTime;
141+
})
103142
.map((notification, index) => (
104143
<React.Fragment key={notification.id || index}>
105144
{notification.type === 'friendRequest' && notification.senderInfo ? (
@@ -119,15 +158,15 @@ const NotificationsDropdown: React.FC = () => {
119158
<Button
120159
size="sm"
121160
variant="outline"
122-
onClick={() => handleAcceptFriendRequest(notification.senderInfo.id)}
161+
onClick={() => handleAcceptFriendRequest(notification.senderInfo!.id, notification.id)}
123162
className="h-7 w-7 p-0"
124163
>
125164
<Check className="h-4 w-4" />
126165
</Button>
127166
<Button
128167
size="sm"
129168
variant="outline"
130-
onClick={() => handleDeclineFriendRequest(notification.senderInfo.id)}
169+
onClick={() => handleDeclineFriendRequest(notification.senderInfo!.id, notification.id)}
131170
className="h-7 w-7 p-0"
132171
>
133172
<X className="h-4 w-4" />

0 commit comments

Comments
 (0)