# Push Notifications Integration Example This shows exactly how to add notifications to your existing code. ## Step 1: Import the notification helpers At the top of your action files, add: ```typescript import { notifyItemAdded, notifyItemRemoved, notifyItemCompleted, notifyListInvitation, notifyInvitationAccepted, notifyRemovedFromList, } from '@/lib/notification-helpers'; ``` ## Step 2: Add notification calls after actions ### Example: Adding an item **Before:** ```typescript export async function createItem(listId: string, data: any) { const session = await getServerSession(authOptions); if (!session?.user?.id) throw new Error('Unauthorized'); const item = await prisma.item.create({ data: { ...data, listId, }, }); revalidatePath(`/list/${listId}`); return item; } ``` **After:** ```typescript export async function createItem(listId: string, data: any) { const session = await getServerSession(authOptions); if (!session?.user?.id) throw new Error('Unauthorized'); const item = await prisma.item.create({ data: { ...data, listId, }, }); // 🔔 Add this line to send notifications await notifyItemAdded(listId, item.title, session.user.id); revalidatePath(`/list/${listId}`); return item; } ``` ### Example: Deleting an item **Before:** ```typescript export async function deleteItem(itemId: string) { const session = await getServerSession(authOptions); if (!session?.user?.id) throw new Error('Unauthorized'); await prisma.item.delete({ where: { id: itemId }, }); revalidatePath('/'); } ``` **After:** ```typescript export async function deleteItem(itemId: string) { const session = await getServerSession(authOptions); if (!session?.user?.id) throw new Error('Unauthorized'); // 🔔 Get item details before deleting const item = await prisma.item.findUnique({ where: { id: itemId }, }); await prisma.item.delete({ where: { id: itemId }, }); // 🔔 Send notification if (item) { await notifyItemRemoved(item.listId, item.title, session.user.id); } revalidatePath('/'); } ``` ### Example: Toggling item completion **Before:** ```typescript export async function toggleItemComplete(itemId: string) { const session = await getServerSession(authOptions); if (!session?.user?.id) throw new Error('Unauthorized'); const item = await prisma.item.findUnique({ where: { id: itemId }, }); const updated = await prisma.item.update({ where: { id: itemId }, data: { completed: !item?.completed }, }); revalidatePath('/'); return updated; } ``` **After:** ```typescript export async function toggleItemComplete(itemId: string) { const session = await getServerSession(authOptions); if (!session?.user?.id) throw new Error('Unauthorized'); const item = await prisma.item.findUnique({ where: { id: itemId }, }); const updated = await prisma.item.update({ where: { id: itemId }, data: { completed: !item?.completed }, }); // 🔔 Notify when item is completed (not uncompleted) if (updated.completed) { await notifyItemCompleted(updated.listId, updated.title, session.user.id); } revalidatePath('/'); return updated; } ``` ### Example: Inviting to a list **Before:** ```typescript export async function inviteToList(listId: string, email: string, permission: string) { const session = await getServerSession(authOptions); if (!session?.user?.id) throw new Error('Unauthorized'); const invitation = await prisma.invitation.create({ data: { listId, email, permission, inviterId: session.user.id, expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days }, }); return invitation; } ``` **After:** ```typescript export async function inviteToList(listId: string, email: string, permission: string) { const session = await getServerSession(authOptions); if (!session?.user?.id) throw new Error('Unauthorized'); const invitation = await prisma.invitation.create({ data: { listId, email, permission, inviterId: session.user.id, expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days }, }); // 🔔 Notify the invitee await notifyListInvitation(invitation.id, email); return invitation; } ``` ### Example: Accepting an invitation **Before:** ```typescript export async function acceptInvitation(invitationId: string) { const session = await getServerSession(authOptions); if (!session?.user?.id) throw new Error('Unauthorized'); const invitation = await prisma.invitation.update({ where: { id: invitationId }, data: { status: 'accepted' }, }); await prisma.collaborator.create({ data: { userId: session.user.id, listId: invitation.listId, permission: invitation.permission, }, }); return invitation; } ``` **After:** ```typescript export async function acceptInvitation(invitationId: string) { const session = await getServerSession(authOptions); if (!session?.user?.id) throw new Error('Unauthorized'); const invitation = await prisma.invitation.update({ where: { id: invitationId }, data: { status: 'accepted' }, }); await prisma.collaborator.create({ data: { userId: session.user.id, listId: invitation.listId, permission: invitation.permission, }, }); // 🔔 Notify the person who sent the invitation await notifyInvitationAccepted(invitationId); return invitation; } ``` ### Example: Removing a collaborator **Before:** ```typescript export async function removeCollaborator(listId: string, userId: string) { const session = await getServerSession(authOptions); if (!session?.user?.id) throw new Error('Unauthorized'); await prisma.collaborator.deleteMany({ where: { listId, userId, }, }); revalidatePath(`/list/${listId}`); } ``` **After:** ```typescript export async function removeCollaborator(listId: string, userId: string) { const session = await getServerSession(authOptions); if (!session?.user?.id) throw new Error('Unauthorized'); // 🔔 Get list details before removing const list = await prisma.list.findUnique({ where: { id: listId }, }); await prisma.collaborator.deleteMany({ where: { listId, userId, }, }); // 🔔 Notify the removed user if (list) { await notifyRemovedFromList(userId, list.title, session.user.id); } revalidatePath(`/list/${listId}`); } ``` ## Step 3: Add NotificationSettings to Profile Page In `app/profile/page.tsx`, add the component: ```typescript import NotificationSettings from '@/components/NotificationSettings'; export default function ProfilePage() { return (