Built Twitter Like App - 27

Add Notification Function

  1. Add Alert to SideBarItem Component
  2. Add Alert to SideBar Component
  3. Add Notification API
  4. Add Hook
  5. Add Notification Page
  6. Add notification content in Like API
  7. Add notification content in Comments API
  8. Add notification content in Follow API

Add Alert to SideBarItem Component

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...
import { BsDot } from "react-icons/bs";
...
<Icon size={28} color="white" />
{alert ?
<BsDot className="text-sky-500 absolute -top-4 left-0" size={70} /> : null
}
...
<Icon size={24} color="white" />
<p className="hidden lg:block text-white text-xl">
{label}
</p>
{alert ?
<BsDot className="text-sky-500 absolute -top-4 left-0" size={70} /> : null
}
...

Add Alert to SideBar Component

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
{
label: 'Notifications',
href:'/notifications',
icon: BsBellFill,
auth: true,
alert: currentUser?.hasNotification
},
...

{items.map((item) =>(
<SidebarItem
key={item.href}
href={item.href}
label={item.label}
icon={item.icon}
auth={item.auth}
alert={item.alert}
/>
))}
...

Add Notification API

Add file pages/api/notifications/[userId].ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import { NextApiRequest, NextApiResponse } from "next";

import prisma from '@/libs/prismadb';

export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if( req.method !=='GET'){
return res.status(405).end();
}

try{
const { userId } = req.query;

if (!userId) {
throw new Error('Invalid ID');
};

const notifications = await prisma.notification.findMany({
where: {
userId: Number(userId)
},
orderBy: {
createdAt: 'desc'
}
});

await prisma.user.update({
where: {
id: Number(userId)
},
data: {
hasNotification: false
}
})

return res.status(200).json(notifications);
} catch(error){
console.log(error);
return res.status(400).end();
}
}

Add Hook

Add file hooks/useNotifcations.ts :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import useSWR from 'swr';

import fetcher from '../libs/fetcher';

const useNotifications = ( userId?:Number ) => {
const url = userId ? `/api/notifications/${userId}` : null
const {
data,
error,
isLoading,
mutate
} = useSWR(url, fetcher);

return {
data,
error,
isLoading,
mutate
}
};

export default useNotifications;

Add Notification Page

Add file components/NotificationFeed.tsx :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import useCurrentUser from "@/hooks/useCurrentUser";
import useNotifications from "@/hooks/useNotifications";
import { useEffect } from "react";
import { BsTwitter } from "react-icons/bs";

const NotificationFeed = () => {
const { data: currentUser,mutate:mutateCurrentUser } = useCurrentUser();
const { data: fetchedNotifications =[] } = useNotifications(currentUser?.id);

useEffect(() => {
mutateCurrentUser();
}, [mutateCurrentUser])

if (fetchedNotifications.length === 0) {
return (
<div className="text-neutral-600 text-center p-6 text-xl">
No notifications
</div>
)
}

return (
<div className="flex flex-col">
{fetchedNotifications.map((notification: Record<string, any>) => (
<div
key={notification.id}
className="flex flex-row items-center p-6 gap-4 border-b-[1px] border-neutral-200"
>
<BsTwitter color="white" size={32} />
<p className="text-white">
{notification.body}
</p>
</div>
))}
</div>
)
}

export default NotificationFeed;

Add notification content in Like API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
...
if(req.method === 'POST') {
await primsa.likedIds.create({
data: {
postId: Number(postId),
likedId: currentUserId
}
});

//Add Notification Function
try{
const post = await primsa.post.findUnique({
where: {
id: Number(postId)
},
include: {
user: true
}
});

if(post?.userId) {
await primsa.notification.create({
data: {
body: 'Someone liked your post!',
userId: Number(post?.userId)
}
});

await primsa.user.update({
where: {
id: Number(post?.userId)
},
data: {
hasNotification: true
}
})
}
} catch(error) {
console.log(error);
}
}
...

Add notification content in Comments API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
try{
const { body } = req.body;
const { user, postId } = req.query;

if(!postId || !user || !body) {
throw new Error('Invalid postId/userId/body');
}

const userId = Number(user);

const comment = await prisma.comment.create({
data: {
body,
userId,
postId: Number(postId)
}
})

//Add Notification Function
try{
const post = await prisma.post.findUnique({
where: {
id: Number(postId)
},
include: {
user: true
}
});

if(post?.userId) {
await prisma.notification.create({
data: {
body: 'Someone replied to your post!',
userId: Number(post?.userId)
}
});

await prisma.user.update({
where: {
id: Number(post?.userId)
},
data: {
hasNotification: true
}
})
}
} catch(error) {
console.log(error);
}

return res.status(200).json(comment);
} catch(error){
console.log(error);
return res.status(400).end();
}

Add notification content in Follow API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
try{
const { userId } = req.body;
const { currUser } = req.query;
const currentUserId = Number(currUser);

//console.log('currentuser user', currentUserId, userId);

if(!userId) {
throw new Error('Invalid ID');
}

if(!currentUserId) {
throw new Error('Invalid currentUserId');
}

if(req.method === 'POST') {
await primsa.followingId.create({
data: {
userId: currentUserId,
followingId: userId
}
});

//Add notification
try {
await prisma?.notification.create({
data: {
body: 'Someone followed you!',
userId
}
});

await primsa.user.update({
where: {
id: userId
},
data: {
hasNotification: true
}
});

} catch(error) {
console.log(error);
}
}

if(req.method === 'DELETE') {
await primsa.followingId.deleteMany({
where: {
userId: currentUserId,
followingId: userId
}
});
}

return res.status(200).end();
} catch(error){
console.log(error);
return res.status(400).end();
}
}

Demo

请我喝杯咖啡吧~

支付宝
微信