From 8aaaf5e9e05e138d4ec8dbf436ebf594d9fa0792 Mon Sep 17 00:00:00 2001
From: ingawei <46611122+ingawei@users.noreply.github.com>
Date: Thu, 15 Sep 2022 01:46:58 -0500
Subject: [PATCH] Inga/bettingfix (#879)
* making betting action panels much more minimal, particularly for mobile
* added tiny follow button
---
web/components/button.tsx | 5 +-
web/components/contract/contract-details.tsx | 252 ++++++++++--------
.../contract/contract-info-dialog.tsx | 11 +-
web/components/contract/contract-overview.tsx | 12 +-
.../contract/extra-contract-actions-row.tsx | 57 +---
.../contract/like-market-button.tsx | 20 +-
web/components/follow-button.tsx | 67 ++++-
web/components/follow-market-button.tsx | 16 +-
web/pages/[username]/[contractSlug].tsx | 2 -
web/tailwind.config.js | 2 +
10 files changed, 262 insertions(+), 182 deletions(-)
diff --git a/web/components/button.tsx b/web/components/button.tsx
index cb39cba8..ea9a3e88 100644
--- a/web/components/button.tsx
+++ b/web/components/button.tsx
@@ -11,6 +11,7 @@ export type ColorType =
| 'gray'
| 'gradient'
| 'gray-white'
+ | 'highlight-blue'
export function Button(props: {
className?: string
@@ -56,7 +57,9 @@ export function Button(props: {
color === 'gradient' &&
'border-none bg-gradient-to-r from-indigo-500 to-blue-500 text-white hover:from-indigo-700 hover:to-blue-700',
color === 'gray-white' &&
- 'border-none bg-white text-gray-500 shadow-none hover:bg-gray-200',
+ 'text-greyscale-6 hover:bg-greyscale-2 border-none shadow-none',
+ color === 'highlight-blue' &&
+ 'text-highlight-blue border-none shadow-none',
className
)}
disabled={disabled}
diff --git a/web/components/contract/contract-details.tsx b/web/components/contract/contract-details.tsx
index e28ab41a..fad62c86 100644
--- a/web/components/contract/contract-details.tsx
+++ b/web/components/contract/contract-details.tsx
@@ -1,9 +1,4 @@
-import {
- ClockIcon,
- DatabaseIcon,
- PencilIcon,
- UserGroupIcon,
-} from '@heroicons/react/outline'
+import { ClockIcon } from '@heroicons/react/outline'
import clsx from 'clsx'
import { Editor } from '@tiptap/react'
import dayjs from 'dayjs'
@@ -16,9 +11,8 @@ import { DateTimeTooltip } from '../datetime-tooltip'
import { fromNow } from 'web/lib/util/time'
import { Avatar } from '../avatar'
import { useState } from 'react'
-import { ContractInfoDialog } from './contract-info-dialog'
import NewContractBadge from '../new-contract-badge'
-import { UserFollowButton } from '../follow-button'
+import { MiniUserFollowButton } from '../follow-button'
import { DAY_MS } from 'common/util/time'
import { useUser } from 'web/hooks/use-user'
import { exhibitExts } from 'common/util/parse'
@@ -34,6 +28,8 @@ import { UserLink } from 'web/components/user-link'
import { FeaturedContractBadge } from 'web/components/contract/featured-contract-badge'
import { Tooltip } from 'web/components/tooltip'
import { useWindowSize } from 'web/hooks/use-window-size'
+import { ExtraContractActionsRow } from './extra-contract-actions-row'
+import { PlusCircleIcon } from '@heroicons/react/solid'
export type ShowTime = 'resolve-date' | 'close-date'
@@ -104,90 +100,174 @@ export function AvatarDetails(props: {
)
}
+export function useIsMobile() {
+ const { width } = useWindowSize()
+ return (width ?? 0) < 600
+}
+
export function ContractDetails(props: {
contract: Contract
disabled?: boolean
}) {
const { contract, disabled } = props
- const {
- closeTime,
- creatorName,
- creatorUsername,
- creatorId,
- creatorAvatarUrl,
- resolutionTime,
- } = contract
- const { volumeLabel, resolvedDate } = contractMetrics(contract)
+ const { creatorName, creatorUsername, creatorId, creatorAvatarUrl } = contract
+ const { resolvedDate } = contractMetrics(contract)
const user = useUser()
const isCreator = user?.id === creatorId
+ const isMobile = useIsMobile()
+
+ return (
+
+
+
+ {!disabled && (
+
+
+
+ )}
+
+
+ {disabled ? (
+ creatorName
+ ) : (
+
+ )}
+
+
+
+ {!isMobile && (
+
+ )}
+
+
+
+
+
+
+ {/* GROUPS */}
+ {isMobile && (
+
+
+
+ )}
+
+ )
+}
+
+export function CloseOrResolveTime(props: {
+ contract: Contract
+ resolvedDate: any
+ isCreator: boolean
+}) {
+ const { contract, resolvedDate, isCreator } = props
+ const { resolutionTime, closeTime } = contract
+ console.log(closeTime, resolvedDate)
+ if (!!closeTime || !!resolvedDate) {
+ return (
+
+ {resolvedDate && resolutionTime ? (
+ <>
+
+
+ resolved
+ {resolvedDate}
+
+
+ >
+ ) : null}
+
+ {!resolvedDate && closeTime && (
+
+ {dayjs().isBefore(closeTime) && closes
}
+ {!dayjs().isBefore(closeTime) && closed
}
+
+
+ )}
+
+ )
+ } else return <>>
+}
+
+export function MarketGroups(props: {
+ contract: Contract
+ isMobile: boolean | undefined
+ disabled: boolean | undefined
+}) {
const [open, setOpen] = useState(false)
- const { width } = useWindowSize()
- const isMobile = (width ?? 0) < 600
+ const user = useUser()
+ const { contract, isMobile, disabled } = props
const groupToDisplay = getGroupLinkToDisplay(contract)
const groupInfo = groupToDisplay ? (
-
- {groupToDisplay.name}
+
+ {groupToDisplay.name}
+
) : (
-
- )
-
- return (
-
-
-
- {disabled ? (
- creatorName
- ) : (
-
+ }
-
-
+ >
+ No Group
+
+
+ )
+ return (
+ <>
+
{disabled ? (
- groupInfo
- ) : !groupToDisplay && !user ? (
-
+ { groupInfo }
) : (
{groupInfo}
- {user && groupToDisplay && (
-
+
+
)}
)}
@@ -201,45 +281,7 @@ export function ContractDetails(props: {
-
- {(!!closeTime || !!resolvedDate) && (
-
- {resolvedDate && resolutionTime ? (
- <>
-
-
- {resolvedDate}
-
- >
- ) : null}
-
- {!resolvedDate && closeTime && user && (
- <>
-
-
- >
- )}
-
- )}
- {user && (
- <>
-
-
- {volumeLabel}
-
- {!disabled && (
-
- )}
- >
- )}
-
+ >
)
}
@@ -280,12 +322,12 @@ export function ExtraMobileContractDetails(props: {
!resolvedDate &&
closeTime && (
+ Closes
- Ends
)
)}
diff --git a/web/components/contract/contract-info-dialog.tsx b/web/components/contract/contract-info-dialog.tsx
index ae586725..07958378 100644
--- a/web/components/contract/contract-info-dialog.tsx
+++ b/web/components/contract/contract-info-dialog.tsx
@@ -18,6 +18,7 @@ import { deleteField } from 'firebase/firestore'
import ShortToggle from '../widgets/short-toggle'
import { DuplicateContractButton } from '../copy-contract-button'
import { Row } from '../layout/row'
+import { Button } from '../button'
export const contractDetailsButtonClassName =
'group flex items-center rounded-md px-3 py-2 text-sm font-medium cursor-pointer hover:bg-gray-100 text-gray-400 hover:text-gray-500'
@@ -67,19 +68,21 @@ export function ContractInfoDialog(props: {
return (
<>
-
+
-
+
diff --git a/web/components/contract/contract-overview.tsx b/web/components/contract/contract-overview.tsx
index 1bfe84de..bfb4829f 100644
--- a/web/components/contract/contract-overview.tsx
+++ b/web/components/contract/contract-overview.tsx
@@ -25,11 +25,11 @@ import {
NumericContract,
PseudoNumericContract,
} from 'common/contract'
-import { ContractDetails, ExtraMobileContractDetails } from './contract-details'
+import { ContractDetails } from './contract-details'
import { NumericGraph } from './numeric-graph'
const OverviewQuestion = (props: { text: string }) => (
-
+
)
const BetWidget = (props: { contract: CPMMContract }) => {
@@ -73,7 +73,7 @@ const BinaryOverview = (props: { contract: BinaryContract; bets: Bet[] }) => {
const { contract, bets } = props
return (
-
+
@@ -85,7 +85,6 @@ const BinaryOverview = (props: { contract: BinaryContract; bets: Bet[] }) => {
-
{tradingAllowed(contract) && (
)}
@@ -113,10 +112,6 @@ const ChoiceOverview = (props: {
-
)
@@ -140,7 +135,6 @@ const PseudoNumericOverview = (props: {
-
{tradingAllowed(contract) && }
diff --git a/web/components/contract/extra-contract-actions-row.tsx b/web/components/contract/extra-contract-actions-row.tsx
index 5d5ee4d8..af5db9c3 100644
--- a/web/components/contract/extra-contract-actions-row.tsx
+++ b/web/components/contract/extra-contract-actions-row.tsx
@@ -11,38 +11,29 @@ import { FollowMarketButton } from 'web/components/follow-market-button'
import { LikeMarketButton } from 'web/components/contract/like-market-button'
import { ContractInfoDialog } from 'web/components/contract/contract-info-dialog'
import { Col } from 'web/components/layout/col'
-import { withTracking } from 'web/lib/service/analytics'
-import { CreateChallengeModal } from 'web/components/challenges/create-challenge-modal'
-import { CHALLENGES_ENABLED } from 'common/challenge'
-import ChallengeIcon from 'web/lib/icons/challenge-icon'
export function ExtraContractActionsRow(props: { contract: Contract }) {
const { contract } = props
- const { outcomeType, resolution } = contract
const user = useUser()
const [isShareOpen, setShareOpen] = useState(false)
- const [openCreateChallengeModal, setOpenCreateChallengeModal] =
- useState(false)
- const showChallenge =
- user && outcomeType === 'BINARY' && !resolution && CHALLENGES_ENABLED
return (
-
+
+
+ {user?.id !== contract.creatorId && (
+
+ )}
-
- {showChallenge && (
-
- )}
-
-
- {user?.id !== contract.creatorId && (
-
- )}
-
+
diff --git a/web/components/contract/like-market-button.tsx b/web/components/contract/like-market-button.tsx
index e35e3e7e..01dce32f 100644
--- a/web/components/contract/like-market-button.tsx
+++ b/web/components/contract/like-market-button.tsx
@@ -38,15 +38,16 @@ export function LikeMarketButton(props: {
return (
)
diff --git a/web/components/follow-button.tsx b/web/components/follow-button.tsx
index 09495169..6344757d 100644
--- a/web/components/follow-button.tsx
+++ b/web/components/follow-button.tsx
@@ -1,4 +1,6 @@
+import { CheckCircleIcon, PlusCircleIcon } from '@heroicons/react/solid'
import clsx from 'clsx'
+import { useEffect, useRef, useState } from 'react'
import { useFollows } from 'web/hooks/use-follows'
import { useUser } from 'web/hooks/use-user'
import { follow, unfollow } from 'web/lib/firebase/users'
@@ -54,18 +56,73 @@ export function FollowButton(props: {
export function UserFollowButton(props: { userId: string; small?: boolean }) {
const { userId, small } = props
- const currentUser = useUser()
- const following = useFollows(currentUser?.id)
+ const user = useUser()
+ const following = useFollows(user?.id)
const isFollowing = following?.includes(userId)
- if (!currentUser || currentUser.id === userId) return null
+ if (!user || user.id === userId) return null
return (
follow(currentUser.id, userId)}
- onUnfollow={() => unfollow(currentUser.id, userId)}
+ onFollow={() => follow(user.id, userId)}
+ onUnfollow={() => unfollow(user.id, userId)}
small={small}
/>
)
}
+
+export function MiniUserFollowButton(props: { userId: string }) {
+ const { userId } = props
+ const user = useUser()
+ const following = useFollows(user?.id)
+ const isFollowing = following?.includes(userId)
+ const isFirstRender = useRef(true)
+ const [justFollowed, setJustFollowed] = useState(false)
+
+ useEffect(() => {
+ if (isFirstRender.current) {
+ if (isFollowing != undefined) {
+ isFirstRender.current = false
+ }
+ return
+ }
+ if (isFollowing) {
+ setJustFollowed(true)
+ setTimeout(() => {
+ setJustFollowed(false)
+ }, 1000)
+ }
+ }, [isFollowing])
+
+ if (justFollowed) {
+ return (
+
+ )
+ }
+ if (
+ !user ||
+ user.id === userId ||
+ isFollowing ||
+ !user ||
+ isFollowing === undefined
+ )
+ return null
+ return (
+ <>
+
+ >
+ )
+}
diff --git a/web/components/follow-market-button.tsx b/web/components/follow-market-button.tsx
index 1dd261cb..0e65165b 100644
--- a/web/components/follow-market-button.tsx
+++ b/web/components/follow-market-button.tsx
@@ -25,7 +25,7 @@ export const FollowMarketButton = (props: {
return (