diff --git a/web/components/contract-search.tsx b/web/components/contract-search.tsx index d6127286..7ec33d3e 100644 --- a/web/components/contract-search.tsx +++ b/web/components/contract-search.tsx @@ -3,6 +3,7 @@ import { InstantSearch, SearchBox, SortBy, + useCurrentRefinements, useInfiniteHits, useRange, useRefinementList, @@ -21,6 +22,8 @@ import { useEffect, useRef, useState } from 'react' import { Spacer } from './layout/spacer' import { useRouter } from 'next/router' import { ENV } from 'common/envs/constants' +import { CategorySelector } from './feed/category-selector' +import { useUser } from 'web/hooks/use-user' const searchClient = algoliasearch( 'GJQPAYENIF', @@ -44,15 +47,18 @@ export function ContractSearch(props: { querySortOptions?: { defaultSort: Sort defaultFilter?: filter - filter?: { - creatorId?: string - tag?: string - } shouldLoadFromStorage?: boolean } + additionalFilter?: { + creatorId?: string + tag?: string + category?: string + } + showCategorySelector: boolean }) { - const { querySortOptions } = props + const { querySortOptions, additionalFilter, showCategorySelector } = props + const user = useUser() const { initialSort } = useInitialQueryAndSort(querySortOptions) const sort = sortIndexes @@ -65,15 +71,15 @@ export function ContractSearch(props: { querySortOptions?.defaultFilter ?? 'open' ) + const [category, setCategory] = useState('all') + if (!sort) return <> return ( @@ -105,10 +111,25 @@ export function ContractSearch(props: { /> - +
+ {showCategorySelector && ( + <> + + + + )} + + + +
) } @@ -116,15 +137,16 @@ export function ContractSearch(props: { export function ContractSearchInner(props: { querySortOptions?: { defaultSort: Sort - filter?: { - creatorId?: string - tag?: string - } shouldLoadFromStorage?: boolean } filter: filter + additionalFilter: { + creatorId?: string + tag?: string + category?: string + } }) { - const { querySortOptions, filter } = props + const { querySortOptions, filter, additionalFilter } = props const { initialQuery } = useInitialQueryAndSort(querySortOptions) const { query, setQuery, setSort } = useUpdateQueryAndSort({ @@ -156,11 +178,11 @@ export function ContractSearchInner(props: { } }, [index]) - const creatorId = querySortOptions?.filter?.creatorId + const { creatorId, category, tag } = additionalFilter + useFilterCreator(creatorId) - const tag = querySortOptions?.filter?.tag - useFilterTag(tag) + useFilterTag(tag ?? (category === 'all' ? undefined : category)) useFilterClosed( filter === 'closed' @@ -173,25 +195,21 @@ export function ContractSearchInner(props: { filter === 'resolved' ? true : filter === 'all' ? undefined : false ) - const { showMore, hits, isLastPage } = useInfiniteHits() + const { showMore, hits, isLastPage, results } = useInfiniteHits() const contracts = hits as any as Contract[] const router = useRouter() const hasLoaded = contracts.length > 0 || router.isReady - return ( -
- + if (!hasLoaded || !results) return <> - {hasLoaded && ( - - )} -
+ return ( + ) } @@ -203,10 +221,15 @@ const useFilterCreator = (creatorId: string | undefined) => { } const useFilterTag = (tag: string | undefined) => { + const { items, refine: deleteRefinement } = useCurrentRefinements({ + includedAttributes: ['lowercaseTags'], + }) const { refine } = useRefinementList({ attribute: 'lowercaseTags' }) useEffect(() => { + const refinements = items[0]?.refinements ?? [] if (tag) refine(tag.toLowerCase()) - }, [tag, refine]) + if (refinements[0]) deleteRefinement(refinements[0]) + }, [tag]) } const useFilterClosed = (value: boolean | undefined) => { diff --git a/web/components/contract/contracts-list.tsx b/web/components/contract/contracts-list.tsx index 2ce43daf..f55ca757 100644 --- a/web/components/contract/contracts-list.tsx +++ b/web/components/contract/contracts-list.tsx @@ -53,13 +53,14 @@ export function CreatorContractsList(props: { creator: User }) { return ( ) } diff --git a/web/components/feed/category-selector.tsx b/web/components/feed/category-selector.tsx index 4b3215d9..bb89da81 100644 --- a/web/components/feed/category-selector.tsx +++ b/web/components/feed/category-selector.tsx @@ -15,7 +15,7 @@ export function CategorySelector(props: { return ( diff --git a/web/components/nav/nav-bar.tsx b/web/components/nav/nav-bar.tsx index cab369fb..04c8e891 100644 --- a/web/components/nav/nav-bar.tsx +++ b/web/components/nav/nav-bar.tsx @@ -5,6 +5,7 @@ import { MenuAlt3Icon, PresentationChartLineIcon, SearchIcon, + ChatAltIcon, XIcon, } from '@heroicons/react/outline' import { Transition, Dialog } from '@headlessui/react' @@ -29,12 +30,21 @@ export function BottomNavBar() { - - - - + {user === null ? ( + + + + + ) : ( + + + + + )} {user !== null && ( diff --git a/web/components/nav/sidebar.tsx b/web/components/nav/sidebar.tsx index 22605fe4..82febb07 100644 --- a/web/components/nav/sidebar.tsx +++ b/web/components/nav/sidebar.tsx @@ -7,6 +7,7 @@ import { CashIcon, HeartIcon, PresentationChartLineIcon, + ChatAltIcon, } from '@heroicons/react/outline' import clsx from 'clsx' import _ from 'lodash' @@ -29,7 +30,7 @@ function IconFromUrl(url: string): React.ComponentType<{ className?: string }> { const navigation = [ { name: 'Home', href: '/home', icon: HomeIcon }, - { name: 'Explore', href: '/markets', icon: SearchIcon }, + { name: 'Activity', href: '/activity', icon: ChatAltIcon }, { name: 'Portfolio', href: '/portfolio', icon: PresentationChartLineIcon }, { name: 'Charity', href: '/charity', icon: HeartIcon }, ] diff --git a/web/pages/activity.tsx b/web/pages/activity.tsx new file mode 100644 index 00000000..dd36ac39 --- /dev/null +++ b/web/pages/activity.tsx @@ -0,0 +1,74 @@ +import React, { useEffect, useState } from 'react' +import Router, { useRouter } from 'next/router' +import { Page } from 'web/components/page' +import { ActivityFeed } from 'web/components/feed/activity-feed' +import { Spacer } from 'web/components/layout/spacer' +import { Col } from 'web/components/layout/col' +import { useUser } from 'web/hooks/use-user' +import { LoadingIndicator } from 'web/components/loading-indicator' +import { useAlgoFeed } from 'web/hooks/use-algo-feed' +import { ContractPageContent } from './[username]/[contractSlug]' +import { CategorySelector } from '../components/feed/category-selector' + +export default function Activity() { + const user = useUser() + const [category, setCategory] = useState('all') + + const feed = useAlgoFeed(user, category) + + const router = useRouter() + const { u: username, s: slug } = router.query + const contract = feed?.find( + ({ contract }) => contract.slug === slug + )?.contract + + useEffect(() => { + // If the page initially loads with query params, redirect to the contract page. + if (router.isReady && slug && username) { + Router.replace(`/${username}/${slug}`) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [router.isReady]) + + if (user === null) { + Router.replace('/') + return <> + } + + return ( + <> + + + + + {feed ? ( + + `activity?u=${c.creatorUsername}&s=${c.slug}` + } + /> + ) : ( + + )} + + + + {contract && ( + + )} + + ) +} diff --git a/web/pages/home.tsx b/web/pages/home.tsx index 8cb02da8..b3fef139 100644 --- a/web/pages/home.tsx +++ b/web/pages/home.tsx @@ -1,35 +1,12 @@ -import React, { useEffect, useState } from 'react' -import Router, { useRouter } from 'next/router' +import React from 'react' +import Router from 'next/router' import { Page } from 'web/components/page' -import { ActivityFeed } from 'web/components/feed/activity-feed' -import FeedCreate from 'web/components/feed-create' -import { Spacer } from 'web/components/layout/spacer' import { Col } from 'web/components/layout/col' import { useUser } from 'web/hooks/use-user' -import { LoadingIndicator } from 'web/components/loading-indicator' -import { useAlgoFeed } from 'web/hooks/use-algo-feed' -import { ContractPageContent } from './[username]/[contractSlug]' -import { CategorySelector } from '../components/feed/category-selector' +import { ContractSearch } from 'web/components/contract-search' const Home = () => { const user = useUser() - const [category, setCategory] = useState('all') - - const feed = useAlgoFeed(user, category) - - const router = useRouter() - const { u: username, s: slug } = router.query - const contract = feed?.find( - ({ contract }) => contract.slug === slug - )?.contract - - useEffect(() => { - // If the page initially loads with query params, redirect to the contract page. - if (router.isReady && slug && username) { - Router.replace(`/${username}/${slug}`) - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [router.isReady]) if (user === null) { Router.replace('/') @@ -37,40 +14,17 @@ const Home = () => { } return ( - <> - - - - - - - {feed ? ( - `home?u=${c.creatorUsername}&s=${c.slug}`} - /> - ) : ( - - )} - - - - {contract && ( - + + - )} - + + ) } diff --git a/web/pages/markets.tsx b/web/pages/markets.tsx index a3e851fc..ab8e064d 100644 --- a/web/pages/markets.tsx +++ b/web/pages/markets.tsx @@ -11,7 +11,7 @@ export default function Markets() { description="Discover what's new, trending, or soon-to-close. Or search among our hundreds of markets." url="/markets" /> - + ) } diff --git a/web/pages/tag/[tag].tsx b/web/pages/tag/[tag].tsx index bf45b70f..089d715e 100644 --- a/web/pages/tag/[tag].tsx +++ b/web/pages/tag/[tag].tsx @@ -13,10 +13,12 @@ export default function TagPage() { <ContractSearch querySortOptions={{ - filter: { tag }, defaultSort: 'newest', + defaultFilter: 'all', shouldLoadFromStorage: false, }} + additionalFilter={{ tag }} + showCategorySelector={false} /> </Page> )