import { ContractComment } from 'common/comment' import { groupConsecutive } from 'common/util/array' import { getUserCommentsQuery } from 'web/lib/firebase/comments' import { usePagination } from 'web/hooks/use-pagination' import { SiteLink } from './site-link' import { Row } from './layout/row' import { Avatar } from './avatar' import { RelativeTimestamp } from './relative-timestamp' import { User } from 'common/user' import { Col } from './layout/col' import { Content } from './editor' import { LoadingIndicator } from './loading-indicator' import { UserLink } from 'web/components/user-link' import { PaginationNextPrev } from 'web/components/pagination' type ContractKey = { contractId: string contractSlug: string contractQuestion: string } function contractPath(slug: string) { // by convention this includes the contract creator username, but we don't // have that handy, so we just put /market/ return `/market/${slug}` } export function UserCommentsList(props: { user: User }) { const { user } = props const page = usePagination({ q: getUserCommentsQuery(user.id), pageSize: 50 }) const { isStart, isEnd, getNext, getPrev, getItems, isLoading } = page const pageComments = groupConsecutive(getItems(), (c) => { return { contractId: c.contractId, contractQuestion: c.contractQuestion, contractSlug: c.contractSlug, } }) if (isLoading) { return <LoadingIndicator /> } if (pageComments.length === 0) { if (isStart && isEnd) { return <p>This user hasn't made any comments yet.</p> } else { // this can happen if their comment count is a multiple of page size return <p>No more comments to display.</p> } } return ( <Col className={'bg-white'}> {pageComments.map(({ key, items }, i) => { return <ProfileCommentGroup key={i} groupKey={key} items={items} /> })} <nav className="border-t border-gray-200 px-4 py-3 sm:px-6" aria-label="Pagination" > <PaginationNextPrev prev={!isStart ? 'Previous' : null} next={!isEnd ? 'Next' : null} onClickPrev={getPrev} onClickNext={getNext} scrollToTop={true} /> </nav> </Col> ) } function ProfileCommentGroup(props: { groupKey: ContractKey items: ContractComment[] }) { const { groupKey, items } = props const { contractSlug, contractQuestion } = groupKey const path = contractPath(contractSlug) return ( <div className="border-b p-5"> <SiteLink className="mb-2 block pb-2 font-medium text-indigo-700" href={path} > {contractQuestion} </SiteLink> <Col className="gap-6"> {items.map((c) => ( <ProfileComment key={c.id} comment={c} /> ))} </Col> </div> ) } function ProfileComment(props: { comment: ContractComment }) { const { comment } = props const { text, content, userUsername, userName, userAvatarUrl, createdTime } = comment // TODO: find and attach relevant bets by comment betId at some point return ( <Row className="relative flex items-start space-x-3"> <Avatar username={userUsername} avatarUrl={userAvatarUrl} /> <div className="min-w-0 flex-1"> <p className="mt-0.5 text-sm text-gray-500"> <UserLink className="text-gray-500" username={userUsername} name={userName} />{' '} <RelativeTimestamp time={createdTime} /> </p> <Content content={content || text} smallImage /> </div> </Row> ) }