withdrawl page
This commit is contained in:
parent
7a8afd56c3
commit
ce55fdfe9c
|
@ -30,6 +30,6 @@ export default gql`
|
|||
msatsPaid: Int
|
||||
msatsFeePaying: Int!
|
||||
msatsFeePaid: Int
|
||||
status: String!
|
||||
status: String
|
||||
}
|
||||
`
|
||||
|
|
|
@ -4,6 +4,8 @@ import BootstrapForm from 'react-bootstrap/Form'
|
|||
import Alert from 'react-bootstrap/Alert'
|
||||
import { Formik, Form as FormikForm, useFormikContext, useField } from 'formik'
|
||||
import { useRef, useState } from 'react'
|
||||
import copy from 'clipboard-copy'
|
||||
import Thumb from '../svgs/thumb-up-fill.svg'
|
||||
|
||||
export function SubmitButton ({ children, variant, ...props }) {
|
||||
const { isSubmitting } = useFormikContext()
|
||||
|
@ -19,8 +21,35 @@ export function SubmitButton ({ children, variant, ...props }) {
|
|||
)
|
||||
}
|
||||
|
||||
export function CopyInput (props) {
|
||||
const [copied, setCopied] = useState(false)
|
||||
|
||||
const handleClick = () => {
|
||||
copy(props.placeholder)
|
||||
setCopied(true)
|
||||
setTimeout(() => setCopied(false), 1500)
|
||||
}
|
||||
|
||||
return (
|
||||
<Input
|
||||
onClick={handleClick}
|
||||
append={<Button onClick={handleClick}>{copied ? <Thumb width={18} height={18} /> : 'copy'}</Button>}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export function InputSkeleton ({ label }) {
|
||||
return (
|
||||
<BootstrapForm.Group>
|
||||
{label && <BootstrapForm.Label>{label}</BootstrapForm.Label>}
|
||||
<div className='clouds form-control' />
|
||||
</BootstrapForm.Group>
|
||||
)
|
||||
}
|
||||
|
||||
export function Input ({ label, prepend, append, hint, ...props }) {
|
||||
const [field, meta] = useField(props)
|
||||
const [field, meta] = props.readOnly ? [{}, {}] : useField(props)
|
||||
|
||||
return (
|
||||
<BootstrapForm.Group>
|
||||
|
@ -28,7 +57,7 @@ export function Input ({ label, prepend, append, hint, ...props }) {
|
|||
<InputGroup hasValidation>
|
||||
{prepend && (
|
||||
<InputGroup.Prepend>
|
||||
<InputGroup.Text>{prepend}</InputGroup.Text>
|
||||
{prepend}
|
||||
</InputGroup.Prepend>
|
||||
)}
|
||||
<BootstrapForm.Control
|
||||
|
@ -37,7 +66,7 @@ export function Input ({ label, prepend, append, hint, ...props }) {
|
|||
/>
|
||||
{append && (
|
||||
<InputGroup.Append>
|
||||
<InputGroup.Text>{append}</InputGroup.Text>
|
||||
{append}
|
||||
</InputGroup.Append>
|
||||
)}
|
||||
<BootstrapForm.Control.Feedback type='invalid'>
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
import Moon from '../svgs/moon-fill.svg'
|
||||
import Check from '../svgs/check-double-line.svg'
|
||||
import Fail from '../svgs/close-line.svg'
|
||||
|
||||
function InvoiceDefaultStatus ({ status }) {
|
||||
return (
|
||||
<div className='d-flex mt-2'>
|
||||
<Moon className='spin fill-grey' />
|
||||
<div className='ml-3 text-muted' style={{ fontWeight: '600' }}>{status}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function InvoiceConfirmedStatus ({ status }) {
|
||||
return (
|
||||
<div className='d-flex mt-2'>
|
||||
<Check className='fill-success' />
|
||||
<div className='ml-3 text-success' style={{ fontWeight: '600' }}>{status}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function InvoiceFailedStatus ({ status }) {
|
||||
return (
|
||||
<div className='d-flex mt-2'>
|
||||
<Fail className='fill-danger' />
|
||||
<div className='ml-3 text-danger' style={{ fontWeight: '600' }}>{status}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default function InvoiceStatus ({ variant, status }) {
|
||||
switch (variant) {
|
||||
case 'confirmed':
|
||||
return <InvoiceConfirmedStatus status={status} />
|
||||
case 'failed':
|
||||
return <InvoiceFailedStatus status={status} />
|
||||
default:
|
||||
return <InvoiceDefaultStatus status={status} />
|
||||
}
|
||||
}
|
|
@ -1,28 +1,20 @@
|
|||
import QRCode from 'qrcode.react'
|
||||
import { InputGroup } from 'react-bootstrap'
|
||||
import Moon from '../svgs/moon-fill.svg'
|
||||
import copy from 'clipboard-copy'
|
||||
import Thumb from '../svgs/thumb-up-fill.svg'
|
||||
import { useState } from 'react'
|
||||
import BootstrapForm from 'react-bootstrap/Form'
|
||||
import Button from 'react-bootstrap/Button'
|
||||
import Check from '../svgs/check-double-line.svg'
|
||||
import Fail from '../svgs/close-line.svg'
|
||||
import { CopyInput, InputSkeleton } from './form'
|
||||
import InvoiceStatus from './invoice-status'
|
||||
|
||||
export function Invoice ({ invoice }) {
|
||||
const [copied, setCopied] = useState(false)
|
||||
const qrValue = 'lightning:' + invoice.bolt11.toUpperCase()
|
||||
|
||||
let InvoiceStatus = InvoiceDefaultStatus
|
||||
let variant = 'default'
|
||||
let status = 'waiting for you'
|
||||
if (invoice.confirmedAt) {
|
||||
InvoiceStatus = InvoiceConfirmedStatus
|
||||
variant = 'confirmed'
|
||||
status = `${invoice.msatsReceived / 1000} sats deposited`
|
||||
} else if (invoice.cancelled) {
|
||||
InvoiceStatus = InvoiceFailedStatus
|
||||
variant = 'failed'
|
||||
status = 'cancelled'
|
||||
} else if (invoice.expiresAt <= new Date()) {
|
||||
InvoiceStatus = InvoiceFailedStatus
|
||||
variant = 'failed'
|
||||
status = 'expired'
|
||||
}
|
||||
|
||||
|
@ -32,58 +24,21 @@ export function Invoice ({ invoice }) {
|
|||
<QRCode className='h-auto mw-100' value={qrValue} renderAs='svg' size={300} />
|
||||
</div>
|
||||
<div className='mt-3 w-100'>
|
||||
<InputGroup onClick={() => {
|
||||
copy(invoice.bolt11)
|
||||
setCopied(true)
|
||||
setTimeout(() => setCopied(false), 1500)
|
||||
}}
|
||||
>
|
||||
<BootstrapForm.Control type='text' placeholder={invoice.bolt11} readOnly />
|
||||
<InputGroup.Append>
|
||||
<Button>{copied ? <Thumb width={20} height={20} /> : 'copy'}</Button>
|
||||
</InputGroup.Append>
|
||||
</InputGroup>
|
||||
<CopyInput type='text' placeholder={invoice.bolt11} readOnly />
|
||||
</div>
|
||||
<InvoiceStatus status={status} />
|
||||
<InvoiceStatus variant={variant} status={status} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export function InvoiceDefaultStatus ({ status }) {
|
||||
return (
|
||||
<div className='d-flex mt-4'>
|
||||
<Moon className='spin fill-grey' />
|
||||
<div className='ml-3 text-muted' style={{ fontWeight: '600' }}>{status}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function InvoiceConfirmedStatus ({ status }) {
|
||||
return (
|
||||
<div className='d-flex mt-4'>
|
||||
<Check className='fill-success' />
|
||||
<div className='ml-3 text-success' style={{ fontWeight: '600' }}>{status}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function InvoiceFailedStatus ({ status }) {
|
||||
return (
|
||||
<div className='d-flex mt-4'>
|
||||
<Fail className='fill-danger' />
|
||||
<div className='ml-3 text-danger' style={{ fontWeight: '600' }}>{status}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function InvoiceSkeleton ({ status }) {
|
||||
return (
|
||||
<>
|
||||
<div className='h-auto w-100 clouds' style={{ paddingTop: 'min(300px, 100%)', maxWidth: '300px' }} />
|
||||
<div className='mt-3 w-100'>
|
||||
<div className='w-100 clouds form-control' />
|
||||
<InputSkeleton />
|
||||
</div>
|
||||
<InvoiceDefaultStatus status={status} />
|
||||
<InvoiceStatus variant='default' status={status} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import * as Yup from 'yup'
|
|||
import { gql, useMutation, useQuery } from '@apollo/client'
|
||||
import { InvoiceSkeleton } from '../components/invoice'
|
||||
import LayoutCenter from '../components/layout-center'
|
||||
import InputGroup from 'react-bootstrap/InputGroup'
|
||||
|
||||
export default function Wallet () {
|
||||
return (
|
||||
|
@ -73,7 +74,7 @@ export function FundForm () {
|
|||
name='amount'
|
||||
required
|
||||
autoFocus
|
||||
append='sats'
|
||||
append={<InputGroup.Text className='text-monospace'>sats</InputGroup.Text>}
|
||||
/>
|
||||
<SubmitButton variant='success' className='mt-2'>generate invoice</SubmitButton>
|
||||
</Form>
|
||||
|
@ -130,7 +131,7 @@ export function WithdrawlForm () {
|
|||
label='max fee'
|
||||
name='maxFee'
|
||||
required
|
||||
append='millisats'
|
||||
append={<InputGroup.Text className='text-monospace'>millisats</InputGroup.Text>}
|
||||
/>
|
||||
<SubmitButton variant='success' className='mt-2'>withdrawl</SubmitButton>
|
||||
</Form>
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import { useQuery } from '@apollo/client'
|
||||
import gql from 'graphql-tag'
|
||||
import LayoutCenter from '../../components/layout-center'
|
||||
import { CopyInput, Input, InputSkeleton } from '../../components/form'
|
||||
import InputGroup from 'react-bootstrap/InputGroup'
|
||||
import InvoiceStatus from '../../components/invoice-status'
|
||||
|
||||
export async function getServerSideProps ({ params: { id } }) {
|
||||
return {
|
||||
|
@ -15,6 +18,8 @@ export default function Withdrawl ({ id }) {
|
|||
{
|
||||
withdrawl(id: ${id}) {
|
||||
bolt11
|
||||
msatsFeePaying
|
||||
status
|
||||
}
|
||||
}`
|
||||
return (
|
||||
|
@ -28,8 +33,35 @@ function LoadWithdrawl ({ query }) {
|
|||
const { loading, error, data } = useQuery(query, { pollInterval: 1000 })
|
||||
if (error) return <div>error</div>
|
||||
if (!data || loading) {
|
||||
return <div>withdrawl loading</div>
|
||||
return (
|
||||
<>
|
||||
<div className='w-100'>
|
||||
<InputSkeleton label='invoice' />
|
||||
</div>
|
||||
<div className='w-100'>
|
||||
<InputSkeleton label='max fee' />
|
||||
</div>
|
||||
<InvoiceStatus status='pending' />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
return <div>hi</div>
|
||||
return (
|
||||
<>
|
||||
<div className='w-100'>
|
||||
<CopyInput
|
||||
label='invoice' type='text'
|
||||
placeholder={data.withdrawl.bolt11} readOnly
|
||||
/>
|
||||
</div>
|
||||
<div className='w-100'>
|
||||
<Input
|
||||
label='max fee' type='text'
|
||||
placeholder={data.withdrawl.msatsFeePaying} readOnly
|
||||
append={<InputGroup.Text className='text-monospace'>millisats</InputGroup.Text>}
|
||||
/>
|
||||
</div>
|
||||
<InvoiceStatus status='pending' />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue