basic market categories
This commit is contained in:
parent
0a63a0ae1f
commit
4d9e2df51f
43
common/categories.ts
Normal file
43
common/categories.ts
Normal file
|
@ -0,0 +1,43 @@
|
|||
export type category =
|
||||
| 'sports'
|
||||
| 'politics'
|
||||
| 'technology'
|
||||
| 'science'
|
||||
| 'manifold'
|
||||
| 'geopolitics'
|
||||
| 'personal'
|
||||
| 'fun'
|
||||
| 'business'
|
||||
| 'finance'
|
||||
| 'society'
|
||||
| 'entertainment'
|
||||
| 'gaming'
|
||||
| 'crypto'
|
||||
| 'health'
|
||||
| 'other'
|
||||
|
||||
export const CATEGORIES = {
|
||||
politics: 'Politics',
|
||||
personal: 'Personal',
|
||||
friends: 'Friends / Community',
|
||||
technology: 'Technology',
|
||||
gaming: 'Gaming / Esports',
|
||||
science: 'Science',
|
||||
manifold: 'Manifold Markets',
|
||||
society: 'Society',
|
||||
sports: 'Sports',
|
||||
geopolitics: 'Geopolitics',
|
||||
fun: 'Goofing around',
|
||||
business: 'Business',
|
||||
finance: 'Finance',
|
||||
crypto: 'Crypto',
|
||||
health: 'Health',
|
||||
entertainment: 'Entertainment',
|
||||
other: 'Other',
|
||||
}
|
||||
|
||||
export const TO_CATEGORY = Object.fromEntries(
|
||||
Object.entries(CATEGORIES).map(([k, v]) => [v, k])
|
||||
)
|
||||
|
||||
export const CATEGORY_LIST = Object.keys(CATEGORIES) as category[]
|
|
@ -1,4 +1,5 @@
|
|||
import { Answer } from './answer'
|
||||
import { category } from './categories'
|
||||
import { Fees } from './fees'
|
||||
|
||||
export type FullContract<
|
||||
|
@ -15,6 +16,7 @@ export type FullContract<
|
|||
|
||||
question: string
|
||||
description: string // More info about what the contract is about
|
||||
category: category
|
||||
tags: string[]
|
||||
lowercaseTags: string[]
|
||||
visibility: 'public' | 'unlisted'
|
||||
|
|
|
@ -11,6 +11,7 @@ import { User } from './user'
|
|||
import { parseTags } from './util/parse'
|
||||
import { removeUndefinedProps } from './util/object'
|
||||
import { calcDpmInitialPool } from './calculate-dpm'
|
||||
import { category } from './categories'
|
||||
|
||||
export function getNewContract(
|
||||
id: string,
|
||||
|
@ -22,6 +23,7 @@ export function getNewContract(
|
|||
initialProb: number,
|
||||
ante: number,
|
||||
closeTime: number,
|
||||
category: category,
|
||||
extraTags: string[]
|
||||
) {
|
||||
const tags = parseTags(
|
||||
|
@ -48,6 +50,7 @@ export function getNewContract(
|
|||
|
||||
question: question.trim(),
|
||||
description: description.trim(),
|
||||
category,
|
||||
tags,
|
||||
lowercaseTags,
|
||||
visibility: 'public',
|
||||
|
|
|
@ -26,6 +26,7 @@ import {
|
|||
MINIMUM_ANTE,
|
||||
} from '../../common/antes'
|
||||
import { getNoneAnswer } from '../../common/answer'
|
||||
import { category, CATEGORY_LIST } from '../../common/categories'
|
||||
|
||||
export const createContract = functions
|
||||
.runWith({ minInstances: 1 })
|
||||
|
@ -35,6 +36,7 @@ export const createContract = functions
|
|||
question: string
|
||||
outcomeType: outcomeType
|
||||
description: string
|
||||
category: category
|
||||
initialProb: number
|
||||
ante: number
|
||||
closeTime: number
|
||||
|
@ -48,7 +50,8 @@ export const createContract = functions
|
|||
const creator = await getUser(userId)
|
||||
if (!creator) return { status: 'error', message: 'User not found' }
|
||||
|
||||
let { question, description, initialProb, closeTime, tags } = data
|
||||
let { question, description, initialProb, closeTime, tags, category } =
|
||||
data
|
||||
|
||||
if (!question || typeof question != 'string')
|
||||
return { status: 'error', message: 'Missing or invalid question field' }
|
||||
|
@ -58,6 +61,10 @@ export const createContract = functions
|
|||
return { status: 'error', message: 'Invalid description field' }
|
||||
description = description.slice(0, MAX_DESCRIPTION_LENGTH)
|
||||
|
||||
if (category !== undefined && !CATEGORY_LIST.includes(category))
|
||||
return { status: 'error', message: 'Invalid category' }
|
||||
|
||||
// deprecated:
|
||||
if (tags !== undefined && !_.isArray(tags))
|
||||
return { status: 'error', message: 'Invalid tags field' }
|
||||
tags = tags?.map((tag) => tag.toString().slice(0, MAX_TAG_LENGTH))
|
||||
|
@ -114,6 +121,7 @@ export const createContract = functions
|
|||
initialProb,
|
||||
ante,
|
||||
closeTime,
|
||||
category,
|
||||
tags ?? []
|
||||
)
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import dayjs from 'dayjs'
|
|||
import _ from 'lodash'
|
||||
import { useState } from 'react'
|
||||
import { Bet } from '../../../common/bet'
|
||||
import { CATEGORIES } from '../../../common/categories'
|
||||
|
||||
import { Contract } from '../../../common/contract'
|
||||
import { formatMoney } from '../../../common/util/format'
|
||||
|
@ -28,7 +29,7 @@ export function ContractInfoDialog(props: { contract: Contract; bets: Bet[] }) {
|
|||
|
||||
const formatTime = (dt: number) => dayjs(dt).format('MMM DD, YYYY hh:mm a z')
|
||||
|
||||
const { createdTime, closeTime, resolutionTime } = contract
|
||||
const { createdTime, closeTime, resolutionTime, category } = contract
|
||||
const tradersCount = _.uniqBy(bets, 'userId').length
|
||||
|
||||
return (
|
||||
|
@ -52,6 +53,13 @@ export function ContractInfoDialog(props: { contract: Contract; bets: Bet[] }) {
|
|||
<div className="text-gray-500">Stats</div>
|
||||
<table className="table-compact table-zebra table w-full text-gray-500">
|
||||
<tbody>
|
||||
{category && (
|
||||
<tr>
|
||||
<td>Category</td>
|
||||
<td>{CATEGORIES[category]}</td>
|
||||
</tr>
|
||||
)}
|
||||
|
||||
<tr>
|
||||
<td>Market created</td>
|
||||
<td>{formatTime(createdTime)}</td>
|
||||
|
|
|
@ -19,6 +19,12 @@ import { Row } from '../components/layout/row'
|
|||
import { MAX_DESCRIPTION_LENGTH, outcomeType } from '../../common/contract'
|
||||
import { formatMoney } from '../../common/util/format'
|
||||
import { useHasCreatedContractToday } from '../hooks/use-has-created-contract-today'
|
||||
import {
|
||||
CATEGORIES,
|
||||
category,
|
||||
CATEGORY_LIST,
|
||||
TO_CATEGORY,
|
||||
} from '../../common/categories'
|
||||
|
||||
export default function Create() {
|
||||
const [question, setQuestion] = useState('')
|
||||
|
@ -67,6 +73,7 @@ export function NewContract(props: { question: string; tag?: string }) {
|
|||
const [outcomeType, setOutcomeType] = useState<outcomeType>('BINARY')
|
||||
const [initialProb, setInitialProb] = useState(50)
|
||||
const [description, setDescription] = useState('')
|
||||
const [category, setCategory] = useState<string>(CATEGORY_LIST[0])
|
||||
const [tagText, setTagText] = useState<string>(tag ?? '')
|
||||
const tags = parseWordsAsTags(tagText)
|
||||
|
||||
|
@ -117,6 +124,7 @@ export function NewContract(props: { question: string; tag?: string }) {
|
|||
initialProb,
|
||||
ante,
|
||||
closeTime,
|
||||
category,
|
||||
tags,
|
||||
}).then((r) => r.data || {})
|
||||
|
||||
|
@ -199,25 +207,27 @@ export function NewContract(props: { question: string; tag?: string }) {
|
|||
/>
|
||||
</div>
|
||||
|
||||
{/* <Spacer h={4} />
|
||||
<Spacer h={4} />
|
||||
|
||||
<div className="form-control max-w-sm items-start">
|
||||
<label className="label gap-2">
|
||||
<span className="mb-1">Tags</span>
|
||||
<InfoTooltip text="Optional. Help categorize your market with related tags." />
|
||||
<span className="mb-1">Category</span>
|
||||
</label>
|
||||
|
||||
<input
|
||||
placeholder="e.g. Politics, Economics..."
|
||||
className="input input-bordered resize-none"
|
||||
disabled={isSubmitting}
|
||||
value={tagText}
|
||||
onChange={(e) => setTagText(e.target.value || '')}
|
||||
/>
|
||||
</div> */}
|
||||
<select
|
||||
className="select select-bordered w-full max-w-xs"
|
||||
onChange={(e) =>
|
||||
setCategory(TO_CATEGORY[e.currentTarget.value] as category)
|
||||
}
|
||||
>
|
||||
{CATEGORY_LIST.map((cat) => (
|
||||
<option selected={category === cat} value={CATEGORIES[cat]}>
|
||||
{CATEGORIES[cat]}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<Spacer h={4} />
|
||||
<TagsList tags={tags} noLink noLabel />
|
||||
<Spacer h={4} />
|
||||
|
||||
<div className="form-control mb-1 items-start">
|
||||
|
|
Loading…
Reference in New Issue
Block a user