From 77ce27f45f2aecd7be1b145ba14bc63fe66726d8 Mon Sep 17 00:00:00 2001 From: jahooma Date: Fri, 10 Dec 2021 11:14:05 -0600 Subject: [PATCH] Submit bets to firestore --- web/components/bet-panel.tsx | 68 ++++++++++++++++++++++++++++++++--- web/lib/firebase/bets.ts | 22 ++++++++++++ web/lib/firebase/contracts.ts | 19 ---------- web/package-lock.json | 14 ++++++++ web/package.json | 1 + 5 files changed, 101 insertions(+), 23 deletions(-) create mode 100644 web/lib/firebase/bets.ts diff --git a/web/components/bet-panel.tsx b/web/components/bet-panel.tsx index 7b1bd550..8a403077 100644 --- a/web/components/bet-panel.tsx +++ b/web/components/bet-panel.tsx @@ -1,4 +1,7 @@ +import clsx from 'clsx' import React, { useState } from 'react' +import { useUser } from '../hooks/use-user' +import { Bet, saveBet } from '../lib/firebase/bets' import { Contract } from '../lib/firebase/contracts' import { Col } from './layout/col' import { Row } from './layout/row' @@ -8,14 +11,51 @@ import { YesNoSelector } from './yes-no-selector' export function BetPanel(props: { contract: Contract; className?: string }) { const { contract, className } = props + const user = useUser() + const [betChoice, setBetChoice] = useState<'YES' | 'NO'>('YES') const [betAmount, setBetAmount] = useState(undefined) + const [isSubmitting, setIsSubmitting] = useState(false) + const [wasSubmitted, setWasSubmitted] = useState(false) + function onBetChange(str: string) { const amount = parseInt(str) setBetAmount(isNaN(amount) ? undefined : amount) } + async function submitBet() { + if (!user || !betAmount) return + + const now = Date.now() + + const bet: Bet = { + id: `${now}-${user.id}`, + userId: user.id, + contractId: contract.id, + createdTime: now, + outcome: betChoice, + amount: betAmount, + + // Placeholder. + dpmWeight: betAmount, + } + + setIsSubmitting(true) + + await saveBet(bet) + + setIsSubmitting(false) + setWasSubmitted(true) + } + + function newBet() { + setBetAmount(undefined) + setWasSubmitted(false) + } + + const betDisabled = isSubmitting || wasSubmitted + return (
Pick outcome
@@ -47,9 +87,7 @@ export function BetPanel(props: { contract: Contract; className?: string }) {
Average price
-
- {betChoice === 'YES' ? 0.57 : 0.43} points -
+
{betChoice === 'YES' ? 0.57 : 0.43} points
@@ -60,7 +98,29 @@ export function BetPanel(props: { contract: Contract; className?: string }) { - + + + {wasSubmitted && ( + + + +
Bet submitted!
+ + + + + + )} )} diff --git a/web/lib/firebase/bets.ts b/web/lib/firebase/bets.ts new file mode 100644 index 00000000..dbfd6f2b --- /dev/null +++ b/web/lib/firebase/bets.ts @@ -0,0 +1,22 @@ +import { doc, setDoc } from 'firebase/firestore' +import { db } from './init' + +export type Bet = { + id: string + userId: string + contractId: string + + amount: number // Amount of USD bid + outcome: 'YES' | 'NO' // Chosen outcome + + // Calculate and replace these on server? + createdTime: number + dpmWeight: number // Dynamic Parimutuel weight +} + +// Push bet to Firestore +// TODO: Should bets be subcollections under its contract? +export async function saveBet(bet: Bet) { + const docRef = doc(db, 'contracts', bet.contractId, 'bets', bet.id) + await setDoc(docRef, bet) +} diff --git a/web/lib/firebase/contracts.ts b/web/lib/firebase/contracts.ts index 1a9a20b9..519fdb5a 100644 --- a/web/lib/firebase/contracts.ts +++ b/web/lib/firebase/contracts.ts @@ -32,18 +32,6 @@ export type Contract = { resolution?: 'YES' | 'NO' | 'CANCEL' // Chosen by creator; must be one of outcomes } -export type Bet = { - id: string - userId: string - contractId: string - - size: number // Amount of USD bid - outcome: 'YES' | 'NO' // Chosen outcome - createdTime: number - - dpmWeight: number // Dynamic Parimutuel weight -} - const db = getFirestore(app) const contractCollection = collection(db, 'contracts') @@ -79,10 +67,3 @@ export function listenForContract( setContract(contractSnap.data() as Contract) }) } - -// Push bet to Firestore -// TODO: Should bets be subcollections under its contract? -export async function setBet(bet: Bet) { - const docRef = doc(db, 'bets', bet.id) - await setDoc(docRef, bet) -} diff --git a/web/package-lock.json b/web/package-lock.json index db44421e..e77370b8 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -9,6 +9,7 @@ "@headlessui/react": "1.4.2", "@heroicons/react": "1.0.5", "chart.js": "3.6.1", + "clsx": "^1.1.1", "daisyui": "1.16.2", "firebase": "9.6.0", "next": "12.0.4", @@ -2879,6 +2880,14 @@ "wrap-ansi": "^7.0.0" } }, + "node_modules/clsx": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", + "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==", + "engines": { + "node": ">=6" + } + }, "node_modules/color": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", @@ -9908,6 +9917,11 @@ "wrap-ansi": "^7.0.0" } }, + "clsx": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", + "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==" + }, "color": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", diff --git a/web/package.json b/web/package.json index e9b33044..0be6979f 100644 --- a/web/package.json +++ b/web/package.json @@ -12,6 +12,7 @@ "@headlessui/react": "1.4.2", "@heroicons/react": "1.0.5", "chart.js": "3.6.1", + "clsx": "^1.1.1", "daisyui": "1.16.2", "firebase": "9.6.0", "next": "12.0.4",