stacker.news/components/header.js

305 lines
10 KiB
JavaScript
Raw Normal View History

2021-04-12 18:05:09 +00:00
import Navbar from 'react-bootstrap/Navbar'
import Nav from 'react-bootstrap/Nav'
import Link from 'next/link'
import styles from './header.module.css'
import { useRouter } from 'next/router'
2021-12-05 17:37:55 +00:00
import { Button, Container, NavDropdown } from 'react-bootstrap'
2021-04-28 19:30:14 +00:00
import Price from './price'
2021-05-25 00:08:56 +00:00
import { useMe } from './me'
import Head from 'next/head'
2023-01-10 00:33:44 +00:00
import { signOut } from 'next-auth/client'
import { useLightning } from './lightning'
2021-10-21 22:05:06 +00:00
import { useEffect, useState } from 'react'
import { randInRange } from '../lib/rand'
2022-10-25 21:35:32 +00:00
import { abbrNum } from '../lib/format'
2022-04-19 21:37:05 +00:00
import NoteIcon from '../svgs/notification-4-fill.svg'
import { useQuery, gql } from '@apollo/client'
2022-09-27 21:27:29 +00:00
import LightningIcon from '../svgs/bolt.svg'
2021-11-12 22:39:52 +00:00
2021-06-24 23:56:01 +00:00
function WalletSummary ({ me }) {
2021-11-12 22:39:52 +00:00
if (!me) return null
2022-10-25 21:35:32 +00:00
return `${abbrNum(me.sats)}`
2021-05-11 15:52:50 +00:00
}
2021-03-25 19:29:24 +00:00
2022-02-17 17:23:43 +00:00
export default function Header ({ sub }) {
2021-04-12 18:05:09 +00:00
const router = useRouter()
2021-05-05 18:13:14 +00:00
const path = router.asPath.split('?')[0]
const [fired, setFired] = useState()
2021-06-24 23:56:01 +00:00
const me = useMe()
2022-02-17 17:23:43 +00:00
const prefix = sub ? `/~${sub}` : ''
2022-08-23 22:34:51 +00:00
// there's always at least 2 on the split, e.g. '/' yields ['','']
const topNavKey = path.split('/')[sub ? 2 : 1]
const { data: subLatestPost } = useQuery(gql`
query subLatestPost($name: ID!) {
subLatestPost(name: $name)
}
`, { variables: { name: 'jobs' }, pollInterval: 600000, fetchPolicy: 'network-only' })
const { data: hasNewNotes } = useQuery(gql`
{
hasNewNotes
}
`, { pollInterval: 30000, fetchPolicy: 'cache-and-network' })
const [lastCheckedJobs, setLastCheckedJobs] = useState(new Date().getTime())
useEffect(() => {
if (me) {
setLastCheckedJobs(me.lastCheckedJobs)
} else {
if (sub === 'jobs') {
localStorage.setItem('lastCheckedJobs', new Date().getTime())
}
setLastCheckedJobs(localStorage.getItem('lastCheckedJobs'))
}
2023-01-10 00:33:44 +00:00
}, [sub])
2021-10-21 22:05:06 +00:00
2021-04-12 18:05:09 +00:00
const Corner = () => {
2021-09-24 23:51:07 +00:00
if (me) {
2021-04-12 18:05:09 +00:00
return (
2021-05-05 18:13:14 +00:00
<div className='d-flex align-items-center'>
2021-08-17 23:59:22 +00:00
<Head>
<link rel='shortcut icon' href={hasNewNotes?.hasNewNotes ? '/favicon-notify.png' : '/favicon.png'} />
2021-08-17 23:59:22 +00:00
</Head>
2022-04-19 21:37:05 +00:00
<Link href='/notifications' passHref>
2022-08-23 22:34:51 +00:00
<Nav.Link eventKey='notifications' className='pl-0 position-relative'>
2023-01-06 01:15:48 +00:00
<NoteIcon className='theme' />
{hasNewNotes?.hasNewNotes &&
2022-04-19 21:37:05 +00:00
<span className={styles.notification}>
<span className='invisible'>{' '}</span>
</span>}
</Nav.Link>
</Link>
2021-11-12 22:39:52 +00:00
<div className='position-relative'>
<NavDropdown
className={styles.dropdown} title={
<Link href={`/${me?.name}`} passHref>
2022-08-23 22:34:51 +00:00
<Nav.Link eventKey={me?.name} as='div' className='p-0' onClick={e => e.preventDefault()}>{`@${me?.name}`}</Nav.Link>
</Link>
} alignRight
>
<Link href={'/' + me?.name} passHref>
2022-08-23 22:34:51 +00:00
<NavDropdown.Item eventKey={me?.name}>
2021-09-24 21:56:51 +00:00
profile
2022-04-28 18:11:05 +00:00
{me && !me.bioId &&
2021-09-24 21:56:51 +00:00
<div className='p-1 d-inline-block bg-secondary ml-1'>
<span className='invisible'>{' '}</span>
</div>}
</NavDropdown.Item>
2021-06-24 23:56:01 +00:00
</Link>
<Link href='/wallet' passHref>
2022-08-23 22:34:51 +00:00
<NavDropdown.Item eventKey='wallet'>wallet</NavDropdown.Item>
2021-06-24 23:56:01 +00:00
</Link>
2022-04-19 21:37:05 +00:00
<Link href='/satistics?inc=invoice,withdrawal,stacked,spent' passHref>
2022-08-23 22:34:51 +00:00
<NavDropdown.Item eventKey='satistics'>satistics</NavDropdown.Item>
2022-04-19 21:37:05 +00:00
</Link>
2021-10-14 21:05:37 +00:00
<NavDropdown.Divider />
2022-12-19 22:27:52 +00:00
<Link href='/referrals/month' passHref>
<NavDropdown.Item eventKey='referrals'>referrals</NavDropdown.Item>
2021-10-14 21:05:37 +00:00
</Link>
2021-05-06 21:15:22 +00:00
<NavDropdown.Divider />
2021-11-04 18:22:03 +00:00
<div className='d-flex align-items-center'>
<Link href='/settings' passHref>
2022-08-23 22:34:51 +00:00
<NavDropdown.Item eventKey='settings'>settings</NavDropdown.Item>
2021-11-04 18:22:03 +00:00
</Link>
</div>
2021-10-30 16:20:11 +00:00
<NavDropdown.Divider />
2021-12-20 22:34:26 +00:00
<NavDropdown.Item onClick={() => signOut({ callbackUrl: '/' })}>logout</NavDropdown.Item>
2021-06-24 23:56:01 +00:00
</NavDropdown>
2022-04-28 18:11:05 +00:00
{me && !me.bioId &&
2022-04-19 21:37:05 +00:00
<span className='position-absolute p-1 bg-secondary' style={{ top: '5px', right: '0px' }}>
2021-09-24 21:56:51 +00:00
<span className='invisible'>{' '}</span>
</span>}
2021-06-24 23:56:01 +00:00
</div>
{me &&
<Nav.Item>
<Link href='/wallet' passHref>
2022-08-23 22:34:51 +00:00
<Nav.Link eventKey='wallet' className='text-success px-0 text-nowrap'><WalletSummary me={me} /></Nav.Link>
2021-05-06 21:15:22 +00:00
</Link>
2021-06-24 23:56:01 +00:00
</Nav.Item>}
2021-05-05 18:13:14 +00:00
</div>
2021-04-12 18:05:09 +00:00
)
} else {
if (!fired) {
const strike = useLightning()
useEffect(() => {
2022-10-26 16:45:16 +00:00
let isMounted = true
if (!localStorage.getItem('striked')) {
setTimeout(() => {
if (isMounted) {
strike()
localStorage.setItem('striked', 'yep')
setFired(true)
}
}, randInRange(3000, 10000))
}
return () => { isMounted = false }
}, [])
}
2023-01-10 00:33:44 +00:00
return path !== '/login' && path !== '/signup' && !path.startsWith('/invites') &&
<div>
<Button
className='align-items-center px-3 py-1 mr-2'
id='signup'
style={{ borderWidth: '2px' }}
variant='outline-grey-darkmode'
onClick={async () => await router.push({ pathname: '/login', query: { callbackUrl: window.location.origin + router.asPath } })}
>
login
</Button>
<Button
className='align-items-center pl-2 py-1 pr-3'
style={{ borderWidth: '2px' }}
id='login'
onClick={async () => await router.push({ pathname: '/signup', query: { callbackUrl: window.location.origin + router.asPath } })}
>
<LightningIcon
width={17}
height={17}
className='mr-1'
/>sign up
</Button>
</div>
2021-04-12 18:05:09 +00:00
}
2021-03-25 19:29:24 +00:00
}
const showJobIndicator = sub !== 'jobs' && (!me || me.noteJobIndicator) &&
(!lastCheckedJobs || lastCheckedJobs < subLatestPost?.subLatestPost)
const NavItems = ({ className }) => {
return (
<>
<Nav.Item className={className}>
<Link href={prefix + '/recent'} passHref>
2022-08-23 22:34:51 +00:00
<Nav.Link eventKey='recent' className={styles.navLink}>recent</Nav.Link>
</Link>
</Nav.Item>
{!prefix &&
<Nav.Item className={className}>
2022-10-25 21:35:32 +00:00
<Link href='/top/posts' passHref>
2022-08-23 22:34:51 +00:00
<Nav.Link eventKey='top' className={styles.navLink}>top</Nav.Link>
</Link>
</Nav.Item>}
<Nav.Item className={className}>
<div className='position-relative'>
<Link href='/~jobs' passHref>
<Nav.Link active={sub === 'jobs'} className={styles.navLink}>
jobs
</Nav.Link>
</Link>
{showJobIndicator &&
<span className={styles.jobIndicator}>
<span className='invisible'>{' '}</span>
</span>}
</div>
</Nav.Item>
{me &&
<Nav.Item className={className}>
<Link href={prefix + '/post'} passHref>
2022-08-23 22:34:51 +00:00
<Nav.Link eventKey='post' className={styles.navLinkButton}>post</Nav.Link>
</Link>
</Nav.Item>}
</>
)
}
2021-03-25 19:29:24 +00:00
return (
2021-04-12 18:05:09 +00:00
<>
2021-04-28 16:30:02 +00:00
<Container className='px-sm-0'>
2022-03-08 20:51:06 +00:00
<Navbar className='pb-0 pb-md-1'>
2021-10-07 03:20:59 +00:00
<Nav
className={styles.navbarNav}
2022-08-23 22:34:51 +00:00
activeKey={topNavKey}
2021-10-07 03:20:59 +00:00
>
2022-02-17 17:23:43 +00:00
<div className='d-flex'>
<Link href='/' passHref>
2022-03-08 20:51:06 +00:00
<Navbar.Brand className={`${styles.brand} d-none d-md-block`}>
STACKER NEWS
2022-02-17 17:23:43 +00:00
</Navbar.Brand>
2021-12-05 17:37:55 +00:00
</Link>
2022-02-17 17:23:43 +00:00
<Link href='/' passHref>
2022-03-08 20:51:06 +00:00
<Navbar.Brand className={`${styles.brand} d-block d-md-none`}>
2022-02-17 17:23:43 +00:00
SN
</Navbar.Brand>
</Link>
</div>
<NavItems className='d-none d-md-flex' />
2022-03-08 20:51:06 +00:00
<Nav.Item className={`text-monospace nav-link px-0 ${me?.name.length > 6 ? 'd-none d-lg-flex' : ''}`}>
2021-11-28 17:29:17 +00:00
<Price />
2021-04-28 19:30:14 +00:00
</Nav.Item>
2021-11-28 17:29:17 +00:00
<Corner />
2021-04-14 00:57:32 +00:00
</Nav>
2021-11-09 22:43:56 +00:00
</Navbar>
2022-03-08 20:51:06 +00:00
<Navbar className='pt-0 pb-1 d-md-none'>
<Nav
2022-03-10 18:38:48 +00:00
className={`${styles.navbarNav} justify-content-around`}
2022-08-23 22:34:51 +00:00
activeKey={topNavKey}
2022-03-08 20:51:06 +00:00
>
<NavItems />
2022-03-08 20:51:06 +00:00
</Nav>
</Navbar>
2021-04-28 16:30:02 +00:00
</Container>
2021-04-12 18:05:09 +00:00
</>
2021-03-25 19:29:24 +00:00
)
}
2022-05-18 20:55:06 +00:00
const NavItemsStatic = ({ className }) => {
return (
<>
<Nav.Item className={className}>
<Link href='/recent' passHref>
<Nav.Link className={styles.navLink}>recent</Nav.Link>
</Link>
</Nav.Item>
<Nav.Item className={className}>
2022-10-25 21:35:32 +00:00
<Link href='/top/posts' passHref>
2022-05-18 20:55:06 +00:00
<Nav.Link className={styles.navLink}>top</Nav.Link>
</Link>
</Nav.Item>
<Nav.Item className={className}>
<div className='position-relative'>
<Link href='/~jobs' passHref>
<Nav.Link className={styles.navLink}>
jobs
</Nav.Link>
</Link>
</div>
</Nav.Item>
</>
)
}
export function HeaderStatic () {
return (
<Container className='px-sm-0'>
<Navbar className='pb-0 pb-md-1'>
<Nav
className={styles.navbarNav}
>
<div className='d-flex'>
<Link href='/' passHref>
<Navbar.Brand className={`${styles.brand} d-none d-md-block`}>
STACKER NEWS
</Navbar.Brand>
</Link>
<Link href='/' passHref>
<Navbar.Brand className={`${styles.brand} d-block d-md-none`}>
SN
</Navbar.Brand>
</Link>
</div>
<NavItemsStatic className='d-none d-md-flex' />
<Nav.Item className='text-monospace nav-link px-0'>
<Price />
</Nav.Item>
</Nav>
</Navbar>
<Navbar className='pt-0 pb-1 d-md-none'>
<Nav
className={`${styles.navbarNav} justify-content-around`}
>
<NavItemsStatic />
</Nav>
</Navbar>
</Container>
)
}