diff --git a/web/components/bet-panel.tsx b/web/components/bet-panel.tsx
index 3ea02776..01f13caf 100644
--- a/web/components/bet-panel.tsx
+++ b/web/components/bet-panel.tsx
@@ -8,7 +8,7 @@ import { Col } from './layout/col'
import { Row } from './layout/row'
import { Spacer } from './layout/spacer'
import { YesNoSelector } from './yes-no-selector'
-import { formatMoney } from '../lib/util/format'
+import { formatMoney, formatPercent } from '../lib/util/format'
import { Title } from './title'
export function BetPanel(props: { contract: Contract; className?: string }) {
@@ -135,13 +135,9 @@ export function BetPanel(props: { contract: Contract; className?: string }) {
Implied probability
-
- {Math.round(initialProb * 100) + '%'}
-
+ {formatPercent(initialProb)}
→
-
- {Math.round(resultProb * 100) + '%'}
-
+ {formatPercent(resultProb)}
diff --git a/web/components/bets-list.tsx b/web/components/bets-list.tsx
new file mode 100644
index 00000000..68b9e59e
--- /dev/null
+++ b/web/components/bets-list.tsx
@@ -0,0 +1,84 @@
+import Link from 'next/link'
+import _ from 'lodash'
+import dayjs from 'dayjs'
+import { useContract } from '../hooks/use-contract'
+import { useUserBets } from '../hooks/use-user-bets'
+import { Bet } from '../lib/firebase/bets'
+import { User } from '../lib/firebase/users'
+import { formatMoney, formatPercent } from '../lib/util/format'
+import { Col } from './layout/col'
+import { ContractDetails } from './contracts-list'
+
+export function BetsList(props: { user: User }) {
+ const { user } = props
+ const bets = useUserBets(user?.id ?? '')
+
+ if (bets === 'loading') {
+ return <>>
+ }
+
+ if (bets.length === 0) return You have not made any bets yet!
+
+ const contractBets = _.groupBy(bets, 'contractId')
+
+ return (
+
+ {Object.keys(contractBets).map((contractId) => (
+
+ ))}
+
+ )
+}
+
+function ContractBets(props: { contractId: string; bets: Bet[] }) {
+ const { contractId, bets } = props
+
+ const contract = useContract(contractId)
+ if (contract === 'loading' || contract === null) return <>>
+
+ return (
+
+
{contract.question}
+
+
+ {bets.map((bet) => (
+
+ ))}
+
+
+ )
+}
+
+function BetCard(props: { bet: Bet }) {
+ const { bet } = props
+ const { contractId, amount, outcome, createdTime, probBefore, probAfter } =
+ bet
+
+ return (
+
+
+
+
+
+
+
+ {formatMoney(amount)} on {outcome}
+
+
+ {formatPercent(probBefore)} → {formatPercent(probAfter)}
+
+
+ {dayjs(createdTime).format('MMM D, H:mma')}
+
+
+
+
+
+
+
+ )
+}
diff --git a/web/components/contracts-list.tsx b/web/components/contracts-list.tsx
index a627a738..e3f43e0b 100644
--- a/web/components/contracts-list.tsx
+++ b/web/components/contracts-list.tsx
@@ -79,7 +79,7 @@ export function ContractsGrid(props: { contracts: Contract[] }) {
return (
{contracts.map((contract) => (
diff --git a/web/lib/firebase/contracts.ts b/web/lib/firebase/contracts.ts
index ef7a46a0..338de519 100644
--- a/web/lib/firebase/contracts.ts
+++ b/web/lib/firebase/contracts.ts
@@ -42,7 +42,9 @@ export function compute(contract: Contract) {
const prob = pot.YES ** 2 / (pot.YES ** 2 + pot.NO ** 2)
const probPercent = Math.round(prob * 100) + '%'
const createdDate = dayjs(createdTime).format('MMM D')
- const resolvedDate = isResolved ? dayjs(resolutionTime).format('MMM D') : undefined
+ const resolvedDate = isResolved
+ ? dayjs(resolutionTime).format('MMM D')
+ : undefined
return { volume, probPercent, createdDate, resolvedDate }
}
@@ -85,10 +87,10 @@ export async function listAllContracts(): Promise {
export function listenForContract(
contractId: string,
- setContract: (contract: Contract) => void
+ setContract: (contract: Contract | null) => void
) {
const contractRef = doc(contractCollection, contractId)
return onSnapshot(contractRef, (contractSnap) => {
- setContract(contractSnap.data() as Contract)
+ setContract((contractSnap.data() ?? null) as Contract | null)
})
}
diff --git a/web/lib/util/format.ts b/web/lib/util/format.ts
index 064f0ab5..5a9e3020 100644
--- a/web/lib/util/format.ts
+++ b/web/lib/util/format.ts
@@ -6,9 +6,13 @@ const formatter = new Intl.NumberFormat('en-US', {
})
export function formatMoney(amount: number) {
- return 'M$ ' + formatter.format(amount).substr(1)
+ return 'M$ ' + formatter.format(amount).substring(1)
}
export function formatWithCommas(amount: number) {
- return formatter.format(amount).substr(1)
+ return formatter.format(amount).substring(1)
+}
+
+export function formatPercent(zeroToOne: number) {
+ return Math.round(zeroToOne * 100) + '%'
}
diff --git a/web/package-lock.json b/web/package-lock.json
index c09f22ed..9a703afc 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -14,12 +14,14 @@
"daisyui": "1.16.4",
"dayjs": "1.10.7",
"firebase": "9.6.0",
+ "lodash": "4.17.21",
"next": "12.0.4",
"react": "17.0.2",
"react-dom": "17.0.2"
},
"devDependencies": {
"@tailwindcss/forms": "0.4.0",
+ "@types/lodash": "^4.14.178",
"@types/node": "16.11.11",
"@types/react": "17.0.37",
"autoprefixer": "10.2.6",
@@ -2280,6 +2282,12 @@
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=",
"dev": true
},
+ "node_modules/@types/lodash": {
+ "version": "4.14.178",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.178.tgz",
+ "integrity": "sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==",
+ "dev": true
+ },
"node_modules/@types/long": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz",
@@ -9929,6 +9937,12 @@
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=",
"dev": true
},
+ "@types/lodash": {
+ "version": "4.14.178",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.178.tgz",
+ "integrity": "sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==",
+ "dev": true
+ },
"@types/long": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz",
diff --git a/web/package.json b/web/package.json
index 92fb20b9..fd8b0c0b 100644
--- a/web/package.json
+++ b/web/package.json
@@ -18,12 +18,14 @@
"daisyui": "1.16.4",
"dayjs": "1.10.7",
"firebase": "9.6.0",
+ "lodash": "4.17.21",
"next": "12.0.4",
"react": "17.0.2",
"react-dom": "17.0.2"
},
"devDependencies": {
"@tailwindcss/forms": "0.4.0",
+ "@types/lodash": "^4.14.178",
"@types/node": "16.11.11",
"@types/react": "17.0.37",
"autoprefixer": "10.2.6",
diff --git a/web/pages/account.tsx b/web/pages/account.tsx
index 5ec011f0..4f278ae1 100644
--- a/web/pages/account.tsx
+++ b/web/pages/account.tsx
@@ -5,6 +5,8 @@ import { ContractsList } from '../components/contracts-list'
import { Title } from '../components/title'
import { Row } from '../components/layout/row'
import { formatMoney } from '../lib/util/format'
+import { BetsList } from '../components/bets-list'
+import { Spacer } from '../components/layout/spacer'
function UserCard(props: { user: User }) {
const { user } = props
@@ -72,8 +74,14 @@ export default function Account() {
{user ? (
+
+
+
+
+
+
) : (