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'
|
2021-07-08 19:52:11 +00:00
|
|
|
import Head from 'next/head'
|
2021-11-28 17:29:17 +00:00
|
|
|
import { signOut, signIn } from 'next-auth/client'
|
2021-07-16 16:47:18 +00:00
|
|
|
import { useLightning } from './lightning'
|
2021-10-21 22:05:06 +00:00
|
|
|
import { useEffect, useState } from 'react'
|
2021-07-16 16:47:18 +00:00
|
|
|
import { randInRange } from '../lib/rand'
|
2022-02-17 17:23:43 +00:00
|
|
|
import { formatSats } from '../lib/format'
|
2022-04-19 21:37:05 +00:00
|
|
|
import NoteIcon from '../svgs/notification-4-fill.svg'
|
2022-05-09 17:30:27 +00:00
|
|
|
import { useQuery, gql } from '@apollo/client'
|
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-04-19 21:37:05 +00:00
|
|
|
return `${formatSats(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]
|
2021-12-06 16:32:58 +00:00
|
|
|
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-05-09 17:30:27 +00:00
|
|
|
const { data: subLatestPost } = useQuery(gql`
|
|
|
|
query subLatestPost($name: ID!) {
|
|
|
|
subLatestPost(name: $name)
|
|
|
|
}
|
|
|
|
`, { variables: { name: 'jobs' }, pollInterval: 600000, fetchPolicy: 'network-only' })
|
|
|
|
|
|
|
|
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'))
|
|
|
|
}
|
|
|
|
})
|
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>
|
2021-09-24 21:56:51 +00:00
|
|
|
<link rel='shortcut icon' href={me?.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>
|
|
|
|
<Nav.Link className='pl-0 position-relative'>
|
2022-04-21 17:48:27 +00:00
|
|
|
<NoteIcon />
|
2022-04-19 21:37:05 +00:00
|
|
|
{me?.hasNewNotes &&
|
|
|
|
<span className={styles.notification}>
|
|
|
|
<span className='invisible'>{' '}</span>
|
|
|
|
</span>}
|
|
|
|
</Nav.Link>
|
|
|
|
</Link>
|
2021-11-12 22:39:52 +00:00
|
|
|
<div className='position-relative'>
|
2022-05-24 21:15:51 +00:00
|
|
|
<NavDropdown
|
|
|
|
className={styles.dropdown} title={
|
|
|
|
<Link href={`/${me?.name}`} passHref>
|
|
|
|
<Nav.Link className='p-0' onClick={e => e.preventDefault()}>{`@${me?.name}`}</Nav.Link>
|
|
|
|
</Link>
|
|
|
|
} alignRight
|
|
|
|
>
|
2021-09-24 23:43:30 +00:00
|
|
|
<Link href={'/' + me?.name} passHref>
|
2021-09-24 21:56:51 +00:00
|
|
|
<NavDropdown.Item>
|
|
|
|
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>
|
|
|
|
<NavDropdown.Item>wallet</NavDropdown.Item>
|
|
|
|
</Link>
|
2022-04-19 21:37:05 +00:00
|
|
|
<Link href='/satistics?inc=invoice,withdrawal,stacked,spent' passHref>
|
|
|
|
<NavDropdown.Item>satistics</NavDropdown.Item>
|
|
|
|
</Link>
|
2021-10-14 21:05:37 +00:00
|
|
|
<NavDropdown.Divider />
|
|
|
|
<Link href='/invites' passHref>
|
2021-10-15 23:07:51 +00:00
|
|
|
<NavDropdown.Item>invites
|
|
|
|
{me && !me.hasInvites &&
|
|
|
|
<div className='p-1 d-inline-block bg-success ml-1'>
|
|
|
|
<span className='invisible'>{' '}</span>
|
|
|
|
</div>}
|
|
|
|
</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>
|
|
|
|
<NavDropdown.Item>settings</NavDropdown.Item>
|
|
|
|
</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>
|
2021-08-19 20:34:33 +00:00
|
|
|
<Nav.Link 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 {
|
2021-12-06 16:32:58 +00:00
|
|
|
if (!fired) {
|
|
|
|
const strike = useLightning()
|
|
|
|
useEffect(() => {
|
|
|
|
setTimeout(strike, randInRange(3000, 10000))
|
2022-01-05 20:37:34 +00:00
|
|
|
setFired(true)
|
2021-12-06 16:32:58 +00:00
|
|
|
}, [router.asPath])
|
|
|
|
}
|
2021-10-15 18:05:34 +00:00
|
|
|
return path !== '/login' && !path.startsWith('/invites') && <Button id='login' onClick={signIn}>login</Button>
|
2021-04-12 18:05:09 +00:00
|
|
|
}
|
2021-03-25 19:29:24 +00:00
|
|
|
}
|
|
|
|
|
2022-05-09 17:30:27 +00:00
|
|
|
const NavItems = ({ className }) => {
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<Nav.Item className={className}>
|
|
|
|
<Link href={prefix + '/recent'} passHref>
|
|
|
|
<Nav.Link className={styles.navLink}>recent</Nav.Link>
|
|
|
|
</Link>
|
|
|
|
</Nav.Item>
|
|
|
|
{!prefix &&
|
|
|
|
<Nav.Item className={className}>
|
|
|
|
<Link href='/top/posts/week' passHref>
|
|
|
|
<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 active={sub === 'jobs'} className={styles.navLink}>
|
|
|
|
jobs
|
|
|
|
</Nav.Link>
|
|
|
|
</Link>
|
|
|
|
{sub !== 'jobs' && (!me || me.noteJobIndicator) && (!lastCheckedJobs || lastCheckedJobs < subLatestPost?.subLatestPost) &&
|
|
|
|
<span className={styles.jobIndicator}>
|
|
|
|
<span className='invisible'>{' '}</span>
|
|
|
|
</span>}
|
|
|
|
</div>
|
|
|
|
</Nav.Item>
|
|
|
|
{me &&
|
|
|
|
<Nav.Item className={className}>
|
|
|
|
<Link href={prefix + '/post'} passHref>
|
|
|
|
<Nav.Link 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}
|
|
|
|
activeKey={path}
|
|
|
|
>
|
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`}>
|
2022-03-07 18:11:58 +00:00
|
|
|
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>
|
2022-05-09 17:30:27 +00:00
|
|
|
<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-03-08 20:51:06 +00:00
|
|
|
activeKey={path}
|
|
|
|
>
|
2022-05-09 17:30:27 +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}>
|
|
|
|
<Link href='/top/posts/week' passHref>
|
|
|
|
<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>
|
|
|
|
)
|
|
|
|
}
|