From 583a797a61bc4baa826dbbaefe2f8a848770a0dc Mon Sep 17 00:00:00 2001 From: Austin Chen Date: Sun, 22 May 2022 14:05:44 -0700 Subject: [PATCH] WIP: Try a toast that counts down before betting There's some weird timing/React hook error that sometimes allows this thing to bet twice? IDK, my brain is fried trying to understand it. Also, progress bar that scrolls down might be cooler than a number countdown? See https://www.npmjs.com/package/react-toastify, although the API for that is more unwieldy/less Tailwind-friendly? --- web/components/contract/contract-card.tsx | 118 +++++++++++++++++++++- 1 file changed, 114 insertions(+), 4 deletions(-) diff --git a/web/components/contract/contract-card.tsx b/web/components/contract/contract-card.tsx index 3aa0869c..7578e9c5 100644 --- a/web/components/contract/contract-card.tsx +++ b/web/components/contract/contract-card.tsx @@ -33,6 +33,10 @@ import { AvatarDetails, MiscDetails } from './contract-details' import { getExpectedValue, getValueFromBucket } from 'common/calculate-dpm' import TriangleFillIcon from 'web/lib/icons/triangle-fill-icon' import TriangleDownFillIcon from 'web/lib/icons/triangle-down-fill-icon' +import toast from 'react-hot-toast' +import { CheckIcon, XIcon } from '@heroicons/react/solid' +import { useEffect, useState } from 'react' +import { APIError, placeBet } from 'web/lib/firebase/api-call' // Return a number from 0 to 1 for this contract // Resolved contracts are set to 1, for coloring purposes (even if NO) @@ -93,6 +97,53 @@ export function ContractCard(props: { const color = getColor(contract) const marketClosed = (contract.closeTime || Infinity) < Date.now() + // TODO: switch to useContract after you place a bet on it + + function betToast(outcome: string) { + let canceled = false + const toastId = toast.custom( + , + { + duration: 3000, + } + ) + + function onToastCancel() { + toast.remove(toastId) + canceled = true + } + + function onToastFinish() { + if (canceled) return + console.log('Finishing toast') + toast.remove(toastId) + placeBet({ + amount: 10, + outcome, + contractId: contract.id, + }) + .then((r) => { + // Success + console.log('placed bet. Result:', r) + toast.success('Bet placed!', { duration: 1000 }) + }) + .catch((e) => { + // Failure + if (e instanceof APIError) { + toast.error(e.toString(), { duration: 1000 }) + } else { + console.error(e) + toast.error('Could not place bet') + } + }) + } + } + return (
{ - console.log('success') - }} + onClick={() => betToast('YES')} >
{formatMoney(20)} @@ -188,7 +237,7 @@ export function ContractCard(props: {
{}} + onClick={() => betToast('NO')} >
{contract.createdTime % 3 == 2 ? ( ) } + +function BetToast(props: { + outcome: string + seconds: number + onToastFinish: () => void + onToastCancel: () => void +}) { + const { outcome, seconds, onToastFinish, onToastCancel } = props + + // Track the number of seconds left, starting with durationMs + const [secondsLeft, setSecondsLeft] = useState(seconds) + console.log('renderings using', secondsLeft) + + // Update the secondsLeft state every second + useEffect(() => { + const interval = setInterval(() => { + setSecondsLeft((seconds) => seconds - 1) + }, 1000) + return () => clearInterval(interval) + }, []) + + if (secondsLeft <= 0) { + console.log('finishing') + onToastFinish() + // return null + } + + return ( +
+
+
+
+

+ Betting M$10 on {outcome} in {secondsLeft}s +

+ +
+ {/*
+ +
*/} +
+
+
+ ) +}