2021-12-15 16:50:11 +00:00
|
|
|
import { useQuery } from '@apollo/client'
|
|
|
|
import Link from 'next/link'
|
2024-03-20 00:37:31 +00:00
|
|
|
import { getGetServerSideProps } from '@/api/ssrApollo'
|
2024-04-28 21:05:23 +00:00
|
|
|
import Nav from 'react-bootstrap/Nav'
|
2024-03-20 00:37:31 +00:00
|
|
|
import Layout from '@/components/layout'
|
|
|
|
import MoreFooter from '@/components/more-footer'
|
|
|
|
import { WALLET_HISTORY } from '@/fragments/wallet'
|
|
|
|
import styles from '@/styles/satistics.module.css'
|
|
|
|
import Moon from '@/svgs/moon-fill.svg'
|
|
|
|
import Check from '@/svgs/check-double-line.svg'
|
|
|
|
import ThumbDown from '@/svgs/thumb-down-fill.svg'
|
|
|
|
import { Checkbox, Form } from '@/components/form'
|
2021-12-16 17:27:12 +00:00
|
|
|
import { useRouter } from 'next/router'
|
2024-03-20 00:37:31 +00:00
|
|
|
import Item from '@/components/item'
|
|
|
|
import { CommentFlat } from '@/components/comment'
|
|
|
|
import ItemJob from '@/components/item-job'
|
|
|
|
import PageLoading from '@/components/page-loading'
|
|
|
|
import PayerData from '@/components/payer-data'
|
2024-01-07 17:00:24 +00:00
|
|
|
import { Badge } from 'react-bootstrap'
|
2024-04-28 21:05:23 +00:00
|
|
|
import navStyles from '../settings/settings.module.css'
|
2024-09-07 15:01:00 +00:00
|
|
|
import classNames from 'classnames'
|
2021-12-15 16:50:11 +00:00
|
|
|
|
2023-08-28 17:52:15 +00:00
|
|
|
export const getServerSideProps = getGetServerSideProps({ query: WALLET_HISTORY, authRequired: true })
|
2021-12-15 16:50:11 +00:00
|
|
|
|
|
|
|
function satusClass (status) {
|
2021-12-16 20:02:17 +00:00
|
|
|
if (!status) {
|
|
|
|
return ''
|
|
|
|
}
|
|
|
|
|
2021-12-15 16:50:11 +00:00
|
|
|
switch (status) {
|
|
|
|
case 'CONFIRMED':
|
2023-07-31 18:00:01 +00:00
|
|
|
return 'text-reset'
|
2021-12-15 16:50:11 +00:00
|
|
|
case 'PENDING':
|
|
|
|
return 'text-muted'
|
|
|
|
default:
|
2023-07-23 15:08:43 +00:00
|
|
|
return `${styles.failed} text-muted`
|
2021-12-15 16:50:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-07 15:01:00 +00:00
|
|
|
function Satus ({ status, className }) {
|
2021-12-15 16:50:11 +00:00
|
|
|
if (!status) {
|
|
|
|
return null
|
|
|
|
}
|
|
|
|
|
2023-07-23 15:08:43 +00:00
|
|
|
let color = 'danger'; let desc
|
|
|
|
switch (status) {
|
|
|
|
case 'CONFIRMED':
|
|
|
|
desc = 'confirmed'
|
|
|
|
color = 'success'
|
|
|
|
break
|
|
|
|
case 'EXPIRED':
|
|
|
|
desc = 'expired'
|
|
|
|
color = 'muted'
|
|
|
|
break
|
2024-07-01 13:43:13 +00:00
|
|
|
case 'CANCELLED':
|
|
|
|
desc = 'cancelled'
|
|
|
|
color = 'muted'
|
|
|
|
break
|
2023-07-23 15:08:43 +00:00
|
|
|
case 'PENDING':
|
|
|
|
desc = 'pending'
|
|
|
|
color = 'muted'
|
|
|
|
break
|
|
|
|
case 'INSUFFICIENT_BALANCE':
|
|
|
|
desc = "you didn't have enough sats"
|
|
|
|
break
|
|
|
|
case 'INVALID_PAYMENT':
|
|
|
|
desc = 'invalid payment'
|
|
|
|
break
|
|
|
|
case 'PATHFINDING_TIMEOUT':
|
|
|
|
case 'ROUTE_NOT_FOUND':
|
|
|
|
desc = 'no route found'
|
|
|
|
break
|
|
|
|
default:
|
|
|
|
return 'unknown failure'
|
2021-12-15 16:50:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const Icon = () => {
|
|
|
|
switch (status) {
|
|
|
|
case 'CONFIRMED':
|
2023-07-23 15:08:43 +00:00
|
|
|
return <Check width='20' height='20' className={`fill-${color}`} />
|
2021-12-15 16:50:11 +00:00
|
|
|
case 'PENDING':
|
2023-07-23 15:08:43 +00:00
|
|
|
return <Moon width='20' height='20' className={`fill-${color} spin`} />
|
2021-12-15 16:50:11 +00:00
|
|
|
default:
|
2023-07-23 15:08:43 +00:00
|
|
|
return <ThumbDown width='18' height='18' className={`fill-${color}`} />
|
2021-12-15 16:50:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
2024-09-07 15:01:00 +00:00
|
|
|
<span className={classNames('d-inline-block', className)}>
|
|
|
|
<Icon /><small className={`text-${color} fw-bold ms-1`}>{desc}</small>
|
2023-07-31 18:00:01 +00:00
|
|
|
</span>
|
2021-12-15 16:50:11 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2021-12-16 20:02:17 +00:00
|
|
|
function Detail ({ fact }) {
|
2022-03-17 20:13:19 +00:00
|
|
|
if (fact.type === 'earn') {
|
|
|
|
return (
|
2023-08-15 17:41:51 +00:00
|
|
|
<Link href={`/rewards/${new Date(fact.createdAt).toISOString().slice(0, 10)}`} className='px-3 text-reset' style={{ lineHeight: '140%' }}>
|
2023-11-21 23:32:22 +00:00
|
|
|
SN distributes the sats it earns back to its best stackers daily. These sats come from jobs, boosts, posting fees, and donations.
|
2023-08-15 17:41:51 +00:00
|
|
|
</Link>
|
2022-03-17 20:13:19 +00:00
|
|
|
)
|
|
|
|
}
|
2022-12-08 00:04:02 +00:00
|
|
|
if (fact.type === 'donation') {
|
|
|
|
return (
|
2023-07-23 15:08:43 +00:00
|
|
|
<div className='px-3'>
|
|
|
|
You made a donation to <Link href='/rewards'>daily rewards</Link>!
|
|
|
|
</div>
|
2022-12-19 22:27:52 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
if (fact.type === 'referral') {
|
|
|
|
return (
|
2023-07-23 15:08:43 +00:00
|
|
|
<div className='px-3'>
|
|
|
|
You stacked sats from <Link href='/referrals/month'>a referral</Link>!
|
|
|
|
</div>
|
2022-12-08 00:04:02 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2023-11-21 23:32:22 +00:00
|
|
|
if (fact.type === 'billing') {
|
|
|
|
return (
|
|
|
|
<div className='px-3'>billing for <Link href={`/~${fact.subName}`}>~{fact.subName}</Link></div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fact.type === 'revenue') {
|
|
|
|
return (
|
|
|
|
<div className='px-3'>revenue for <Link href={`/~${fact.subName}`}>~{fact.subName}</Link></div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2021-12-16 20:02:17 +00:00
|
|
|
if (!fact.item) {
|
2023-09-27 01:59:15 +00:00
|
|
|
let zap
|
|
|
|
try {
|
2023-09-27 17:19:56 +00:00
|
|
|
zap = JSON.parse(fact.description)
|
2023-09-27 01:59:15 +00:00
|
|
|
} catch { }
|
2024-08-14 17:59:27 +00:00
|
|
|
|
|
|
|
const pathRoot = fact.type === 'p2p' ? 'withdrawal' : fact.type
|
2021-12-16 20:02:17 +00:00
|
|
|
return (
|
2023-07-23 15:08:43 +00:00
|
|
|
<div className='px-3'>
|
2024-08-14 17:59:27 +00:00
|
|
|
<Link className={satusClass(fact.status)} href={`/${pathRoot}s/${fact.id}`}>
|
2023-11-09 17:50:43 +00:00
|
|
|
{(!fact.bolt11 && <span className='d-block text-muted fw-bold fst-italic'>invoice deleted</span>) ||
|
|
|
|
(zap && <span className='d-block'>nostr zap{zap.content && `: ${zap.content}`}</span>) ||
|
2023-09-27 01:59:15 +00:00
|
|
|
(fact.description && <span className='d-block'>{fact.description}</span>)}
|
2023-10-03 19:35:53 +00:00
|
|
|
<PayerData data={fact.invoicePayerData} className='text-muted' header />
|
|
|
|
{fact.invoiceComment && <small className='text-muted'><b>sender says:</b> {fact.invoiceComment}</small>}
|
2024-09-07 15:01:00 +00:00
|
|
|
<Satus className={fact.invoiceComment ? 'ms-1' : ''} status={fact.status} />
|
|
|
|
{fact.autoWithdraw && <Badge className={styles.badge} bg={null}>{fact.type === 'p2p' ? 'p2p' : 'autowithdraw'}</Badge>}
|
2023-07-31 18:00:01 +00:00
|
|
|
</Link>
|
2023-07-23 15:08:43 +00:00
|
|
|
</div>
|
2021-12-16 20:02:17 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fact.item.title) {
|
2023-01-12 23:53:09 +00:00
|
|
|
if (fact.item.isJob) {
|
|
|
|
return <ItemJob className={styles.itemWrapper} item={fact.item} />
|
|
|
|
}
|
2023-07-23 15:08:43 +00:00
|
|
|
return <Item item={fact.item} siblingComments />
|
2021-12-16 20:02:17 +00:00
|
|
|
}
|
|
|
|
|
2023-07-23 15:08:43 +00:00
|
|
|
return <CommentFlat item={fact.item} includeParent noReply truncate />
|
2021-12-16 20:02:17 +00:00
|
|
|
}
|
|
|
|
|
2023-07-23 15:08:43 +00:00
|
|
|
function Fact ({ fact }) {
|
2023-10-25 18:06:15 +00:00
|
|
|
const factDate = new Date(fact.createdAt)
|
2023-07-23 15:08:43 +00:00
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<div className={`${styles.type} ${satusClass(fact.status)} ${fact.sats > 0 ? '' : 'text-muted'}`}>{fact.type}</div>
|
|
|
|
<div className={styles.detail}>
|
|
|
|
<Detail fact={fact} />
|
2023-10-25 18:06:15 +00:00
|
|
|
<div className='text-muted px-3'>{`${factDate.toLocaleDateString()} ${factDate.toLocaleTimeString()}`}</div>
|
2023-07-23 15:08:43 +00:00
|
|
|
</div>
|
|
|
|
<div className={`${styles.sats} ${satusClass(fact.status)} ${fact.sats > 0 ? '' : 'text-muted'}`}>{fact.sats}</div>
|
|
|
|
</>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2024-04-28 21:05:23 +00:00
|
|
|
export function SatisticsHeader () {
|
|
|
|
const router = useRouter()
|
|
|
|
const pathParts = router.asPath.split('?')[0].split('/').filter(segment => !!segment)
|
|
|
|
const activeKey = pathParts[1] ?? 'history'
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<h2 className='mb-2 text-start'>satistics</h2>
|
|
|
|
<Nav
|
|
|
|
className={navStyles.nav}
|
|
|
|
activeKey={activeKey}
|
|
|
|
>
|
|
|
|
<Nav.Item>
|
2024-04-30 22:52:34 +00:00
|
|
|
<Link href='/satistics?inc=invoice,withdrawal,stacked,spent' passHref legacyBehavior>
|
2024-04-28 21:05:23 +00:00
|
|
|
<Nav.Link eventKey='history'>history</Nav.Link>
|
|
|
|
</Link>
|
|
|
|
</Nav.Item>
|
|
|
|
<Nav.Item>
|
|
|
|
<Link href='/satistics/graphs/day' passHref legacyBehavior>
|
|
|
|
<Nav.Link eventKey='graphs'>graphs</Nav.Link>
|
|
|
|
</Link>
|
|
|
|
</Nav.Item>
|
|
|
|
</Nav>
|
|
|
|
</>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2023-07-23 15:08:43 +00:00
|
|
|
export default function Satistics ({ ssrData }) {
|
2021-12-16 17:27:12 +00:00
|
|
|
const router = useRouter()
|
|
|
|
const { data, fetchMore } = useQuery(WALLET_HISTORY, { variables: { inc: router.query.inc } })
|
2023-07-23 15:08:43 +00:00
|
|
|
if (!data && !ssrData) return <PageLoading />
|
2021-12-16 17:27:12 +00:00
|
|
|
|
|
|
|
function filterRoutePush (filter, add) {
|
2021-12-16 20:17:50 +00:00
|
|
|
const inc = new Set(router.query.inc?.split(','))
|
2021-12-16 17:27:12 +00:00
|
|
|
inc.delete('')
|
|
|
|
// depending on addrem, add or remove filter
|
|
|
|
if (add) {
|
|
|
|
inc.add(filter)
|
|
|
|
} else {
|
|
|
|
inc.delete(filter)
|
|
|
|
}
|
|
|
|
|
|
|
|
const incstr = [...inc].join(',')
|
2024-04-30 22:52:34 +00:00
|
|
|
router.push(`/satistics?inc=${incstr}`)
|
2021-12-16 17:27:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function included (filter) {
|
2021-12-16 20:17:50 +00:00
|
|
|
const inc = new Set(router.query.inc?.split(','))
|
2021-12-16 17:27:12 +00:00
|
|
|
return inc.has(filter)
|
|
|
|
}
|
2021-12-15 16:50:11 +00:00
|
|
|
|
2023-07-23 15:08:43 +00:00
|
|
|
const { walletHistory: { facts, cursor } } = data || ssrData
|
2021-12-15 16:50:11 +00:00
|
|
|
|
|
|
|
return (
|
2023-02-16 22:23:59 +00:00
|
|
|
<Layout>
|
2024-03-28 22:09:57 +00:00
|
|
|
<div className='mt-2'>
|
2024-04-28 21:05:23 +00:00
|
|
|
<SatisticsHeader />
|
2021-12-16 17:27:12 +00:00
|
|
|
<Form
|
|
|
|
initial={{
|
|
|
|
invoice: included('invoice'),
|
|
|
|
withdrawal: included('withdrawal'),
|
|
|
|
stacked: included('stacked'),
|
|
|
|
spent: included('spent')
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<div className='d-flex justify-content-around flex-wrap'>
|
|
|
|
<Checkbox
|
|
|
|
label='invoice' name='invoice' inline
|
2022-01-19 21:51:55 +00:00
|
|
|
checked={included('invoice')}
|
2021-12-16 17:27:12 +00:00
|
|
|
handleChange={c => filterRoutePush('invoice', c)}
|
|
|
|
/>
|
|
|
|
<Checkbox
|
|
|
|
label='withdrawal' name='withdrawal' inline
|
2022-01-19 21:51:55 +00:00
|
|
|
checked={included('withdrawal')}
|
2021-12-16 17:27:12 +00:00
|
|
|
handleChange={c => filterRoutePush('withdrawal', c)}
|
|
|
|
/>
|
|
|
|
<Checkbox
|
|
|
|
label='stacked' name='stacked' inline
|
2022-01-19 21:51:55 +00:00
|
|
|
checked={included('stacked')}
|
2021-12-16 17:27:12 +00:00
|
|
|
handleChange={c => filterRoutePush('stacked', c)}
|
|
|
|
/>
|
|
|
|
<Checkbox
|
|
|
|
label='spent' name='spent' inline
|
2022-01-19 21:51:55 +00:00
|
|
|
checked={included('spent')}
|
2021-12-16 17:27:12 +00:00
|
|
|
handleChange={c => filterRoutePush('spent', c)}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</Form>
|
2023-07-23 15:08:43 +00:00
|
|
|
<div className='py-2 px-0 mb-0 mw-100'>
|
|
|
|
<div className={styles.rows}>
|
|
|
|
<div className={[styles.type, styles.head].join(' ')}>type</div>
|
|
|
|
<div className={[styles.detail, styles.head].join(' ')}>detail</div>
|
|
|
|
<div className={[styles.sats, styles.head].join(' ')}>sats</div>
|
2023-11-21 23:32:22 +00:00
|
|
|
{facts.map(f => <Fact key={f.type + f.id} fact={f} />)}
|
2023-07-23 15:08:43 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<MoreFooter cursor={cursor} count={facts?.length} fetchMore={fetchMore} Skeleton={PageLoading} />
|
2021-12-16 17:27:12 +00:00
|
|
|
</div>
|
2021-12-15 16:50:11 +00:00
|
|
|
</Layout>
|
|
|
|
)
|
|
|
|
}
|