2023-10-14 11:39:24 +00:00
|
|
|
import { clsx } from 'clsx'
|
|
|
|
import styles from './NotificationsPanel.module.scss'
|
|
|
|
import { useEscKeyDownHandler } from '../../utils/useEscKeyDownHandler'
|
|
|
|
import { useOutsideClickHandler } from '../../utils/useOutsideClickHandler'
|
|
|
|
import { useLocalize } from '../../context/localize'
|
|
|
|
import { Icon } from '../_shared/Icon'
|
2023-10-16 15:57:29 +00:00
|
|
|
import { createEffect, For } from 'solid-js'
|
2023-10-14 11:39:24 +00:00
|
|
|
import { useNotifications } from '../../context/notifications'
|
|
|
|
import { NotificationView } from './NotificationView'
|
2023-10-16 17:24:33 +00:00
|
|
|
import { EmptyMessage } from './EmptyMessage'
|
2023-10-14 11:39:24 +00:00
|
|
|
|
|
|
|
type Props = {
|
|
|
|
isOpen: boolean
|
|
|
|
onClose: () => void
|
|
|
|
}
|
|
|
|
|
|
|
|
export const NotificationsPanel = (props: Props) => {
|
|
|
|
const { t } = useLocalize()
|
|
|
|
const { sortedNotifications } = useNotifications()
|
|
|
|
const handleHide = () => {
|
|
|
|
props.onClose()
|
|
|
|
}
|
|
|
|
|
|
|
|
const panelRef: { current: HTMLDivElement } = {
|
|
|
|
current: null
|
|
|
|
}
|
|
|
|
|
|
|
|
useOutsideClickHandler({
|
|
|
|
containerRef: panelRef,
|
|
|
|
predicate: () => props.isOpen,
|
|
|
|
handler: () => handleHide()
|
|
|
|
})
|
|
|
|
|
2023-10-16 17:24:33 +00:00
|
|
|
let windowScrollTop = 0
|
|
|
|
|
2023-10-14 11:39:24 +00:00
|
|
|
createEffect(() => {
|
2023-10-16 17:24:33 +00:00
|
|
|
const mainContent = document.querySelector<HTMLDivElement>('.main-content')
|
|
|
|
|
|
|
|
if (props.isOpen) {
|
|
|
|
windowScrollTop = window.scrollY
|
|
|
|
mainContent.style.marginTop = `-${windowScrollTop}px`
|
|
|
|
}
|
|
|
|
|
2023-10-14 11:39:24 +00:00
|
|
|
document.body.classList.toggle('fixed', props.isOpen)
|
2023-10-16 17:24:33 +00:00
|
|
|
|
|
|
|
if (!props.isOpen) {
|
|
|
|
mainContent.style.marginTop = ''
|
|
|
|
window.scrollTo(0, windowScrollTop)
|
|
|
|
}
|
2023-10-14 11:39:24 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
useEscKeyDownHandler(handleHide)
|
|
|
|
|
|
|
|
const handleNotificationViewClick = () => {
|
|
|
|
handleHide()
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div
|
|
|
|
class={clsx(styles.container, {
|
|
|
|
[styles.isOpened]: props.isOpen
|
|
|
|
})}
|
|
|
|
>
|
|
|
|
<div ref={(el) => (panelRef.current = el)} class={styles.panel}>
|
|
|
|
<div class={styles.closeButton} onClick={handleHide}>
|
|
|
|
{/*TODO: check markup (hover)*/}
|
|
|
|
<Icon name="close" />
|
|
|
|
</div>
|
|
|
|
<div class={styles.title}>{t('Notifications')}</div>
|
2023-10-16 17:24:33 +00:00
|
|
|
<For each={sortedNotifications()} fallback={<EmptyMessage />}>
|
2023-10-14 11:39:24 +00:00
|
|
|
{(notification) => (
|
|
|
|
<NotificationView
|
|
|
|
notification={notification}
|
|
|
|
class={styles.notificationView}
|
|
|
|
onClick={handleNotificationViewClick}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</For>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|