add top spenders to top page
This commit is contained in:
parent
9490b3dc5f
commit
8829fccdef
|
@ -41,19 +41,33 @@ export default {
|
||||||
|
|
||||||
return me.name?.toUpperCase() === name?.toUpperCase() || !(await models.user.findUnique({ where: { name } }))
|
return me.name?.toUpperCase() === name?.toUpperCase() || !(await models.user.findUnique({ where: { name } }))
|
||||||
},
|
},
|
||||||
topUsers: async (parent, { cursor, within }, { models, me }) => {
|
topUsers: async (parent, { cursor, within, userType }, { models, me }) => {
|
||||||
const decodedCursor = decodeCursor(cursor)
|
const decodedCursor = decodeCursor(cursor)
|
||||||
const users = await models.$queryRaw(`
|
let users
|
||||||
SELECT users.name, users.created_at, sum("ItemAct".sats) as stacked
|
if (userType === 'spent') {
|
||||||
|
users = await models.$queryRaw(`
|
||||||
|
SELECT users.name, users.created_at, sum("ItemAct".sats) as amount
|
||||||
|
FROM "ItemAct"
|
||||||
|
JOIN users on "ItemAct"."userId" = users.id
|
||||||
|
WHERE "ItemAct".created_at <= $1
|
||||||
|
${topClause(within)}
|
||||||
|
GROUP BY users.id, users.name
|
||||||
|
ORDER BY amount DESC NULLS LAST, users.created_at DESC
|
||||||
|
OFFSET $2
|
||||||
|
LIMIT ${LIMIT}`, decodedCursor.time, decodedCursor.offset)
|
||||||
|
} else {
|
||||||
|
users = await models.$queryRaw(`
|
||||||
|
SELECT users.name, users.created_at, sum("ItemAct".sats) as amount
|
||||||
FROM "ItemAct"
|
FROM "ItemAct"
|
||||||
JOIN "Item" on "ItemAct"."itemId" = "Item".id
|
JOIN "Item" on "ItemAct"."itemId" = "Item".id
|
||||||
JOIN users on "Item"."userId" = users.id
|
JOIN users on "Item"."userId" = users.id
|
||||||
WHERE act <> 'BOOST' AND "ItemAct"."userId" <> users.id AND "ItemAct".created_at <= $1
|
WHERE act <> 'BOOST' AND "ItemAct"."userId" <> users.id AND "ItemAct".created_at <= $1
|
||||||
${topClause(within)}
|
${topClause(within)}
|
||||||
GROUP BY users.id, users.name
|
GROUP BY users.id, users.name
|
||||||
ORDER BY stacked DESC NULLS LAST, users.created_at DESC
|
ORDER BY amount DESC NULLS LAST, users.created_at DESC
|
||||||
OFFSET $2
|
OFFSET $2
|
||||||
LIMIT ${LIMIT}`, decodedCursor.time, decodedCursor.offset)
|
LIMIT ${LIMIT}`, decodedCursor.time, decodedCursor.offset)
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
cursor: users.length === LIMIT ? nextCursorEncoded(decodedCursor) : null,
|
cursor: users.length === LIMIT ? nextCursorEncoded(decodedCursor) : null,
|
||||||
|
|
|
@ -6,7 +6,7 @@ export default gql`
|
||||||
user(name: String!): User
|
user(name: String!): User
|
||||||
users: [User!]
|
users: [User!]
|
||||||
nameAvailable(name: String!): Boolean!
|
nameAvailable(name: String!): Boolean!
|
||||||
topUsers(cursor: String, within: String!): Users
|
topUsers(cursor: String, within: String!, userType: String!): TopUsers
|
||||||
}
|
}
|
||||||
|
|
||||||
type Users {
|
type Users {
|
||||||
|
@ -14,6 +14,17 @@ export default gql`
|
||||||
users: [User!]!
|
users: [User!]!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TopUsers {
|
||||||
|
cursor: String
|
||||||
|
users: [TopUser!]!
|
||||||
|
}
|
||||||
|
|
||||||
|
type TopUser {
|
||||||
|
name: String!
|
||||||
|
createdAt: String!
|
||||||
|
amount: Int!
|
||||||
|
}
|
||||||
|
|
||||||
extend type Mutation {
|
extend type Mutation {
|
||||||
setName(name: String!): Boolean
|
setName(name: String!): Boolean
|
||||||
setSettings(tipDefault: Int!): Boolean
|
setSettings(tipDefault: Int!): Boolean
|
||||||
|
|
|
@ -6,20 +6,20 @@ import { useRouter } from 'next/router'
|
||||||
export default function TopHeader ({ cat }) {
|
export default function TopHeader ({ cat }) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const within = router.query.within
|
const within = router.query.within
|
||||||
|
const userType = router.query.userType || 'stacked'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Navbar className='pt-0'>
|
<Navbar className='pt-0'>
|
||||||
<Nav
|
<Nav
|
||||||
className={`${styles.navbarNav} justify-content-around`}
|
className={`${styles.navbarNav} justify-content-around`}
|
||||||
activeKey={cat}
|
activeKey={cat.split('/')[0]}
|
||||||
>
|
>
|
||||||
<Nav.Item>
|
<Nav.Item>
|
||||||
<Link href={`/top/posts/${within}`} passHref>
|
<Link href={`/top/posts/${within}`} passHref>
|
||||||
<Nav.Link
|
<Nav.Link
|
||||||
eventKey='posts'
|
eventKey='posts'
|
||||||
className={styles.navLink}
|
className={styles.navLink}
|
||||||
onClick={() => localStorage.setItem('topWithin', 'day')}
|
|
||||||
>
|
>
|
||||||
posts
|
posts
|
||||||
</Nav.Link>
|
</Nav.Link>
|
||||||
|
@ -30,18 +30,16 @@ export default function TopHeader ({ cat }) {
|
||||||
<Nav.Link
|
<Nav.Link
|
||||||
eventKey='comments'
|
eventKey='comments'
|
||||||
className={styles.navLink}
|
className={styles.navLink}
|
||||||
onClick={() => localStorage.setItem('topWithin', 'week')}
|
|
||||||
>
|
>
|
||||||
comments
|
comments
|
||||||
</Nav.Link>
|
</Nav.Link>
|
||||||
</Link>
|
</Link>
|
||||||
</Nav.Item>
|
</Nav.Item>
|
||||||
<Nav.Item>
|
<Nav.Item>
|
||||||
<Link href={`/top/users/${within}`} passHref>
|
<Link href={`/top/users/stacked/${within}`} passHref>
|
||||||
<Nav.Link
|
<Nav.Link
|
||||||
eventKey='users'
|
eventKey='users'
|
||||||
className={styles.navLink}
|
className={styles.navLink}
|
||||||
onClick={() => localStorage.setItem('topWithin', 'month')}
|
|
||||||
>
|
>
|
||||||
users
|
users
|
||||||
</Nav.Link>
|
</Nav.Link>
|
||||||
|
@ -49,6 +47,34 @@ export default function TopHeader ({ cat }) {
|
||||||
</Nav.Item>
|
</Nav.Item>
|
||||||
</Nav>
|
</Nav>
|
||||||
</Navbar>
|
</Navbar>
|
||||||
|
{cat.split('/')[0] === 'users' &&
|
||||||
|
<Navbar className='pt-0'>
|
||||||
|
<Nav
|
||||||
|
className={`${styles.navbarNav} justify-content-around`}
|
||||||
|
activeKey={userType}
|
||||||
|
>
|
||||||
|
<Nav.Item>
|
||||||
|
<Link href={`/top/users/stacked/${within}`} passHref>
|
||||||
|
<Nav.Link
|
||||||
|
eventKey='stacked'
|
||||||
|
className={styles.navLink}
|
||||||
|
>
|
||||||
|
stacked
|
||||||
|
</Nav.Link>
|
||||||
|
</Link>
|
||||||
|
</Nav.Item>
|
||||||
|
<Nav.Item>
|
||||||
|
<Link href={`/top/users/spent/${within}`} passHref>
|
||||||
|
<Nav.Link
|
||||||
|
eventKey='spent'
|
||||||
|
className={styles.navLink}
|
||||||
|
>
|
||||||
|
spent
|
||||||
|
</Nav.Link>
|
||||||
|
</Link>
|
||||||
|
</Nav.Item>
|
||||||
|
</Nav>
|
||||||
|
</Navbar>}
|
||||||
<Navbar className='pt-0'>
|
<Navbar className='pt-0'>
|
||||||
<Nav
|
<Nav
|
||||||
className={styles.navbarNav}
|
className={styles.navbarNav}
|
||||||
|
@ -59,7 +85,6 @@ export default function TopHeader ({ cat }) {
|
||||||
<Nav.Link
|
<Nav.Link
|
||||||
eventKey='day'
|
eventKey='day'
|
||||||
className={styles.navLink}
|
className={styles.navLink}
|
||||||
onClick={() => localStorage.setItem('topWithin', 'day')}
|
|
||||||
>
|
>
|
||||||
day
|
day
|
||||||
</Nav.Link>
|
</Nav.Link>
|
||||||
|
@ -70,7 +95,6 @@ export default function TopHeader ({ cat }) {
|
||||||
<Nav.Link
|
<Nav.Link
|
||||||
eventKey='week'
|
eventKey='week'
|
||||||
className={styles.navLink}
|
className={styles.navLink}
|
||||||
onClick={() => localStorage.setItem('topWithin', 'week')}
|
|
||||||
>
|
>
|
||||||
week
|
week
|
||||||
</Nav.Link>
|
</Nav.Link>
|
||||||
|
@ -81,7 +105,6 @@ export default function TopHeader ({ cat }) {
|
||||||
<Nav.Link
|
<Nav.Link
|
||||||
eventKey='month'
|
eventKey='month'
|
||||||
className={styles.navLink}
|
className={styles.navLink}
|
||||||
onClick={() => localStorage.setItem('topWithin', 'month')}
|
|
||||||
>
|
>
|
||||||
month
|
month
|
||||||
</Nav.Link>
|
</Nav.Link>
|
||||||
|
@ -92,7 +115,6 @@ export default function TopHeader ({ cat }) {
|
||||||
<Nav.Link
|
<Nav.Link
|
||||||
eventKey='year'
|
eventKey='year'
|
||||||
className={styles.navLink}
|
className={styles.navLink}
|
||||||
onClick={() => localStorage.setItem('topWithin', 'year')}
|
|
||||||
>
|
>
|
||||||
year
|
year
|
||||||
</Nav.Link>
|
</Nav.Link>
|
||||||
|
@ -103,7 +125,6 @@ export default function TopHeader ({ cat }) {
|
||||||
<Nav.Link
|
<Nav.Link
|
||||||
eventKey='forever'
|
eventKey='forever'
|
||||||
className={styles.navLink}
|
className={styles.navLink}
|
||||||
onClick={() => localStorage.removeItem('topWithin')}
|
|
||||||
>
|
>
|
||||||
forever
|
forever
|
||||||
</Nav.Link>
|
</Nav.Link>
|
||||||
|
|
|
@ -39,11 +39,11 @@ export const USER_FIELDS = gql`
|
||||||
}`
|
}`
|
||||||
|
|
||||||
export const TOP_USERS = gql`
|
export const TOP_USERS = gql`
|
||||||
query TopUsers($cursor: String, $within: String!) {
|
query TopUsers($cursor: String, $within: String!, $userType: String!) {
|
||||||
topUsers(cursor: $cursor, within: $within) {
|
topUsers(cursor: $cursor, within: $within, userType: $userType) {
|
||||||
users {
|
users {
|
||||||
name
|
name
|
||||||
stacked
|
amount
|
||||||
}
|
}
|
||||||
cursor
|
cursor
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,20 @@
|
||||||
import Layout from '../../../components/layout'
|
import Layout from '../../../../components/layout'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { getGetServerSideProps } from '../../../api/ssrApollo'
|
import { getGetServerSideProps } from '../../../../api/ssrApollo'
|
||||||
import TopHeader from '../../../components/top-header'
|
import TopHeader from '../../../../components/top-header'
|
||||||
import { TOP_USERS } from '../../../fragments/users'
|
import { TOP_USERS } from '../../../../fragments/users'
|
||||||
import { useQuery } from '@apollo/client'
|
import { useQuery } from '@apollo/client'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import MoreFooter from '../../../components/more-footer'
|
import MoreFooter from '../../../../components/more-footer'
|
||||||
|
|
||||||
export const getServerSideProps = getGetServerSideProps(TOP_USERS)
|
export const getServerSideProps = getGetServerSideProps(TOP_USERS)
|
||||||
|
|
||||||
export default function Index ({ data: { topUsers: { users, cursor } } }) {
|
export default function Index ({ data: { topUsers: { users, cursor } } }) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const userType = router.query.userType
|
||||||
|
|
||||||
const { data, fetchMore } = useQuery(TOP_USERS, {
|
const { data, fetchMore } = useQuery(TOP_USERS, {
|
||||||
variables: { within: router.query?.within }
|
variables: { within: router.query?.within, userType: router.query?.userType }
|
||||||
})
|
})
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
|
@ -22,12 +23,12 @@ export default function Index ({ data: { topUsers: { users, cursor } } }) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
<TopHeader cat='users' />
|
<TopHeader cat={'users/' + userType} />
|
||||||
{users.map(user => (
|
{users.map(user => (
|
||||||
<Link href={`/${user.name}`} key={user.name}>
|
<Link href={`/${user.name}`} key={user.name}>
|
||||||
<div className='d-flex align-items-center pointer'>
|
<div className='d-flex align-items-center pointer'>
|
||||||
<h3 className='mb-0'>@{user.name}</h3>
|
<h3 className='mb-0'>@{user.name}</h3>
|
||||||
<h2 className='ml-2 mb-0'><small className='text-success'>{user.stacked} stacked</small></h2>
|
<h2 className='ml-2 mb-0'><small className='text-success'>{user.amount} {userType}</small></h2>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
))}
|
))}
|
Loading…
Reference in New Issue