Use Tabs on Fold pages too

This commit is contained in:
Austin Chen 2022-03-30 23:21:41 -07:00
parent af86bc1acf
commit 7ddbb09403
2 changed files with 122 additions and 138 deletions

View File

@ -1,10 +1,13 @@
import clsx from 'clsx'
import Link from 'next/link'
import { useState } from 'react'
type Tab = {
title: string
tabIcon?: JSX.Element
content: JSX.Element
// If set, change the url to this href when the tab is selected
href?: string
}
export function Tabs(props: { tabs: Tab[]; defaultIndex?: number }) {
@ -16,24 +19,27 @@ export function Tabs(props: { tabs: Tab[]; defaultIndex?: number }) {
<div>
<nav className="flex space-x-4" aria-label="Tabs">
{tabs.map((tab, i) => (
<a
key={tab.title}
href="#"
className={clsx(
tab.title === activeTab.title
? 'bg-gray-200 text-gray-700'
: 'text-gray-500 hover:bg-gray-100 hover:text-gray-700',
'rounded-md px-3 py-2 text-sm font-medium'
)}
aria-current={tab.title === activeTab.title ? 'page' : undefined}
onClick={(e) => {
e.preventDefault()
setActiveIndex(i)
}}
>
{tab.tabIcon ? <span className="mr-2">{tab.tabIcon}</span> : null}
{tab.title}
</a>
<Link href={tab.href ?? '#'} key={tab.title} shallow={!!tab.href}>
<a
key={tab.title}
className={clsx(
tab.title === activeTab.title
? 'bg-gray-200 text-gray-700'
: 'text-gray-500 hover:bg-gray-100 hover:text-gray-700',
'rounded-md px-3 py-2 text-sm font-medium'
)}
aria-current={tab.title === activeTab.title ? 'page' : undefined}
onClick={(e) => {
if (!tab.href) {
e.preventDefault()
}
setActiveIndex(i)
}}
>
{tab.tabIcon ? <span className="mr-2">{tab.tabIcon}</span> : null}
{tab.title}
</a>
</Link>
))}
</nav>

View File

@ -40,6 +40,7 @@ import { useRecentBets } from '../../../hooks/use-bets'
import { useRecentComments } from '../../../hooks/use-comments'
import { LoadingIndicator } from '../../../components/loading-indicator'
import { findActiveContracts } from '../../../components/feed/find-active-contracts'
import { Tabs } from '../../../components/layout/tabs'
export const getStaticProps = fromPropz(getStaticPropz)
export async function getStaticPropz(props: { params: { slugs: string[] } }) {
@ -169,6 +170,47 @@ export default function FoldPage(props: {
)}
</Row>
<FoldOverview fold={fold} curator={curator} />
<YourPerformance
traderScores={traderScores}
creatorScores={creatorScores}
user={user}
/>
</Col>
)
const activityTab = (
<Col className="flex-1">
{user !== null && !fold.disallowMarketCreation && (
<FeedCreate
className={clsx('border-b-2')}
user={user}
tag={toCamelCase(fold.name)}
placeholder={`Type your question about ${fold.name}`}
/>
)}
{recentBets && recentComments ? (
<>
<ActivityFeed
contracts={activeContracts}
recentBets={recentBets ?? []}
recentComments={recentComments ?? []}
mode="abbreviated"
/>
{activeContracts.length === 0 && (
<div className="mx-2 mt-4 text-gray-500 lg:mx-0">
No activity from matching markets.{' '}
{isCurator && 'Try editing to add more tags!'}
</div>
)}
</>
) : (
<LoadingIndicator className="mt-4" />
)}
</Col>
)
const leaderboardsTab = (
<Col className="gap-8 px-4 lg:flex-row">
<FoldLeaderboards
traderScores={traderScores}
creatorScores={creatorScores}
@ -205,90 +247,25 @@ export default function FoldPage(props: {
</Col>
</div>
<div className="tabs mb-2">
<Link href={foldPath(fold)} shallow>
<a
className={clsx(
'tab tab-bordered',
page === 'activity' && 'tab-active'
)}
>
Activity
</a>
</Link>
<Link href={foldPath(fold, 'markets')} shallow>
<a
className={clsx(
'tab tab-bordered',
page === 'markets' && 'tab-active'
)}
>
Markets
</a>
</Link>
<Link href={foldPath(fold, 'leaderboards')} shallow>
<a
className={clsx(
'tab tab-bordered',
page === 'leaderboards' && 'tab-active',
page !== 'leaderboards' && 'md:hidden'
)}
>
Leaderboards
</a>
</Link>
</div>
{(page === 'activity' || page === 'markets') && (
<Row className={clsx(page === 'activity' ? 'gap-16' : 'gap-8')}>
<Col className="flex-1">
{user !== null && !fold.disallowMarketCreation && (
<FeedCreate
className={clsx('border-b-2', page !== 'activity' && 'hidden')}
user={user}
tag={toCamelCase(fold.name)}
placeholder={`Type your question about ${fold.name}`}
/>
)}
{page === 'activity' ? (
recentBets && recentComments ? (
<>
<ActivityFeed
contracts={activeContracts}
recentBets={recentBets ?? []}
recentComments={recentComments ?? []}
mode="abbreviated"
/>
{activeContracts.length === 0 && (
<div className="mx-2 mt-4 text-gray-500 lg:mx-0">
No activity from matching markets.{' '}
{isCurator && 'Try editing to add more tags!'}
</div>
)}
</>
) : (
<LoadingIndicator className="mt-4" />
)
) : (
<SearchableGrid contracts={contracts} />
)}
</Col>
</Row>
)}
{page === 'leaderboards' && (
<Col className="gap-8 px-4 lg:flex-row">
<FoldLeaderboards
traderScores={traderScores}
creatorScores={creatorScores}
topTraders={topTraders}
topCreators={topCreators}
user={user}
yourPerformanceClassName="lg:hidden"
/>
</Col>
)}
<Tabs
tabs={[
{
title: 'Activity',
content: activityTab,
href: foldPath(fold),
},
{
title: 'Markets',
content: <SearchableGrid contracts={contracts} />,
href: foldPath(fold, 'markets'),
},
{
title: 'Leaderboards',
content: leaderboardsTab,
href: foldPath(fold, 'leaderboards'),
},
]}
/>
</Page>
)
}
@ -333,55 +310,56 @@ function FoldOverview(props: { fold: Fold; curator: User }) {
)
}
function YourPerformance(props: {
traderScores: { [userId: string]: number }
creatorScores: { [userId: string]: number }
user: User | null | undefined
}) {
const { traderScores, creatorScores, user } = props
const yourTraderScore = user ? traderScores[user.id] : undefined
const yourCreatorScore = user ? creatorScores[user.id] : undefined
return user ? (
<Col>
<div className="rounded bg-indigo-500 px-4 py-3 text-sm text-white">
Your performance
</div>
<div className="bg-white p-2">
<table className="table-compact table w-full text-gray-500">
<tbody>
<tr>
<td>Trading profit</td>
<td>{formatMoney(yourTraderScore ?? 0)}</td>
</tr>
{yourCreatorScore && (
<tr>
<td>Created market vol</td>
<td>{formatMoney(yourCreatorScore)}</td>
</tr>
)}
</tbody>
</table>
</div>
</Col>
) : null
}
function FoldLeaderboards(props: {
traderScores: { [userId: string]: number }
creatorScores: { [userId: string]: number }
topTraders: User[]
topCreators: User[]
user: User | null | undefined
yourPerformanceClassName?: string
}) {
const {
traderScores,
creatorScores,
topTraders,
topCreators,
user,
yourPerformanceClassName,
} = props
const yourTraderScore = user ? traderScores[user.id] : undefined
const yourCreatorScore = user ? creatorScores[user.id] : undefined
const { traderScores, creatorScores, topTraders, topCreators } = props
const topTraderScores = topTraders.map((user) => traderScores[user.id])
const topCreatorScores = topCreators.map((user) => creatorScores[user.id])
return (
<>
{user && (
<Col className={yourPerformanceClassName}>
<div className="rounded bg-indigo-500 px-4 py-3 text-sm text-white">
Your performance
</div>
<div className="bg-white p-2">
<table className="table-compact table w-full text-gray-500">
<tbody>
<tr>
<td>Trading profit</td>
<td>{formatMoney(yourTraderScore ?? 0)}</td>
</tr>
{yourCreatorScore && (
<tr>
<td>Created market vol</td>
<td>{formatMoney(yourCreatorScore)}</td>
</tr>
)}
</tbody>
</table>
</div>
</Col>
)}
<Leaderboard
className="max-w-xl"
title="🏅 Top traders"