ssr me and price
This commit is contained in:
parent
996d0a9352
commit
c7ae5dc8ac
@ -7,6 +7,8 @@ import typeDefs from './typeDefs'
|
||||
import models from './models'
|
||||
import { print } from 'graphql'
|
||||
import lnd from './lnd'
|
||||
import { ME } from '../fragments/users'
|
||||
import { getPrice } from '../components/price'
|
||||
|
||||
export default async function getSSRApolloClient (req, me = null) {
|
||||
const session = req && await getSession({ req })
|
||||
@ -41,12 +43,20 @@ export function getGetServerSideProps (query, variables = null, foundField) {
|
||||
}
|
||||
}
|
||||
|
||||
const { data: { me } } = await client.query({
|
||||
query: ME
|
||||
})
|
||||
|
||||
const price = await getPrice()
|
||||
|
||||
return {
|
||||
props: {
|
||||
apollo: {
|
||||
query: print(query),
|
||||
variables: { ...params, ...variables }
|
||||
},
|
||||
me,
|
||||
price,
|
||||
data
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import { Button, Container, NavDropdown, SplitButton, Dropdown } from 'react-boo
|
||||
import Price from './price'
|
||||
import { useMe } from './me'
|
||||
import Head from 'next/head'
|
||||
import { signOut, signIn, useSession } from 'next-auth/client'
|
||||
import { signOut, signIn } from 'next-auth/client'
|
||||
import { useLightning } from './lightning'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { randInRange } from '../lib/rand'
|
||||
@ -30,10 +30,8 @@ export default function Header () {
|
||||
const router = useRouter()
|
||||
const path = router.asPath.split('?')[0]
|
||||
const me = useMe()
|
||||
const [session, loading] = useSession()
|
||||
const [sort, setSort] = useState('recent')
|
||||
const [within, setWithin] = useState()
|
||||
const [priceReady, setPriceReady] = useState()
|
||||
|
||||
useEffect(() => {
|
||||
setSort(localStorage.getItem('sort') || 'recent')
|
||||
@ -127,9 +125,6 @@ export default function Header () {
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
if (loading || session) {
|
||||
return null
|
||||
}
|
||||
const strike = useLightning()
|
||||
useEffect(() => {
|
||||
setTimeout(strike, randInRange(3000, 10000))
|
||||
@ -138,8 +133,6 @@ export default function Header () {
|
||||
}
|
||||
}
|
||||
|
||||
const visible = ((session && me) || (!session && !loading)) && priceReady ? 'visible' : 'invisible'
|
||||
|
||||
return (
|
||||
<>
|
||||
<Container className='px-sm-0'>
|
||||
@ -154,7 +147,7 @@ export default function Header () {
|
||||
<Link href='/' passHref>
|
||||
<Navbar.Brand className={`${styles.brand} d-block d-sm-none`}>SN</Navbar.Brand>
|
||||
</Link>
|
||||
<Nav.Item className={`d-md-flex d-none nav-dropdown-toggle ${visible}`}>
|
||||
<Nav.Item className='d-md-flex d-none nav-dropdown-toggle'>
|
||||
<SplitButton
|
||||
title={
|
||||
<Link href={sortLink} passHref>
|
||||
@ -171,7 +164,7 @@ export default function Header () {
|
||||
</Link>
|
||||
</SplitButton>
|
||||
</Nav.Item>
|
||||
<Nav.Item className={`d-md-flex d-none ${visible}`}>
|
||||
<Nav.Item className='d-md-flex d-none'>
|
||||
{me
|
||||
? (
|
||||
<Link href='/post' passHref>
|
||||
@ -180,15 +173,13 @@ export default function Header () {
|
||||
)
|
||||
: <Nav.Link className={styles.navLink} onClick={signIn}>post</Nav.Link>}
|
||||
</Nav.Item>
|
||||
<Nav.Item className={`d-md-flex d-none ${visible}`}>
|
||||
<Nav.Item className='d-md-flex d-none'>
|
||||
<Nav.Link href='https://bitcoinerjobs.co' target='_blank' className={styles.navLink}>jobs</Nav.Link>
|
||||
</Nav.Item>
|
||||
<Nav.Item className={`text-monospace ${visible}`} style={{ opacity: '.5' }}>
|
||||
<Price onReady={() => setPriceReady(true)} />
|
||||
<Nav.Item className='text-monospace' style={{ opacity: '.5' }}>
|
||||
<Price />
|
||||
</Nav.Item>
|
||||
<div className={visible}>
|
||||
<Corner />
|
||||
</div>
|
||||
</Nav>
|
||||
</Navbar>
|
||||
</Container>
|
||||
|
@ -1,33 +1,16 @@
|
||||
import React, { useContext } from 'react'
|
||||
import { gql, useQuery } from '@apollo/client'
|
||||
import { useQuery } from '@apollo/client'
|
||||
import { ME } from '../fragments/users'
|
||||
|
||||
export const MeContext = React.createContext({
|
||||
me: null
|
||||
})
|
||||
|
||||
export function MeProvider ({ children }) {
|
||||
const query = gql`
|
||||
{
|
||||
me {
|
||||
id
|
||||
name
|
||||
sats
|
||||
stacked
|
||||
freePosts
|
||||
freeComments
|
||||
hasNewNotes
|
||||
tipDefault
|
||||
bio {
|
||||
id
|
||||
}
|
||||
hasInvites
|
||||
theme
|
||||
}
|
||||
}`
|
||||
const { data } = useQuery(query, { pollInterval: 1000 })
|
||||
export function MeProvider ({ me, children }) {
|
||||
const { data } = useQuery(ME, { pollInterval: 1000 })
|
||||
|
||||
const contextValue = {
|
||||
me: data ? data.me : null
|
||||
me: data ? data.me : me
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -1,29 +1,53 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import React, { useContext, useEffect, useState } from 'react'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import useSWR from 'swr'
|
||||
|
||||
const fetcher = url => fetch(url).then(res => res.json())
|
||||
|
||||
export default function Price ({ onReady }) {
|
||||
const [asSats, setAsSats] = useState(undefined)
|
||||
useEffect(() => {
|
||||
setAsSats(localStorage.getItem('asSats'))
|
||||
}, [])
|
||||
export const PriceContext = React.createContext({
|
||||
price: null
|
||||
})
|
||||
|
||||
const ENDPOINT = 'https://api.coinbase.com/v2/prices/BTC-USD/spot'
|
||||
|
||||
export async function getPrice () {
|
||||
const data = await fetcher(ENDPOINT)
|
||||
return data?.data?.amount
|
||||
}
|
||||
|
||||
export function PriceProvider ({ price, children }) {
|
||||
const { data } = useSWR(
|
||||
'https://api.coinbase.com/v2/prices/BTC-USD/spot',
|
||||
ENDPOINT,
|
||||
fetcher,
|
||||
{
|
||||
refreshInterval: 30000
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (onReady) {
|
||||
onReady()
|
||||
const contextValue = {
|
||||
price: data?.data?.amount || price
|
||||
}
|
||||
}, [data])
|
||||
|
||||
if (!data || !data.data) return null
|
||||
return (
|
||||
<PriceContext.Provider value={contextValue}>
|
||||
{children}
|
||||
</PriceContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export function usePrice () {
|
||||
const { price } = useContext(PriceContext)
|
||||
return price
|
||||
}
|
||||
|
||||
export default function Price () {
|
||||
const [asSats, setAsSats] = useState(undefined)
|
||||
useEffect(() => {
|
||||
setAsSats(localStorage.getItem('asSats'))
|
||||
}, [])
|
||||
|
||||
const price = usePrice()
|
||||
|
||||
if (!price) return null
|
||||
|
||||
const fixed = (n, f) => Number.parseFloat(n).toFixed(f)
|
||||
const handleClick = () => {
|
||||
@ -39,14 +63,14 @@ export default function Price ({ onReady }) {
|
||||
if (asSats) {
|
||||
return (
|
||||
<Button className='text-reset px-1 py-0' onClick={handleClick} variant='link'>
|
||||
{fixed(100000000 / data.data.amount, 0) + ' sats/$'}
|
||||
{fixed(100000000 / price, 0) + ' sats/$'}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Button className='text-reset px-1 py-0' onClick={handleClick} variant='link'>
|
||||
{'$' + fixed(data.data.amount, 2)}
|
||||
{'$' + fixed(price, 2)}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
@ -2,6 +2,25 @@ import { gql } from '@apollo/client'
|
||||
import { COMMENT_FIELDS } from './comments'
|
||||
import { ITEM_FIELDS, ITEM_WITH_COMMENTS } from './items'
|
||||
|
||||
export const ME = gql`
|
||||
{
|
||||
me {
|
||||
id
|
||||
name
|
||||
sats
|
||||
stacked
|
||||
freePosts
|
||||
freeComments
|
||||
hasNewNotes
|
||||
tipDefault
|
||||
bio {
|
||||
id
|
||||
}
|
||||
hasInvites
|
||||
theme
|
||||
}
|
||||
}`
|
||||
|
||||
export const USER_FIELDS = gql`
|
||||
${ITEM_FIELDS}
|
||||
fragment UserFields on User {
|
||||
|
@ -8,6 +8,7 @@ import { LightningProvider } from '../components/lightning'
|
||||
import { ItemActModal, ItemActProvider } from '../components/item-act'
|
||||
import getApolloClient from '../lib/apollo'
|
||||
import NextNProgress from 'nextjs-progressbar'
|
||||
import { PriceProvider } from '../components/price'
|
||||
|
||||
function MyApp ({ Component, pageProps: { session, ...props } }) {
|
||||
const client = getApolloClient()
|
||||
@ -27,6 +28,8 @@ function MyApp ({ Component, pageProps: { session, ...props } }) {
|
||||
}
|
||||
}
|
||||
|
||||
const { me, price } = props
|
||||
|
||||
return (
|
||||
<>
|
||||
<NextNProgress
|
||||
@ -40,7 +43,8 @@ function MyApp ({ Component, pageProps: { session, ...props } }) {
|
||||
<PlausibleProvider domain='stacker.news' trackOutboundLinks>
|
||||
<Provider session={session}>
|
||||
<ApolloProvider client={client}>
|
||||
<MeProvider>
|
||||
<MeProvider me={me}>
|
||||
<PriceProvider price={price}>
|
||||
<LightningProvider>
|
||||
<FundErrorProvider>
|
||||
<FundErrorModal />
|
||||
@ -50,6 +54,7 @@ function MyApp ({ Component, pageProps: { session, ...props } }) {
|
||||
</ItemActProvider>
|
||||
</FundErrorProvider>
|
||||
</LightningProvider>
|
||||
</PriceProvider>
|
||||
</MeProvider>
|
||||
</ApolloProvider>
|
||||
</Provider>
|
||||
|
@ -44,8 +44,6 @@ export async function getServerSideProps ({ req, res, query: { id, error = null
|
||||
return { props: {} }
|
||||
}
|
||||
|
||||
console.log(process.env.PUBLIC_URL + req.url)
|
||||
|
||||
return {
|
||||
props: {
|
||||
providers: await providers({ req, res }),
|
||||
|
Loading…
x
Reference in New Issue
Block a user