[resumes][feat] Render replies

pull/401/head
Terence Ho 3 years ago
parent a1445e9de8
commit c112b785d3

@ -1,3 +1,4 @@
import clsx from 'clsx';
import { useState } from 'react'; import { useState } from 'react';
import { FaceSmileIcon } from '@heroicons/react/24/outline'; import { FaceSmileIcon } from '@heroicons/react/24/outline';
@ -23,27 +24,45 @@ export default function ResumeCommentListItem({
const [isReplyingComment, setIsReplyingComment] = useState(false); const [isReplyingComment, setIsReplyingComment] = useState(false);
return ( return (
<div className="border-primary-300 w-11/12 min-w-fit rounded-md border-2 bg-white p-2 drop-shadow-md"> <div
className={clsx(
'min-w-fit rounded-md bg-white ',
!comment.parentId &&
'w-11/12 border-2 border-indigo-300 p-2 drop-shadow-md',
)}>
<div className="flex flex-row space-x-2 p-1 align-top"> <div className="flex flex-row space-x-2 p-1 align-top">
{/* Image Icon */}
{comment.user.image ? ( {comment.user.image ? (
<img <img
alt={comment.user.name ?? 'Reviewer'} alt={comment.user.name ?? 'Reviewer'}
className="mt-1 h-8 w-8 rounded-full" className={clsx(
'mt-1 rounded-full',
comment.parentId ? 'h-6 w-6' : 'h-8 w-8 ',
)}
src={comment.user.image!} src={comment.user.image!}
/> />
) : ( ) : (
<FaceSmileIcon className="h-8 w-8 rounded-full" /> <FaceSmileIcon
className={clsx(
'mt-1 rounded-full',
comment.parentId ? 'h-6 w-6' : 'h-8 w-8 ',
)}
/>
)} )}
<div className="flex w-full flex-col space-y-1"> <div className="flex w-full flex-col space-y-1">
{/* Name and creation time */} {/* Name and creation time */}
<div className="flex flex-row justify-between"> <div className="flex flex-row justify-between">
<div className="flex flex-row items-center space-x-1"> <div className="flex flex-row items-center space-x-1">
<p className="font-medium"> <p
className={clsx(
'font-medium',
!!comment.parentId && 'text-sm',
)}>
{comment.user.name ?? 'Reviewer ABC'} {comment.user.name ?? 'Reviewer ABC'}
</p> </p>
<p className="text-primary-800 text-xs font-medium"> <p className="text-xs font-medium text-indigo-800">
{isCommentOwner ? '(Me)' : ''} {isCommentOwner ? '(Me)' : ''}
</p> </p>
@ -72,26 +91,29 @@ export default function ResumeCommentListItem({
<div className="flex flex-row space-x-1 pt-1 align-middle"> <div className="flex flex-row space-x-1 pt-1 align-middle">
<ResumeCommentVoteButtons commentId={comment.id} userId={userId} /> <ResumeCommentVoteButtons commentId={comment.id} userId={userId} />
{/* Action buttons; only present when not editing/replying */}
{isCommentOwner && !isEditingComment && !isReplyingComment && ( {isCommentOwner && !isEditingComment && !isReplyingComment && (
<> <>
<button <button
className="text-primary-800 hover:text-primary-400 px-1 text-xs" className="px-1 text-xs text-indigo-800 hover:text-indigo-400"
type="button" type="button"
onClick={() => setIsEditingComment(true)}> onClick={() => setIsEditingComment(true)}>
Edit Edit
</button> </button>
{!comment.parentId && (
<button <button
className="text-primary-800 hover:text-primary-400 px-1 text-xs" className="px-1 text-xs text-indigo-800 hover:text-indigo-400"
type="button" type="button"
onClick={() => setIsReplyingComment(true)}> onClick={() => setIsReplyingComment(true)}>
Reply Reply
</button> </button>
)}
</> </>
)} )}
</div> </div>
{/* Replies */} {/* Reply Form */}
{isReplyingComment && ( {isReplyingComment && (
<ResumeCommentReplyForm <ResumeCommentReplyForm
parentId={comment.id} parentId={comment.id}
@ -100,6 +122,30 @@ export default function ResumeCommentListItem({
setIsReplyingComment={setIsReplyingComment} setIsReplyingComment={setIsReplyingComment}
/> />
)} )}
{/* Replies */}
{comment.children.length > 0 && (
// Horizontal Divider
<div className="min-w-fit space-y-1 pt-1">
<div className="relative flex items-center">
<div className="flex-grow border-t border-gray-300" />
<span className="mx-4 flex-shrink text-xs text-gray-400">
Replies
</span>
<div className="flex-grow border-t border-gray-300" />
</div>
{comment.children.map((child) => {
return (
<ResumeCommentListItem
key={child.id}
comment={child}
userId={userId}
/>
);
})}
</div>
)}
</div> </div>
</div> </div>
</div> </div>

@ -69,7 +69,7 @@ export default function ResumeCommentReplyForm({
return ( return (
<form onSubmit={handleSubmit(onSubmit)}> <form onSubmit={handleSubmit(onSubmit)}>
<div className="flex-column mt-1 space-y-2"> <div className="flex-column space-y-2 pt-2">
<TextArea <TextArea
{...(register('description', { {...(register('description', {
required: 'Reply cannot be empty!', required: 'Reply cannot be empty!',

@ -50,6 +50,7 @@ export const resumeCommentsRouter = createRouter().query('list', {
createdAt: child.createdAt, createdAt: child.createdAt,
description: child.description, description: child.description,
id: child.id, id: child.id,
parentId: data.id,
resumeId: child.resumeId, resumeId: child.resumeId,
section: child.section, section: child.section,
updatedAt: child.updatedAt, updatedAt: child.updatedAt,
@ -66,6 +67,7 @@ export const resumeCommentsRouter = createRouter().query('list', {
createdAt: data.createdAt, createdAt: data.createdAt,
description: data.description, description: data.description,
id: data.id, id: data.id,
parentId: data.parentId,
resumeId: data.resumeId, resumeId: data.resumeId,
section: data.section, section: data.section,
updatedAt: data.updatedAt, updatedAt: data.updatedAt,

@ -9,6 +9,7 @@ export type ResumeComment = Readonly<{
createdAt: Date; createdAt: Date;
description: string; description: string;
id: string; id: string;
parentId: string?;
resumeId: string; resumeId: string;
section: ResumesSection; section: ResumesSection;
updatedAt: Date; updatedAt: Date;

Loading…
Cancel
Save