From 67b4eeb5728067222c374e76b7d1d485e1d7bc85 Mon Sep 17 00:00:00 2001 From: Austin Chen Date: Mon, 20 Dec 2021 13:13:27 -0800 Subject: [PATCH] Set up a page to make bulk predictions --- web/pages/make-predictions.tsx | 177 +++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 web/pages/make-predictions.tsx diff --git a/web/pages/make-predictions.tsx b/web/pages/make-predictions.tsx new file mode 100644 index 00000000..1519d425 --- /dev/null +++ b/web/pages/make-predictions.tsx @@ -0,0 +1,177 @@ +import { useState } from 'react' +import { Col } from '../components/layout/col' +import { Row } from '../components/layout/row' +import { Spacer } from '../components/layout/spacer' +import { Linkify } from '../components/linkify' +import { Page } from '../components/page' +import { Title } from '../components/title' +import { useUser } from '../hooks/use-user' +import { createContract } from '../lib/service/create-contract' + +type Prediction = { + question: string + description: string + initalProb: number +} + +function PredictionRow(props: { prediction: Prediction }) { + const { prediction } = props + return ( + + +
+ +
+
{prediction.description}
+ + {/* Initial probability */} +
+
+
+ {prediction.initalProb}%
chance
+
+
+
+ {/* Current probability; hidden for now */} + {/*
+
+
+ {prediction.initalProb}%
chance
+
+
+
*/} +
+ ) +} + +function PredictionList(props: { predictions: Prediction[] }) { + const { predictions } = props + return ( +
+ + {predictions.map((prediction) => ( + + ))} + +
+ ) +} + +const TEST_VALUE = `1. Biden approval rating (as per 538) is greater than 50%: 80% +2. Court packing is clearly going to happen (new justices don't have to be appointed by end of year): 5% +3. Yang is New York mayor: 80% +4. Newsom recalled as CA governor: 5% +5. At least $250 million in damage from BLM protests this year: 30% +6. Significant capital gains tax hike (above 30% for highest bracket): 20%` + +export default function MakePredictions() { + const user = useUser() + const [predictionsString, setBulkContracts] = useState('') + const [description, setDescription] = useState('') + + const bulkPlaceholder = `e.g. +${TEST_VALUE} +... +` + + const predictions: Prediction[] = [] + + // Parse bulkContracts, then run createContract for each + const lines = predictionsString.split('\n') + for (const line of lines) { + // Parse line with regex + const matches = line.match(/^(.*):\s*(\d+)%\s*$/) || ['', '', ''] + const [_, question, prob] = matches + + if (!user || !question || !prob) { + console.error('Invalid prediction: ', line) + continue + } + + predictions.push({ + question, + description, + initalProb: parseInt(prob), + }) + } + + async function createContracts() { + if (!user) { + // TODO: Convey error with snackbar/toast + console.error('You need to be signed in!') + return + } + for (const prediction of predictions) { + await createContract( + prediction.question, + prediction.description, + prediction.initalProb, + user + ) + // TODO: Convey success in the UI + console.log('Created contract: ', prediction.question) + } + } + + return ( + + + <div className="w-full bg-gray-100 rounded-lg shadow-xl px-6 py-4"> + <form> + <div className="form-control"> + <label className="label"> + <span className="label-text">Prediction</span> + </label> + + <textarea + className="textarea h-60 textarea-bordered" + placeholder={bulkPlaceholder} + value={predictionsString} + onChange={(e) => setBulkContracts(e.target.value || '')} + ></textarea> + </div> + </form> + + <Spacer h={4} /> + + <div className="form-control w-full"> + <label className="label"> + <span className="label-text">Tags</span> + </label> + + <input + type="text" + placeholder="e.g. #ACX2021 #World" + className="input" + value={description} + onChange={(e) => setDescription(e.target.value || '')} + /> + </div> + </div> + + {predictions.length > 0 && ( + <div> + <Spacer h={16} /> + <Title text="Preview" /> + <PredictionList predictions={predictions} /> + </div> + )} + + <Spacer h={4} /> + + <div className="flex justify-end my-4"> + <button + type="submit" + className="btn btn-primary" + // disabled={isSubmitting || !question} + onClick={(e) => { + e.preventDefault() + createContracts() + }} + > + Create all + </button> + </div> + </Page> + ) +}