69 lines
2.2 KiB
Plaintext
69 lines
2.2 KiB
Plaintext
---
|
|
import { Icon } from 'astro-icon/components'
|
|
|
|
import { cn } from '../lib/cn'
|
|
import { prisma } from '../lib/prisma'
|
|
|
|
import type { HTMLAttributes } from 'astro/types'
|
|
|
|
type Props = Omit<HTMLAttributes<'a'>, 'href'> & {
|
|
count?: number | null
|
|
}
|
|
|
|
const { count: propsCount, class: className, ...htmlProps } = Astro.props
|
|
|
|
const user = Astro.locals.user
|
|
|
|
const count =
|
|
propsCount ??
|
|
(await Astro.locals.banners.try(
|
|
'Error getting unread notification count',
|
|
async () => (user ? await prisma.notification.count({ where: { userId: user.id, read: false } }) : 0),
|
|
0
|
|
))
|
|
---
|
|
|
|
{
|
|
user && (
|
|
<a
|
|
href="/notifications"
|
|
data-notification-count-link
|
|
data-current-count={count}
|
|
class={cn(
|
|
'group relative flex cursor-pointer items-center justify-center text-gray-400 transition-colors duration-100 hover:text-white',
|
|
className
|
|
)}
|
|
aria-label={`Go to notifications${count > 0 ? ` (${count} unread)` : ''}`}
|
|
{...htmlProps}
|
|
>
|
|
<Icon name="material-symbols:notifications-outline" class="size-5" />
|
|
<span
|
|
data-notification-count-badge
|
|
class="absolute top-[calc(50%-var(--spacing)*3.5)] right-[calc(50%-var(--spacing)*3.5)] flex size-3.5 items-center justify-center rounded-full bg-blue-600 text-[10px] font-bold tracking-tighter text-white group-hover:bg-blue-500 empty:hidden"
|
|
>
|
|
{count > 0 ? (count > 99 ? '★' : count.toLocaleString()) : ''}
|
|
</span>
|
|
</a>
|
|
)
|
|
}
|
|
|
|
<script>
|
|
document.addEventListener('sse-new-notification', () => {
|
|
document.querySelectorAll<HTMLElement>('[data-notification-count-link]').forEach((link) => {
|
|
const currentCount = Number(link.getAttribute('data-current-count') || 0)
|
|
const newCount = currentCount + 1
|
|
|
|
link.querySelectorAll<HTMLElement>('[data-notification-count-badge]').forEach((badge) => {
|
|
badge.textContent = newCount > 0 ? (newCount > 99 ? '★' : newCount.toLocaleString()) : ''
|
|
})
|
|
|
|
link.setAttribute(
|
|
'aria-label',
|
|
`Go to notifications${newCount > 0 ? ` (${newCount.toLocaleString()} unread)` : ''}`
|
|
)
|
|
|
|
link.setAttribute('data-current-count', String(newCount))
|
|
})
|
|
})
|
|
</script>
|