user search
This commit is contained in:
parent
032c04959a
commit
30b1ee33aa
|
@ -134,9 +134,9 @@ export default {
|
|||
users
|
||||
}
|
||||
},
|
||||
searchUsers: async (parent, { name }, { models }) => {
|
||||
searchUsers: async (parent, { q, limit, similarity }, { models }) => {
|
||||
return await models.$queryRaw`
|
||||
SELECT * FROM users where id > 615 AND SIMILARITY(name, ${name}) > .1 ORDER BY SIMILARITY(name, ${name}) DESC LIMIT 5`
|
||||
SELECT * FROM users where id > 615 AND SIMILARITY(name, ${q}) > ${Number(similarity) || 0.1} ORDER BY SIMILARITY(name, ${q}) DESC LIMIT ${Number(limit) || 5}`
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -272,6 +272,18 @@ export default {
|
|||
|
||||
return Math.floor((user.stackedMsats || 0) / 1000)
|
||||
},
|
||||
spent: async (user, args, { models }) => {
|
||||
const { sum: { sats } } = await models.itemAct.aggregate({
|
||||
sum: {
|
||||
sats: true
|
||||
},
|
||||
where: {
|
||||
userId: user.id
|
||||
}
|
||||
})
|
||||
|
||||
return sats || 0
|
||||
},
|
||||
sats: async (user, args, { models, me }) => {
|
||||
if (me?.id !== user.id) {
|
||||
return 0
|
||||
|
|
|
@ -8,7 +8,7 @@ export default gql`
|
|||
users: [User!]
|
||||
nameAvailable(name: String!): Boolean!
|
||||
topUsers(cursor: String, within: String!, userType: String!): TopUsers
|
||||
searchUsers(name: String!): [User!]!
|
||||
searchUsers(q: String!, limit: Int, similarity: Float): [User!]!
|
||||
}
|
||||
|
||||
type Users {
|
||||
|
@ -54,6 +54,7 @@ export default gql`
|
|||
nitems: Int!
|
||||
ncomments: Int!
|
||||
stacked: Int!
|
||||
spent: Int!
|
||||
freePosts: Int!
|
||||
freeComments: Int!
|
||||
hasNewNotes: Boolean!
|
||||
|
|
|
@ -238,7 +238,7 @@ export function InputUserSuggest ({ label, groupClassName, ...props }) {
|
|||
<InputInner
|
||||
{...props}
|
||||
autoComplete='off'
|
||||
onChange={(_, e) => getSuggestions({ variables: { name: e.target.value } })}
|
||||
onChange={(_, e) => getSuggestions({ variables: { q: e.target.value } })}
|
||||
overrideValue={ovalue}
|
||||
onKeyDown={(e) => {
|
||||
switch (e.code) {
|
||||
|
|
|
@ -28,7 +28,16 @@ export default function Search ({ sub }) {
|
|||
if (sub) {
|
||||
prefix = `/~${sub}`
|
||||
}
|
||||
|
||||
if (values.q?.trim() !== '') {
|
||||
if (values.what === 'users') {
|
||||
await router.push({
|
||||
pathname: '/users/search',
|
||||
query: { q, what: 'users' }
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (values.what === '') delete values.what
|
||||
if (values.sort === '') delete values.sort
|
||||
if (values.when === '') delete values.when
|
||||
|
@ -64,24 +73,28 @@ export default function Search ({ sub }) {
|
|||
onChange={(formik, e) => search({ ...formik?.values, what: e.target.value })}
|
||||
name='what'
|
||||
size='sm'
|
||||
items={['all', 'posts', 'comments']}
|
||||
/>
|
||||
by
|
||||
<Select
|
||||
groupClassName='mx-2 mb-0'
|
||||
onChange={(formik, e) => search({ ...formik?.values, sort: e.target.value })}
|
||||
name='sort'
|
||||
size='sm'
|
||||
items={['match', 'recent', 'comments', 'sats', 'votes']}
|
||||
/>
|
||||
for
|
||||
<Select
|
||||
groupClassName='mb-0 ml-2'
|
||||
onChange={(formik, e) => search({ ...formik?.values, when: e.target.value })}
|
||||
name='when'
|
||||
size='sm'
|
||||
items={['forever', 'day', 'week', 'month', 'year']}
|
||||
items={['all', 'posts', 'comments', 'users']}
|
||||
/>
|
||||
{router.query.what !== 'users' &&
|
||||
<>
|
||||
by
|
||||
<Select
|
||||
groupClassName='mx-2 mb-0'
|
||||
onChange={(formik, e) => search({ ...formik?.values, sort: e.target.value })}
|
||||
name='sort'
|
||||
size='sm'
|
||||
items={['match', 'recent', 'comments', 'sats', 'votes']}
|
||||
/>
|
||||
for
|
||||
<Select
|
||||
groupClassName='mb-0 ml-2'
|
||||
onChange={(formik, e) => search({ ...formik?.values, when: e.target.value })}
|
||||
name='when'
|
||||
size='sm'
|
||||
items={['forever', 'day', 'week', 'month', 'year']}
|
||||
/>
|
||||
|
||||
</>}
|
||||
</div>}
|
||||
<div className={`${styles.active}`}>
|
||||
<Input
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
import Link from 'next/link'
|
||||
import { Image } from 'react-bootstrap'
|
||||
import styles from './item.module.css'
|
||||
import userStyles from './user-header.module.css'
|
||||
|
||||
export default function UserList ({ users }) {
|
||||
return (
|
||||
<> {users.map(user => (
|
||||
<div className={`${styles.item} mb-2`} key={user.name}>
|
||||
<Link href={`/${user.name}`} passHref>
|
||||
<a>
|
||||
<Image
|
||||
src={user.photoId ? `https://${process.env.NEXT_PUBLIC_AWS_UPLOAD_BUCKET}.s3.amazonaws.com/${user.photoId}` : '/dorian400.jpg'} width='32' height='32'
|
||||
className={`${userStyles.userimg} mr-2`}
|
||||
/>
|
||||
</a>
|
||||
</Link>
|
||||
<div className={styles.hunk}>
|
||||
<Link href={`/${user.name}`} passHref>
|
||||
<a className={`${styles.title} text-reset`}>
|
||||
@{user.name}
|
||||
</a>
|
||||
</Link>
|
||||
<div className={styles.other}>
|
||||
<span>{user.stacked} stacked</span>
|
||||
<span> \ </span>
|
||||
<span>{user.spent} spent</span>
|
||||
<span> \ </span>
|
||||
<Link href={`/${user.name}/posts`} passHref>
|
||||
<a className='text-reset'>
|
||||
{user.nitems} posts
|
||||
</a>
|
||||
</Link>
|
||||
<span> \ </span>
|
||||
<Link href={`/${user.name}/comments`} passHref>
|
||||
<a className='text-reset'>
|
||||
{user.ncomments} comments
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
}
|
|
@ -123,9 +123,14 @@ gql`
|
|||
|
||||
export const USER_SEARCH =
|
||||
gql`
|
||||
query searchUsers($name: String!) {
|
||||
searchUsers(name: $name) {
|
||||
query searchUsers($q: String!, $limit: Int, $similarity: Float) {
|
||||
searchUsers(q: $q, limit: $limit, similarity: $similarity) {
|
||||
name
|
||||
photoId
|
||||
stacked
|
||||
spent
|
||||
ncomments
|
||||
nitems
|
||||
}
|
||||
}`
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ export default function Index ({ data: { topUsers: { users, cursor } } }) {
|
|||
|
||||
return (
|
||||
<Layout>
|
||||
<TopHeader cat={'users/' + userType} />
|
||||
<TopHeader cat={'users/' + userType} />
|
||||
{users.map(user => (
|
||||
<Link href={`/${user.name}`} key={user.name}>
|
||||
<div className='d-flex align-items-center pointer'>
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
import Layout from '../../components/layout'
|
||||
import { getGetServerSideProps } from '../../api/ssrApollo'
|
||||
import { SeoSearch } from '../../components/seo'
|
||||
import { USER_SEARCH } from '../../fragments/users'
|
||||
import UserList from '../../components/user-list'
|
||||
|
||||
export const getServerSideProps = getGetServerSideProps(USER_SEARCH, { limit: 21, similarity: 0.2 })
|
||||
|
||||
export default function Index ({ data: { searchUsers } }) {
|
||||
return (
|
||||
<Layout noSeo>
|
||||
<SeoSearch />
|
||||
<UserList users={searchUsers} />
|
||||
</Layout>
|
||||
)
|
||||
}
|
Loading…
Reference in New Issue