Separate free response answers & comments (#100)

* Just for playing with, bad code

* Whiten answer cards

* Separate answers and comments in FR markets

* Highlight FR answer in bet w/ comment

* Darken answer text and move classname

* Normalcase Comment
This commit is contained in:
Boa 2022-04-26 07:24:57 -06:00 committed by GitHub
parent 9270d48e12
commit 7722c723c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 115 additions and 48 deletions

View File

@ -68,7 +68,7 @@ export type BetGroupItem = BaseActivityItem & {
} }
export type AnswerGroupItem = BaseActivityItem & { export type AnswerGroupItem = BaseActivityItem & {
type: 'answergroup' type: 'answergroup' | 'answer'
answer: Answer answer: Answer
items: ActivityItem[] items: ActivityItem[]
} }
@ -256,6 +256,38 @@ function getAnswerGroups(
return answerGroups return answerGroups
} }
function getAnswers(
contract: FullContract<DPM, FreeResponse>,
bets: Bet[],
user: User | undefined | null
) {
let outcomes = _.uniq(bets.map((bet) => bet.outcome)).filter(
(outcome) => getOutcomeProbability(contract, outcome) > 0.0001
)
outcomes = _.sortBy(outcomes, (outcome) =>
getOutcomeProbability(contract, outcome)
)
const answerGroups = outcomes
.map((outcome) => {
const answer = contract.answers?.find(
(answer) => answer.id === outcome
) as Answer
return {
id: outcome,
type: 'answer' as const,
contract,
answer,
items: [] as ActivityItem[],
user,
}
})
.filter((group) => group.answer)
return answerGroups
}
function groupBetsAndComments( function groupBetsAndComments(
bets: Bet[], bets: Bet[],
comments: Comment[], comments: Comment[],
@ -328,19 +360,37 @@ export function getAllContractActivityItems(
: [{ type: 'description', id: '0', contract }] : [{ type: 'description', id: '0', contract }]
if (outcomeType === 'FREE_RESPONSE') { if (outcomeType === 'FREE_RESPONSE') {
const onlyUsersBetsOrBetsWithComments = bets.filter((bet) =>
comments.some(
(comment) => comment.betId === bet.id || bet.userId === user?.id
)
)
items.push( items.push(
...getAnswerGroups( ...groupBetsAndComments(
contract as FullContract<DPM, FreeResponse>, onlyUsersBetsOrBetsWithComments,
bets,
comments, comments,
user, contract,
user?.id,
{ {
sortByProb: true, hideOutcome: false,
abbreviated, abbreviated,
smallAvatar: false,
reversed, reversed,
} }
) )
) )
const commentsByBetId = mapCommentsByBetId(comments)
items.push({
type: 'commentInput',
id: 'commentInput',
bets,
commentsByBetId,
contract,
})
items.push(
...getAnswers(contract as FullContract<DPM, FreeResponse>, bets, user)
)
} else { } else {
items.push( items.push(
...groupBetsAndComments(bets, comments, contract, user?.id, { ...groupBetsAndComments(bets, comments, contract, user?.id, {
@ -359,6 +409,7 @@ export function getAllContractActivityItems(
items.push({ type: 'resolve', id: `${contract.resolutionTime}`, contract }) items.push({ type: 'resolve', id: `${contract.resolutionTime}`, contract })
} }
if (outcomeType === 'BINARY') {
const commentsByBetId = mapCommentsByBetId(comments) const commentsByBetId = mapCommentsByBetId(comments)
items.push({ items.push({
type: 'commentInput', type: 'commentInput',
@ -367,6 +418,7 @@ export function getAllContractActivityItems(
commentsByBetId, commentsByBetId,
contract, contract,
}) })
}
if (reversed) items.reverse() if (reversed) items.reverse()

View File

@ -1,5 +1,5 @@
// From https://tailwindui.com/components/application-ui/lists/feeds // From https://tailwindui.com/components/application-ui/lists/feeds
import { Fragment, useRef, useState } from 'react' import React, { Fragment, useRef, useState } from 'react'
import * as _ from 'lodash' import * as _ from 'lodash'
import { import {
BanIcon, BanIcon,
@ -67,7 +67,12 @@ export function FeedItems(props: {
<div className={clsx('flow-root pr-2 md:pr-0', className)} ref={ref}> <div className={clsx('flow-root pr-2 md:pr-0', className)} ref={ref}>
<div className={clsx(tradingAllowed(contract) ? '' : '-mb-6')}> <div className={clsx(tradingAllowed(contract) ? '' : '-mb-6')}>
{items.map((item, activityItemIdx) => ( {items.map((item, activityItemIdx) => (
<div key={item.id} className="relative pb-6"> <div
key={item.id}
className={
item.type === 'answer' ? 'relative pb-2' : 'relative pb-6'
}
>
{activityItemIdx !== items.length - 1 || {activityItemIdx !== items.length - 1 ||
item.type === 'answergroup' ? ( item.type === 'answergroup' ? (
<span <span
@ -104,6 +109,8 @@ function FeedItem(props: { item: ActivityItem }) {
return <FeedBetGroup {...item} /> return <FeedBetGroup {...item} />
case 'answergroup': case 'answergroup':
return <FeedAnswerGroup {...item} /> return <FeedAnswerGroup {...item} />
case 'answer':
return <FeedAnswerGroup {...item} />
case 'close': case 'close':
return <FeedClose {...item} /> return <FeedClose {...item} />
case 'resolve': case 'resolve':
@ -195,10 +202,6 @@ export function CommentInput(props: {
const user = useUser() const user = useUser()
const [comment, setComment] = useState('') const [comment, setComment] = useState('')
if (outcomeType === 'FREE_RESPONSE') {
return <div />
}
let canCommentOnABet = false let canCommentOnABet = false
bets.some((bet) => { bets.some((bet) => {
// make sure there is not already a comment with a matching bet id: // make sure there is not already a comment with a matching bet id:
@ -224,6 +227,7 @@ export function CommentInput(props: {
return ( return (
<> <>
<Row className={'flex w-full gap-2 pt-5'}>
<div> <div>
<Avatar avatarUrl={user?.avatarUrl} username={user?.username} /> <Avatar avatarUrl={user?.avatarUrl} username={user?.username} />
</div> </div>
@ -244,14 +248,17 @@ export function CommentInput(props: {
}} }}
/> />
<button <button
className="btn btn-outline btn-sm mt-1" className={
'btn btn-outline btn-sm text-transform: mt-1 capitalize'
}
onClick={submitComment} onClick={submitComment}
> >
Comment {user ? 'Comment' : 'Sign in to comment'}
</button> </button>
</div> </div>
</div> </div>
</div> </div>
</Row>
</> </>
) )
} }
@ -644,8 +651,9 @@ function FeedAnswerGroup(props: {
contract: FullContract<any, FreeResponse> contract: FullContract<any, FreeResponse>
answer: Answer answer: Answer
items: ActivityItem[] items: ActivityItem[]
type: string
}) { }) {
const { answer, items, contract } = props const { answer, items, contract, type } = props
const { username, avatarUrl, name, text } = answer const { username, avatarUrl, name, text } = answer
const prob = getDpmOutcomeProbability(contract.totalShares, answer.id) const prob = getDpmOutcomeProbability(contract.totalShares, answer.id)
@ -653,7 +661,13 @@ function FeedAnswerGroup(props: {
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
return ( return (
<Col className="flex-1 gap-2"> <Col
className={
type === 'answer'
? 'border-base-200 bg-base-200 flex-1 rounded-md p-3'
: 'flex-1 gap-2'
}
>
<Modal open={open} setOpen={setOpen}> <Modal open={open} setOpen={setOpen}>
<AnswerBetPanel <AnswerBetPanel
answer={answer} answer={answer}

View File

@ -27,6 +27,7 @@ export function OutcomeLabel(props: {
contract={contract as FullContract<DPM, FreeResponse>} contract={contract as FullContract<DPM, FreeResponse>}
resolution={outcome} resolution={outcome}
truncate={truncate} truncate={truncate}
answerClassName={'font-bold text-base-400'}
/> />
) )
} }