2023-11-09 17:50:43 +00:00
import { useQuery , useMutation } from '@apollo/client'
2024-03-20 00:37:31 +00:00
import { CenterLayout } from '@/components/layout'
import { CopyInput , Input , InputSkeleton } from '@/components/form'
2021-05-13 13:28:38 +00:00
import InputGroup from 'react-bootstrap/InputGroup'
2024-03-20 00:37:31 +00:00
import InvoiceStatus from '@/components/invoice-status'
2021-10-26 20:49:37 +00:00
import { useRouter } from 'next/router'
2024-03-20 00:37:31 +00:00
import { WITHDRAWL } from '@/fragments/wallet'
2022-01-07 21:22:44 +00:00
import Link from 'next/link'
2024-03-20 00:37:31 +00:00
import { SSR , INVOICE _RETENTION _DAYS } from '@/lib/constants'
import { numWithUnits } from '@/lib/format'
import Bolt11Info from '@/components/bolt11-info'
import { datePivot , timeLeft } from '@/lib/time'
import { useMe } from '@/components/me'
import { useToast } from '@/components/toast'
2023-11-09 17:50:43 +00:00
import { gql } from 'graphql-tag'
2024-03-20 00:37:31 +00:00
import { useShowModal } from '@/components/modal'
import { DeleteConfirm } from '@/components/delete'
import { getGetServerSideProps } from '@/api/ssrApollo'
2024-02-13 22:40:26 +00:00
// force SSR to include CSP nonces
export const getServerSideProps = getGetServerSideProps ( { query : null } )
2021-05-13 01:51:37 +00:00
2021-10-26 20:49:37 +00:00
export default function Withdrawl ( ) {
2021-05-13 01:51:37 +00:00
return (
2023-07-23 15:08:43 +00:00
< CenterLayout >
2021-10-26 20:49:37 +00:00
< LoadWithdrawl / >
2023-07-23 15:08:43 +00:00
< / C e n t e r L a y o u t >
2021-05-13 01:51:37 +00:00
)
}
2021-05-13 21:19:51 +00:00
export function WithdrawlSkeleton ( { status } ) {
return (
< >
< div className = 'w-100' >
< InputSkeleton label = 'invoice' / >
< / d i v >
< div className = 'w-100' >
< InputSkeleton label = 'max fee' / >
< / d i v >
< InvoiceStatus status = { status } / >
< / >
)
}
2021-10-26 20:49:37 +00:00
function LoadWithdrawl ( ) {
const router = useRouter ( )
2023-07-31 19:54:30 +00:00
const { loading , error , data } = useQuery ( WITHDRAWL , SSR
? { }
: {
variables : { id : router . query . id } ,
pollInterval : 1000 ,
nextFetchPolicy : 'cache-and-network'
} )
2021-05-13 01:51:37 +00:00
if ( error ) return < div > error < / d i v >
if ( ! data || loading ) {
2021-05-13 21:19:51 +00:00
return < WithdrawlSkeleton status = 'loading' / >
}
2022-01-07 21:22:44 +00:00
const TryMaxFee = ( ) =>
2023-07-23 15:08:43 +00:00
< Link href = '/wallet?type=withdraw' className = 'text-reset text-underline' >
2023-07-24 18:35:05 +00:00
< small className = 'ms-3' > try increasing max fee < / s m a l l >
2022-01-07 21:22:44 +00:00
< / L i n k >
2021-05-13 21:19:51 +00:00
let status = 'pending'
let variant = 'default'
switch ( data . withdrawl . status ) {
case 'CONFIRMED' :
2023-08-08 21:04:06 +00:00
status = ` sent ${ numWithUnits ( data . withdrawl . satsPaid , { abbreviate : false } )} with ${ numWithUnits ( data . withdrawl . satsFeePaid , { abbreviate : false } )} in routing fees `
2021-05-13 21:19:51 +00:00
variant = 'confirmed'
break
case 'INSUFFICIENT_BALANCE' :
2023-07-24 18:35:05 +00:00
status = < > insufficient balance < small className = 'ms-3' > contact keyan ! < /small></ >
2021-05-13 21:19:51 +00:00
variant = 'failed'
break
case 'INVALID_PAYMENT' :
status = 'invalid invoice'
variant = 'failed'
break
case 'PATHFINDING_TIMEOUT' :
2022-01-07 21:22:44 +00:00
status = < > timed out finding route < TryMaxFee / > < / >
2021-05-13 21:19:51 +00:00
variant = 'failed'
break
case 'ROUTE_NOT_FOUND' :
2022-01-07 21:22:44 +00:00
status = < > no route < TryMaxFee / > < / >
2021-05-13 21:19:51 +00:00
variant = 'failed'
break
2022-01-05 20:37:34 +00:00
case 'UNKNOWN_FAILURE' :
status = < > unknown error < / >
variant = 'failed'
break
2021-05-13 21:19:51 +00:00
default :
break
2021-05-13 01:51:37 +00:00
}
2021-05-13 13:28:38 +00:00
return (
< >
< div className = 'w-100' >
< CopyInput
label = 'invoice' type = 'text'
2023-11-09 17:50:43 +00:00
placeholder = { data . withdrawl . bolt11 || 'deleted' } readOnly noForm
2021-05-13 13:28:38 +00:00
/ >
< / d i v >
< div className = 'w-100' >
< Input
label = 'max fee' type = 'text'
2022-08-18 18:15:24 +00:00
placeholder = { data . withdrawl . satsFeePaying } readOnly noForm
2021-05-13 21:19:51 +00:00
append = { < InputGroup . Text className = 'text-monospace' > sats < / I n p u t G r o u p . T e x t > }
2021-05-13 13:28:38 +00:00
/ >
< / d i v >
2021-05-13 21:19:51 +00:00
< InvoiceStatus variant = { variant } status = { status } / >
2023-11-09 17:50:43 +00:00
< Bolt11Info bolt11 = { data . withdrawl . bolt11 } >
< PrivacyOption wd = { data . withdrawl } / >
< / B o l t 1 1 I n f o >
2021-05-13 13:28:38 +00:00
< / >
)
2021-05-13 01:51:37 +00:00
}
2023-11-09 17:50:43 +00:00
function PrivacyOption ( { wd } ) {
if ( ! wd . bolt11 ) return
const me = useMe ( )
const keepUntil = datePivot ( new Date ( wd . createdAt ) , { days : INVOICE _RETENTION _DAYS } )
const oldEnough = new Date ( ) >= keepUntil
if ( ! oldEnough ) {
return (
< span className = 'text-muted fst-italic' >
2023-11-20 15:04:38 +00:00
{ ` this invoice ${ me . privates ? . autoDropBolt11s ? 'will be auto-deleted' : 'can be deleted' } in ${ timeLeft ( keepUntil ) } ` }
2023-11-09 17:50:43 +00:00
< / s p a n >
)
}
const showModal = useShowModal ( )
const toaster = useToast ( )
const [ dropBolt11 ] = useMutation (
gql `
mutation dropBolt11 ( $id : ID ! ) {
dropBolt11 ( id : $id ) {
id
}
} ` , {
update ( cache ) {
cache . modify ( {
id : ` Withdrawl: ${ wd . id } ` ,
fields : {
bolt11 : ( ) => null ,
hash : ( ) => null
}
} )
}
} )
return (
< span
className = 'btn btn-md btn-danger' onClick = { ( ) => {
showModal ( onClose => {
return (
< DeleteConfirm
type = 'invoice'
onConfirm = { async ( ) => {
if ( me ) {
try {
await dropBolt11 ( { variables : { id : wd . id } } )
} catch ( err ) {
2024-02-14 23:31:25 +00:00
toaster . danger ( 'unable to delete invoice: ' + err . message || err . toString ? . ( ) )
throw err
} finally {
onClose ( )
2023-11-09 17:50:43 +00:00
}
}
} }
/ >
)
} )
} }
> delete invoice
< / s p a n >
)
}