global modal + small fixes/enhancements
This commit is contained in:
parent
e2d7506ebf
commit
ae5c6c457f
@ -3,7 +3,7 @@ import ArrowRight from '../svgs/arrow-right-s-fill.svg'
|
|||||||
import ArrowDown from '../svgs/arrow-down-s-fill.svg'
|
import ArrowDown from '../svgs/arrow-down-s-fill.svg'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
|
|
||||||
export default function AccordianItem ({ header, body, className, headerColor = 'var(--theme-grey)', show }) {
|
export default function AccordianItem ({ header, body, headerColor = 'var(--theme-grey)', show }) {
|
||||||
const [open, setOpen] = useState(show)
|
const [open, setOpen] = useState(show)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -19,7 +19,6 @@ export default function AccordianItem ({ header, body, className, headerColor =
|
|||||||
eventKey='0'
|
eventKey='0'
|
||||||
style={{ cursor: 'pointer', display: 'flex', alignItems: 'center' }}
|
style={{ cursor: 'pointer', display: 'flex', alignItems: 'center' }}
|
||||||
onClick={() => setOpen(!open)}
|
onClick={() => setOpen(!open)}
|
||||||
className={className}
|
|
||||||
>
|
>
|
||||||
{open
|
{open
|
||||||
? <ArrowDown style={{ fill: headerColor }} height={20} width={20} />
|
? <ArrowDown style={{ fill: headerColor }} height={20} width={20} />
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { gql, useMutation } from '@apollo/client'
|
import { gql, useMutation } from '@apollo/client'
|
||||||
import { Dropdown } from 'react-bootstrap'
|
import { Dropdown } from 'react-bootstrap'
|
||||||
import MoreIcon from '../svgs/more-fill.svg'
|
import MoreIcon from '../svgs/more-fill.svg'
|
||||||
import { useFundError } from './fund-error'
|
import FundError from './fund-error'
|
||||||
|
import { useShowModal } from './modal'
|
||||||
|
|
||||||
export default function DontLikeThis ({ id }) {
|
export default function DontLikeThis ({ id }) {
|
||||||
const { setError } = useFundError()
|
const showModal = useShowModal()
|
||||||
|
|
||||||
const [dontLikeThis] = useMutation(
|
const [dontLikeThis] = useMutation(
|
||||||
gql`
|
gql`
|
||||||
@ -41,7 +42,9 @@ export default function DontLikeThis ({ id }) {
|
|||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.toString().includes('insufficient funds')) {
|
if (error.toString().includes('insufficient funds')) {
|
||||||
setError(true)
|
showModal(onClose => {
|
||||||
|
return <FundError onClose={onClose} />
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
@ -1,48 +1,15 @@
|
|||||||
import { Button, Modal } from 'react-bootstrap'
|
|
||||||
import React, { useState, useCallback, useContext } from 'react'
|
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
import { Button } from 'react-bootstrap'
|
||||||
|
|
||||||
export const FundErrorContext = React.createContext({
|
export default function FundError ({ onClose }) {
|
||||||
error: null,
|
|
||||||
toggleError: () => {}
|
|
||||||
})
|
|
||||||
|
|
||||||
export function FundErrorProvider ({ children }) {
|
|
||||||
const [error, setError] = useState(false)
|
|
||||||
|
|
||||||
const contextValue = {
|
|
||||||
error,
|
|
||||||
setError: useCallback(e => setError(e), [])
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FundErrorContext.Provider value={contextValue}>
|
<>
|
||||||
{children}
|
<p className='font-weight-bolder'>you need more sats</p>
|
||||||
</FundErrorContext.Provider>
|
<div className='d-flex justify-content-end'>
|
||||||
)
|
<Link href='/wallet?type=fund'>
|
||||||
}
|
<Button variant='success' onClick={onClose}>fund</Button>
|
||||||
|
</Link>
|
||||||
export function useFundError () {
|
</div>
|
||||||
const { error, setError } = useContext(FundErrorContext)
|
</>
|
||||||
return { error, setError }
|
|
||||||
}
|
|
||||||
|
|
||||||
export function FundErrorModal () {
|
|
||||||
const { error, setError } = useFundError()
|
|
||||||
return (
|
|
||||||
<Modal
|
|
||||||
show={error}
|
|
||||||
onHide={() => setError(false)}
|
|
||||||
>
|
|
||||||
<div className='modal-close' onClick={() => setError(false)}>X</div>
|
|
||||||
<Modal.Body>
|
|
||||||
<p className='font-weight-bolder'>you need more sats</p>
|
|
||||||
<div className='d-flex justify-content-end'>
|
|
||||||
<Link href='/wallet?type=fund'>
|
|
||||||
<Button variant='success' onClick={() => setError(false)}>fund</Button>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</Modal.Body>
|
|
||||||
</Modal>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,105 +1,69 @@
|
|||||||
import { Button, InputGroup, Modal } from 'react-bootstrap'
|
import { Button, InputGroup } from 'react-bootstrap'
|
||||||
import React, { useState, useCallback, useContext, useRef, useEffect } from 'react'
|
import React, { useState, useRef, useEffect } from 'react'
|
||||||
import * as Yup from 'yup'
|
import * as Yup from 'yup'
|
||||||
import { Form, Input, SubmitButton } from './form'
|
import { Form, Input, SubmitButton } from './form'
|
||||||
import { useMe } from './me'
|
import { useMe } from './me'
|
||||||
import UpBolt from '../svgs/bolt.svg'
|
import UpBolt from '../svgs/bolt.svg'
|
||||||
|
|
||||||
export const ItemActContext = React.createContext({
|
|
||||||
item: null,
|
|
||||||
setItem: () => {}
|
|
||||||
})
|
|
||||||
|
|
||||||
export function ItemActProvider ({ children }) {
|
|
||||||
const [item, setItem] = useState(null)
|
|
||||||
|
|
||||||
const contextValue = {
|
|
||||||
item,
|
|
||||||
setItem: useCallback(i => setItem(i), [])
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ItemActContext.Provider value={contextValue}>
|
|
||||||
{children}
|
|
||||||
</ItemActContext.Provider>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useItemAct () {
|
|
||||||
const { item, setItem } = useContext(ItemActContext)
|
|
||||||
return { item, setItem }
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ActSchema = Yup.object({
|
export const ActSchema = Yup.object({
|
||||||
amount: Yup.number().typeError('must be a number').required('required')
|
amount: Yup.number().typeError('must be a number').required('required')
|
||||||
.positive('must be positive').integer('must be whole')
|
.positive('must be positive').integer('must be whole')
|
||||||
})
|
})
|
||||||
|
|
||||||
export function ItemActModal () {
|
export default function ItemAct ({ onClose, itemId, act, strike }) {
|
||||||
const { item, setItem } = useItemAct()
|
|
||||||
const inputRef = useRef(null)
|
const inputRef = useRef(null)
|
||||||
const me = useMe()
|
const me = useMe()
|
||||||
const [oValue, setOValue] = useState()
|
const [oValue, setOValue] = useState()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
inputRef.current?.focus()
|
inputRef.current?.focus()
|
||||||
}, [item])
|
}, [onClose, itemId])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Form
|
||||||
show={!!item}
|
initial={{
|
||||||
onHide={() => {
|
amount: me?.tipDefault,
|
||||||
setItem(null)
|
default: false
|
||||||
|
}}
|
||||||
|
schema={ActSchema}
|
||||||
|
onSubmit={async ({ amount }) => {
|
||||||
|
await act({
|
||||||
|
variables: {
|
||||||
|
id: itemId,
|
||||||
|
sats: Number(amount)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
await strike()
|
||||||
|
onClose()
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className='modal-close' onClick={() => setItem(null)}>X</div>
|
<Input
|
||||||
<Modal.Body>
|
label='amount'
|
||||||
<Form
|
name='amount'
|
||||||
initial={{
|
innerRef={inputRef}
|
||||||
amount: me?.tipDefault,
|
overrideValue={oValue}
|
||||||
default: false
|
required
|
||||||
}}
|
autoFocus
|
||||||
schema={ActSchema}
|
append={<InputGroup.Text className='text-monospace'>sats</InputGroup.Text>}
|
||||||
onSubmit={async ({ amount }) => {
|
/>
|
||||||
await item.act({
|
<div>
|
||||||
variables: {
|
{[1, 10, 100, 1000, 10000].map(num =>
|
||||||
id: item.itemId,
|
<Button
|
||||||
sats: Number(amount)
|
size='sm'
|
||||||
}
|
className={`${num > 1 ? 'ml-2' : ''} mb-2`}
|
||||||
})
|
key={num}
|
||||||
await item.strike()
|
onClick={() => { setOValue(num) }}
|
||||||
setItem(null)
|
>
|
||||||
}}
|
<UpBolt
|
||||||
>
|
className='mr-1'
|
||||||
<Input
|
width={14}
|
||||||
label='amount'
|
height={14}
|
||||||
name='amount'
|
/>{num}
|
||||||
innerRef={inputRef}
|
</Button>)}
|
||||||
overrideValue={oValue}
|
</div>
|
||||||
required
|
<div className='d-flex'>
|
||||||
autoFocus
|
<SubmitButton variant='success' className='ml-auto mt-1 px-4' value='TIP'>tip</SubmitButton>
|
||||||
append={<InputGroup.Text className='text-monospace'>sats</InputGroup.Text>}
|
</div>
|
||||||
/>
|
</Form>
|
||||||
<div>
|
|
||||||
{[1, 10, 100, 1000, 10000].map(num =>
|
|
||||||
<Button
|
|
||||||
size='sm'
|
|
||||||
className={`${num > 1 ? 'ml-2' : ''} mb-2`}
|
|
||||||
key={num}
|
|
||||||
onClick={() => { setOValue(num) }}
|
|
||||||
>
|
|
||||||
<UpBolt
|
|
||||||
className='mr-1'
|
|
||||||
width={14}
|
|
||||||
height={14}
|
|
||||||
/>{num}
|
|
||||||
</Button>)}
|
|
||||||
</div>
|
|
||||||
<div className='d-flex'>
|
|
||||||
<SubmitButton variant='success' className='ml-auto mt-1 px-4' value='TIP'>tip</SubmitButton>
|
|
||||||
</div>
|
|
||||||
</Form>
|
|
||||||
</Modal.Body>
|
|
||||||
</Modal>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ import { Form, Input, SubmitButton } from '../components/form'
|
|||||||
import * as Yup from 'yup'
|
import * as Yup from 'yup'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import Alert from 'react-bootstrap/Alert'
|
import Alert from 'react-bootstrap/Alert'
|
||||||
import LayoutCenter from '../components/layout-center'
|
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { LightningAuth } from './lightning-auth'
|
import { LightningAuth } from './lightning-auth'
|
||||||
|
|
||||||
@ -56,60 +55,59 @@ export default function Login ({ providers, callbackUrl, error, text, Header, Fo
|
|||||||
const [errorMessage, setErrorMessage] = useState(error && (errors[error] ?? errors.default))
|
const [errorMessage, setErrorMessage] = useState(error && (errors[error] ?? errors.default))
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
|
if (router.query.type === 'lightning') {
|
||||||
|
return <LightningAuth callbackUrl={callbackUrl} text={text} />
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LayoutCenter>
|
<div className={styles.login}>
|
||||||
{router.query.type === 'lightning'
|
{Header && <Header />}
|
||||||
? <LightningAuth callbackUrl={callbackUrl} text={text} />
|
{errorMessage &&
|
||||||
: (
|
<Alert
|
||||||
<div className={styles.login}>
|
variant='danger'
|
||||||
{Header && <Header />}
|
onClose={() => setErrorMessage(undefined)}
|
||||||
{errorMessage &&
|
dismissible
|
||||||
<Alert
|
>{errorMessage}
|
||||||
variant='danger'
|
</Alert>}
|
||||||
onClose={() => setErrorMessage(undefined)}
|
<Button
|
||||||
dismissible
|
className={`mt-2 ${styles.providerButton}`}
|
||||||
>{errorMessage}
|
variant='primary'
|
||||||
</Alert>}
|
onClick={() => router.push({
|
||||||
<Button
|
pathname: router.pathname,
|
||||||
className={`mt-2 ${styles.providerButton}`}
|
query: { ...router.query, type: 'lightning' }
|
||||||
variant='primary'
|
})}
|
||||||
onClick={() => router.push({
|
>
|
||||||
pathname: router.pathname,
|
<LightningIcon
|
||||||
query: { ...router.query, type: 'lightning' }
|
width={20}
|
||||||
})}
|
height={20}
|
||||||
>
|
className='mr-3'
|
||||||
<LightningIcon
|
/>{text || 'Login'} with Lightning
|
||||||
width={20}
|
</Button>
|
||||||
height={20}
|
{providers && Object.values(providers).map(provider => {
|
||||||
className='mr-3'
|
if (provider.name === 'Email' || provider.name === 'Lightning') {
|
||||||
/>{text || 'Login'} with Lightning
|
return null
|
||||||
</Button>
|
}
|
||||||
{Object.values(providers).map(provider => {
|
const [variant, Icon] =
|
||||||
if (provider.name === 'Email' || provider.name === 'Lightning') {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
const [variant, Icon] =
|
|
||||||
provider.name === 'Twitter'
|
provider.name === 'Twitter'
|
||||||
? ['twitter', TwitterIcon]
|
? ['twitter', TwitterIcon]
|
||||||
: ['dark', GithubIcon]
|
: ['dark', GithubIcon]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
className={`mt-2 ${styles.providerButton}`}
|
className={`mt-2 ${styles.providerButton}`}
|
||||||
key={provider.name}
|
key={provider.name}
|
||||||
variant={variant}
|
variant={variant}
|
||||||
onClick={() => signIn(provider.id, { callbackUrl })}
|
onClick={() => signIn(provider.id, { callbackUrl })}
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
className='mr-3'
|
className='mr-3'
|
||||||
/>{text || 'Login'} with {provider.name}
|
/>{text || 'Login'} with {provider.name}
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
<div className='mt-2 text-center text-muted font-weight-bold'>or</div>
|
<div className='mt-2 text-center text-muted font-weight-bold'>or</div>
|
||||||
<EmailLoginForm text={text} callbackUrl={callbackUrl} />
|
<EmailLoginForm text={text} callbackUrl={callbackUrl} />
|
||||||
{Footer && <Footer />}
|
{Footer && <Footer />}
|
||||||
</div>)}
|
</div>
|
||||||
</LayoutCenter>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
51
components/modal.js
Normal file
51
components/modal.js
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import { createContext, useCallback, useContext, useMemo, useState } from 'react'
|
||||||
|
import { Modal } from 'react-bootstrap'
|
||||||
|
|
||||||
|
export const ShowModalContext = createContext(() => null)
|
||||||
|
|
||||||
|
export function ShowModalProvider ({ children }) {
|
||||||
|
const [modal, showModal] = useModal()
|
||||||
|
const contextValue = showModal
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ShowModalContext.Provider value={contextValue}>
|
||||||
|
{children}
|
||||||
|
{modal}
|
||||||
|
</ShowModalContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useShowModal () {
|
||||||
|
return useContext(ShowModalContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function useModal () {
|
||||||
|
const [modalContent, setModalContent] = useState(null)
|
||||||
|
|
||||||
|
const onClose = useCallback(() => {
|
||||||
|
setModalContent(null)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const modal = useMemo(() => {
|
||||||
|
if (modalContent === null) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Modal onHide={onClose} show={!!modalContent}>
|
||||||
|
<div className='modal-close' onClick={onClose}>X</div>
|
||||||
|
<Modal.Body>
|
||||||
|
{modalContent}
|
||||||
|
</Modal.Body>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}, [modalContent, onClose])
|
||||||
|
|
||||||
|
const showModal = useCallback(
|
||||||
|
(getContent) => {
|
||||||
|
setModalContent(getContent(onClose))
|
||||||
|
},
|
||||||
|
[onClose]
|
||||||
|
)
|
||||||
|
|
||||||
|
return [modal, showModal]
|
||||||
|
}
|
@ -6,12 +6,13 @@ import { useMe } from './me'
|
|||||||
import styles from './poll.module.css'
|
import styles from './poll.module.css'
|
||||||
import Check from '../svgs/checkbox-circle-fill.svg'
|
import Check from '../svgs/checkbox-circle-fill.svg'
|
||||||
import { signIn } from 'next-auth/client'
|
import { signIn } from 'next-auth/client'
|
||||||
import { useFundError } from './fund-error'
|
|
||||||
import ActionTooltip from './action-tooltip'
|
import ActionTooltip from './action-tooltip'
|
||||||
|
import { useShowModal } from './modal'
|
||||||
|
import FundError from './fund-error'
|
||||||
|
|
||||||
export default function Poll ({ item }) {
|
export default function Poll ({ item }) {
|
||||||
const me = useMe()
|
const me = useMe()
|
||||||
const { setError } = useFundError()
|
const showModal = useShowModal()
|
||||||
const [pollVote] = useMutation(
|
const [pollVote] = useMutation(
|
||||||
gql`
|
gql`
|
||||||
mutation pollVote($id: ID!) {
|
mutation pollVote($id: ID!) {
|
||||||
@ -60,7 +61,9 @@ export default function Poll ({ item }) {
|
|||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.toString().includes('insufficient funds')) {
|
if (error.toString().includes('insufficient funds')) {
|
||||||
setError(true)
|
showModal(onClose => {
|
||||||
|
return <FundError onClose={onClose} />
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,15 +2,16 @@ import { LightningConsumer } from './lightning'
|
|||||||
import UpBolt from '../svgs/bolt.svg'
|
import UpBolt from '../svgs/bolt.svg'
|
||||||
import styles from './upvote.module.css'
|
import styles from './upvote.module.css'
|
||||||
import { gql, useMutation } from '@apollo/client'
|
import { gql, useMutation } from '@apollo/client'
|
||||||
import { signIn } from 'next-auth/client'
|
import FundError from './fund-error'
|
||||||
import { useFundError } from './fund-error'
|
|
||||||
import ActionTooltip from './action-tooltip'
|
import ActionTooltip from './action-tooltip'
|
||||||
import { useItemAct } from './item-act'
|
import ItemAct from './item-act'
|
||||||
import { useMe } from './me'
|
import { useMe } from './me'
|
||||||
import Rainbow from '../lib/rainbow'
|
import Rainbow from '../lib/rainbow'
|
||||||
import { useRef, useState } from 'react'
|
import { useRef, useState } from 'react'
|
||||||
import LongPressable from 'react-longpressable'
|
import LongPressable from 'react-longpressable'
|
||||||
import { Overlay, Popover } from 'react-bootstrap'
|
import { Overlay, Popover } from 'react-bootstrap'
|
||||||
|
import { useShowModal } from './modal'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
|
||||||
const getColor = (meSats) => {
|
const getColor = (meSats) => {
|
||||||
if (!meSats || meSats <= 10) {
|
if (!meSats || meSats <= 10) {
|
||||||
@ -63,8 +64,8 @@ const TipPopover = ({ target, show, handleClose }) => (
|
|||||||
)
|
)
|
||||||
|
|
||||||
export default function UpVote ({ item, className }) {
|
export default function UpVote ({ item, className }) {
|
||||||
const { setError } = useFundError()
|
const showModal = useShowModal()
|
||||||
const { setItem } = useItemAct()
|
const router = useRouter()
|
||||||
const [voteShow, _setVoteShow] = useState(false)
|
const [voteShow, _setVoteShow] = useState(false)
|
||||||
const [tipShow, _setTipShow] = useState(false)
|
const [tipShow, _setTipShow] = useState(false)
|
||||||
const ref = useRef()
|
const ref = useRef()
|
||||||
@ -123,11 +124,14 @@ export default function UpVote ({ item, className }) {
|
|||||||
return existingSats + sats
|
return existingSats + sats
|
||||||
},
|
},
|
||||||
meSats (existingSats = 0) {
|
meSats (existingSats = 0) {
|
||||||
if (existingSats === 0) {
|
if (sats <= me.sats) {
|
||||||
setVoteShow(true)
|
if (existingSats === 0) {
|
||||||
} else {
|
setVoteShow(true)
|
||||||
setTipShow(true)
|
} else {
|
||||||
|
setTipShow(true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return existingSats + sats
|
return existingSats + sats
|
||||||
},
|
},
|
||||||
upvotes (existingUpvotes = 0) {
|
upvotes (existingUpvotes = 0) {
|
||||||
@ -183,7 +187,8 @@ export default function UpVote ({ item, className }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setTipShow(false)
|
setTipShow(false)
|
||||||
setItem({ itemId: item.id, act, strike })
|
showModal(onClose =>
|
||||||
|
<ItemAct onClose={onClose} itemId={item.id} act={act} strike={strike} />)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onShortPress={
|
onShortPress={
|
||||||
@ -215,13 +220,18 @@ export default function UpVote ({ item, className }) {
|
|||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.toString().includes('insufficient funds')) {
|
if (error.toString().includes('insufficient funds')) {
|
||||||
setError(true)
|
showModal(onClose => {
|
||||||
|
return <FundError onClose={onClose} />
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
throw new Error({ message: error.toString() })
|
throw new Error({ message: error.toString() })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
: signIn
|
: async () => await router.push({
|
||||||
|
pathname: '/signup',
|
||||||
|
query: { callbackUrl: window.location.origin + router.asPath }
|
||||||
|
})
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<ActionTooltip notForm disable={item?.mine || fwd2me} overlayText={overlayText()}>
|
<ActionTooltip notForm disable={item?.mine || fwd2me} overlayText={overlayText()}>
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
import '../styles/globals.scss'
|
import '../styles/globals.scss'
|
||||||
import { ApolloProvider, gql, useQuery } from '@apollo/client'
|
import { ApolloProvider, gql, useQuery } from '@apollo/client'
|
||||||
import { Provider } from 'next-auth/client'
|
import { Provider } from 'next-auth/client'
|
||||||
import { FundErrorModal, FundErrorProvider } from '../components/fund-error'
|
|
||||||
import { MeProvider } from '../components/me'
|
import { MeProvider } from '../components/me'
|
||||||
import PlausibleProvider from 'next-plausible'
|
import PlausibleProvider from 'next-plausible'
|
||||||
import { LightningProvider } from '../components/lightning'
|
import { LightningProvider } from '../components/lightning'
|
||||||
import { ItemActModal, ItemActProvider } from '../components/item-act'
|
|
||||||
import getApolloClient from '../lib/apollo'
|
import getApolloClient from '../lib/apollo'
|
||||||
import NextNProgress from 'nextjs-progressbar'
|
import NextNProgress from 'nextjs-progressbar'
|
||||||
import { PriceProvider } from '../components/price'
|
import { PriceProvider } from '../components/price'
|
||||||
@ -14,6 +12,7 @@ import { useRouter } from 'next/dist/client/router'
|
|||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import Moon from '../svgs/moon-fill.svg'
|
import Moon from '../svgs/moon-fill.svg'
|
||||||
import Layout from '../components/layout'
|
import Layout from '../components/layout'
|
||||||
|
import { ShowModalProvider } from '../components/modal'
|
||||||
|
|
||||||
function CSRWrapper ({ Component, apollo, ...props }) {
|
function CSRWrapper ({ Component, apollo, ...props }) {
|
||||||
const { data, error } = useQuery(gql`${apollo.query}`, { variables: apollo.variables, fetchPolicy: 'cache-first' })
|
const { data, error } = useQuery(gql`${apollo.query}`, { variables: apollo.variables, fetchPolicy: 'cache-first' })
|
||||||
@ -89,15 +88,11 @@ function MyApp ({ Component, pageProps: { session, ...props } }) {
|
|||||||
<MeProvider me={me}>
|
<MeProvider me={me}>
|
||||||
<PriceProvider price={price}>
|
<PriceProvider price={price}>
|
||||||
<LightningProvider>
|
<LightningProvider>
|
||||||
<FundErrorProvider>
|
<ShowModalProvider>
|
||||||
<FundErrorModal />
|
{data || !apollo?.query
|
||||||
<ItemActProvider>
|
? <Component {...props} />
|
||||||
<ItemActModal />
|
: <CSRWrapper Component={Component} {...props} />}
|
||||||
{data || !apollo?.query
|
</ShowModalProvider>
|
||||||
? <Component {...props} />
|
|
||||||
: <CSRWrapper Component={Component} {...props} />}
|
|
||||||
</ItemActProvider>
|
|
||||||
</FundErrorProvider>
|
|
||||||
</LightningProvider>
|
</LightningProvider>
|
||||||
</PriceProvider>
|
</PriceProvider>
|
||||||
</MeProvider>
|
</MeProvider>
|
||||||
|
@ -136,7 +136,8 @@ export default (req, res) => NextAuth(req, res, {
|
|||||||
signingKey: process.env.JWT_SIGNING_PRIVATE_KEY
|
signingKey: process.env.JWT_SIGNING_PRIVATE_KEY
|
||||||
},
|
},
|
||||||
pages: {
|
pages: {
|
||||||
signIn: '/login'
|
signIn: '/login',
|
||||||
|
verifyRequest: '/email'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
14
pages/email.js
Normal file
14
pages/email.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import LayoutError from '../components/layout-error'
|
||||||
|
import { Image } from 'react-bootstrap'
|
||||||
|
|
||||||
|
export default function Email () {
|
||||||
|
return (
|
||||||
|
<LayoutError>
|
||||||
|
<div className='p-4 text-center'>
|
||||||
|
<h1>Check your email</h1>
|
||||||
|
<h4 className='pb-4'>A sign in link has been sent to your email address</h4>
|
||||||
|
<Image width='500' height='376' src='/hello.gif' fluid />
|
||||||
|
</div>
|
||||||
|
</LayoutError>
|
||||||
|
)
|
||||||
|
}
|
@ -6,6 +6,7 @@ import { gql } from '@apollo/client'
|
|||||||
import { INVITE_FIELDS } from '../../fragments/invites'
|
import { INVITE_FIELDS } from '../../fragments/invites'
|
||||||
import getSSRApolloClient from '../../api/ssrApollo'
|
import getSSRApolloClient from '../../api/ssrApollo'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
import LayoutCenter from '../../components/layout-center'
|
||||||
|
|
||||||
export async function getServerSideProps ({ req, res, query: { id, error = null } }) {
|
export async function getServerSideProps ({ req, res, query: { id, error = null } }) {
|
||||||
const session = await getSession({ req })
|
const session = await getSession({ req })
|
||||||
@ -78,5 +79,9 @@ function InviteHeader ({ invite }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function Invite ({ invite, ...props }) {
|
export default function Invite ({ invite, ...props }) {
|
||||||
return <Login Header={() => <InviteHeader invite={invite} />} text='Sign up' {...props} />
|
return (
|
||||||
|
<LayoutCenter>
|
||||||
|
<Login Header={() => <InviteHeader invite={invite} />} text='Sign up' {...props} />
|
||||||
|
</LayoutCenter>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { providers, getSession } from 'next-auth/client'
|
import { providers, getSession } from 'next-auth/client'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
import LayoutCenter from '../components/layout-center'
|
||||||
import Login from '../components/login'
|
import Login from '../components/login'
|
||||||
|
|
||||||
export async function getServerSideProps ({ req, res, query: { callbackUrl, error = null } }) {
|
export async function getServerSideProps ({ req, res, query: { callbackUrl, error = null } }) {
|
||||||
@ -30,9 +31,11 @@ function LoginFooter ({ callbackUrl }) {
|
|||||||
|
|
||||||
export default function LoginPage (props) {
|
export default function LoginPage (props) {
|
||||||
return (
|
return (
|
||||||
<Login
|
<LayoutCenter>
|
||||||
Footer={() => <LoginFooter callbackUrl={props.callbackUrl} />}
|
<Login
|
||||||
{...props}
|
Footer={() => <LoginFooter callbackUrl={props.callbackUrl} />}
|
||||||
/>
|
{...props}
|
||||||
|
/>
|
||||||
|
</LayoutCenter>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { providers, getSession } from 'next-auth/client'
|
import { providers, getSession } from 'next-auth/client'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
import LayoutCenter from '../components/layout-center'
|
||||||
import Login from '../components/login'
|
import Login from '../components/login'
|
||||||
|
|
||||||
export async function getServerSideProps ({ req, res, query: { callbackUrl, error = null } }) {
|
export async function getServerSideProps ({ req, res, query: { callbackUrl, error = null } }) {
|
||||||
@ -41,11 +42,13 @@ function SignUpFooter ({ callbackUrl }) {
|
|||||||
|
|
||||||
export default function SignUp ({ ...props }) {
|
export default function SignUp ({ ...props }) {
|
||||||
return (
|
return (
|
||||||
<Login
|
<LayoutCenter>
|
||||||
Header={() => <SignUpHeader />}
|
<Login
|
||||||
Footer={() => <SignUpFooter callbackUrl={props.callbackUrl} />}
|
Header={() => <SignUpHeader />}
|
||||||
text='Sign up'
|
Footer={() => <SignUpFooter callbackUrl={props.callbackUrl} />}
|
||||||
{...props}
|
text='Sign up'
|
||||||
/>
|
{...props}
|
||||||
|
/>
|
||||||
|
</LayoutCenter>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// This will help to prevent a flash if dark mode is the default.
|
// This will help to prevent a flash if dark mode is the default.
|
||||||
const COLORS = {
|
const COLORS = {
|
||||||
light: {
|
light: {
|
||||||
body: '#f5f5f5',
|
body: '#f5f5f7',
|
||||||
color: '#212529',
|
color: '#212529',
|
||||||
navbarVariant: 'light',
|
navbarVariant: 'light',
|
||||||
navLink: 'rgba(0, 0, 0, 0.55)',
|
navLink: 'rgba(0, 0, 0, 0.55)',
|
||||||
|
BIN
public/hello.gif
Normal file
BIN
public/hello.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 418 KiB |
@ -11,7 +11,7 @@ $theme-colors: (
|
|||||||
"grey-darkmode": #8c8c8c
|
"grey-darkmode": #8c8c8c
|
||||||
);
|
);
|
||||||
|
|
||||||
$body-bg: #f5f5f5;
|
$body-bg: #f5f5f7;
|
||||||
$border-radius: .4rem;
|
$border-radius: .4rem;
|
||||||
$enable-transitions: false;
|
$enable-transitions: false;
|
||||||
$enable-gradients: false;
|
$enable-gradients: false;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user