Merge branch 'main' of https://github.com/manticmarkets/mantic
This commit is contained in:
commit
41b24d415d
|
@ -115,7 +115,10 @@ export function BetPanel(props: { contract: Contract; className?: string }) {
|
|||
<Col
|
||||
className={clsx('bg-gray-100 shadow-md px-8 py-6 rounded-md', className)}
|
||||
>
|
||||
<Title className="!mt-0 whitespace-nowrap" text={`Buy ${betChoice}`} />
|
||||
<Title
|
||||
className="mt-0 whitespace-nowrap text-neutral"
|
||||
text={`Buy ${betChoice}`}
|
||||
/>
|
||||
|
||||
<div className="mt-2 mb-1 text-sm text-gray-500">Outcome</div>
|
||||
<YesNoSelector
|
||||
|
|
|
@ -151,9 +151,10 @@ function MyContractBets(props: { contract: Contract; bets: Bet[] }) {
|
|||
</Row>
|
||||
|
||||
<Row className="gap-2 text-gray-500 text-sm">
|
||||
<div>
|
||||
<UserLink username={contract.creatorUsername} />
|
||||
</div>
|
||||
<UserLink
|
||||
name={contract.creatorName}
|
||||
username={contract.creatorUsername}
|
||||
/>
|
||||
{resolution && (
|
||||
<>
|
||||
<div>•</div>
|
||||
|
|
|
@ -24,8 +24,8 @@ export function ContractCard(props: {
|
|||
|
||||
return (
|
||||
<Link href={contractPath(contract)}>
|
||||
<a>
|
||||
<li className="col-span-1 bg-white hover:bg-gray-100 shadow-md rounded-lg divide-y divide-gray-200">
|
||||
<a className="col-span-1">
|
||||
<li className="bg-white hover:bg-gray-100 shadow-md rounded-lg divide-y divide-gray-200">
|
||||
<div className="card">
|
||||
<div className="card-body p-6">
|
||||
<Row className="justify-between gap-4 mb-2">
|
||||
|
@ -102,15 +102,17 @@ export function AbbrContractDetails(props: {
|
|||
showHotVolume?: boolean
|
||||
}) {
|
||||
const { contract, showHotVolume } = props
|
||||
const { volume24Hours } = contract
|
||||
const { volume24Hours, creatorName, creatorUsername } = contract
|
||||
const { truePool } = contractMetrics(contract)
|
||||
|
||||
return (
|
||||
<Col className={clsx('text-sm text-gray-500 gap-2')}>
|
||||
<Row className="gap-2 flex-wrap">
|
||||
<div className="whitespace-nowrap">
|
||||
<UserLink username={contract.creatorUsername} />
|
||||
</div>
|
||||
<UserLink
|
||||
className="whitespace-nowrap"
|
||||
name={creatorName}
|
||||
username={creatorUsername}
|
||||
/>
|
||||
<div>•</div>
|
||||
{showHotVolume ? (
|
||||
<div className="whitespace-nowrap">
|
||||
|
@ -127,7 +129,8 @@ export function AbbrContractDetails(props: {
|
|||
|
||||
export function ContractDetails(props: { contract: Contract }) {
|
||||
const { contract } = props
|
||||
const { question, description, closeTime } = contract
|
||||
const { question, description, closeTime, creatorName, creatorUsername } =
|
||||
contract
|
||||
const { truePool, createdDate, resolvedDate } = contractMetrics(contract)
|
||||
|
||||
const tags = parseTags(`${question} ${description}`).map((tag) => `#${tag}`)
|
||||
|
@ -135,9 +138,11 @@ export function ContractDetails(props: { contract: Contract }) {
|
|||
return (
|
||||
<Col className="text-sm text-gray-500 gap-2 sm:flex-row sm:flex-wrap">
|
||||
<Row className="gap-2 flex-wrap">
|
||||
<div className="whitespace-nowrap">
|
||||
<UserLink username={contract.creatorUsername} />
|
||||
</div>
|
||||
<UserLink
|
||||
className="whitespace-nowrap"
|
||||
name={creatorName}
|
||||
username={creatorUsername}
|
||||
/>
|
||||
<div className="">•</div>
|
||||
<div className="whitespace-nowrap">
|
||||
{resolvedDate ? `${createdDate} - ${resolvedDate}` : createdDate}
|
||||
|
|
|
@ -31,6 +31,7 @@ import { formatMoney } from '../lib/util/format'
|
|||
import { ResolutionOrChance } from './contract-card'
|
||||
import { SiteLink } from './site-link'
|
||||
import { Col } from './layout/col'
|
||||
import { UserLink } from './user-page'
|
||||
dayjs.extend(relativeTime)
|
||||
|
||||
function FeedComment(props: { activityItem: any }) {
|
||||
|
@ -38,7 +39,7 @@ function FeedComment(props: { activityItem: any }) {
|
|||
const { person, text, amount, outcome, createdTime } = activityItem
|
||||
return (
|
||||
<>
|
||||
<div className="relative">
|
||||
<SiteLink className="relative" href={`/${person.username}`}>
|
||||
<img
|
||||
className="h-10 w-10 rounded-full bg-gray-400 flex items-center justify-center ring-8 ring-gray-50"
|
||||
src={person.avatarUrl}
|
||||
|
@ -48,13 +49,15 @@ function FeedComment(props: { activityItem: any }) {
|
|||
<span className="absolute -bottom-3 -right-2 bg-gray-50 rounded-tl px-0.5 py-px">
|
||||
<ChatAltIcon className="h-5 w-5 text-gray-400" aria-hidden="true" />
|
||||
</span>
|
||||
</div>
|
||||
</SiteLink>
|
||||
<div className="min-w-0 flex-1">
|
||||
<div>
|
||||
<p className="mt-0.5 text-sm text-gray-500">
|
||||
<a href={person.href} className="font-medium text-gray-900">
|
||||
{person.name}
|
||||
</a>{' '}
|
||||
<UserLink
|
||||
className="text-gray-500"
|
||||
username={person.username}
|
||||
name={person.name}
|
||||
/>{' '}
|
||||
placed {formatMoney(amount)} on <OutcomeLabel outcome={outcome} />{' '}
|
||||
<Timestamp time={createdTime} />
|
||||
</p>
|
||||
|
@ -205,6 +208,8 @@ export function ContractDescription(props: {
|
|||
|
||||
function FeedQuestion(props: { contract: Contract }) {
|
||||
const { contract } = props
|
||||
const { creatorName, creatorUsername, createdTime, question, resolution } =
|
||||
contract
|
||||
const { probPercent } = contractMetrics(contract)
|
||||
|
||||
return (
|
||||
|
@ -218,19 +223,23 @@ function FeedQuestion(props: { contract: Contract }) {
|
|||
</div>
|
||||
<div className="min-w-0 flex-1 py-1.5">
|
||||
<div className="text-sm text-gray-500 mb-2">
|
||||
<span className="text-gray-900">{contract.creatorName}</span> asked{' '}
|
||||
<Timestamp time={contract.createdTime} />
|
||||
<UserLink
|
||||
className="text-gray-900"
|
||||
name={creatorName}
|
||||
username={creatorUsername}
|
||||
/>{' '}
|
||||
asked <Timestamp time={createdTime} />
|
||||
</div>
|
||||
<Col className="items-start sm:flex-row justify-between gap-2 sm:gap-4 mb-4 mr-2">
|
||||
<SiteLink
|
||||
href={contractPath(contract)}
|
||||
className="text-lg sm:text-xl text-indigo-700"
|
||||
>
|
||||
{contract.question}
|
||||
{question}
|
||||
</SiteLink>
|
||||
<ResolutionOrChance
|
||||
className="items-center"
|
||||
resolution={contract.resolution}
|
||||
resolution={resolution}
|
||||
probPercent={probPercent}
|
||||
/>
|
||||
</Col>
|
||||
|
@ -242,6 +251,7 @@ function FeedQuestion(props: { contract: Contract }) {
|
|||
|
||||
function FeedDescription(props: { contract: Contract }) {
|
||||
const { contract } = props
|
||||
const { creatorName, creatorUsername } = contract
|
||||
const user = useUser()
|
||||
const isCreator = user?.id === contract.creatorId
|
||||
|
||||
|
@ -256,8 +266,12 @@ function FeedDescription(props: { contract: Contract }) {
|
|||
</div>
|
||||
<div className="min-w-0 flex-1 py-1.5">
|
||||
<div className="text-sm text-gray-500">
|
||||
<span className="text-gray-900">{contract.creatorName}</span> created
|
||||
this market <Timestamp time={contract.createdTime} />
|
||||
<UserLink
|
||||
className="text-gray-900"
|
||||
name={creatorName}
|
||||
username={creatorUsername}
|
||||
/>{' '}
|
||||
created this market <Timestamp time={contract.createdTime} />
|
||||
</div>
|
||||
<ContractDescription contract={contract} isCreator={isCreator} />
|
||||
</div>
|
||||
|
@ -280,6 +294,7 @@ function OutcomeIcon(props: { outcome?: 'YES' | 'NO' | 'CANCEL' }) {
|
|||
|
||||
function FeedResolve(props: { contract: Contract }) {
|
||||
const { contract } = props
|
||||
const { creatorName, creatorUsername } = contract
|
||||
const resolution = contract.resolution || 'CANCEL'
|
||||
|
||||
return (
|
||||
|
@ -293,8 +308,12 @@ function FeedResolve(props: { contract: Contract }) {
|
|||
</div>
|
||||
<div className="min-w-0 flex-1 py-1.5">
|
||||
<div className="text-sm text-gray-500">
|
||||
<span className="text-gray-900">{contract.creatorName}</span> resolved
|
||||
this market to <OutcomeLabel outcome={resolution} />{' '}
|
||||
<UserLink
|
||||
className="text-gray-900"
|
||||
name={creatorName}
|
||||
username={creatorUsername}
|
||||
/>{' '}
|
||||
resolved this market to <OutcomeLabel outcome={resolution} />{' '}
|
||||
<Timestamp time={contract.resolutionTime || 0} />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -354,7 +373,7 @@ function toFeedComment(bet: Bet, comment: Comment) {
|
|||
// Invariant: bet.comment exists
|
||||
text: comment.text,
|
||||
person: {
|
||||
href: `/${comment.userUsername}`,
|
||||
username: comment.userUsername,
|
||||
name: comment.userName,
|
||||
avatarUrl: comment.userAvatarUrl,
|
||||
},
|
||||
|
|
|
@ -40,7 +40,7 @@ export const ContractOverview = (props: {
|
|||
|
||||
return (
|
||||
<Col className={clsx('mb-6', className)}>
|
||||
<Row className="justify-between gap-4">
|
||||
<Row className="justify-between gap-4 px-2">
|
||||
<Col className="gap-4">
|
||||
<div className="text-2xl md:text-3xl text-indigo-700">
|
||||
<Linkify text={contract.question} />
|
||||
|
|
|
@ -42,7 +42,7 @@ export function ContractsGrid(props: {
|
|||
}
|
||||
|
||||
return (
|
||||
<ul role="list" className="grid grid-cols-1 gap-6 lg:grid-cols-2">
|
||||
<ul className="w-full grid grid-cols-1 gap-6 md:grid-cols-2">
|
||||
{contracts.map((contract) => (
|
||||
<ContractCard
|
||||
contract={contract}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import Link from 'next/link'
|
||||
import Image from 'next/image'
|
||||
import clsx from 'clsx'
|
||||
|
||||
export function ManifoldLogo(props: { darkBackground?: boolean }) {
|
||||
|
@ -6,8 +7,8 @@ export function ManifoldLogo(props: { darkBackground?: boolean }) {
|
|||
|
||||
return (
|
||||
<Link href="/">
|
||||
<a className="flex flex-row gap-4">
|
||||
<img
|
||||
<a className="flex flex-row gap-4 flex-shrink-0">
|
||||
<Image
|
||||
className="hover:rotate-12 transition-all"
|
||||
src={darkBackground ? '/logo-white.svg' : '/logo.svg'}
|
||||
width={45}
|
||||
|
|
|
@ -9,10 +9,7 @@ export function MenuButton(props: {
|
|||
}) {
|
||||
const { buttonContent, menuItems, className } = props
|
||||
return (
|
||||
<Menu
|
||||
as="div"
|
||||
className={clsx('flex-shrink-0 relative ml-4 z-10', className)}
|
||||
>
|
||||
<Menu as="div" className={clsx('flex-shrink-0 relative z-10', className)}>
|
||||
<div>
|
||||
<Menu.Button className="rounded-full flex">
|
||||
<span className="sr-only">Open user menu</span>
|
||||
|
|
|
@ -10,11 +10,9 @@ import { ProfileMenu } from './profile-menu'
|
|||
export function NavBar(props: {
|
||||
darkBackground?: boolean
|
||||
wide?: boolean
|
||||
isLandingPage?: boolean
|
||||
className?: string
|
||||
children?: any
|
||||
}) {
|
||||
const { darkBackground, wide, isLandingPage, className, children } = props
|
||||
const { darkBackground, wide, className } = props
|
||||
|
||||
const user = useUser()
|
||||
|
||||
|
@ -27,44 +25,14 @@ export function NavBar(props: {
|
|||
<Row
|
||||
className={clsx(
|
||||
'justify-between items-center mx-auto sm:px-4',
|
||||
isLandingPage ? 'max-w-7xl' : wide ? 'max-w-6xl' : 'max-w-4xl'
|
||||
wide ? 'max-w-6xl' : 'max-w-4xl'
|
||||
)}
|
||||
>
|
||||
<ManifoldLogo darkBackground={darkBackground} />
|
||||
|
||||
<Row className="items-center gap-6 sm:gap-8 md:ml-16 lg:ml-40">
|
||||
{children}
|
||||
|
||||
{!user && (
|
||||
<Link href="/about">
|
||||
<a
|
||||
className={clsx(
|
||||
'text-base hidden md:block whitespace-nowrap',
|
||||
themeClasses
|
||||
)}
|
||||
>
|
||||
About
|
||||
</a>
|
||||
</Link>
|
||||
)}
|
||||
|
||||
{!isLandingPage && (
|
||||
<Link href="/markets">
|
||||
<a
|
||||
className={clsx(
|
||||
'text-base hidden md:block whitespace-nowrap',
|
||||
themeClasses
|
||||
)}
|
||||
>
|
||||
All markets
|
||||
</a>
|
||||
</Link>
|
||||
)}
|
||||
|
||||
{user ? (
|
||||
<SignedInHeaders user={user} themeClasses={themeClasses} />
|
||||
) : (
|
||||
<SignedOutHeaders themeClasses={themeClasses} />
|
||||
<Row className="items-center gap-6 sm:gap-8 ml-6">
|
||||
{(user || user === null) && (
|
||||
<NavOptions user={user} themeClasses={themeClasses} />
|
||||
)}
|
||||
</Row>
|
||||
</Row>
|
||||
|
@ -72,41 +40,62 @@ export function NavBar(props: {
|
|||
)
|
||||
}
|
||||
|
||||
function SignedInHeaders(props: { user: User; themeClasses?: string }) {
|
||||
function NavOptions(props: { user: User | null; themeClasses: string }) {
|
||||
const { user, themeClasses } = props
|
||||
|
||||
return (
|
||||
<>
|
||||
<Link href="/create">
|
||||
{user === null && (
|
||||
<Link href="/about">
|
||||
<a
|
||||
className={clsx(
|
||||
'text-base hidden md:block whitespace-nowrap',
|
||||
themeClasses
|
||||
)}
|
||||
>
|
||||
About
|
||||
</a>
|
||||
</Link>
|
||||
)}
|
||||
|
||||
<Link href="/markets">
|
||||
<a
|
||||
className={clsx(
|
||||
'text-base hidden md:block whitespace-nowrap',
|
||||
themeClasses
|
||||
)}
|
||||
>
|
||||
Create a market
|
||||
All markets
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
<ProfileMenu user={user} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function SignedOutHeaders(props: { themeClasses?: string }) {
|
||||
const { themeClasses } = props
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={clsx(
|
||||
'text-base font-medium cursor-pointer whitespace-nowrap',
|
||||
themeClasses
|
||||
)}
|
||||
onClick={firebaseLogin}
|
||||
>
|
||||
Sign in
|
||||
</div>
|
||||
{user === null ? (
|
||||
<>
|
||||
<div
|
||||
className={clsx(
|
||||
'text-base font-medium cursor-pointer whitespace-nowrap',
|
||||
themeClasses
|
||||
)}
|
||||
onClick={firebaseLogin}
|
||||
>
|
||||
Sign in
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Link href="/create">
|
||||
<a
|
||||
className={clsx(
|
||||
'text-base hidden md:block whitespace-nowrap',
|
||||
themeClasses
|
||||
)}
|
||||
>
|
||||
Create a market
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
<ProfileMenu user={user} />
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -51,10 +51,6 @@ function getNavigationOptions(user: User, options: { mobile: boolean }) {
|
|||
name: 'Your markets',
|
||||
href: `/${user.username}`,
|
||||
},
|
||||
// {
|
||||
// name: 'Add funds',
|
||||
// href: '/add-funds',
|
||||
// },
|
||||
{
|
||||
name: 'Discord',
|
||||
href: 'https://discord.gg/eHQBNBqXuh',
|
||||
|
|
|
@ -60,7 +60,7 @@ export function ResolutionPanel(props: {
|
|||
<Col
|
||||
className={clsx('bg-gray-100 shadow-md px-8 py-6 rounded-md', className)}
|
||||
>
|
||||
<Title className="mt-0" text="Your market" />
|
||||
<Title className="mt-0 text-neutral" text="Your market" />
|
||||
|
||||
<div className="pt-2 pb-1 text-sm text-gray-500">Resolve outcome</div>
|
||||
|
||||
|
|
|
@ -7,12 +7,18 @@ import { SEO } from './SEO'
|
|||
import { Page } from './page'
|
||||
import { SiteLink } from './site-link'
|
||||
|
||||
export function UserLink(props: { username: string; className?: string }) {
|
||||
const { username, className } = props
|
||||
export function UserLink(props: {
|
||||
name: string
|
||||
username: string
|
||||
showUsername?: boolean
|
||||
className?: string
|
||||
}) {
|
||||
const { name, username, showUsername, className } = props
|
||||
|
||||
return (
|
||||
<SiteLink href={`/${username}`} className={className}>
|
||||
@{username}
|
||||
{name}
|
||||
{showUsername && ` (@${username})`}
|
||||
</SiteLink>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -119,8 +119,13 @@ function BetsSection(props: { contract: Contract; user: User | null }) {
|
|||
|
||||
return (
|
||||
<div>
|
||||
<Title text="Your trades" />
|
||||
<MyBetsSummary contract={contract} bets={userBets} showMKT />
|
||||
<Title className="px-2" text="Your trades" />
|
||||
<MyBetsSummary
|
||||
className="px-2"
|
||||
contract={contract}
|
||||
bets={userBets}
|
||||
showMKT
|
||||
/>
|
||||
<Spacer h={6} />
|
||||
<ContractBetsTable contract={contract} bets={userBets} />
|
||||
<Spacer h={12} />
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import { useUser } from '../hooks/use-user'
|
||||
import {
|
||||
Contract,
|
||||
getHotContracts,
|
||||
listAllContracts,
|
||||
} from '../lib/firebase/contracts'
|
||||
import LandingPage from './landing-page'
|
||||
import { ContractsGrid } from '../components/contracts-list'
|
||||
import { Spacer } from '../components/layout/spacer'
|
||||
import { Page } from '../components/page'
|
||||
|
@ -37,16 +35,8 @@ const Home = (props: {
|
|||
hotContracts: Contract[]
|
||||
recentComments: Comment[]
|
||||
}) => {
|
||||
const user = useUser()
|
||||
|
||||
if (user === undefined) return <></>
|
||||
|
||||
const { contracts, hotContracts, recentComments } = props
|
||||
|
||||
if (user === null) {
|
||||
return <LandingPage hotContracts={hotContracts} />
|
||||
}
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<div className="w-full bg-indigo-50 border-2 border-indigo-100 p-6 rounded-lg shadow-md">
|
||||
|
|
|
@ -34,7 +34,7 @@ const scrollToAbout = () => {
|
|||
function Hero() {
|
||||
return (
|
||||
<div className="overflow-hidden h-screen bg-world-trading bg-cover bg-gray-900 bg-center lg:bg-left">
|
||||
<NavBar isLandingPage darkBackground />
|
||||
<NavBar darkBackground />
|
||||
<main>
|
||||
<div className="pt-32 sm:pt-8 lg:pt-0 lg:pb-14 lg:overflow-hidden">
|
||||
<div className="mx-auto max-w-7xl lg:px-8 xl:px-0">
|
||||
|
|
Loading…
Reference in New Issue
Block a user