webapp/src/components/Nav/Header.tsx
2022-09-18 18:31:48 +03:00

160 lines
5.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { For, Show, createSignal, createMemo, createEffect, onMount, onCleanup } from 'solid-js'
import Private from './Private'
import Notifications from './Notifications'
import Icon from './Icon'
import { Modal } from './Modal'
import AuthModal from './AuthModal'
import { t } from '../../utils/intl'
import { useModalStore, showModal, useWarningsStore } from '../../stores/ui'
import { useStore } from '@nanostores/solid'
import { session as ssession } from '../../stores/auth'
import { handleClientRouteLinkClick, router } from '../../stores/router'
import './Header.scss'
const resources = [
{ name: t('zine'), href: '/' },
{ name: t('feed'), href: '/feed' },
{ name: t('topics'), href: '/topics' }
//{ name: t('community'), href: '/community' }
]
export const Header = () => {
// signals
const [getIsScrollingBottom, setIsScrollingBottom] = createSignal(false)
const [getIsScrolled, setIsScrolled] = createSignal(false)
const [fixed, setFixed] = createSignal(false)
const [visibleWarnings, setVisibleWarnings] = createSignal(false)
// stores
const { getWarnings } = useWarningsStore()
const session = useStore(ssession)
const { getModal } = useModalStore()
const routing = useStore(router)
const subpath = createMemo(() => routing().path)
// methods
const toggleWarnings = () => setVisibleWarnings(!visibleWarnings())
const toggleFixed = () => setFixed(!fixed())
// effects
createEffect(() => {
if (fixed() || getModal()) {
document.body.classList.add('fixed')
} else {
document.body.classList.remove('fixed')
}
}, [fixed(), getModal()])
// derived
const authorized = createMemo(() => session()?.user?.slug)
const handleEnterClick = (ev) => {
showModal('auth')
handleClientRouteLinkClick(ev)
}
const handleBellIconClick = (ev) => {
if (!authorized()) {
handleEnterClick(ev)
return
}
toggleWarnings()
handleClientRouteLinkClick(ev)
}
onMount(() => {
let scrollTop = window.scrollY
const handleScroll = () => {
setIsScrollingBottom(window.scrollY > scrollTop)
setIsScrolled(window.scrollY > 0)
scrollTop = window.scrollY
}
window.addEventListener('scroll', handleScroll, { passive: true })
onCleanup(() => {
window.removeEventListener('scroll', handleScroll)
})
})
return (
<header
classList={{
['header--scrolled-top']: !getIsScrollingBottom() && getIsScrolled(),
['header--scrolled-bottom']: getIsScrollingBottom() && getIsScrolled()
}}
>
<Modal name="auth">
<AuthModal />
</Modal>
<div class="wide-container">
<nav class="row header__inner" classList={{ fixed: fixed() }}>
<div class="main-logo col-auto">
<a href="/" onClick={handleClientRouteLinkClick}>
<img src="/logo.svg" alt={t('Discours')} />
</a>
</div>
<div class="col main-navigation">
{/*FIXME article header*/}
<div class="article-header">
Дискурс независимый художественно-аналитический журнал с горизонтальной редакцией,
основанный на принципах свободы слова, прямой демократии и совместного редактирования.
</div>
<ul class="text-xl inline-flex" classList={{ fixed: fixed() }}>
<For each={resources}>
{(r: { href: string; name: string }) => (
<li classList={{ selected: r.href === subpath() }}>
<a href={r.href} onClick={handleClientRouteLinkClick}>
{r.name}
</a>
</li>
)}
</For>
<li class="header__search">
<a href="#">
<Icon name="search" />
{t('Search')}
</a>
</li>
</ul>
</div>
<div class="usernav">
<div class="usercontrol col">
<div class="usercontrol__item">
<a href="#auth" onClick={handleBellIconClick}>
<div>
<Icon name="bell-white" counter={authorized() ? getWarnings().length : 1} />
</div>
</a>
</div>
<Show when={visibleWarnings()}>
<div class="usercontrol__item notifications">
<Notifications />
</div>
</Show>
<Show
when={authorized()}
fallback={
<div class="usercontrol__item loginbtn">
<a href="#auth" onClick={handleEnterClick}>
{t('enter')}
</a>
</div>
}
>
<Private />
</Show>
</div>
</div>
<div class="burger-container">
<div class="burger" classList={{ fixed: fixed() }} onClick={toggleFixed}>
<div />
</div>
</div>
</nav>
</div>
</header>
)
}