qmining-page/src/components/layout.jsx
2023-04-08 18:21:08 +02:00

298 lines
7.5 KiB
JavaScript

import React, { useState, useEffect } from 'react'
import ReactDOM from 'react-dom'
import Link from 'next/link'
import dynamic from 'next/dynamic'
const Snowfall = dynamic(() => import('react-snowfall'), { ssr: false })
import LogoutIcon from './logoutIcon'
import Modal from './modal'
import constants from '../constants'
import BB from './b'
import styles from './layout.module.css'
import tabs from '../data/tabs.json'
import topBarLinks from '../data/topBarLinks.json'
const shouldRenderSnow = () => {
const date = new Date()
// if its december, and date is more than 5
return date.getMonth() === 11 && date.getDate() > 5
}
function Snow() {
const [windowSize, setWindowSize] = useState([100, 200])
const [snowShowing, setSnowShowing] = useState(true)
useEffect(() => {
setWindowSize([window.innerWidth, window.innerHeight])
window.addEventListener('resize', () => {
setWindowSize([window.innerWidth, window.innerHeight])
})
}, [])
const snowflakeCount = (windowSize[0] + windowSize[1]) / 26
if (typeof window !== 'object') return null
return ReactDOM.createPortal(
<>
<div
onClick={() => setSnowShowing(!snowShowing)}
className={styles.snowToggleButton}
>
{snowShowing ? 'off' : 'on'}
</div>
<div
style={{
pointerEvents: 'none',
zIndex: 900,
position: 'fixed',
width: `${windowSize[0]}px`,
height: `${windowSize[1]}px`,
}}
>
{snowShowing && <Snowfall snowflakeCount={snowflakeCount} />}
</div>
</>,
document.body
)
}
function TopBar({
setSidebarOpen,
sidebarOpen,
closeSideBar,
href,
unreads,
userId,
}) {
return (
<>
<MenuIcon setSidebarOpen={setSidebarOpen} sidebarOpen={sidebarOpen} />
<Link href="/">
<img
src={`${constants.siteUrl}img/frylabs-logo_small_transparent.png`}
alt="Qmining"
/>
</Link>
<div className={styles.topBarLinks}>
{Object.keys(topBarLinks).map((key) => {
const item = topBarLinks[key]
return (
<Link
key={key}
href={item.href}
onClick={closeSideBar}
className={href.includes(key) ? styles.active : undefined}
>
{item.text}
</Link>
)
})}
</div>
<div className={'seperator'} />
<UserStatus onClick={closeSideBar} unreads={unreads} userId={userId} />
</>
)
}
function SideBar({ sidebarOpen, closeSideBar, href, setDonateShowing }) {
return sidebarOpen ? (
<>
<div id="sideBarLinks" className={styles.sidebarLinks}>
{Object.keys(tabs).map((key) => {
const item = tabs[key]
if (item.seperator) {
return <hr key={key} />
}
return (
<Link
href={item.href}
key={key}
onClick={closeSideBar}
className={href.includes(key) ? styles.active : undefined}
id={item.id || undefined}
>
{item.text}
</Link>
)
})}
<a
onClick={() => {
closeSideBar()
setDonateShowing(true)
}}
>
Donate
</a>
</div>
</>
) : null
}
function Donate() {
return (
<div>
<div className={styles.modalHead}>Donate</div>
<div style={{ textAlign: 'justify', margin: '8px' }}>
Paypalon és Patreonon látszódik a neved, de Patreonon könnyen meg lehet
változtatni. Ha név nélkül szeretnél adakozni, akkor írd át egy
nickname-re. De akárhova adakozol, a neved sehova se lesz kiadva, és nem
látja 3. személy.
<p />A kapott összegekből van fizetve a szerver fenntartása (áram,
domain név, ...), ezen túl pedig a sok programozással eltelt idő
kipihenése közben használt különböző élvezeti cikkek
</div>
<div className={styles.donateLogoContainer}>
<a
href={`${constants.siteUrl}patreon`}
target="_blank"
rel="noreferrer"
>
<img
style={{
border: 'none',
margin: '15px',
}}
src={`${constants.siteUrl}img/patreon-logo.png`}
/>
</a>
<a href={`${constants.siteUrl}donate`} target="_blank" rel="noreferrer">
<img
style={{
border: 'none',
margin: '15px',
}}
src={`${constants.siteUrl}img/paypal-logo.png`}
/>
</a>
</div>
</div>
)
}
function UserStatus({ userId, unreads, onClick }) {
const unreadCount = unreads ? unreads.length : 0
return (
<div className={styles.userStatus}>
<div className={'uid'} title="User ID">
UID: {userId || '...'}
</div>
<Link
href="/chat"
onClick={onClick}
title={`Chat${unreadCount ? ' (' + unreadCount + ' új üzenet)' : ''}`}
className={styles.unreadNotification}
>
<span>💬</span>
{unreadCount ? <div>{unreadCount}</div> : null}
</Link>
<div
className={styles.logout}
title="Kijelentkezés"
onClick={() => {
const res = window.confirm('Kijelentkezel?')
if (!res) return
fetch(constants.apiUrl + 'logout', {
method: 'GET',
credentials: 'include',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
}).then(() => {
location.reload()
})
}}
>
<LogoutIcon size={28} />
</div>
</div>
)
}
function MenuIcon({ setSidebarOpen, sidebarOpen }) {
return (
<div
onClick={() => {
setSidebarOpen(!sidebarOpen)
}}
className={styles.menuicon}
>
<div />
<div />
<div />
</div>
)
}
export default function Layout({ children, router, globalData }) {
const [sidebarOpen, setSidebarOpen] = useState(true)
const [donateShowing, setDonateShowing] = useState(false)
const userId = globalData.userId
const unreads = globalData.unreads
useEffect(() => {
setDonateShowing(!!router.query.donate)
}, [router.query.donate])
let href = router.route
if (href === '/' || href === '') {
href = 'index'
}
const closeSideBar = () => {
if (typeof window !== 'undefined') {
if (window.innerWidth < constants.mobileWindowWidth) {
setSidebarOpen(false)
}
}
}
useEffect(() => {
closeSideBar()
window.addEventListener('resize', () => {
setSidebarOpen(window.innerWidth >= 700)
})
}, [])
return (
<>
<div className={styles.topBar}>
<TopBar
setSidebarOpen={setSidebarOpen}
sidebarOpen={sidebarOpen}
closeSideBar={closeSideBar}
href={href}
unreads={unreads}
userId={userId}
/>
</div>
<div className={styles.sidebar}>
<SideBar
sidebarOpen={sidebarOpen}
closeSideBar={closeSideBar}
href={href}
setDonateShowing={setDonateShowing}
/>
</div>
{donateShowing ? (
<Modal
closeClick={() => {
setDonateShowing(false)
}}
>
<Donate />
</Modal>
) : null}
<div className={styles.content}>{children}</div>
<BB />
{shouldRenderSnow() && <Snow />}
</>
)
}