making answer reply button work
This commit is contained in:
parent
e5af7bf76f
commit
0e842ab391
|
@ -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
|
||||
// }
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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} />}
|
||||
|
|
Loading…
Reference in New Issue
Block a user