[offers][feat] offer discussion section (#392)
* [offers][feat] add comment components * [offers][feat] add comment reply components * [offers][feat] offer discussion section * [offers][chore] remove commentspull/394/head
parent
bde445859a
commit
1ed11d9787
@ -0,0 +1,152 @@
|
|||||||
|
import { signIn, useSession } from 'next-auth/react';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { ChatBubbleBottomCenterIcon } from '@heroicons/react/24/outline';
|
||||||
|
import { Button, HorizontalDivider, TextArea } from '@tih/ui';
|
||||||
|
|
||||||
|
import { timeSinceNow } from '~/utils/offers/time';
|
||||||
|
|
||||||
|
import { trpc } from '../../../../utils/trpc';
|
||||||
|
|
||||||
|
import type { Reply } from '~/types/offers';
|
||||||
|
|
||||||
|
type Props = Readonly<{
|
||||||
|
comment: Reply;
|
||||||
|
disableReply?: boolean;
|
||||||
|
handleExpanded?: () => void;
|
||||||
|
isExpanded?: boolean;
|
||||||
|
profileId: string;
|
||||||
|
replyLength?: number;
|
||||||
|
token?: string;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export default function CommentCard({
|
||||||
|
comment: { createdAt, id, message, user },
|
||||||
|
disableReply,
|
||||||
|
handleExpanded,
|
||||||
|
isExpanded,
|
||||||
|
profileId,
|
||||||
|
token = '',
|
||||||
|
replyLength = 0,
|
||||||
|
}: Props) {
|
||||||
|
const { data: session, status } = useSession();
|
||||||
|
const [isReplying, setIsReplying] = useState(false);
|
||||||
|
const [currentReply, setCurrentReply] = useState<string>('');
|
||||||
|
|
||||||
|
const trpcContext = trpc.useContext();
|
||||||
|
const createCommentMutation = trpc.useMutation(['offers.comments.create'], {
|
||||||
|
onSuccess() {
|
||||||
|
trpcContext.invalidateQueries([
|
||||||
|
'offers.comments.getComments',
|
||||||
|
{ profileId },
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleReply() {
|
||||||
|
if (token && token.length > 0) {
|
||||||
|
// If it is with edit permission, send comment to API with username = null
|
||||||
|
createCommentMutation.mutate(
|
||||||
|
{
|
||||||
|
message: currentReply,
|
||||||
|
profileId,
|
||||||
|
replyingToId: id,
|
||||||
|
token,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onSuccess: () => {
|
||||||
|
setCurrentReply('');
|
||||||
|
setIsReplying(false);
|
||||||
|
if (!isExpanded) {
|
||||||
|
handleExpanded?.();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else if (status === 'authenticated') {
|
||||||
|
// If not the OP and logged in, send comment to API
|
||||||
|
createCommentMutation.mutate(
|
||||||
|
{
|
||||||
|
message: currentReply,
|
||||||
|
profileId,
|
||||||
|
replyingToId: id,
|
||||||
|
userId: session.user?.id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onSuccess: () => {
|
||||||
|
setCurrentReply('');
|
||||||
|
setIsReplying(false);
|
||||||
|
if (!isExpanded) {
|
||||||
|
handleExpanded?.();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// If not the OP and not logged in, direct users to log in
|
||||||
|
signIn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="flex pl-2">
|
||||||
|
<div className="flex w-full flex-col">
|
||||||
|
<div className="flex flex-row font-bold">
|
||||||
|
{user?.name ?? 'unknown user'}
|
||||||
|
</div>
|
||||||
|
<div className="mt-2 mb-2 flex flex-row ">{message}</div>
|
||||||
|
<div className="flex flex-row items-center justify-start space-x-4 ">
|
||||||
|
<div className="flex flex-col text-sm font-light text-gray-400">{`${timeSinceNow(
|
||||||
|
createdAt,
|
||||||
|
)} ago`}</div>
|
||||||
|
{replyLength > 0 && (
|
||||||
|
<div
|
||||||
|
className="flex cursor-pointer flex-col text-sm text-purple-600 hover:underline"
|
||||||
|
onClick={handleExpanded}>
|
||||||
|
{isExpanded ? `Hide replies` : `View replies (${replyLength})`}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{!disableReply && (
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<Button
|
||||||
|
icon={ChatBubbleBottomCenterIcon}
|
||||||
|
isLabelHidden={true}
|
||||||
|
label="Reply"
|
||||||
|
size="sm"
|
||||||
|
variant="tertiary"
|
||||||
|
onClick={() => setIsReplying(!isReplying)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{!disableReply && isReplying && (
|
||||||
|
<div className="mt-2 mr-2">
|
||||||
|
<TextArea
|
||||||
|
isLabelHidden={true}
|
||||||
|
label="Comment"
|
||||||
|
placeholder="Type your comment here"
|
||||||
|
resize="none"
|
||||||
|
value={currentReply}
|
||||||
|
onChange={(value) => setCurrentReply(value)}
|
||||||
|
/>
|
||||||
|
<div className="mt-2 flex w-full justify-end">
|
||||||
|
<div className="w-fit">
|
||||||
|
<Button
|
||||||
|
display="block"
|
||||||
|
isLabelHidden={false}
|
||||||
|
isLoading={createCommentMutation.isLoading}
|
||||||
|
label="Reply"
|
||||||
|
size="sm"
|
||||||
|
variant="primary"
|
||||||
|
onClick={handleReply}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<HorizontalDivider />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
import CommentCard from '~/components/offers/profile/comments/CommentCard';
|
||||||
|
|
||||||
|
import type { Reply } from '~/types/offers';
|
||||||
|
|
||||||
|
type Props = Readonly<{
|
||||||
|
comment: Reply;
|
||||||
|
profileId: string;
|
||||||
|
token?: string;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export default function ExpandableCommentCard({
|
||||||
|
comment,
|
||||||
|
profileId,
|
||||||
|
token = '',
|
||||||
|
}: Props) {
|
||||||
|
const [isExpanded, setIsExpanded] = useState(false);
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<CommentCard
|
||||||
|
comment={comment}
|
||||||
|
handleExpanded={() => setIsExpanded(!isExpanded)}
|
||||||
|
isExpanded={isExpanded}
|
||||||
|
profileId={profileId}
|
||||||
|
replyLength={comment.replies?.length ?? 0}
|
||||||
|
token={token}
|
||||||
|
/>
|
||||||
|
{comment.replies && (
|
||||||
|
<div className="pl-8">
|
||||||
|
{isExpanded &&
|
||||||
|
comment.replies.map((reply) => (
|
||||||
|
<CommentCard
|
||||||
|
key={reply.id}
|
||||||
|
comment={reply}
|
||||||
|
disableReply={true}
|
||||||
|
profileId={profileId}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
Loading…
Reference in new issue