making answer reply button work

This commit is contained in:
ingawei 2022-10-08 01:13:22 -07:00
parent e5af7bf76f
commit 0e842ab391
4 changed files with 129 additions and 30 deletions

View File

@ -1,7 +1,11 @@
import { sortBy, partition, sum } from 'lodash'
import { useEffect, useState } from 'react'
import { FreeResponseContract, MultipleChoiceContract } from 'common/contract'
import {
Contract,
FreeResponseContract,
MultipleChoiceContract,
} from 'common/contract'
import { Col } from '../layout/col'
import { useUser } from 'web/hooks/use-user'
import { getDpmOutcomeProbability } from 'common/calculate-dpm'
@ -29,11 +33,22 @@ import { ChatAlt2Icon, ChatAltIcon } from '@heroicons/react/solid'
import { ChatIcon } from '@heroicons/react/outline'
import { ReplyTo } from '../feed/feed-comments'
// TODO: get a color
// export function useAnswerColor(answer: Answer, contract:Contract) {
// const colorSortedAnswer = useChartAnswers(contract).map(
// (value, _index) => value.text
// )
// colorIndex={colorSortedAnswer.indexOf(answer.text)}
// const color =
// colorIndex != undefined ? CATEGORY_COLORS[colorIndex] : '#B1B1C7'
// }
export function AnswersPanel(props: {
contract: FreeResponseContract | MultipleChoiceContract
onAnswerCommentClick: (answer: Answer) => void
}) {
const isAdmin = useAdmin()
const { contract } = props
const { contract, onAnswerCommentClick } = props
const { creatorId, resolution, resolutions, totalBets, outcomeType } =
contract
const [showAllAnswers, setShowAllAnswers] = useState(false)
@ -141,6 +156,7 @@ export function AnswersPanel(props: {
answer={item}
contract={contract}
colorIndex={colorSortedAnswer.indexOf(item.text)}
onAnswerCommentClick={onAnswerCommentClick}
/>
))}
{hasZeroBetAnswers && !showAllAnswers && (
@ -188,8 +204,9 @@ function OpenAnswer(props: {
contract: FreeResponseContract | MultipleChoiceContract
answer: Answer
colorIndex: number | undefined
onAnswerCommentClick: (answer: Answer) => void
}) {
const { answer, contract, colorIndex } = props
const { answer, contract, colorIndex, onAnswerCommentClick } = props
const { username, avatarUrl, text } = answer
const prob = getDpmOutcomeProbability(contract.totalShares, answer.id)
const probPercent = formatPercent(prob)
@ -242,6 +259,7 @@ function OpenAnswer(props: {
{
<button
className="p-1"
onClick={() => onAnswerCommentClick(answer)}
// onClick={() =>
// //TODO: make replies
// }

View File

@ -8,6 +8,7 @@ import {
FeedCommentThread,
ContractCommentInput,
CommentActions,
AnswerCommentInput,
} from '../feed/feed-comments'
import { groupBy, sortBy, sum } from 'lodash'
import { Bet } from 'common/bet'
@ -46,16 +47,27 @@ import { Avatar } from '../avatar'
import { UserLink } from '../user-link'
import { CopyLinkDateTimeComponent } from '../feed/copy-link-date-time'
import { Linkify } from '../linkify'
import { ArrowRightIcon, ReplyIcon } from '@heroicons/react/solid'
import { ArrowRightIcon, ReplyIcon, XIcon } from '@heroicons/react/solid'
import Curve from 'web/public/custom-components/curve'
import { Answer } from 'common/answer'
import dayjs from 'dayjs'
export function ContractTabs(props: {
contract: Contract
bets: Bet[]
userBets: Bet[]
comments: ContractComment[]
answerResponse?: Answer | undefined
onCancelAnswerResponse?: () => void
}) {
const { contract, bets, userBets, comments } = props
const {
contract,
bets,
userBets,
comments,
answerResponse,
onCancelAnswerResponse,
} = props
const yourTrades = (
<div>
@ -68,7 +80,14 @@ export function ContractTabs(props: {
const tabs = buildArray(
{
title: 'Comments',
content: <CommentsTabContent contract={contract} comments={comments} />,
content: (
<CommentsTabContent
contract={contract}
comments={comments}
answerResponse={answerResponse}
onCancelAnswerResponse={onCancelAnswerResponse}
/>
),
},
bets.length > 0 && {
title: capitalize(PAST_BETS),
@ -88,8 +107,10 @@ export function ContractTabs(props: {
const CommentsTabContent = memo(function CommentsTabContent(props: {
contract: Contract
comments: ContractComment[]
answerResponse?: Answer
onCancelAnswerResponse?: () => void
}) {
const { contract } = props
const { contract, answerResponse, onCancelAnswerResponse } = props
const tips = useTipTxns({ contractId: contract.id })
const comments = useComments(contract.id) ?? props.comments
const [sort, setSort] = usePersistentState<'Newest' | 'Best'>('Newest', {
@ -107,10 +128,7 @@ const CommentsTabContent = memo(function CommentsTabContent(props: {
// replied to answers/comments are NOT newest, otherwise newest first
const shouldBeNewestFirst = (c: ContractComment) =>
c.replyToCommentId == undefined &&
(contract.outcomeType === 'FREE_RESPONSE'
? c.betId === undefined && c.answerOutcome == undefined
: true)
c.replyToCommentId == undefined
// TODO: links to comments are broken because tips load after render and
// comments will reorganize themselves if there are tips/bounties awarded
@ -160,11 +178,28 @@ const CommentsTabContent = memo(function CommentsTabContent(props: {
</Row>
)
// console.log('answer response:: ', answerResponse)
// sortedComments.map((comment, index) =>
// console.log(
// index,
// ',',
// comment.content.content[0].content[0].text,
// ':',
// dayjs(comment.createdTime).format('MM/DD/YY H:mm')
// )
// )
if (contract.outcomeType === 'FREE_RESPONSE') {
return (
<>
{sortRow}
<ContractCommentInput className="mb-5" contract={contract} />
{sortRow}
{answerResponse && (
<AnswerCommentInput
contract={contract}
answerResponse={answerResponse}
onCancelAnswerResponse={onCancelAnswerResponse}
/>
)}
{topLevelComments.map((parent) => {
if (parent.answerOutcome != undefined) {
const answer = contract.answers.find(

View File

@ -20,9 +20,13 @@ import { Editor } from '@tiptap/react'
import { UserLink } from 'web/components/user-link'
import { CommentInput } from '../comment-input'
import { AwardBountyButton } from 'web/components/award-bounty-button'
import { ReplyIcon } from '@heroicons/react/solid'
import { ReplyIcon, XIcon } from '@heroicons/react/solid'
import { Button } from '../button'
import { ReplyToggle } from '../comments/comments'
import { CommentsAnswer } from './feed-answer-comment-group'
import Curve from 'web/public/custom-components/curve'
import { Answer } from 'common/answer'
import { useEvent } from 'web/hooks/use-event'
export type ReplyTo = { id: string; username: string }
@ -124,8 +128,6 @@ export function ParentFeedComment(props: {
'hover:bg-greyscale-1 ml-3 gap-2 transition-colors',
highlighted ? `-m-1.5 rounded bg-indigo-500/[0.2] p-1.5` : ''
)}
onMouseOver={() => setShowActions(true)}
onMouseLeave={() => setShowActions(false)}
>
<Col className="-ml-3.5">
<Avatar size="sm" username={userUsername} avatarUrl={userAvatarUrl} />
@ -146,7 +148,6 @@ export function ParentFeedComment(props: {
/>
<Row className="grow justify-end">
<CommentActions
showActions={showActions}
onReplyClick={onReplyClick}
tips={tips}
comment={comment}
@ -178,8 +179,6 @@ export function FeedComment(props: {
}
}, [highlighted])
const [showActions, setShowActions] = useState(false)
return (
<Row
ref={commentRef}
@ -188,8 +187,6 @@ export function FeedComment(props: {
'hover:bg-greyscale-1 ml-10 gap-2 transition-colors',
highlighted ? `-m-1.5 rounded bg-indigo-500/[0.2] p-1.5` : ''
)}
onMouseOver={() => setShowActions(true)}
onMouseLeave={() => setShowActions(false)}
>
<Col className="-ml-3">
<Avatar size="xs" username={userUsername} avatarUrl={userAvatarUrl} />
@ -208,7 +205,6 @@ export function FeedComment(props: {
/>
<Row className="justify-end">
<CommentActions
showActions={showActions}
onReplyClick={onReplyClick}
tips={tips}
comment={comment}
@ -221,20 +217,14 @@ export function FeedComment(props: {
}
export function CommentActions(props: {
showActions: boolean
onReplyClick?: () => void
tips?: CommentTips | undefined
comment: ContractComment
contract: Contract<AnyContractType>
}) {
const { showActions, onReplyClick, tips, comment, contract } = props
const { onReplyClick, tips, comment, contract } = props
return (
<Row
className={clsx(
'ml-2 items-center gap-2 text-xs text-gray-500 transition-opacity',
showActions ? '' : 'md:opacity-0'
)}
>
<Row className={clsx('ml-2 items-center gap-2 text-xs text-gray-500')}>
{onReplyClick && (
<Button
className="font-bold hover:underline"
@ -377,3 +367,42 @@ export function FeedCommentHeader(props: {
</Row>
)
}
export function AnswerCommentInput(props: {
contract: Contract<AnyContractType>
answerResponse: Answer
onCancelAnswerResponse?: () => void
}) {
const { contract, answerResponse, onCancelAnswerResponse } = props
const [replyTo, setReplyTo] = useState<ReplyTo | undefined>({
id: answerResponse.id,
username: answerResponse.username,
})
const onSubmitComment = useEvent(() => {
setReplyTo(undefined)
onCancelAnswerResponse
})
return (
<>
<Row className="gap-2">
<CommentsAnswer answer={answerResponse} contract={contract} />
</Row>
<Row>
<div className="ml-1">
<Curve size={28} strokeWidth={1} color="#D8D8EB" />
</div>
<div className="w-full pt-1">
<ContractCommentInput
contract={contract}
parentAnswerOutcome={answerResponse.number.toString()}
replyTo={replyTo}
onSubmitComment={onSubmitComment}
/>
</div>
<button onClick={onCancelAnswerResponse}>
<XIcon className="h-5 w-5" />
</button>
</Row>
</>
)
}

View File

@ -46,6 +46,8 @@ import { BetsSummary } from 'web/components/bet-summary'
import { listAllComments } from 'web/lib/firebase/comments'
import { ContractComment } from 'common/comment'
import { ScrollToTopButton } from 'web/components/scroll-to-top-button'
import { Answer } from 'common/answer'
import { useEvent } from 'web/hooks/use-event'
export const getStaticProps = fromPropz(getStaticPropz)
export async function getStaticPropz(props: {
@ -204,6 +206,16 @@ export function ContractPageContent(
contractId: contract.id,
})
const [answerResponse, setAnswerResponse] = useState<Answer | undefined>(
undefined
)
const onAnswerCommentClick = useEvent((answer: Answer) => {
setAnswerResponse(answer)
})
const onCancelAnswerResponse = useEvent(() => setAnswerResponse(undefined))
return (
<Page
rightSidebar={
@ -253,7 +265,10 @@ export function ContractPageContent(
outcomeType === 'MULTIPLE_CHOICE') && (
<>
<Spacer h={4} />
<AnswersPanel contract={contract} />
<AnswersPanel
contract={contract}
onAnswerCommentClick={onAnswerCommentClick}
/>
<Spacer h={4} />
</>
)}
@ -283,6 +298,8 @@ export function ContractPageContent(
bets={bets}
userBets={userBets}
comments={comments}
answerResponse={answerResponse}
onCancelAnswerResponse={onCancelAnswerResponse}
/>
</Col>
{!isCreator && <RecommendedContractsWidget contract={contract} />}