Inga/colorful answer comments (#1040)
* changing answers in comments to match colors, no longer indenting those responses
This commit is contained in:
		
							parent
							
								
									41a46aad9b
								
							
						
					
					
						commit
						3f8988bf27
					
				| 
						 | 
				
			
			@ -27,6 +27,13 @@ import { CHOICE_ANSWER_COLORS } from '../charts/contract/choice'
 | 
			
		|||
import { useChartAnswers } from '../charts/contract/choice'
 | 
			
		||||
import { ChatIcon } from '@heroicons/react/outline'
 | 
			
		||||
 | 
			
		||||
export function getAnswerColor(answer: Answer, answersArray: string[]) {
 | 
			
		||||
  const colorIndex = answersArray.indexOf(answer.text)
 | 
			
		||||
  return colorIndex != undefined && colorIndex < CHOICE_ANSWER_COLORS.length
 | 
			
		||||
    ? CHOICE_ANSWER_COLORS[colorIndex]
 | 
			
		||||
    : '#B1B1C7'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function AnswersPanel(props: {
 | 
			
		||||
  contract: FreeResponseContract | MultipleChoiceContract
 | 
			
		||||
  onAnswerCommentClick: (answer: Answer) => void
 | 
			
		||||
| 
						 | 
				
			
			@ -107,8 +114,8 @@ export function AnswersPanel(props: {
 | 
			
		|||
    ? 'checkbox'
 | 
			
		||||
    : undefined
 | 
			
		||||
 | 
			
		||||
  const colorSortedAnswer = useChartAnswers(contract).map(
 | 
			
		||||
    (value, _index) => value.text
 | 
			
		||||
  const answersArray = useChartAnswers(contract).map(
 | 
			
		||||
    (answer, _index) => answer.text
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
| 
						 | 
				
			
			@ -139,8 +146,8 @@ export function AnswersPanel(props: {
 | 
			
		|||
              key={item.id}
 | 
			
		||||
              answer={item}
 | 
			
		||||
              contract={contract}
 | 
			
		||||
              colorIndex={colorSortedAnswer.indexOf(item.text)}
 | 
			
		||||
              onAnswerCommentClick={onAnswerCommentClick}
 | 
			
		||||
              color={getAnswerColor(item, answersArray)}
 | 
			
		||||
            />
 | 
			
		||||
          ))}
 | 
			
		||||
          {hasZeroBetAnswers && !showAllAnswers && (
 | 
			
		||||
| 
						 | 
				
			
			@ -185,18 +192,14 @@ export function AnswersPanel(props: {
 | 
			
		|||
function OpenAnswer(props: {
 | 
			
		||||
  contract: FreeResponseContract | MultipleChoiceContract
 | 
			
		||||
  answer: Answer
 | 
			
		||||
  colorIndex: number | undefined
 | 
			
		||||
  color: string
 | 
			
		||||
  onAnswerCommentClick: (answer: Answer) => void
 | 
			
		||||
}) {
 | 
			
		||||
  const { answer, contract, colorIndex, onAnswerCommentClick } = props
 | 
			
		||||
  const { answer, contract, onAnswerCommentClick, color } = props
 | 
			
		||||
  const { username, avatarUrl, text } = answer
 | 
			
		||||
  const prob = getDpmOutcomeProbability(contract.totalShares, answer.id)
 | 
			
		||||
  const probPercent = formatPercent(prob)
 | 
			
		||||
  const [open, setOpen] = useState(false)
 | 
			
		||||
  const color =
 | 
			
		||||
    colorIndex != undefined && colorIndex < CHOICE_ANSWER_COLORS.length
 | 
			
		||||
      ? CHOICE_ANSWER_COLORS[colorIndex] + '55' // semi-transparent
 | 
			
		||||
      : '#B1B1C755'
 | 
			
		||||
  const colorWidth = 100 * Math.max(prob, 0.01)
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
| 
						 | 
				
			
			@ -217,7 +220,7 @@ function OpenAnswer(props: {
 | 
			
		|||
          tradingAllowed(contract) ? 'text-greyscale-7' : 'text-greyscale-5'
 | 
			
		||||
        )}
 | 
			
		||||
        style={{
 | 
			
		||||
          background: `linear-gradient(to right, ${color} ${colorWidth}%, #FBFBFF ${colorWidth}%)`,
 | 
			
		||||
          background: `linear-gradient(to right, ${color}90 ${colorWidth}%, #FBFBFF ${colorWidth}%)`,
 | 
			
		||||
        }}
 | 
			
		||||
      >
 | 
			
		||||
        <Row className="z-20 -mb-1 justify-between gap-2 py-2 px-3">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,10 +8,12 @@ import { useEffect, useState } from 'react'
 | 
			
		|||
import { useUser } from 'web/hooks/use-user'
 | 
			
		||||
import { MAX_COMMENT_LENGTH } from 'web/lib/firebase/comments'
 | 
			
		||||
import Curve from 'web/public/custom-components/curve'
 | 
			
		||||
import { getAnswerColor } from './answers/answers-panel'
 | 
			
		||||
import { Avatar } from './avatar'
 | 
			
		||||
import { TextEditor, useTextEditor } from './editor'
 | 
			
		||||
import { CommentsAnswer } from './feed/feed-answer-comment-group'
 | 
			
		||||
import { ContractCommentInput } from './feed/feed-comments'
 | 
			
		||||
import { Col } from './layout/col'
 | 
			
		||||
import { Row } from './layout/row'
 | 
			
		||||
import { LoadingIndicator } from './loading-indicator'
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -81,20 +83,30 @@ export function AnswerCommentInput(props: {
 | 
			
		|||
  contract: Contract<AnyContractType>
 | 
			
		||||
  answerResponse: Answer
 | 
			
		||||
  onCancelAnswerResponse?: () => void
 | 
			
		||||
  answersArray: string[]
 | 
			
		||||
}) {
 | 
			
		||||
  const { contract, answerResponse, onCancelAnswerResponse } = props
 | 
			
		||||
  const { contract, answerResponse, onCancelAnswerResponse, answersArray } =
 | 
			
		||||
    props
 | 
			
		||||
  const replyTo = {
 | 
			
		||||
    id: answerResponse.id,
 | 
			
		||||
    username: answerResponse.username,
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const color = getAnswerColor(answerResponse, answersArray)
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      <CommentsAnswer answer={answerResponse} contract={contract} />
 | 
			
		||||
      <Row>
 | 
			
		||||
        <div className="ml-1">
 | 
			
		||||
          <Curve size={28} strokeWidth={1} color="#D8D8EB" />
 | 
			
		||||
      <Col>
 | 
			
		||||
        <Row className="relative">
 | 
			
		||||
          <div className="absolute -bottom-1 left-1.5">
 | 
			
		||||
            <Curve size={32} strokeWidth={1} color="#D8D8EB" />
 | 
			
		||||
          </div>
 | 
			
		||||
          <div className="ml-[38px]">
 | 
			
		||||
            <CommentsAnswer
 | 
			
		||||
              answer={answerResponse}
 | 
			
		||||
              contract={contract}
 | 
			
		||||
              color={color}
 | 
			
		||||
            />
 | 
			
		||||
          </div>
 | 
			
		||||
        </Row>
 | 
			
		||||
        <div className="relative w-full pt-1">
 | 
			
		||||
          <ContractCommentInput
 | 
			
		||||
            contract={contract}
 | 
			
		||||
| 
						 | 
				
			
			@ -107,7 +119,7 @@ export function AnswerCommentInput(props: {
 | 
			
		|||
            <XCircleIcon className="text-greyscale-5 hover:text-greyscale-6 absolute -top-1 -right-2 h-5 w-5" />
 | 
			
		||||
          </button>
 | 
			
		||||
        </div>
 | 
			
		||||
      </Row>
 | 
			
		||||
      </Col>
 | 
			
		||||
    </>
 | 
			
		||||
  )
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,11 +2,11 @@ import { memo, useState } from 'react'
 | 
			
		|||
import { Pagination } from 'web/components/pagination'
 | 
			
		||||
import { FeedBet } from '../feed/feed-bets'
 | 
			
		||||
import { FeedLiquidity } from '../feed/feed-liquidity'
 | 
			
		||||
import { CommentsAnswer } from '../feed/feed-answer-comment-group'
 | 
			
		||||
import { FreeResponseComments } from '../feed/feed-answer-comment-group'
 | 
			
		||||
import { FeedCommentThread, ContractCommentInput } from '../feed/feed-comments'
 | 
			
		||||
import { groupBy, sortBy, sum } from 'lodash'
 | 
			
		||||
import { Bet } from 'common/bet'
 | 
			
		||||
import { Contract } from 'common/contract'
 | 
			
		||||
import { AnyContractType, Contract } from 'common/contract'
 | 
			
		||||
import { PAST_BETS } from 'common/user'
 | 
			
		||||
import { ContractBetsTable } from '../bets-list'
 | 
			
		||||
import { Spacer } from '../layout/spacer'
 | 
			
		||||
| 
						 | 
				
			
			@ -35,9 +35,7 @@ import {
 | 
			
		|||
} from 'web/hooks/use-persistent-state'
 | 
			
		||||
import { safeLocalStorage } from 'web/lib/util/local'
 | 
			
		||||
import TriangleDownFillIcon from 'web/lib/icons/triangle-down-fill-icon'
 | 
			
		||||
import Curve from 'web/public/custom-components/curve'
 | 
			
		||||
import { Answer } from 'common/answer'
 | 
			
		||||
import { AnswerCommentInput } from '../comment-input'
 | 
			
		||||
 | 
			
		||||
export function ContractTabs(props: {
 | 
			
		||||
  contract: Contract
 | 
			
		||||
| 
						 | 
				
			
			@ -139,95 +137,27 @@ const CommentsTabContent = memo(function CommentsTabContent(props: {
 | 
			
		|||
  )
 | 
			
		||||
  const topLevelComments = commentsByParent['_'] ?? []
 | 
			
		||||
 | 
			
		||||
  const sortRow = comments.length > 0 && (
 | 
			
		||||
    <Row className="mb-4 items-center justify-end gap-4">
 | 
			
		||||
      <BountiedContractSmallBadge contract={contract} showAmount />
 | 
			
		||||
      <Row className="items-center gap-1">
 | 
			
		||||
        <div className="text-greyscale-4 text-sm">Sort by:</div>
 | 
			
		||||
        <button
 | 
			
		||||
          className="text-greyscale-6 w-20 text-sm"
 | 
			
		||||
          onClick={() => setSort(sort === 'Newest' ? 'Best' : 'Newest')}
 | 
			
		||||
        >
 | 
			
		||||
          <Tooltip
 | 
			
		||||
            text={sort === 'Best' ? 'Highest tips + bounties first.' : ''}
 | 
			
		||||
          >
 | 
			
		||||
            <Row className="items-center gap-1">
 | 
			
		||||
              {sort}
 | 
			
		||||
              <TriangleDownFillIcon className=" h-2 w-2" />
 | 
			
		||||
            </Row>
 | 
			
		||||
          </Tooltip>
 | 
			
		||||
        </button>
 | 
			
		||||
      </Row>
 | 
			
		||||
    </Row>
 | 
			
		||||
  )
 | 
			
		||||
  if (contract.outcomeType === 'FREE_RESPONSE') {
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      <ContractCommentInput className="mb-5" contract={contract} />
 | 
			
		||||
        {sortRow}
 | 
			
		||||
        {answerResponse && (
 | 
			
		||||
          <AnswerCommentInput
 | 
			
		||||
      <SortRow
 | 
			
		||||
        comments={comments}
 | 
			
		||||
        contract={contract}
 | 
			
		||||
        sort={sort}
 | 
			
		||||
        onSortClick={() => setSort(sort === 'Newest' ? 'Best' : 'Newest')}
 | 
			
		||||
      />
 | 
			
		||||
      {contract.outcomeType === 'FREE_RESPONSE' && (
 | 
			
		||||
        <FreeResponseComments
 | 
			
		||||
          contract={contract}
 | 
			
		||||
          answerResponse={answerResponse}
 | 
			
		||||
          onCancelAnswerResponse={onCancelAnswerResponse}
 | 
			
		||||
          />
 | 
			
		||||
        )}
 | 
			
		||||
        {topLevelComments.map((parent) => {
 | 
			
		||||
          if (parent.answerOutcome === undefined) {
 | 
			
		||||
            return (
 | 
			
		||||
              <FeedCommentThread
 | 
			
		||||
                key={parent.id}
 | 
			
		||||
                contract={contract}
 | 
			
		||||
                parentComment={parent}
 | 
			
		||||
                threadComments={sortBy(
 | 
			
		||||
                  commentsByParent[parent.id] ?? [],
 | 
			
		||||
                  (c) => c.createdTime
 | 
			
		||||
                )}
 | 
			
		||||
          topLevelComments={topLevelComments}
 | 
			
		||||
          commentsByParent={commentsByParent}
 | 
			
		||||
          tips={tips}
 | 
			
		||||
        />
 | 
			
		||||
            )
 | 
			
		||||
          }
 | 
			
		||||
          const answer = contract.answers.find(
 | 
			
		||||
            (answer) => answer.id === parent.answerOutcome
 | 
			
		||||
          )
 | 
			
		||||
          if (answer === undefined) {
 | 
			
		||||
            console.error('Could not find answer that matches ID')
 | 
			
		||||
            return <></>
 | 
			
		||||
          }
 | 
			
		||||
          return (
 | 
			
		||||
            <>
 | 
			
		||||
              <Row className="gap-2">
 | 
			
		||||
                <CommentsAnswer answer={answer} contract={contract} />
 | 
			
		||||
              </Row>
 | 
			
		||||
              <Row>
 | 
			
		||||
                <div className="ml-1">
 | 
			
		||||
                  <Curve size={28} strokeWidth={1} color="#D8D8EB" />
 | 
			
		||||
                </div>
 | 
			
		||||
                <div className="w-full pt-1">
 | 
			
		||||
                  <FeedCommentThread
 | 
			
		||||
                    key={parent.id}
 | 
			
		||||
                    contract={contract}
 | 
			
		||||
                    parentComment={parent}
 | 
			
		||||
                    threadComments={sortBy(
 | 
			
		||||
                      commentsByParent[parent.id] ?? [],
 | 
			
		||||
                      (c) => c.createdTime
 | 
			
		||||
      )}
 | 
			
		||||
                    tips={tips}
 | 
			
		||||
                  />
 | 
			
		||||
                </div>
 | 
			
		||||
              </Row>
 | 
			
		||||
            </>
 | 
			
		||||
          )
 | 
			
		||||
        })}
 | 
			
		||||
      </>
 | 
			
		||||
    )
 | 
			
		||||
  } else {
 | 
			
		||||
    return (
 | 
			
		||||
      <>
 | 
			
		||||
        <ContractCommentInput className="mb-5" contract={contract} />
 | 
			
		||||
        {sortRow}
 | 
			
		||||
 | 
			
		||||
        {topLevelComments.map((parent) => (
 | 
			
		||||
      {contract.outcomeType !== 'FREE_RESPONSE' &&
 | 
			
		||||
        topLevelComments.map((parent) => (
 | 
			
		||||
          <FeedCommentThread
 | 
			
		||||
            key={parent.id}
 | 
			
		||||
            contract={contract}
 | 
			
		||||
| 
						 | 
				
			
			@ -241,7 +171,6 @@ const CommentsTabContent = memo(function CommentsTabContent(props: {
 | 
			
		|||
        ))}
 | 
			
		||||
    </>
 | 
			
		||||
  )
 | 
			
		||||
  }
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
const BetsTabContent = memo(function BetsTabContent(props: {
 | 
			
		||||
| 
						 | 
				
			
			@ -310,3 +239,33 @@ const BetsTabContent = memo(function BetsTabContent(props: {
 | 
			
		|||
    </>
 | 
			
		||||
  )
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
export function SortRow(props: {
 | 
			
		||||
  comments: ContractComment[]
 | 
			
		||||
  contract: Contract<AnyContractType>
 | 
			
		||||
  sort: 'Best' | 'Newest'
 | 
			
		||||
  onSortClick: () => void
 | 
			
		||||
}) {
 | 
			
		||||
  const { comments, contract, sort, onSortClick } = props
 | 
			
		||||
  if (comments.length <= 0) {
 | 
			
		||||
    return <></>
 | 
			
		||||
  }
 | 
			
		||||
  return (
 | 
			
		||||
    <Row className="mb-4 items-center justify-end gap-4">
 | 
			
		||||
      <BountiedContractSmallBadge contract={contract} showAmount />
 | 
			
		||||
      <Row className="items-center gap-1">
 | 
			
		||||
        <div className="text-greyscale-4 text-sm">Sort by:</div>
 | 
			
		||||
        <button className="text-greyscale-6 w-20 text-sm" onClick={onSortClick}>
 | 
			
		||||
          <Tooltip
 | 
			
		||||
            text={sort === 'Best' ? 'Highest tips + bounties first.' : ''}
 | 
			
		||||
          >
 | 
			
		||||
            <Row className="items-center gap-1">
 | 
			
		||||
              {sort}
 | 
			
		||||
              <TriangleDownFillIcon className=" h-2 w-2" />
 | 
			
		||||
            </Row>
 | 
			
		||||
          </Tooltip>
 | 
			
		||||
        </button>
 | 
			
		||||
      </Row>
 | 
			
		||||
    </Row>
 | 
			
		||||
  )
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,32 +1,60 @@
 | 
			
		|||
import { Answer } from 'common/answer'
 | 
			
		||||
import { Contract } from 'common/contract'
 | 
			
		||||
import React, { useEffect, useRef } from 'react'
 | 
			
		||||
import {
 | 
			
		||||
  Contract,
 | 
			
		||||
  FreeResponseContract,
 | 
			
		||||
  MultipleChoiceContract,
 | 
			
		||||
} from 'common/contract'
 | 
			
		||||
import React, { useEffect, useRef, useState } from 'react'
 | 
			
		||||
import { Col } from 'web/components/layout/col'
 | 
			
		||||
import { Row } from 'web/components/layout/row'
 | 
			
		||||
import { Avatar } from 'web/components/avatar'
 | 
			
		||||
import { CopyLinkDateTimeComponent } from 'web/components/feed/copy-link-date-time'
 | 
			
		||||
import { useRouter } from 'next/router'
 | 
			
		||||
import { UserLink } from 'web/components/user-link'
 | 
			
		||||
import { FeedCommentThread } from './feed-comments'
 | 
			
		||||
import { AnswerCommentInput } from '../comment-input'
 | 
			
		||||
import { ContractComment } from 'common/comment'
 | 
			
		||||
import { Dictionary, sortBy } from 'lodash'
 | 
			
		||||
import { getAnswerColor } from '../answers/answers-panel'
 | 
			
		||||
import Curve from 'web/public/custom-components/curve'
 | 
			
		||||
import { CommentTipMap } from 'web/hooks/use-tip-txns'
 | 
			
		||||
import { useChartAnswers } from '../charts/contract/choice'
 | 
			
		||||
 | 
			
		||||
export function CommentsAnswer(props: { answer: Answer; contract: Contract }) {
 | 
			
		||||
  const { answer, contract } = props
 | 
			
		||||
  const { username, avatarUrl, name, text } = answer
 | 
			
		||||
export function CommentsAnswer(props: {
 | 
			
		||||
  answer: Answer
 | 
			
		||||
  contract: Contract
 | 
			
		||||
  color: string
 | 
			
		||||
}) {
 | 
			
		||||
  const { answer, contract, color } = props
 | 
			
		||||
  const { username, name, text } = answer
 | 
			
		||||
  const answerElementId = `answer-${answer.id}`
 | 
			
		||||
  const router = useRouter()
 | 
			
		||||
  const highlighted = router.asPath.endsWith(`#${answerElementId}`)
 | 
			
		||||
 | 
			
		||||
  const { isReady, asPath } = useRouter()
 | 
			
		||||
  const [highlighted, setHighlighted] = useState(false)
 | 
			
		||||
  const answerRef = useRef<HTMLDivElement>(null)
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    if (highlighted && answerRef.current != null) {
 | 
			
		||||
    if (isReady && asPath.endsWith(`#${answerElementId}`)) {
 | 
			
		||||
      setHighlighted(true)
 | 
			
		||||
    }
 | 
			
		||||
  }, [isReady, asPath, answerElementId])
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    if (highlighted && answerRef.current) {
 | 
			
		||||
      answerRef.current.scrollIntoView(true)
 | 
			
		||||
    }
 | 
			
		||||
  }, [highlighted])
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Col className="bg-greyscale-2 w-fit gap-1 rounded-t-xl rounded-bl-xl py-2 px-4">
 | 
			
		||||
    <Row>
 | 
			
		||||
      <div
 | 
			
		||||
        className="w-2"
 | 
			
		||||
        style={{
 | 
			
		||||
          background: color ? color : '#B1B1C7',
 | 
			
		||||
        }}
 | 
			
		||||
      />
 | 
			
		||||
      <Col className="w-fit bg-gray-100 py-1 pl-2 pr-2">
 | 
			
		||||
        <Row className="gap-2">
 | 
			
		||||
        <Avatar username={username} avatarUrl={avatarUrl} size="xxs" />
 | 
			
		||||
        <div className="text-greyscale-6 text-xs">
 | 
			
		||||
          <div className="text-greyscale-4 text-xs">
 | 
			
		||||
            <UserLink username={username} name={name} /> answered
 | 
			
		||||
            <CopyLinkDateTimeComponent
 | 
			
		||||
              prefix={contract.creatorUsername}
 | 
			
		||||
| 
						 | 
				
			
			@ -38,5 +66,89 @@ export function CommentsAnswer(props: { answer: Answer; contract: Contract }) {
 | 
			
		|||
        </Row>
 | 
			
		||||
        <div className="text-sm">{text}</div>
 | 
			
		||||
      </Col>
 | 
			
		||||
    </Row>
 | 
			
		||||
  )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function FreeResponseComments(props: {
 | 
			
		||||
  contract: FreeResponseContract | MultipleChoiceContract
 | 
			
		||||
  answerResponse: Answer | undefined
 | 
			
		||||
  onCancelAnswerResponse?: () => void
 | 
			
		||||
  topLevelComments: ContractComment[]
 | 
			
		||||
  commentsByParent: Dictionary<[ContractComment, ...ContractComment[]]>
 | 
			
		||||
  tips: CommentTipMap
 | 
			
		||||
}) {
 | 
			
		||||
  const {
 | 
			
		||||
    contract,
 | 
			
		||||
    answerResponse,
 | 
			
		||||
    onCancelAnswerResponse,
 | 
			
		||||
    topLevelComments,
 | 
			
		||||
    commentsByParent,
 | 
			
		||||
    tips,
 | 
			
		||||
  } = props
 | 
			
		||||
  const answersArray = useChartAnswers(contract).map((answer) => answer.text)
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      {answerResponse && (
 | 
			
		||||
        <AnswerCommentInput
 | 
			
		||||
          contract={contract}
 | 
			
		||||
          answerResponse={answerResponse}
 | 
			
		||||
          onCancelAnswerResponse={onCancelAnswerResponse}
 | 
			
		||||
          answersArray={answersArray}
 | 
			
		||||
        />
 | 
			
		||||
      )}
 | 
			
		||||
      {topLevelComments.map((parent) => {
 | 
			
		||||
        if (parent.answerOutcome === undefined) {
 | 
			
		||||
          return (
 | 
			
		||||
            <FeedCommentThread
 | 
			
		||||
              key={parent.id}
 | 
			
		||||
              contract={contract}
 | 
			
		||||
              parentComment={parent}
 | 
			
		||||
              threadComments={sortBy(
 | 
			
		||||
                commentsByParent[parent.id] ?? [],
 | 
			
		||||
                (c) => c.createdTime
 | 
			
		||||
              )}
 | 
			
		||||
              tips={tips}
 | 
			
		||||
            />
 | 
			
		||||
          )
 | 
			
		||||
        }
 | 
			
		||||
        const answer = contract.answers.find(
 | 
			
		||||
          (answer) => answer.id === parent.answerOutcome
 | 
			
		||||
        )
 | 
			
		||||
        if (answer === undefined) {
 | 
			
		||||
          console.error('Could not find answer that matches ID')
 | 
			
		||||
          return <></>
 | 
			
		||||
        }
 | 
			
		||||
        const color = getAnswerColor(answer, answersArray)
 | 
			
		||||
        return (
 | 
			
		||||
          <>
 | 
			
		||||
            <Row className="relative">
 | 
			
		||||
              <div className="absolute -bottom-1 left-1.5">
 | 
			
		||||
                <Curve size={32} strokeWidth={1} color="#D8D8EB" />
 | 
			
		||||
              </div>
 | 
			
		||||
              <div className="ml-[38px]">
 | 
			
		||||
                <CommentsAnswer
 | 
			
		||||
                  answer={answer}
 | 
			
		||||
                  contract={contract}
 | 
			
		||||
                  color={color}
 | 
			
		||||
                />
 | 
			
		||||
              </div>
 | 
			
		||||
            </Row>
 | 
			
		||||
            <div className="w-full pt-1">
 | 
			
		||||
              <FeedCommentThread
 | 
			
		||||
                key={parent.id}
 | 
			
		||||
                contract={contract}
 | 
			
		||||
                parentComment={parent}
 | 
			
		||||
                threadComments={sortBy(
 | 
			
		||||
                  commentsByParent[parent.id] ?? [],
 | 
			
		||||
                  (c) => c.createdTime
 | 
			
		||||
                )}
 | 
			
		||||
                tips={tips}
 | 
			
		||||
              />
 | 
			
		||||
            </div>
 | 
			
		||||
          </>
 | 
			
		||||
        )
 | 
			
		||||
      })}
 | 
			
		||||
    </>
 | 
			
		||||
  )
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,7 @@ export default function Curve({
 | 
			
		|||
      fill="none"
 | 
			
		||||
      stroke={color}
 | 
			
		||||
      strokeWidth={strokeWidth}
 | 
			
		||||
      transform="rotate(90)"
 | 
			
		||||
    >
 | 
			
		||||
      <path d="M5.02,0V5.24c0,4.3,3.49,7.79,7.79,7.79h5.2" />
 | 
			
		||||
    </svg>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user