mirror of
https://github.com/CompassConnections/Compass.git
synced 2026-03-25 01:51:37 -04:00
111 lines
3.7 KiB
TypeScript
111 lines
3.7 KiB
TypeScript
import {type Notification, NOTIFICATIONS_PER_PAGE} from 'common/notifications'
|
|
import {type User} from 'common/user'
|
|
import {first, groupBy, sortBy} from 'lodash'
|
|
import {useEffect, useMemo} from 'react'
|
|
import {api} from 'web/lib/api'
|
|
import {useLocale} from 'web/lib/locale'
|
|
|
|
import {useApiSubscription} from './use-api-subscription'
|
|
import {usePersistentLocalState} from './use-persistent-local-state'
|
|
|
|
export function useGroupedUnseenNotifications(userId: string, selectTypes?: string[]) {
|
|
const notifications = useUnseenNotifications(userId)?.filter((n) =>
|
|
selectTypes ? selectTypes.includes(n.sourceType) : true,
|
|
)
|
|
return useMemo(() => {
|
|
return notifications ? groupNotificationsForIcon(notifications) : undefined
|
|
}, [notifications])
|
|
}
|
|
|
|
export function useGroupedNotifications(user: User, selectTypes?: string[]) {
|
|
const notifications = useNotifications(user.id)?.filter((n) =>
|
|
selectTypes ? selectTypes.includes(n.sourceType) : true,
|
|
)
|
|
const sortedNotifications = notifications
|
|
? sortBy(notifications, (n) => -n.createdTime)
|
|
: undefined
|
|
|
|
const [groupedNotifications, mostRecentNotification] = groupGeneralNotifications(
|
|
sortedNotifications,
|
|
['loan_income', 'contract_from_followed_user'],
|
|
)
|
|
|
|
return useMemo(
|
|
() => ({
|
|
mostRecentNotification,
|
|
groupedNotifications,
|
|
}),
|
|
[notifications],
|
|
)
|
|
}
|
|
|
|
function groupGeneralNotifications(
|
|
sortedNotifications: Notification[] | undefined,
|
|
except: string[],
|
|
) {
|
|
if (!sortedNotifications) return []
|
|
|
|
const groupedNotificationsByDayAndContract = groupBy(
|
|
sortedNotifications.filter((n) => !except.includes(n.reason ?? '')),
|
|
(n) =>
|
|
new Date(n.createdTime).toDateString() +
|
|
(n.sourceType === 'betting_streak_bonus' || n.reason === 'quest_payout'
|
|
? 'quest_payout'
|
|
: n.sourceType === 'profile_like'
|
|
? 'profile_like'
|
|
: n.sourceType === 'profile_ship'
|
|
? 'profile_ship'
|
|
: n.data?.isPartner
|
|
? 'isPartner'
|
|
: 'unknown'),
|
|
)
|
|
const mostRecentNotification = first(sortedNotifications)
|
|
const groupedNotifications = groupNotifications(groupedNotificationsByDayAndContract)
|
|
|
|
return [groupedNotifications, mostRecentNotification] as const
|
|
}
|
|
|
|
function useNotifications(userId: string, count = 15 * NOTIFICATIONS_PER_PAGE) {
|
|
const [notifications, setNotifications] = usePersistentLocalState<Notification[] | undefined>(
|
|
undefined,
|
|
'notifications-' + userId,
|
|
)
|
|
const {locale} = useLocale()
|
|
useEffect(() => {
|
|
if (userId)
|
|
api('get-notifications', {limit: count, locale}).then((data) => {
|
|
setNotifications(data)
|
|
})
|
|
}, [userId, locale])
|
|
useApiSubscription({
|
|
topics: [`user-notifications/${userId}`],
|
|
onBroadcast: ({data}) => {
|
|
setNotifications((notifs) => [data.notification as Notification, ...(notifs ?? [])])
|
|
},
|
|
})
|
|
return notifications
|
|
}
|
|
|
|
function useUnseenNotifications(userId: string, count = NOTIFICATIONS_PER_PAGE) {
|
|
const notifs = useNotifications(userId, count)
|
|
return notifs?.filter((n) => !n.isSeen)
|
|
}
|
|
|
|
const groupNotifications = (notifications: Record<string, Notification[]>) => {
|
|
return Object.entries(notifications).map(([key, value]) => ({
|
|
notifications: value,
|
|
groupedById: key,
|
|
isSeen: value.every((n: any) => n.isSeen),
|
|
}))
|
|
}
|
|
|
|
function groupNotificationsForIcon(notifications: Notification[]) {
|
|
const sortedNotifications = sortBy(notifications, (n) => -n.createdTime)
|
|
const notificationGroupsByDayOrDayAndContract = groupBy(
|
|
sortedNotifications,
|
|
(notification) => new Date(notification.createdTime).toDateString() + notification.sourceTitle,
|
|
)
|
|
|
|
return groupNotifications(notificationGroupsByDayOrDayAndContract)
|
|
}
|