diff --git a/components/notifications/NotificationDropdown.tsx b/components/notifications/NotificationDropdown.tsx index 12032373..9a5b983e 100644 --- a/components/notifications/NotificationDropdown.tsx +++ b/components/notifications/NotificationDropdown.tsx @@ -12,6 +12,7 @@ import { Notification } from '@/types/notifications'; import { Skeleton } from '@/components/ui/skeleton'; import { markAsRead } from '@/lib/api/notifications'; import { toast } from 'sonner'; +import { getProjectUrlFromNotification } from '@/lib/notifications'; interface NotificationDropdownProps { notifications: Notification[]; @@ -109,11 +110,17 @@ export const NotificationDropdown = ({ notification.data.teamInvitationId && notification.data.projectId ) { - router.push(`/projects/${notification.data.projectId}`); + const url = getProjectUrlFromNotification(notification.data); + if (url) { + router.push(url); + } } // Project notifications else if (notification.data.projectId) { - router.push(`/projects/${notification.data.projectId}`); + const url = getProjectUrlFromNotification(notification.data); + if (url) { + router.push(url); + } } // Comment notifications else if (notification.data.commentId) { diff --git a/components/notifications/NotificationItem.tsx b/components/notifications/NotificationItem.tsx index 3fc8b549..9591bb6d 100644 --- a/components/notifications/NotificationItem.tsx +++ b/components/notifications/NotificationItem.tsx @@ -5,6 +5,7 @@ import Link from 'next/link'; import { Notification } from '@/types/notifications'; import { getNotificationIcon } from './NotificationIcon'; import { cn } from '@/lib/utils'; +import { getProjectUrlFromNotification } from '@/lib/notifications'; interface NotificationItemProps { notification: Notification; @@ -37,12 +38,12 @@ export const NotificationItem = ({ // Team invitation notifications (navigate to project if available) if (notification.data.teamInvitationId && notification.data.projectId) { - return `/projects/${notification.data.projectId}`; + return getProjectUrlFromNotification(notification.data) || '#'; } // Project notifications if (notification.data.projectId) { - return `/projects/${notification.data.projectId}`; + return getProjectUrlFromNotification(notification.data) || '#'; } // Comment notifications diff --git a/lib/notifications.ts b/lib/notifications.ts new file mode 100644 index 00000000..eb298136 --- /dev/null +++ b/lib/notifications.ts @@ -0,0 +1,25 @@ +import { Notification } from '@/types/notifications'; + +/** + * Generates a project URL from notification data. + * Prefers slug over ID for SEO-friendly URLs. + * + * @param data - The notification data object + * @returns The project URL path, or empty string if neither slug nor ID is available + */ +export const getProjectUrlFromNotification = ( + data: Notification['data'] +): string => { + // Prefer slug over ID for project links + if (data.projectSlug) { + return `/projects/${data.projectSlug}`; + } + + // Fallback to ID if slug is not available + if (data.projectId) { + return `/projects/${data.projectId}`; + } + + // Return empty string if neither is available + return ''; +}; diff --git a/types/notifications.ts b/types/notifications.ts index c33b71ec..80b37fb3 100644 --- a/types/notifications.ts +++ b/types/notifications.ts @@ -104,6 +104,7 @@ export interface Notification { // Project fields projectId?: string; projectName?: string; + projectSlug?: string; // Member fields memberEmail?: string; role?: string;