getting comments pretty much looking how I want, now need help on group organizing

This commit is contained in:
ingawei 2022-10-05 23:24:20 -07:00
parent 4ed1ca7e76
commit d685f0288b
4 changed files with 194 additions and 180 deletions

View File

@ -149,62 +149,58 @@ const CommentsTabContent = memo(function CommentsTabContent(props: {
</Row> </Row>
) )
if (contract.outcomeType === 'FREE_RESPONSE') { // if (contract.outcomeType === 'FREE_RESPONSE') {
const sortedAnswers = sortBy( // const sortedAnswers = sortBy(
contract.answers, // contract.answers,
(a) => -getOutcomeProbability(contract, a.id) // (a) => -getOutcomeProbability(contract, a.id)
) // )
const commentsByOutcome = groupBy( // const commentsByOutcome = groupBy(
sortedComments, // sortedComments,
(c) => c.answerOutcome ?? c.betOutcome ?? '_' // (c) => c.answerOutcome ?? c.betOutcome ?? '_'
) // )
const generalTopLevelComments = topLevelComments.filter( // const generalTopLevelComments = topLevelComments.filter(
(c) => c.answerOutcome === undefined && c.betId === undefined // (c) => c.answerOutcome === undefined && c.betId === undefined
) // )
return ( // return (
<> // <>
<Col className="flex w-full"> // <Col className="flex w-full">
<div className="mb-4 w-full border-gray-200" /> // <div className="mb-4 w-full border-gray-200" />
{sortedAnswers.map((answer) => { // {sortedAnswers.map((answer) => {
const answerComments = // const answerComments =
commentsByOutcome[answer.number.toString()] ?? [] // commentsByOutcome[answer.number.toString()] ?? []
if (answerComments.length > 0) { // if (answerComments.length > 0) {
return ( // return (
<div key={answer.id} className="relative pb-4"> // <div key={answer.id} className="relative pb-4">
{/* <span // <FeedAnswerCommentGroup
className="absolute top-5 left-5 -ml-px h-[calc(100%-2rem)] w-0.5 bg-gray-200" // contract={contract}
aria-hidden="true" // answer={answer}
/> */} // answerComments={
<FeedAnswerCommentGroup // commentsByOutcome[answer.number.toString()] ?? []
contract={contract} // }
answer={answer} // tips={tips}
answerComments={ // />
commentsByOutcome[answer.number.toString()] ?? [] // </div>
} // )
tips={tips} // } else {
/> // return <></>
</div> // }
) // })}
} else { // <ContractCommentInput className="mb-5" contract={contract} />
return <></> // {sortRow}
} // {generalTopLevelComments.map((comment) => (
})} // <FeedCommentThread
{sortRow} // key={comment.id}
<ContractCommentInput className="mb-5" contract={contract} /> // contract={contract}
{generalTopLevelComments.map((comment) => ( // parentComment={comment}
<FeedCommentThread // threadComments={commentsByParent[comment.id] ?? []}
key={comment.id} // tips={tips}
contract={contract} // />
parentComment={comment} // ))}
threadComments={commentsByParent[comment.id] ?? []} // </Col>
tips={tips} // </>
/> // )
))} // } else {
</Col>
</>
)
} else {
return ( return (
<> <>
{sortRow} {sortRow}
@ -223,7 +219,7 @@ const CommentsTabContent = memo(function CommentsTabContent(props: {
))} ))}
</> </>
) )
} // }
}) })
const BetsTabContent = memo(function BetsTabContent(props: { const BetsTabContent = memo(function BetsTabContent(props: {

View File

@ -37,7 +37,7 @@ export function TipButton(props: {
<Col className={'relative items-center sm:flex-row'}> <Col className={'relative items-center sm:flex-row'}>
<HeartIcon <HeartIcon
className={clsx( className={clsx(
'h-5 w-5 sm:h-6 sm:w-6', 'h-5 w-5',
totalTipped > 0 ? 'mr-2' : '', totalTipped > 0 ? 'mr-2' : '',
userTipped ? 'fill-green-700 text-green-700' : '' userTipped ? 'fill-green-700 text-green-700' : ''
)} )}

View File

@ -51,15 +51,7 @@ export function FeedAnswerCommentGroup(props: {
ref={answerRef} ref={answerRef}
id={answerElementId} id={answerElementId}
> >
<Col> <Avatar username={username} avatarUrl={avatarUrl} size="sm" />
<Avatar username={username} avatarUrl={avatarUrl} size="xs" />
{seeReplies && (
<span
className="mx-auto h-full w-0.5 bg-gray-200"
aria-hidden="true"
/>
)}
</Col>
<Col className="min-w-0 flex-1"> <Col className="min-w-0 flex-1">
<div className="text-greyscale-6 text-xs"> <div className="text-greyscale-6 text-xs">
<UserLink username={username} name={name} /> answered <UserLink username={username} name={name} /> answered
@ -93,7 +85,7 @@ export function FeedAnswerCommentGroup(props: {
</Col> </Col>
</Row> </Row>
{seeReplies && ( {seeReplies && (
<Col className="gap-3 pl-1"> <Col className="w-full gap-3 pl-1">
{answerComments.map((comment) => ( {answerComments.map((comment) => (
<FeedComment <FeedComment
key={comment.id} key={comment.id}

View File

@ -20,6 +20,8 @@ import { Editor } from '@tiptap/react'
import { UserLink } from 'web/components/user-link' import { UserLink } from 'web/components/user-link'
import { CommentInput } from '../comment-input' import { CommentInput } from '../comment-input'
import { AwardBountyButton } from 'web/components/award-bounty-button' 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 } export type ReplyTo = { id: string; username: string }
@ -34,10 +36,6 @@ export function FeedCommentThread(props: {
return ( return (
<Col className="relative w-full items-stretch gap-3 pb-4"> <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) => ( {[parentComment].concat(threadComments).map((comment, commentIdx) => (
<FeedComment <FeedComment
key={comment.id} key={comment.id}
@ -76,26 +74,7 @@ export function FeedComment(props: {
onReplyClick?: () => void onReplyClick?: () => void
}) { }) {
const { contract, comment, tips, indent, onReplyClick } = props const { contract, comment, tips, indent, onReplyClick } = props
const { const { text, content, userUsername, userAvatarUrl } = comment
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 router = useRouter() const router = useRouter()
const highlighted = router.asPath.endsWith(`#${comment.id}`) const highlighted = router.asPath.endsWith(`#${comment.id}`)
@ -107,88 +86,64 @@ export function FeedComment(props: {
} }
}, [highlighted]) }, [highlighted])
const [showActions, setShowActions] = useState(false)
return ( return (
<Row <Row
ref={commentRef} ref={commentRef}
id={comment.id} id={comment.id}
className={clsx( className={clsx(
'relative', 'hover:bg-greyscale-1 gap-2 transition-colors',
indent ? 'ml-6' : '', indent ? 'ml-8' : '',
highlighted ? `-m-1.5 rounded bg-indigo-500/[0.2] p-1.5` : '' 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:*/} <Col className={clsx(indent ? '-ml-3' : '')}>
{indent ? ( <Avatar
size={indent ? 'xs' : 'sm'}
username={userUsername}
avatarUrl={userAvatarUrl}
/>
{indent && (
<span <span
className="bg-greyscale-2 absolute -left-1 -ml-[1px] mt-[0.8rem] h-2 w-0.5 rotate-90" className="bg-greyscale-2 mx-auto h-full w-0.5"
aria-hidden="true" aria-hidden="true"
/> />
) : 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} </Col>
{contract.outcomeType !== 'FREE_RESPONSE' && betOutcome && ( <Col className="w-full">
<> <FeedCommentHeader comment={comment} contract={contract} />
{' '} <Row>
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>
<Content <Content
className="mt-2 text-[12px] text-gray-700" className="text-greyscale-7 mt-2 grow text-[14px]"
content={content || text} content={content || text}
smallImage smallImage
/> />
<Row className="mt-2 items-center gap-6 text-xs text-gray-500"> <Row
className={clsx(
'ml-2 items-center gap-2 text-xs text-gray-500 transition-opacity',
showActions ? '' : 'opacity-0'
)}
>
{onReplyClick && ( {onReplyClick && (
<button <Button
className="font-bold hover:underline" className="font-bold hover:underline"
onClick={onReplyClick} onClick={onReplyClick}
size="2xs"
color="gray-white"
> >
Reply <ReplyIcon className="h-5 w-5" />
</button> </Button>
)} )}
{tips && <Tipper comment={comment} tips={tips} />} {tips && <Tipper comment={comment} tips={tips} />}
{(contract.openCommentBounties ?? 0) > 0 && ( {(contract.openCommentBounties ?? 0) > 0 && (
<AwardBountyButton comment={comment} contract={contract} /> <AwardBountyButton comment={comment} contract={contract} />
)} )}
</Row> </Row>
</div> </Row>
</Col>
</Row> </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>
)
}