@@ -14,9 +14,10 @@ import {
1414import type { ComponentProps , ForwardRefExoticComponent , RefAttributes } from "react"
1515import * as DropdownMenu from "@radix-ui/react-dropdown-menu"
1616import { Badge , cn } from "@dotkomonline/ui"
17- import type { NotificationType , UserNotificationDTO } from "@dotkomonline/rpc"
17+ import type { NotificationType , NotificationPayloadType , UserNotificationDTO } from "@dotkomonline/rpc"
1818import { formatDistanceToNow , format , differenceInDays } from "date-fns"
1919import { nb } from "date-fns/locale"
20+ import Link from "next/link"
2021
2122const formatNotificationTime = ( date : Date ) : string => {
2223 const now = new Date ( )
@@ -47,6 +48,27 @@ export const NotificationIconMap: Record<
4748 NEW_FEEDBACK_FORM : IconSpeakerphone ,
4849}
4950
51+ const getNotificationUrl = ( payloadType : NotificationPayloadType , payload : string | null ) : string | null => {
52+ switch ( payloadType ) {
53+ case "URL" :
54+ return payload
55+ case "EVENT" :
56+ return payload ? `/arrangementer/${ payload } ` : null
57+ case "ARTICLE" :
58+ return payload ? `/artikler/${ payload } ` : null
59+ case "GROUP" :
60+ return payload ? `/grupper/${ payload } ` : null
61+ case "USER" :
62+ return payload ? `/profil/${ payload } ` : null
63+ case "OFFLINE" :
64+ return `/offline` // TODO: Fix in the future
65+ case "JOB_LISTING" :
66+ return payload ? `/karriere/${ payload } ` : null
67+ case "NONE" :
68+ return null
69+ }
70+ }
71+
5072interface NotificationItem extends ComponentProps < typeof DropdownMenu . Item > {
5173 userNotification : UserNotificationDTO
5274 onItemClick ?: ( ) => void
@@ -67,61 +89,73 @@ export const NotificationItem = ({ userNotification, onItemClick, className, ...
6789 const unreadIconBgColor = isImportant ? "bg-red-500/20" : "bg-blue-500/20"
6890
6991 const handleSelect = ( event : Event ) => {
70- // Prevent dropdown from closing if payloadType is NONE
7192 if ( notification . payloadType === "NONE" ) {
7293 event . preventDefault ( )
7394 }
7495 }
7596
76- return (
77- < DropdownMenu . Item
78- { ...props }
79- className = { cn (
80- "flex gap-4 px-5 py-4 cursor-pointer border-l-4 focus-visible:outline-none not-last:border-b not-last:border-b-white/10" ,
81- { [ unreadItemColor ] : ! isRead } ,
82- {
83- "opacity-80 border-transparent hover:bg-blue-100 focus-visible:bg-blue-100 dark:hover:bg-white/5 dark:focus-visible:bg-white/10" :
84- isRead ,
85- } ,
86- className
87- ) }
88- onSelect = { handleSelect }
89- onClick = { onItemClick }
90- >
91- < div className = "flex flex-row gap-3 w-full" >
92- < div >
93- < div
94- className = { cn (
95- "rounded-lg flex items-center justify-center h-10 w-10" ,
96- { [ unreadIconBgColor ] : ! isRead } ,
97- { "bg-black/10" : isRead }
98- ) }
99- >
100- < Icon
101- className = { cn ( "w-6 h-6" , { [ unreadTextColor ] : ! isRead } , { "text-stone-800 dark:text-white" : isRead } ) }
102- />
103- </ div >
104- { ! isRead && < div className = { cn ( "h-2 w-2 rounded-full mx-auto mt-2" , unreadDotColor ) } /> }
105- </ div >
106- < div className = "flex flex-col p-0.5 w-full relative" >
107- < p className = "text-black/70 dark:text-white/70 text-xs ml-auto absolute top-0 right-0" >
108- { formatNotificationTime ( new Date ( notification . createdAt ) ) }
109- </ p >
110-
111- { isImportant && (
112- < Badge
113- variant = "solid"
114- color = "red"
115- className = { cn ( "bg-red-500 text-white text-xs py-1 px-2" , { "mb-1" : isImportant } ) }
116- >
117- Viktig melding
118- </ Badge >
119- ) }
97+ const notificationUrl = getNotificationUrl ( notification . payloadType , notification . payload )
12098
121- < p className = "font-semibold text-black dark:text-white text-sm" > { notification . title } </ p >
122- < p className = "text-black dark:text-white/80 text-sm" > { notification . shortDescription } </ p >
99+ const itemContent = (
100+ < div className = "flex flex-row gap-3 w-full" >
101+ < div >
102+ < div
103+ className = { cn (
104+ "rounded-lg flex items-center justify-center h-10 w-10" ,
105+ { [ unreadIconBgColor ] : ! isRead } ,
106+ { "bg-black/10" : isRead }
107+ ) }
108+ >
109+ < Icon
110+ className = { cn ( "w-6 h-6" , { [ unreadTextColor ] : ! isRead } , { "text-stone-800 dark:text-white" : isRead } ) }
111+ />
123112 </ div >
113+ { ! isRead && < div className = { cn ( "h-2 w-2 rounded-full mx-auto mt-2" , unreadDotColor ) } /> }
124114 </ div >
115+ < div className = "flex flex-col p-0.5 w-full relative" >
116+ < p className = "text-black/70 dark:text-white/70 text-xs ml-auto absolute top-0 right-0" >
117+ { formatNotificationTime ( new Date ( notification . createdAt ) ) }
118+ </ p >
119+
120+ { isImportant && (
121+ < Badge
122+ variant = "solid"
123+ color = "red"
124+ className = { cn ( "bg-red-500 text-white text-xs py-1 px-2" , { "mb-1" : isImportant } ) }
125+ >
126+ Viktig melding
127+ </ Badge >
128+ ) }
129+
130+ < p className = "font-semibold text-black dark:text-white text-sm" > { notification . title } </ p >
131+ < p className = "text-black dark:text-white/80 text-sm" > { notification . shortDescription } </ p >
132+ </ div >
133+ </ div >
134+ )
135+
136+ const itemClassName = cn (
137+ "flex gap-4 px-5 py-4 cursor-pointer border-l-4 focus-visible:outline-none not-last:border-b not-last:border-b-white/10" ,
138+ { [ unreadItemColor ] : ! isRead } ,
139+ {
140+ "opacity-80 border-transparent hover:bg-blue-100 focus-visible:bg-blue-100 dark:hover:bg-white/5 dark:focus-visible:bg-white/10" :
141+ isRead ,
142+ } ,
143+ className
144+ )
145+
146+ if ( notificationUrl !== null ) {
147+ return (
148+ < DropdownMenu . Item { ...props } asChild onSelect = { handleSelect } onClick = { onItemClick } >
149+ < Link href = { notificationUrl } className = { itemClassName } >
150+ { itemContent }
151+ </ Link >
152+ </ DropdownMenu . Item >
153+ )
154+ }
155+
156+ return (
157+ < DropdownMenu . Item { ...props } className = { itemClassName } onSelect = { handleSelect } onClick = { onItemClick } >
158+ { itemContent }
125159 </ DropdownMenu . Item >
126160 )
127161}
0 commit comments