Home: Show pills that are groups (in addition to All, For you)

This commit is contained in:
James Grugett 2022-07-19 18:22:55 -05:00
parent 921ac4b2a9
commit b2c89d36cf
3 changed files with 84 additions and 36 deletions

View File

@ -13,7 +13,7 @@ export function PillButton(props: {
return ( return (
<button <button
className={clsx( className={clsx(
'cursor-pointer select-none rounded-full', 'cursor-pointer select-none whitespace-nowrap rounded-full',
selected selected
? ['text-white', color ?? 'bg-gray-700'] ? ['text-white', color ?? 'bg-gray-700']
: 'bg-gray-100 hover:bg-gray-200', : 'bg-gray-100 hover:bg-gray-200',

View File

@ -27,7 +27,7 @@ import ContractSearchFirestore from 'web/pages/contract-search-firestore'
import { useMemberGroups } from 'web/hooks/use-group' import { useMemberGroups } from 'web/hooks/use-group'
import { NEW_USER_GROUP_SLUGS } from 'common/group' import { NEW_USER_GROUP_SLUGS } from 'common/group'
import { PillButton } from './buttons/pill-button' import { PillButton } from './buttons/pill-button'
import { toPairs } from 'lodash' import { sortBy } from 'lodash'
const searchClient = algoliasearch( const searchClient = algoliasearch(
'GJQPAYENIF', 'GJQPAYENIF',
@ -49,13 +49,6 @@ const sortIndexes = [
export const DEFAULT_SORT = 'score' export const DEFAULT_SORT = 'score'
type filter = 'personal' | 'open' | 'closed' | 'resolved' | 'all' type filter = 'personal' | 'open' | 'closed' | 'resolved' | 'all'
const filterOptions: { [label: string]: filter } = {
All: 'all',
Open: 'open',
Closed: 'closed',
Resolved: 'resolved',
'For you': 'personal',
}
export function ContractSearch(props: { export function ContractSearch(props: {
querySortOptions?: { querySortOptions?: {
@ -86,9 +79,14 @@ export function ContractSearch(props: {
} = props } = props
const user = useUser() const user = useUser()
const memberGroupSlugs = useMemberGroups(user?.id) const memberGroups = (useMemberGroups(user?.id) ?? []).filter(
?.map((g) => g.slug) (group) => !NEW_USER_GROUP_SLUGS.includes(group.slug)
.filter((s) => !NEW_USER_GROUP_SLUGS.includes(s)) )
const memberGroupSlugs = memberGroups.map((g) => g.slug)
const pillGroups = sortBy(
memberGroups.filter((group) => group.contractIds.length > 0),
(group) => group.contractIds.length
).reverse()
const follows = useFollows(user?.id) const follows = useFollows(user?.id)
const { initialSort } = useInitialQueryAndSort(querySortOptions) const { initialSort } = useInitialQueryAndSort(querySortOptions)
@ -101,15 +99,27 @@ export function ContractSearch(props: {
const [filter, setFilter] = useState<filter>( const [filter, setFilter] = useState<filter>(
querySortOptions?.defaultFilter ?? 'open' querySortOptions?.defaultFilter ?? 'open'
) )
const [pillFilter, setPillFilter] = useState<string | undefined>()
const { filters, numericFilters } = useMemo(() => { const { filters, numericFilters } = useMemo(() => {
let filters = [ let filters = [
filter === 'open' ? 'isResolved:false' : '', filter === 'open' ? 'isResolved:false' : '',
filter === 'closed' ? 'isResolved:false' : '', filter === 'closed' ? 'isResolved:false' : '',
filter === 'resolved' ? 'isResolved:true' : '', filter === 'resolved' ? 'isResolved:true' : '',
filter === 'personal' additionalFilter?.creatorId
? `creatorId:${additionalFilter.creatorId}`
: '',
additionalFilter?.tag ? `lowercaseTags:${additionalFilter.tag}` : '',
additionalFilter?.groupSlug
? `groupSlugs:${additionalFilter.groupSlug}`
: '',
pillFilter && pillFilter !== 'personal'
? `groupSlugs:${pillFilter}`
: '',
pillFilter === 'personal'
? // Show contracts in groups that the user is a member of ? // Show contracts in groups that the user is a member of
(memberGroupSlugs?.map((slug) => `groupSlugs:${slug}`) ?? []) memberGroupSlugs
.map((slug) => `groupSlugs:${slug}`)
// Show contracts created by users the user follows // Show contracts created by users the user follows
.concat(follows?.map((followId) => `creatorId:${followId}`) ?? []) .concat(follows?.map((followId) => `creatorId:${followId}`) ?? [])
// Show contracts bet on by users the user follows // Show contracts bet on by users the user follows
@ -119,13 +129,6 @@ export function ContractSearch(props: {
) )
.concat(user ? `uniqueBettorIds:${user.id}` : []) .concat(user ? `uniqueBettorIds:${user.id}` : [])
: '', : '',
additionalFilter?.creatorId
? `creatorId:${additionalFilter.creatorId}`
: '',
additionalFilter?.tag ? `lowercaseTags:${additionalFilter.tag}` : '',
additionalFilter?.groupSlug
? `groupSlugs:${additionalFilter.groupSlug}`
: '',
].filter((f) => f) ].filter((f) => f)
// Hack to make Algolia work. // Hack to make Algolia work.
filters = ['', ...filters] filters = ['', ...filters]
@ -139,8 +142,9 @@ export function ContractSearch(props: {
}, [ }, [
filter, filter,
Object.values(additionalFilter ?? {}).join(','), Object.values(additionalFilter ?? {}).join(','),
(memberGroupSlugs ?? []).join(','), memberGroupSlugs.join(','),
(follows ?? []).join(','), (follows ?? []).join(','),
pillFilter,
]) ])
const indexName = `${indexPrefix}contracts-${sort}` const indexName = `${indexPrefix}contracts-${sort}`
@ -167,6 +171,17 @@ export function ContractSearch(props: {
}} }}
/> />
{/*// TODO track WHICH filter users are using*/} {/*// TODO track WHICH filter users are using*/}
<select
className="!select !select-bordered"
value={filter}
onChange={(e) => setFilter(e.target.value as filter)}
onBlur={trackCallback('select search filter')}
>
<option value="open">Open</option>
<option value="closed">Closed</option>
<option value="resolved">Resolved</option>
<option value="all">All</option>
</select>
{!hideOrderSelector && ( {!hideOrderSelector && (
<SortBy <SortBy
items={sortIndexes} items={sortIndexes}
@ -186,25 +201,41 @@ export function ContractSearch(props: {
<Spacer h={3} /> <Spacer h={3} />
<Row className="gap-2"> {!additionalFilter?.creatorId && !additionalFilter?.groupSlug && (
{toPairs<filter>(filterOptions).map(([label, f]) => { <Row className="scrollbar-hide items-start gap-2 overflow-x-auto">
return ( <PillButton
<PillButton key={'all'}
key={f} selected={pillFilter === undefined}
selected={filter === f} onSelect={() => setPillFilter(undefined)}
onSelect={() => setFilter(f)} >
> All
{label} </PillButton>
</PillButton> <PillButton
) key={'personal'}
})} selected={pillFilter === 'personal'}
</Row> onSelect={() => setPillFilter('personal')}
>
For you
</PillButton>
{pillGroups.map(({ name, slug }) => {
return (
<PillButton
key={slug}
selected={pillFilter === slug}
onSelect={() => setPillFilter(slug)}
>
{name}
</PillButton>
)
})}
</Row>
)}
<Spacer h={3} /> <Spacer h={3} />
{filter === 'personal' && {filter === 'personal' &&
(follows ?? []).length === 0 && (follows ?? []).length === 0 &&
(memberGroupSlugs ?? []).length === 0 ? ( memberGroupSlugs.length === 0 ? (
<>You're not following anyone, nor in any of your own groups yet.</> <>You're not following anyone, nor in any of your own groups yet.</>
) : ( ) : (
<ContractSearchInner <ContractSearchInner

View File

@ -1,4 +1,5 @@
const defaultTheme = require('tailwindcss/defaultTheme') const defaultTheme = require('tailwindcss/defaultTheme')
const plugin = require('tailwindcss/plugin')
module.exports = { module.exports = {
content: [ content: [
@ -32,6 +33,22 @@ module.exports = {
require('@tailwindcss/typography'), require('@tailwindcss/typography'),
require('@tailwindcss/line-clamp'), require('@tailwindcss/line-clamp'),
require('daisyui'), require('daisyui'),
plugin(function ({ addUtilities }) {
addUtilities({
'.scrollbar-hide': {
/* IE and Edge */
'-ms-overflow-style': 'none',
/* Firefox */
'scrollbar-width': 'none',
/* Safari and Chrome */
'&::-webkit-scrollbar': {
display: 'none',
},
},
})
}),
], ],
daisyui: { daisyui: {
themes: [ themes: [