Merge branch 'main' into theoremone
This commit is contained in:
		
						commit
						e29174d622
					
				| 
						 | 
					@ -8,6 +8,7 @@ import { Bet } from '../../common/bet'
 | 
				
			||||||
import { getUser, payUser } from './utils'
 | 
					import { getUser, payUser } from './utils'
 | 
				
			||||||
import { sendMarketResolutionEmail } from './emails'
 | 
					import { sendMarketResolutionEmail } from './emails'
 | 
				
			||||||
import { getPayouts, getPayoutsMultiOutcome } from '../../common/payouts'
 | 
					import { getPayouts, getPayoutsMultiOutcome } from '../../common/payouts'
 | 
				
			||||||
 | 
					import { removeUndefinedProps } from '../../common/util/object'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const resolveMarket = functions
 | 
					export const resolveMarket = functions
 | 
				
			||||||
  .runWith({ minInstances: 1 })
 | 
					  .runWith({ minInstances: 1 })
 | 
				
			||||||
| 
						 | 
					@ -31,7 +32,7 @@ export const resolveMarket = functions
 | 
				
			||||||
      if (!contractSnap.exists)
 | 
					      if (!contractSnap.exists)
 | 
				
			||||||
        return { status: 'error', message: 'Invalid contract' }
 | 
					        return { status: 'error', message: 'Invalid contract' }
 | 
				
			||||||
      const contract = contractSnap.data() as Contract
 | 
					      const contract = contractSnap.data() as Contract
 | 
				
			||||||
      const { creatorId, outcomeType } = contract
 | 
					      const { creatorId, outcomeType, closeTime } = contract
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (outcomeType === 'BINARY') {
 | 
					      if (outcomeType === 'BINARY') {
 | 
				
			||||||
        if (!['YES', 'NO', 'MKT', 'CANCEL'].includes(outcome))
 | 
					        if (!['YES', 'NO', 'MKT', 'CANCEL'].includes(outcome))
 | 
				
			||||||
| 
						 | 
					@ -68,15 +69,21 @@ export const resolveMarket = functions
 | 
				
			||||||
      const resolutionProbability =
 | 
					      const resolutionProbability =
 | 
				
			||||||
        probabilityInt !== undefined ? probabilityInt / 100 : undefined
 | 
					        probabilityInt !== undefined ? probabilityInt / 100 : undefined
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      await contractDoc.update({
 | 
					      const resolutionTime = Date.now()
 | 
				
			||||||
        isResolved: true,
 | 
					      const newCloseTime = closeTime
 | 
				
			||||||
        resolution: outcome,
 | 
					        ? Math.min(closeTime, resolutionTime)
 | 
				
			||||||
        resolutionTime: Date.now(),
 | 
					        : closeTime
 | 
				
			||||||
        ...(resolutionProbability === undefined
 | 
					
 | 
				
			||||||
          ? {}
 | 
					      await contractDoc.update(
 | 
				
			||||||
          : { resolutionProbability }),
 | 
					        removeUndefinedProps({
 | 
				
			||||||
        ...(resolutions === undefined ? {} : { resolutions }),
 | 
					          isResolved: true,
 | 
				
			||||||
      })
 | 
					          resolution: outcome,
 | 
				
			||||||
 | 
					          resolutionTime,
 | 
				
			||||||
 | 
					          closeTime: newCloseTime,
 | 
				
			||||||
 | 
					          resolutionProbability,
 | 
				
			||||||
 | 
					          resolutions,
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      console.log('contract ', contractId, 'resolved to:', outcome)
 | 
					      console.log('contract ', contractId, 'resolved to:', outcome)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -157,8 +157,8 @@ export function BetsList(props: { user: User }) {
 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
          <option value="value">By value</option>
 | 
					          <option value="value">By value</option>
 | 
				
			||||||
          <option value="profit">By profit</option>
 | 
					          <option value="profit">By profit</option>
 | 
				
			||||||
          <option value="newest">Newest</option>
 | 
					          <option value="newest">Most recent</option>
 | 
				
			||||||
          <option value="settled">Settled</option>
 | 
					          <option value="settled">Resolved</option>
 | 
				
			||||||
        </select>
 | 
					        </select>
 | 
				
			||||||
      </Col>
 | 
					      </Col>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -358,22 +358,26 @@ export function MyBetsSummary(props: {
 | 
				
			||||||
                  {formatMoney(expectation)}
 | 
					                  {formatMoney(expectation)}
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
              </Col> */}
 | 
					              </Col> */}
 | 
				
			||||||
              <Col>
 | 
					              {isBinary && (
 | 
				
			||||||
                <div className="whitespace-nowrap text-sm text-gray-500">
 | 
					                <>
 | 
				
			||||||
                  Payout if <YesLabel />
 | 
					                  <Col>
 | 
				
			||||||
                </div>
 | 
					                    <div className="whitespace-nowrap text-sm text-gray-500">
 | 
				
			||||||
                <div className="whitespace-nowrap">
 | 
					                      Payout if <YesLabel />
 | 
				
			||||||
                  {formatMoney(yesWinnings)}
 | 
					                    </div>
 | 
				
			||||||
                </div>
 | 
					                    <div className="whitespace-nowrap">
 | 
				
			||||||
              </Col>
 | 
					                      {formatMoney(yesWinnings)}
 | 
				
			||||||
              <Col>
 | 
					                    </div>
 | 
				
			||||||
                <div className="whitespace-nowrap text-sm text-gray-500">
 | 
					                  </Col>
 | 
				
			||||||
                  Payout if <NoLabel />
 | 
					                  <Col>
 | 
				
			||||||
                </div>
 | 
					                    <div className="whitespace-nowrap text-sm text-gray-500">
 | 
				
			||||||
                <div className="whitespace-nowrap">
 | 
					                      Payout if <NoLabel />
 | 
				
			||||||
                  {formatMoney(noWinnings)}
 | 
					                    </div>
 | 
				
			||||||
                </div>
 | 
					                    <div className="whitespace-nowrap">
 | 
				
			||||||
              </Col>
 | 
					                      {formatMoney(noWinnings)}
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                  </Col>
 | 
				
			||||||
 | 
					                </>
 | 
				
			||||||
 | 
					              )}
 | 
				
			||||||
              <Col>
 | 
					              <Col>
 | 
				
			||||||
                <div className="whitespace-nowrap text-sm text-gray-500">
 | 
					                <div className="whitespace-nowrap text-sm text-gray-500">
 | 
				
			||||||
                  {isBinary ? (
 | 
					                  {isBinary ? (
 | 
				
			||||||
| 
						 | 
					@ -418,9 +422,10 @@ export function ContractBetsTable(props: {
 | 
				
			||||||
        <thead>
 | 
					        <thead>
 | 
				
			||||||
          <tr className="p-2">
 | 
					          <tr className="p-2">
 | 
				
			||||||
            <th></th>
 | 
					            <th></th>
 | 
				
			||||||
            <th>{isResolved ? <>Payout</> : <>Sale price</>}</th>
 | 
					 | 
				
			||||||
            <th>Outcome</th>
 | 
					            <th>Outcome</th>
 | 
				
			||||||
            <th>Amount</th>
 | 
					            <th>Amount</th>
 | 
				
			||||||
 | 
					            <th>{isResolved ? <>Payout</> : <>Sale price</>}</th>
 | 
				
			||||||
 | 
					            {!isResolved && <th>Payout if chosen</th>}
 | 
				
			||||||
            <th>Probability</th>
 | 
					            <th>Probability</th>
 | 
				
			||||||
            <th>Shares</th>
 | 
					            <th>Shares</th>
 | 
				
			||||||
            <th>Date</th>
 | 
					            <th>Date</th>
 | 
				
			||||||
| 
						 | 
					@ -471,6 +476,11 @@ function BetRow(props: { bet: Bet; contract: Contract; saleBet?: Bet }) {
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const payoutIfChosenDisplay =
 | 
				
			||||||
 | 
					    bet.outcome === '0' && bet.isAnte
 | 
				
			||||||
 | 
					      ? 'N/A'
 | 
				
			||||||
 | 
					      : formatMoney(calculatePayout(contract, bet, bet.outcome))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <tr>
 | 
					    <tr>
 | 
				
			||||||
      <td className="text-neutral">
 | 
					      <td className="text-neutral">
 | 
				
			||||||
| 
						 | 
					@ -478,11 +488,12 @@ function BetRow(props: { bet: Bet; contract: Contract; saleBet?: Bet }) {
 | 
				
			||||||
          <SellButton contract={contract} bet={bet} />
 | 
					          <SellButton contract={contract} bet={bet} />
 | 
				
			||||||
        )}
 | 
					        )}
 | 
				
			||||||
      </td>
 | 
					      </td>
 | 
				
			||||||
      <td>{saleDisplay}</td>
 | 
					 | 
				
			||||||
      <td>
 | 
					      <td>
 | 
				
			||||||
        <OutcomeLabel outcome={outcome} />
 | 
					        <OutcomeLabel outcome={outcome} />
 | 
				
			||||||
      </td>
 | 
					      </td>
 | 
				
			||||||
      <td>{formatMoney(amount)}</td>
 | 
					      <td>{formatMoney(amount)}</td>
 | 
				
			||||||
 | 
					      <td>{saleDisplay}</td>
 | 
				
			||||||
 | 
					      {!isResolved && <td>{payoutIfChosenDisplay}</td>}
 | 
				
			||||||
      <td>
 | 
					      <td>
 | 
				
			||||||
        {formatPercent(probBefore)} → {formatPercent(probAfter)}
 | 
					        {formatPercent(probBefore)} → {formatPercent(probAfter)}
 | 
				
			||||||
      </td>
 | 
					      </td>
 | 
				
			||||||
| 
						 | 
					@ -499,6 +510,7 @@ function SellButton(props: { contract: Contract; bet: Bet }) {
 | 
				
			||||||
  }, [])
 | 
					  }, [])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const { contract, bet } = props
 | 
					  const { contract, bet } = props
 | 
				
			||||||
 | 
					  const isBinary = contract.outcomeType === 'BINARY'
 | 
				
			||||||
  const [isSubmitting, setIsSubmitting] = useState(false)
 | 
					  const [isSubmitting, setIsSubmitting] = useState(false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const initialProb = getOutcomeProbability(
 | 
					  const initialProb = getOutcomeProbability(
 | 
				
			||||||
| 
						 | 
					@ -537,8 +549,9 @@ function SellButton(props: { contract: Contract; bet: Bet }) {
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <div className="mt-2 mb-1 text-sm text-gray-500">
 | 
					      <div className="mt-2 mb-1 text-sm text-gray-500">
 | 
				
			||||||
        Implied probability: {formatPercent(initialProb)} →{' '}
 | 
					        ({isBinary ? 'Updated' : <OutcomeLabel outcome={bet.outcome} />}{' '}
 | 
				
			||||||
        {formatPercent(outcomeProb)}
 | 
					        probability: {formatPercent(initialProb)} → {formatPercent(outcomeProb)}
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </ConfirmationButton>
 | 
					    </ConfirmationButton>
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -790,3 +790,27 @@ export function ContractFeed(props: {
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function ContractSummaryFeed(props: {
 | 
				
			||||||
 | 
					  contract: Contract
 | 
				
			||||||
 | 
					  betRowClassName?: string
 | 
				
			||||||
 | 
					}) {
 | 
				
			||||||
 | 
					  const { contract, betRowClassName } = props
 | 
				
			||||||
 | 
					  const { outcomeType } = contract
 | 
				
			||||||
 | 
					  const isBinary = outcomeType === 'BINARY'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <div className="flow-root pr-2 md:pr-0">
 | 
				
			||||||
 | 
					      <div className={clsx(tradingAllowed(contract) ? '' : '-mb-8')}>
 | 
				
			||||||
 | 
					        <div className="relative pb-8">
 | 
				
			||||||
 | 
					          <div className="relative flex items-start space-x-3">
 | 
				
			||||||
 | 
					            <FeedQuestion contract={contract} />
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      {isBinary && tradingAllowed(contract) && (
 | 
				
			||||||
 | 
					        <BetRow contract={contract} className={clsx('mb-2', betRowClassName)} />
 | 
				
			||||||
 | 
					      )}
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -205,9 +205,11 @@ export function SearchableGrid(props: {
 | 
				
			||||||
}) {
 | 
					}) {
 | 
				
			||||||
  const { contracts, query, setQuery, sort, setSort, byOneCreator } = props
 | 
					  const { contracts, query, setQuery, sort, setSort, byOneCreator } = props
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const queryWords = query.toLowerCase().split(' ')
 | 
				
			||||||
  function check(corpus: String) {
 | 
					  function check(corpus: String) {
 | 
				
			||||||
    return corpus.toLowerCase().includes(query.toLowerCase())
 | 
					    return queryWords.every((word) => corpus.toLowerCase().includes(word))
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let matches = contracts.filter(
 | 
					  let matches = contracts.filter(
 | 
				
			||||||
    (c) =>
 | 
					    (c) =>
 | 
				
			||||||
      check(c.question) ||
 | 
					      check(c.question) ||
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,7 +32,7 @@ function FollowFoldButton(props: {
 | 
				
			||||||
      className={clsx(
 | 
					      className={clsx(
 | 
				
			||||||
        'rounded-full border-2 px-4 py-1 shadow-md',
 | 
					        'rounded-full border-2 px-4 py-1 shadow-md',
 | 
				
			||||||
        'cursor-pointer',
 | 
					        'cursor-pointer',
 | 
				
			||||||
        followed ? 'bg-gray-300 border-gray-300' : 'bg-white'
 | 
					        followed ? 'border-gray-300 bg-gray-300' : 'bg-white'
 | 
				
			||||||
      )}
 | 
					      )}
 | 
				
			||||||
      onClick={onClick}
 | 
					      onClick={onClick}
 | 
				
			||||||
    >
 | 
					    >
 | 
				
			||||||
| 
						 | 
					@ -101,7 +101,7 @@ export const FastFoldFollowing = (props: {
 | 
				
			||||||
        ]}
 | 
					        ]}
 | 
				
			||||||
      />
 | 
					      />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <Spacer h={10} />
 | 
					      <Spacer h={5} />
 | 
				
			||||||
    </>
 | 
					    </>
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -54,6 +54,10 @@ function getNavigationOptions(
 | 
				
			||||||
      name: 'Your trades',
 | 
					      name: 'Your trades',
 | 
				
			||||||
      href: '/trades',
 | 
					      href: '/trades',
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      name: 'Add funds',
 | 
				
			||||||
 | 
					      href: '/add-funds',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      name: 'Leaderboards',
 | 
					      name: 'Leaderboards',
 | 
				
			||||||
      href: '/leaderboards',
 | 
					      href: '/leaderboards',
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ import {
 | 
				
			||||||
  listenForActiveContracts,
 | 
					  listenForActiveContracts,
 | 
				
			||||||
  listenForContracts,
 | 
					  listenForContracts,
 | 
				
			||||||
  listenForHotContracts,
 | 
					  listenForHotContracts,
 | 
				
			||||||
 | 
					  listenForInactiveContracts,
 | 
				
			||||||
} from '../lib/firebase/contracts'
 | 
					} from '../lib/firebase/contracts'
 | 
				
			||||||
import { listenForTaggedContracts } from '../lib/firebase/folds'
 | 
					import { listenForTaggedContracts } from '../lib/firebase/folds'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,6 +29,16 @@ export const useActiveContracts = () => {
 | 
				
			||||||
  return contracts
 | 
					  return contracts
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const useInactiveContracts = () => {
 | 
				
			||||||
 | 
					  const [contracts, setContracts] = useState<Contract[] | undefined>()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  useEffect(() => {
 | 
				
			||||||
 | 
					    return listenForInactiveContracts(setContracts)
 | 
				
			||||||
 | 
					  }, [])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return contracts
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const useUpdatedContracts = (initialContracts: Contract[]) => {
 | 
					export const useUpdatedContracts = (initialContracts: Contract[]) => {
 | 
				
			||||||
  const [contracts, setContracts] = useState(initialContracts)
 | 
					  const [contracts, setContracts] = useState(initialContracts)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
import _ from 'lodash'
 | 
					import _ from 'lodash'
 | 
				
			||||||
import { useRef } from 'react'
 | 
					import { useMemo, useRef } from 'react'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Fold } from '../../common/fold'
 | 
					import { Fold } from '../../common/fold'
 | 
				
			||||||
import { User } from '../../common/user'
 | 
					import { User } from '../../common/user'
 | 
				
			||||||
| 
						 | 
					@ -9,7 +9,7 @@ import { Comment, getRecentComments } from '../lib/firebase/comments'
 | 
				
			||||||
import { Contract, getActiveContracts } from '../lib/firebase/contracts'
 | 
					import { Contract, getActiveContracts } from '../lib/firebase/contracts'
 | 
				
			||||||
import { listAllFolds } from '../lib/firebase/folds'
 | 
					import { listAllFolds } from '../lib/firebase/folds'
 | 
				
			||||||
import { findActiveContracts } from '../pages/activity'
 | 
					import { findActiveContracts } from '../pages/activity'
 | 
				
			||||||
import { useActiveContracts } from './use-contracts'
 | 
					import { useInactiveContracts } from './use-contracts'
 | 
				
			||||||
import { useFollowedFolds } from './use-fold'
 | 
					import { useFollowedFolds } from './use-fold'
 | 
				
			||||||
import { useUserBetContracts } from './use-user-bets'
 | 
					import { useUserBetContracts } from './use-user-bets'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,24 +28,15 @@ export const getAllContractInfo = async () => {
 | 
				
			||||||
  return { contracts, recentBets, recentComments, folds }
 | 
					  return { contracts, recentBets, recentComments, folds }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const useFindActiveContracts = (
 | 
					export const useFilterYourContracts = (
 | 
				
			||||||
  props: {
 | 
					  user: User | undefined | null,
 | 
				
			||||||
    contracts: Contract[]
 | 
					  folds: Fold[],
 | 
				
			||||||
    folds: Fold[]
 | 
					  contracts: Contract[]
 | 
				
			||||||
    recentBets: Bet[]
 | 
					 | 
				
			||||||
    recentComments: Comment[]
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  user: User | undefined | null
 | 
					 | 
				
			||||||
) => {
 | 
					) => {
 | 
				
			||||||
  const { recentBets, recentComments } = props
 | 
					 | 
				
			||||||
  const contracts = useActiveContracts() ?? props.contracts
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const followedFoldIds = useFollowedFolds(user)
 | 
					  const followedFoldIds = useFollowedFolds(user)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const followedFolds = filterDefined(
 | 
					  const followedFolds = filterDefined(
 | 
				
			||||||
    (followedFoldIds ?? []).map((id) =>
 | 
					    (followedFoldIds ?? []).map((id) => folds.find((fold) => fold.id === id))
 | 
				
			||||||
      props.folds.find((fold) => fold.id === id)
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Save the initial followed fold slugs.
 | 
					  // Save the initial followed fold slugs.
 | 
				
			||||||
| 
						 | 
					@ -64,20 +55,33 @@ export const useFindActiveContracts = (
 | 
				
			||||||
    : undefined
 | 
					    : undefined
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Show no contracts before your info is loaded.
 | 
					  // Show no contracts before your info is loaded.
 | 
				
			||||||
  let feedContracts: Contract[] = []
 | 
					  let yourContracts: Contract[] = []
 | 
				
			||||||
  if (yourBetContracts && followedFoldIds) {
 | 
					  if (yourBetContracts && followedFoldIds) {
 | 
				
			||||||
    // Show all contracts if no folds are followed.
 | 
					    // Show all contracts if no folds are followed.
 | 
				
			||||||
    if (followedFoldIds.length === 0) feedContracts = contracts
 | 
					    if (followedFoldIds.length === 0) yourContracts = contracts
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
      feedContracts = contracts.filter(
 | 
					      yourContracts = contracts.filter(
 | 
				
			||||||
        (contract) =>
 | 
					        (contract) =>
 | 
				
			||||||
          contract.lowercaseTags.some((tag) => tagSet.has(tag)) ||
 | 
					          contract.lowercaseTags.some((tag) => tagSet.has(tag)) ||
 | 
				
			||||||
          yourBetContracts.has(contract.id)
 | 
					          yourBetContracts.has(contract.id)
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return {
 | 
				
			||||||
 | 
					    yourContracts,
 | 
				
			||||||
 | 
					    initialFollowedFoldSlugs,
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const useFindActiveContracts = (props: {
 | 
				
			||||||
 | 
					  contracts: Contract[]
 | 
				
			||||||
 | 
					  recentBets: Bet[]
 | 
				
			||||||
 | 
					  recentComments: Comment[]
 | 
				
			||||||
 | 
					}) => {
 | 
				
			||||||
 | 
					  const { contracts, recentBets, recentComments } = props
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const activeContracts = findActiveContracts(
 | 
					  const activeContracts = findActiveContracts(
 | 
				
			||||||
    feedContracts,
 | 
					    contracts,
 | 
				
			||||||
    recentComments,
 | 
					    recentComments,
 | 
				
			||||||
    recentBets
 | 
					    recentBets
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
| 
						 | 
					@ -101,6 +105,24 @@ export const useFindActiveContracts = (
 | 
				
			||||||
    activeContracts,
 | 
					    activeContracts,
 | 
				
			||||||
    activeBets,
 | 
					    activeBets,
 | 
				
			||||||
    activeComments,
 | 
					    activeComments,
 | 
				
			||||||
    initialFollowedFoldSlugs,
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const useExploreContracts = (maxContracts = 75) => {
 | 
				
			||||||
 | 
					  const inactiveContracts = useInactiveContracts()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const contractsDict = _.fromPairs(
 | 
				
			||||||
 | 
					    (inactiveContracts ?? []).map((c) => [c.id, c])
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Preserve random ordering once inactiveContracts loaded.
 | 
				
			||||||
 | 
					  const exploreContractIds = useMemo(
 | 
				
			||||||
 | 
					    () => _.shuffle(Object.keys(contractsDict)),
 | 
				
			||||||
 | 
					    // eslint-disable-next-line react-hooks/exhaustive-deps
 | 
				
			||||||
 | 
					    [!!inactiveContracts]
 | 
				
			||||||
 | 
					  ).slice(0, maxContracts)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!inactiveContracts) return undefined
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return filterDefined(exploreContractIds.map((id) => contractsDict[id]))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -115,7 +115,7 @@ export function listenForContracts(
 | 
				
			||||||
  return listenForValues<Contract>(q, setContracts)
 | 
					  return listenForValues<Contract>(q, setContracts)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const activeContracts = query(
 | 
					const activeContractsQuery = query(
 | 
				
			||||||
  contractCollection,
 | 
					  contractCollection,
 | 
				
			||||||
  where('isResolved', '==', false),
 | 
					  where('isResolved', '==', false),
 | 
				
			||||||
  where('visibility', '==', 'public'),
 | 
					  where('visibility', '==', 'public'),
 | 
				
			||||||
| 
						 | 
					@ -123,13 +123,31 @@ const activeContracts = query(
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function getActiveContracts() {
 | 
					export function getActiveContracts() {
 | 
				
			||||||
  return getValues<Contract>(activeContracts)
 | 
					  return getValues<Contract>(activeContractsQuery)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function listenForActiveContracts(
 | 
					export function listenForActiveContracts(
 | 
				
			||||||
  setContracts: (contracts: Contract[]) => void
 | 
					  setContracts: (contracts: Contract[]) => void
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
  return listenForValues<Contract>(activeContracts, setContracts)
 | 
					  return listenForValues<Contract>(activeContractsQuery, setContracts)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const inactiveContractsQuery = query(
 | 
				
			||||||
 | 
					  contractCollection,
 | 
				
			||||||
 | 
					  where('isResolved', '==', false),
 | 
				
			||||||
 | 
					  where('closeTime', '>', Date.now()),
 | 
				
			||||||
 | 
					  where('visibility', '==', 'public'),
 | 
				
			||||||
 | 
					  where('volume24Hours', '==', 0)
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function getInactiveContracts() {
 | 
				
			||||||
 | 
					  return getValues<Contract>(inactiveContractsQuery)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function listenForInactiveContracts(
 | 
				
			||||||
 | 
					  setContracts: (contracts: Contract[]) => void
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					  return listenForValues<Contract>(inactiveContractsQuery, setContracts)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function listenForContract(
 | 
					export function listenForContract(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -188,12 +188,8 @@ function BetsSection(props: {
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <div>
 | 
					    <div>
 | 
				
			||||||
      <Title className="px-2" text="Your trades" />
 | 
					      <Title className="px-2" text="Your trades" />
 | 
				
			||||||
      {isBinary && (
 | 
					      <MyBetsSummary className="px-2" contract={contract} bets={userBets} />
 | 
				
			||||||
        <>
 | 
					      <Spacer h={6} />
 | 
				
			||||||
          <MyBetsSummary className="px-2" contract={contract} bets={userBets} />
 | 
					 | 
				
			||||||
          <Spacer h={6} />
 | 
					 | 
				
			||||||
        </>
 | 
					 | 
				
			||||||
      )}
 | 
					 | 
				
			||||||
      <ContractBetsTable contract={contract} bets={userBets} />
 | 
					      <ContractBetsTable contract={contract} bets={userBets} />
 | 
				
			||||||
      <Spacer h={12} />
 | 
					      <Spacer h={12} />
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -139,6 +139,15 @@ function Contents() {
 | 
				
			||||||
        bettors that are correct more often will gain influence, leading to
 | 
					        bettors that are correct more often will gain influence, leading to
 | 
				
			||||||
        better-calibrated forecasts over time.
 | 
					        better-calibrated forecasts over time.
 | 
				
			||||||
      </p>
 | 
					      </p>
 | 
				
			||||||
 | 
					      <p>
 | 
				
			||||||
 | 
					        Since our launch, we've seen hundreds of users trade each day, on over a
 | 
				
			||||||
 | 
					        thousand different markets! You can track the popularity of our platform
 | 
				
			||||||
 | 
					        at{' '}
 | 
				
			||||||
 | 
					        <a href="http://manifold.markets/analytics">
 | 
				
			||||||
 | 
					          http://manifold.markets/analytics
 | 
				
			||||||
 | 
					        </a>
 | 
				
			||||||
 | 
					        .
 | 
				
			||||||
 | 
					      </p>
 | 
				
			||||||
      <h3 id="how-are-markets-resolved-">How are markets resolved?</h3>
 | 
					      <h3 id="how-are-markets-resolved-">How are markets resolved?</h3>
 | 
				
			||||||
      <p>
 | 
					      <p>
 | 
				
			||||||
        The creator of the prediction market decides the outcome and earns{' '}
 | 
					        The creator of the prediction market decides the outcome and earns{' '}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
import _ from 'lodash'
 | 
					import _ from 'lodash'
 | 
				
			||||||
import { ContractFeed } from '../components/contract-feed'
 | 
					import { ContractFeed, ContractSummaryFeed } from '../components/contract-feed'
 | 
				
			||||||
import { Page } from '../components/page'
 | 
					import { Page } from '../components/page'
 | 
				
			||||||
import { Contract } from '../lib/firebase/contracts'
 | 
					import { Contract } from '../lib/firebase/contracts'
 | 
				
			||||||
import { Comment } from '../lib/firebase/comments'
 | 
					import { Comment } from '../lib/firebase/comments'
 | 
				
			||||||
| 
						 | 
					@ -99,6 +99,24 @@ export function ActivityFeed(props: {
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function SummaryActivityFeed(props: { contracts: Contract[] }) {
 | 
				
			||||||
 | 
					  const { contracts } = props
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <Col className="items-center">
 | 
				
			||||||
 | 
					      <Col className="w-full max-w-3xl">
 | 
				
			||||||
 | 
					        <Col className="w-full divide-y divide-gray-300 self-center bg-white">
 | 
				
			||||||
 | 
					          {contracts.map((contract) => (
 | 
				
			||||||
 | 
					            <div key={contract.id} className="py-6 px-2 sm:px-4">
 | 
				
			||||||
 | 
					              <ContractSummaryFeed contract={contract} />
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          ))}
 | 
				
			||||||
 | 
					        </Col>
 | 
				
			||||||
 | 
					      </Col>
 | 
				
			||||||
 | 
					    </Col>
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function ActivityPage() {
 | 
					export default function ActivityPage() {
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <Page>
 | 
					    <Page>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,11 +19,11 @@ export default function AddFundsPage() {
 | 
				
			||||||
      <SEO title="Add funds" description="Add funds" url="/add-funds" />
 | 
					      <SEO title="Add funds" description="Add funds" url="/add-funds" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <Col className="items-center">
 | 
					      <Col className="items-center">
 | 
				
			||||||
        <Col>
 | 
					        <Col className="h-full rounded bg-white p-4 py-8 sm:p-8 sm:shadow-md">
 | 
				
			||||||
          <Title text="Get Manifold Dollars" />
 | 
					          <Title className="!mt-0" text="Get Manifold Dollars" />
 | 
				
			||||||
          <img
 | 
					          <img
 | 
				
			||||||
            className="mt-6 block"
 | 
					            className="mb-6 block -scale-x-100 self-center"
 | 
				
			||||||
            src="/praying-mantis-light.svg"
 | 
					            src="/stylized-crane-black.png"
 | 
				
			||||||
            width={200}
 | 
					            width={200}
 | 
				
			||||||
            height={200}
 | 
					            height={200}
 | 
				
			||||||
          />
 | 
					          />
 | 
				
			||||||
| 
						 | 
					@ -50,7 +50,7 @@ export default function AddFundsPage() {
 | 
				
			||||||
          <form
 | 
					          <form
 | 
				
			||||||
            action={checkoutURL(user?.id || '', amountSelected)}
 | 
					            action={checkoutURL(user?.id || '', amountSelected)}
 | 
				
			||||||
            method="POST"
 | 
					            method="POST"
 | 
				
			||||||
            className="mt-12"
 | 
					            className="mt-8"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            <button
 | 
					            <button
 | 
				
			||||||
              type="submit"
 | 
					              type="submit"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,6 +26,7 @@ export type LiteMarket = {
 | 
				
			||||||
  volume24Hours: number
 | 
					  volume24Hours: number
 | 
				
			||||||
  isResolved: boolean
 | 
					  isResolved: boolean
 | 
				
			||||||
  resolution?: string
 | 
					  resolution?: string
 | 
				
			||||||
 | 
					  resolutionTime?: number
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type FullMarket = LiteMarket & {
 | 
					export type FullMarket = LiteMarket & {
 | 
				
			||||||
| 
						 | 
					@ -54,6 +55,7 @@ export function toLiteMarket({
 | 
				
			||||||
  volume24Hours,
 | 
					  volume24Hours,
 | 
				
			||||||
  isResolved,
 | 
					  isResolved,
 | 
				
			||||||
  resolution,
 | 
					  resolution,
 | 
				
			||||||
 | 
					  resolutionTime,
 | 
				
			||||||
}: Contract): LiteMarket {
 | 
					}: Contract): LiteMarket {
 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
    id,
 | 
					    id,
 | 
				
			||||||
| 
						 | 
					@ -61,7 +63,10 @@ export function toLiteMarket({
 | 
				
			||||||
    creatorName,
 | 
					    creatorName,
 | 
				
			||||||
    createdTime,
 | 
					    createdTime,
 | 
				
			||||||
    creatorAvatarUrl,
 | 
					    creatorAvatarUrl,
 | 
				
			||||||
    closeTime,
 | 
					    closeTime:
 | 
				
			||||||
 | 
					      resolutionTime && closeTime
 | 
				
			||||||
 | 
					        ? Math.min(resolutionTime, closeTime)
 | 
				
			||||||
 | 
					        : closeTime,
 | 
				
			||||||
    question,
 | 
					    question,
 | 
				
			||||||
    description,
 | 
					    description,
 | 
				
			||||||
    tags,
 | 
					    tags,
 | 
				
			||||||
| 
						 | 
					@ -72,5 +77,6 @@ export function toLiteMarket({
 | 
				
			||||||
    volume24Hours,
 | 
					    volume24Hours,
 | 
				
			||||||
    isResolved,
 | 
					    isResolved,
 | 
				
			||||||
    resolution,
 | 
					    resolution,
 | 
				
			||||||
 | 
					    resolutionTime,
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,6 +41,7 @@ import { SEO } from '../../../components/SEO'
 | 
				
			||||||
import { useTaggedContracts } from '../../../hooks/use-contracts'
 | 
					import { useTaggedContracts } from '../../../hooks/use-contracts'
 | 
				
			||||||
import { Linkify } from '../../../components/linkify'
 | 
					import { Linkify } from '../../../components/linkify'
 | 
				
			||||||
import { usePropz } from '../../../hooks/use-propz'
 | 
					import { usePropz } from '../../../hooks/use-propz'
 | 
				
			||||||
 | 
					import { filterDefined } from '../../../../common/util/array'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export async function getStaticPropz(props: { params: { slugs: string[] } }) {
 | 
					export async function getStaticPropz(props: { params: { slugs: string[] } }) {
 | 
				
			||||||
  const { slugs } = props.params
 | 
					  const { slugs } = props.params
 | 
				
			||||||
| 
						 | 
					@ -182,9 +183,11 @@ export default function FoldPage(props: {
 | 
				
			||||||
    taggedContracts.map((contract) => [contract.id, contract])
 | 
					    taggedContracts.map((contract) => [contract.id, contract])
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const contracts = props.contracts.map((contract) => contractsMap[contract.id])
 | 
					  const contracts = filterDefined(
 | 
				
			||||||
  const activeContracts = props.activeContracts.map(
 | 
					    props.contracts.map((contract) => contractsMap[contract.id])
 | 
				
			||||||
    (contract) => contractsMap[contract.id]
 | 
					  )
 | 
				
			||||||
 | 
					  const activeContracts = filterDefined(
 | 
				
			||||||
 | 
					    props.activeContracts.map((contract) => contractsMap[contract.id])
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (fold === null || !foldSubpages.includes(page) || slugs[2]) {
 | 
					  if (fold === null || !foldSubpages.includes(page) || slugs[2]) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,12 @@
 | 
				
			||||||
import React from 'react'
 | 
					import React, { useState } from 'react'
 | 
				
			||||||
import Router from 'next/router'
 | 
					import Router from 'next/router'
 | 
				
			||||||
 | 
					import { SparklesIcon, GlobeAltIcon } from '@heroicons/react/solid'
 | 
				
			||||||
 | 
					import clsx from 'clsx'
 | 
				
			||||||
 | 
					import _ from 'lodash'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Contract } from '../lib/firebase/contracts'
 | 
					import { Contract } from '../lib/firebase/contracts'
 | 
				
			||||||
import { Page } from '../components/page'
 | 
					import { Page } from '../components/page'
 | 
				
			||||||
import { ActivityFeed } from './activity'
 | 
					import { ActivityFeed, SummaryActivityFeed } from './activity'
 | 
				
			||||||
import { Comment } from '../lib/firebase/comments'
 | 
					import { Comment } from '../lib/firebase/comments'
 | 
				
			||||||
import { Bet } from '../lib/firebase/bets'
 | 
					import { Bet } from '../lib/firebase/bets'
 | 
				
			||||||
import FeedCreate from '../components/feed-create'
 | 
					import FeedCreate from '../components/feed-create'
 | 
				
			||||||
| 
						 | 
					@ -13,14 +16,16 @@ import { useUser } from '../hooks/use-user'
 | 
				
			||||||
import { Fold } from '../../common/fold'
 | 
					import { Fold } from '../../common/fold'
 | 
				
			||||||
import { LoadingIndicator } from '../components/loading-indicator'
 | 
					import { LoadingIndicator } from '../components/loading-indicator'
 | 
				
			||||||
import { Row } from '../components/layout/row'
 | 
					import { Row } from '../components/layout/row'
 | 
				
			||||||
import { SparklesIcon } from '@heroicons/react/solid'
 | 
					 | 
				
			||||||
import { FastFoldFollowing } from '../components/fast-fold-following'
 | 
					import { FastFoldFollowing } from '../components/fast-fold-following'
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  getAllContractInfo,
 | 
					  getAllContractInfo,
 | 
				
			||||||
 | 
					  useExploreContracts,
 | 
				
			||||||
 | 
					  useFilterYourContracts,
 | 
				
			||||||
  useFindActiveContracts,
 | 
					  useFindActiveContracts,
 | 
				
			||||||
} from '../hooks/use-active-contracts'
 | 
					} from '../hooks/use-find-active-contracts'
 | 
				
			||||||
import { useGetRecentBets } from '../hooks/use-bets'
 | 
					import { useGetRecentBets } from '../hooks/use-bets'
 | 
				
			||||||
import { usePropz } from '../hooks/use-propz'
 | 
					import { usePropz } from '../hooks/use-propz'
 | 
				
			||||||
 | 
					import { useActiveContracts } from '../hooks/use-contracts'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export async function getStaticPropz() {
 | 
					export async function getStaticPropz() {
 | 
				
			||||||
  const contractInfo = await getAllContractInfo()
 | 
					  const contractInfo = await getAllContractInfo()
 | 
				
			||||||
| 
						 | 
					@ -42,21 +47,28 @@ const Home = (props: {
 | 
				
			||||||
    folds: [],
 | 
					    folds: [],
 | 
				
			||||||
    recentComments: [],
 | 
					    recentComments: [],
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  const { contracts, folds, recentComments } = props
 | 
					  const { folds, recentComments } = props
 | 
				
			||||||
  const user = useUser()
 | 
					  const user = useUser()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const recentBets = useGetRecentBets()
 | 
					  const contracts = useActiveContracts() ?? props.contracts
 | 
				
			||||||
 | 
					  const { yourContracts, initialFollowedFoldSlugs } = useFilterYourContracts(
 | 
				
			||||||
  const {
 | 
					    user,
 | 
				
			||||||
    activeContracts,
 | 
					    folds,
 | 
				
			||||||
    activeBets,
 | 
					    contracts
 | 
				
			||||||
    activeComments,
 | 
					 | 
				
			||||||
    initialFollowedFoldSlugs,
 | 
					 | 
				
			||||||
  } = useFindActiveContracts(
 | 
					 | 
				
			||||||
    { contracts, folds, recentBets: recentBets ?? [], recentComments },
 | 
					 | 
				
			||||||
    user
 | 
					 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const recentBets = useGetRecentBets()
 | 
				
			||||||
 | 
					  const { activeContracts, activeBets, activeComments } =
 | 
				
			||||||
 | 
					    useFindActiveContracts({
 | 
				
			||||||
 | 
					      contracts: yourContracts,
 | 
				
			||||||
 | 
					      recentBets: recentBets ?? [],
 | 
				
			||||||
 | 
					      recentComments,
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const exploreContracts = useExploreContracts()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const [feedMode, setFeedMode] = useState<'activity' | 'explore'>('activity')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (user === null) {
 | 
					  if (user === null) {
 | 
				
			||||||
    Router.replace('/')
 | 
					    Router.replace('/')
 | 
				
			||||||
    return <></>
 | 
					    return <></>
 | 
				
			||||||
| 
						 | 
					@ -77,22 +89,52 @@ const Home = (props: {
 | 
				
			||||||
              />
 | 
					              />
 | 
				
			||||||
            )}
 | 
					            )}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          <Spacer h={5} />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          <Col className="mx-3 mb-3 gap-2 text-sm text-gray-800 sm:flex-row">
 | 
					          <Col className="mx-3 mb-3 gap-2 text-sm text-gray-800 sm:flex-row">
 | 
				
			||||||
            <Row className="gap-2">
 | 
					            <Row className="gap-2">
 | 
				
			||||||
              <SparklesIcon className="inline h-5 w-5" aria-hidden="true" />
 | 
					              <div className="tabs">
 | 
				
			||||||
              <span className="whitespace-nowrap">Recent activity</span>
 | 
					                <div
 | 
				
			||||||
 | 
					                  className={clsx(
 | 
				
			||||||
 | 
					                    'tab gap-2',
 | 
				
			||||||
 | 
					                    feedMode === 'activity' && 'tab-active'
 | 
				
			||||||
 | 
					                  )}
 | 
				
			||||||
 | 
					                  onClick={() => setFeedMode('activity')}
 | 
				
			||||||
 | 
					                >
 | 
				
			||||||
 | 
					                  <SparklesIcon className="inline h-5 w-5" aria-hidden="true" />
 | 
				
			||||||
 | 
					                  Recent activity
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                <div
 | 
				
			||||||
 | 
					                  className={clsx(
 | 
				
			||||||
 | 
					                    'tab gap-2',
 | 
				
			||||||
 | 
					                    feedMode === 'explore' && 'tab-active'
 | 
				
			||||||
 | 
					                  )}
 | 
				
			||||||
 | 
					                  onClick={() => setFeedMode('explore')}
 | 
				
			||||||
 | 
					                >
 | 
				
			||||||
 | 
					                  <GlobeAltIcon className="inline h-5 w-5" aria-hidden="true" />
 | 
				
			||||||
 | 
					                  Explore
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
            </Row>
 | 
					            </Row>
 | 
				
			||||||
          </Col>
 | 
					          </Col>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          {activeContracts && recentBets ? (
 | 
					          {feedMode === 'activity' &&
 | 
				
			||||||
            <ActivityFeed
 | 
					            (recentBets ? (
 | 
				
			||||||
              contracts={activeContracts}
 | 
					              <ActivityFeed
 | 
				
			||||||
              contractBets={activeBets}
 | 
					                contracts={activeContracts}
 | 
				
			||||||
              contractComments={activeComments}
 | 
					                contractBets={activeBets}
 | 
				
			||||||
            />
 | 
					                contractComments={activeComments}
 | 
				
			||||||
          ) : (
 | 
					              />
 | 
				
			||||||
            <LoadingIndicator className="mt-4" />
 | 
					            ) : (
 | 
				
			||||||
          )}
 | 
					              <LoadingIndicator className="mt-4" />
 | 
				
			||||||
 | 
					            ))}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          {feedMode === 'explore' &&
 | 
				
			||||||
 | 
					            (exploreContracts ? (
 | 
				
			||||||
 | 
					              <SummaryActivityFeed contracts={exploreContracts} />
 | 
				
			||||||
 | 
					            ) : (
 | 
				
			||||||
 | 
					              <LoadingIndicator className="mt-4" />
 | 
				
			||||||
 | 
					            ))}
 | 
				
			||||||
        </Col>
 | 
					        </Col>
 | 
				
			||||||
      </Col>
 | 
					      </Col>
 | 
				
			||||||
    </Page>
 | 
					    </Page>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								web/public/stylized-crane-black.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								web/public/stylized-crane-black.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 683 KiB  | 
		Loading…
	
		Reference in New Issue
	
	Block a user