getting comments pretty much looking how I want, now need help on group organizing
This commit is contained in:
parent
4ed1ca7e76
commit
d685f0288b
|
@ -149,81 +149,77 @@ const CommentsTabContent = memo(function CommentsTabContent(props: {
|
|||
</Row>
|
||||
)
|
||||
|
||||
if (contract.outcomeType === 'FREE_RESPONSE') {
|
||||
const sortedAnswers = sortBy(
|
||||
contract.answers,
|
||||
(a) => -getOutcomeProbability(contract, a.id)
|
||||
)
|
||||
const commentsByOutcome = groupBy(
|
||||
sortedComments,
|
||||
(c) => c.answerOutcome ?? c.betOutcome ?? '_'
|
||||
)
|
||||
const generalTopLevelComments = topLevelComments.filter(
|
||||
(c) => c.answerOutcome === undefined && c.betId === undefined
|
||||
)
|
||||
// if (contract.outcomeType === 'FREE_RESPONSE') {
|
||||
// const sortedAnswers = sortBy(
|
||||
// contract.answers,
|
||||
// (a) => -getOutcomeProbability(contract, a.id)
|
||||
// )
|
||||
// const commentsByOutcome = groupBy(
|
||||
// sortedComments,
|
||||
// (c) => c.answerOutcome ?? c.betOutcome ?? '_'
|
||||
// )
|
||||
// const generalTopLevelComments = topLevelComments.filter(
|
||||
// (c) => c.answerOutcome === undefined && c.betId === undefined
|
||||
// )
|
||||
|
||||
return (
|
||||
<>
|
||||
<Col className="flex w-full">
|
||||
<div className="mb-4 w-full border-gray-200" />
|
||||
{sortedAnswers.map((answer) => {
|
||||
const answerComments =
|
||||
commentsByOutcome[answer.number.toString()] ?? []
|
||||
if (answerComments.length > 0) {
|
||||
return (
|
||||
<div key={answer.id} className="relative pb-4">
|
||||
{/* <span
|
||||
className="absolute top-5 left-5 -ml-px h-[calc(100%-2rem)] w-0.5 bg-gray-200"
|
||||
aria-hidden="true"
|
||||
/> */}
|
||||
<FeedAnswerCommentGroup
|
||||
contract={contract}
|
||||
answer={answer}
|
||||
answerComments={
|
||||
commentsByOutcome[answer.number.toString()] ?? []
|
||||
}
|
||||
tips={tips}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
return <></>
|
||||
}
|
||||
})}
|
||||
{sortRow}
|
||||
<ContractCommentInput className="mb-5" contract={contract} />
|
||||
{generalTopLevelComments.map((comment) => (
|
||||
<FeedCommentThread
|
||||
key={comment.id}
|
||||
contract={contract}
|
||||
parentComment={comment}
|
||||
threadComments={commentsByParent[comment.id] ?? []}
|
||||
tips={tips}
|
||||
/>
|
||||
))}
|
||||
</Col>
|
||||
</>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<>
|
||||
{sortRow}
|
||||
<ContractCommentInput className="mb-5" contract={contract} />
|
||||
{topLevelComments.map((parent) => (
|
||||
<FeedCommentThread
|
||||
key={parent.id}
|
||||
contract={contract}
|
||||
parentComment={parent}
|
||||
threadComments={sortBy(
|
||||
commentsByParent[parent.id] ?? [],
|
||||
(c) => c.createdTime
|
||||
)}
|
||||
tips={tips}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
}
|
||||
// return (
|
||||
// <>
|
||||
// <Col className="flex w-full">
|
||||
// <div className="mb-4 w-full border-gray-200" />
|
||||
// {sortedAnswers.map((answer) => {
|
||||
// const answerComments =
|
||||
// commentsByOutcome[answer.number.toString()] ?? []
|
||||
// if (answerComments.length > 0) {
|
||||
// return (
|
||||
// <div key={answer.id} className="relative pb-4">
|
||||
// <FeedAnswerCommentGroup
|
||||
// contract={contract}
|
||||
// answer={answer}
|
||||
// answerComments={
|
||||
// commentsByOutcome[answer.number.toString()] ?? []
|
||||
// }
|
||||
// tips={tips}
|
||||
// />
|
||||
// </div>
|
||||
// )
|
||||
// } else {
|
||||
// return <></>
|
||||
// }
|
||||
// })}
|
||||
// <ContractCommentInput className="mb-5" contract={contract} />
|
||||
// {sortRow}
|
||||
// {generalTopLevelComments.map((comment) => (
|
||||
// <FeedCommentThread
|
||||
// key={comment.id}
|
||||
// contract={contract}
|
||||
// parentComment={comment}
|
||||
// threadComments={commentsByParent[comment.id] ?? []}
|
||||
// tips={tips}
|
||||
// />
|
||||
// ))}
|
||||
// </Col>
|
||||
// </>
|
||||
// )
|
||||
// } else {
|
||||
return (
|
||||
<>
|
||||
{sortRow}
|
||||
<ContractCommentInput className="mb-5" contract={contract} />
|
||||
{topLevelComments.map((parent) => (
|
||||
<FeedCommentThread
|
||||
key={parent.id}
|
||||
contract={contract}
|
||||
parentComment={parent}
|
||||
threadComments={sortBy(
|
||||
commentsByParent[parent.id] ?? [],
|
||||
(c) => c.createdTime
|
||||
)}
|
||||
tips={tips}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
// }
|
||||
})
|
||||
|
||||
const BetsTabContent = memo(function BetsTabContent(props: {
|
||||
|
|
|
@ -37,7 +37,7 @@ export function TipButton(props: {
|
|||
<Col className={'relative items-center sm:flex-row'}>
|
||||
<HeartIcon
|
||||
className={clsx(
|
||||
'h-5 w-5 sm:h-6 sm:w-6',
|
||||
'h-5 w-5',
|
||||
totalTipped > 0 ? 'mr-2' : '',
|
||||
userTipped ? 'fill-green-700 text-green-700' : ''
|
||||
)}
|
||||
|
|
|
@ -51,15 +51,7 @@ export function FeedAnswerCommentGroup(props: {
|
|||
ref={answerRef}
|
||||
id={answerElementId}
|
||||
>
|
||||
<Col>
|
||||
<Avatar username={username} avatarUrl={avatarUrl} size="xs" />
|
||||
{seeReplies && (
|
||||
<span
|
||||
className="mx-auto h-full w-0.5 bg-gray-200"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
)}
|
||||
</Col>
|
||||
<Avatar username={username} avatarUrl={avatarUrl} size="sm" />
|
||||
<Col className="min-w-0 flex-1">
|
||||
<div className="text-greyscale-6 text-xs">
|
||||
<UserLink username={username} name={name} /> answered
|
||||
|
@ -93,7 +85,7 @@ export function FeedAnswerCommentGroup(props: {
|
|||
</Col>
|
||||
</Row>
|
||||
{seeReplies && (
|
||||
<Col className="gap-3 pl-1">
|
||||
<Col className="w-full gap-3 pl-1">
|
||||
{answerComments.map((comment) => (
|
||||
<FeedComment
|
||||
key={comment.id}
|
||||
|
|
|
@ -20,6 +20,8 @@ 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 { Button } from '../button'
|
||||
|
||||
export type ReplyTo = { id: string; username: string }
|
||||
|
||||
|
@ -34,10 +36,6 @@ export function FeedCommentThread(props: {
|
|||
|
||||
return (
|
||||
<Col className="relative w-full items-stretch gap-3 pb-4">
|
||||
<span
|
||||
className="absolute top-5 left-4 -ml-px h-[calc(100%-2rem)] w-0.5 bg-gray-200"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
{[parentComment].concat(threadComments).map((comment, commentIdx) => (
|
||||
<FeedComment
|
||||
key={comment.id}
|
||||
|
@ -76,26 +74,7 @@ export function FeedComment(props: {
|
|||
onReplyClick?: () => void
|
||||
}) {
|
||||
const { contract, comment, tips, indent, onReplyClick } = props
|
||||
const {
|
||||
text,
|
||||
content,
|
||||
userUsername,
|
||||
userName,
|
||||
userAvatarUrl,
|
||||
commenterPositionProb,
|
||||
commenterPositionShares,
|
||||
commenterPositionOutcome,
|
||||
createdTime,
|
||||
bountiesAwarded,
|
||||
} = comment
|
||||
const betOutcome = comment.betOutcome
|
||||
let bought: string | undefined
|
||||
let money: string | undefined
|
||||
if (comment.betAmount != null) {
|
||||
bought = comment.betAmount >= 0 ? 'bought' : 'sold'
|
||||
money = formatMoney(Math.abs(comment.betAmount))
|
||||
}
|
||||
const totalAwarded = bountiesAwarded ?? 0
|
||||
const { text, content, userUsername, userAvatarUrl } = comment
|
||||
|
||||
const router = useRouter()
|
||||
const highlighted = router.asPath.endsWith(`#${comment.id}`)
|
||||
|
@ -107,88 +86,64 @@ export function FeedComment(props: {
|
|||
}
|
||||
}, [highlighted])
|
||||
|
||||
const [showActions, setShowActions] = useState(false)
|
||||
|
||||
return (
|
||||
<Row
|
||||
ref={commentRef}
|
||||
id={comment.id}
|
||||
className={clsx(
|
||||
'relative',
|
||||
indent ? 'ml-6' : '',
|
||||
'hover:bg-greyscale-1 gap-2 transition-colors',
|
||||
indent ? 'ml-8' : '',
|
||||
highlighted ? `-m-1.5 rounded bg-indigo-500/[0.2] p-1.5` : ''
|
||||
)}
|
||||
onMouseOver={() => setShowActions(true)}
|
||||
onMouseLeave={() => setShowActions(false)}
|
||||
>
|
||||
{/*draw a gray line from the comment to the left:*/}
|
||||
{indent ? (
|
||||
<span
|
||||
className="bg-greyscale-2 absolute -left-1 -ml-[1px] mt-[0.8rem] h-2 w-0.5 rotate-90"
|
||||
aria-hidden="true"
|
||||
<Col className={clsx(indent ? '-ml-3' : '')}>
|
||||
<Avatar
|
||||
size={indent ? 'xs' : 'sm'}
|
||||
username={userUsername}
|
||||
avatarUrl={userAvatarUrl}
|
||||
/>
|
||||
) : null}
|
||||
<Avatar size="xs" username={userUsername} avatarUrl={userAvatarUrl} />
|
||||
<div>
|
||||
<div className="text-greyscale-6 mt-0.5 text-xs">
|
||||
<UserLink username={userUsername} name={userName} />{' '}
|
||||
<span className="text-greyscale-4">
|
||||
{comment.betId == null &&
|
||||
commenterPositionProb != null &&
|
||||
commenterPositionOutcome != null &&
|
||||
commenterPositionShares != null &&
|
||||
commenterPositionShares > 0 &&
|
||||
contract.outcomeType !== 'NUMERIC' && (
|
||||
<>
|
||||
{'is '}
|
||||
<CommentStatus
|
||||
prob={commenterPositionProb}
|
||||
outcome={commenterPositionOutcome}
|
||||
contract={contract}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{bought} {money}
|
||||
{contract.outcomeType !== 'FREE_RESPONSE' && betOutcome && (
|
||||
<>
|
||||
{' '}
|
||||
of{' '}
|
||||
<OutcomeLabel
|
||||
outcome={betOutcome ? betOutcome : ''}
|
||||
contract={contract}
|
||||
truncate="short"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
<CopyLinkDateTimeComponent
|
||||
prefix={contract.creatorUsername}
|
||||
slug={contract.slug}
|
||||
createdTime={createdTime}
|
||||
elementId={comment.id}
|
||||
{indent && (
|
||||
<span
|
||||
className="bg-greyscale-2 mx-auto h-full w-0.5"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
{totalAwarded > 0 && (
|
||||
<span className=" text-primary ml-2 text-sm">
|
||||
+{formatMoney(totalAwarded)}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<Content
|
||||
className="mt-2 text-[12px] text-gray-700"
|
||||
content={content || text}
|
||||
smallImage
|
||||
/>
|
||||
<Row className="mt-2 items-center gap-6 text-xs text-gray-500">
|
||||
{onReplyClick && (
|
||||
<button
|
||||
className="font-bold hover:underline"
|
||||
onClick={onReplyClick}
|
||||
>
|
||||
Reply
|
||||
</button>
|
||||
)}
|
||||
{tips && <Tipper comment={comment} tips={tips} />}
|
||||
{(contract.openCommentBounties ?? 0) > 0 && (
|
||||
<AwardBountyButton comment={comment} contract={contract} />
|
||||
)}
|
||||
)}
|
||||
</Col>
|
||||
<Col className="w-full">
|
||||
<FeedCommentHeader comment={comment} contract={contract} />
|
||||
<Row>
|
||||
<Content
|
||||
className="text-greyscale-7 mt-2 grow text-[14px]"
|
||||
content={content || text}
|
||||
smallImage
|
||||
/>
|
||||
<Row
|
||||
className={clsx(
|
||||
'ml-2 items-center gap-2 text-xs text-gray-500 transition-opacity',
|
||||
showActions ? '' : 'opacity-0'
|
||||
)}
|
||||
>
|
||||
{onReplyClick && (
|
||||
<Button
|
||||
className="font-bold hover:underline"
|
||||
onClick={onReplyClick}
|
||||
size="2xs"
|
||||
color="gray-white"
|
||||
>
|
||||
<ReplyIcon className="h-5 w-5" />
|
||||
</Button>
|
||||
)}
|
||||
{tips && <Tipper comment={comment} tips={tips} />}
|
||||
{(contract.openCommentBounties ?? 0) > 0 && (
|
||||
<AwardBountyButton comment={comment} contract={contract} />
|
||||
)}
|
||||
</Row>
|
||||
</Row>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
)
|
||||
}
|
||||
|
@ -246,3 +201,74 @@ export function ContractCommentInput(props: {
|
|||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export function FeedCommentHeader(props: {
|
||||
comment: ContractComment
|
||||
contract: Contract
|
||||
}) {
|
||||
const { comment, contract } = props
|
||||
const {
|
||||
userUsername,
|
||||
userName,
|
||||
commenterPositionProb,
|
||||
commenterPositionShares,
|
||||
commenterPositionOutcome,
|
||||
createdTime,
|
||||
bountiesAwarded,
|
||||
} = comment
|
||||
const betOutcome = comment.betOutcome
|
||||
let bought: string | undefined
|
||||
let money: string | undefined
|
||||
if (comment.betAmount != null) {
|
||||
bought = comment.betAmount >= 0 ? 'bought' : 'sold'
|
||||
money = formatMoney(Math.abs(comment.betAmount))
|
||||
}
|
||||
const totalAwarded = bountiesAwarded ?? 0
|
||||
return (
|
||||
<Row>
|
||||
<div className="text-greyscale-6 mt-0.5 text-xs">
|
||||
<UserLink username={userUsername} name={userName} />{' '}
|
||||
<span className="text-greyscale-4">
|
||||
{comment.betId == null &&
|
||||
commenterPositionProb != null &&
|
||||
commenterPositionOutcome != null &&
|
||||
commenterPositionShares != null &&
|
||||
commenterPositionShares > 0 &&
|
||||
contract.outcomeType !== 'NUMERIC' && (
|
||||
<>
|
||||
{'is '}
|
||||
<CommentStatus
|
||||
prob={commenterPositionProb}
|
||||
outcome={commenterPositionOutcome}
|
||||
contract={contract}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{bought} {money}
|
||||
{contract.outcomeType !== 'FREE_RESPONSE' && betOutcome && (
|
||||
<>
|
||||
{' '}
|
||||
of{' '}
|
||||
<OutcomeLabel
|
||||
outcome={betOutcome ? betOutcome : ''}
|
||||
contract={contract}
|
||||
truncate="short"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
<CopyLinkDateTimeComponent
|
||||
prefix={contract.creatorUsername}
|
||||
slug={contract.slug}
|
||||
createdTime={createdTime}
|
||||
elementId={comment.id}
|
||||
/>
|
||||
{totalAwarded > 0 && (
|
||||
<span className=" text-primary ml-2 text-sm">
|
||||
+{formatMoney(totalAwarded)}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</Row>
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user