diff --git a/apps/portal/src/components/resumes/comments/ResumeCommentListItem.tsx b/apps/portal/src/components/resumes/comments/ResumeCommentListItem.tsx index 9a871070..1be17cf7 100644 --- a/apps/portal/src/components/resumes/comments/ResumeCommentListItem.tsx +++ b/apps/portal/src/components/resumes/comments/ResumeCommentListItem.tsx @@ -2,6 +2,7 @@ import { useState } from 'react'; import { FaceSmileIcon } from '@heroicons/react/24/outline'; import ResumeCommentEditForm from './comment/ResumeCommentEditForm'; +import ResumeCommentReplyForm from './comment/ResumeCommentReplyForm'; import ResumeCommentVoteButtons from './comment/ResumeCommentVoteButtons'; import ResumeUserBadges from '../badges/ResumeUserBadges'; import ResumeExpandableText from '../shared/ResumeExpandableText'; @@ -19,6 +20,7 @@ export default function ResumeCommentListItem({ }: ResumeCommentListItemProps) { const isCommentOwner = userId === comment.user.userId; const [isEditingComment, setIsEditingComment] = useState(false); + const [isReplyingComment, setIsReplyingComment] = useState(false); return (
@@ -70,15 +72,34 @@ export default function ResumeCommentListItem({
- {isCommentOwner && !isEditingComment && ( - + {isCommentOwner && !isEditingComment && !isReplyingComment && ( + <> + + + + )}
+ + {/* Replies */} + {isReplyingComment && ( + + )}
diff --git a/apps/portal/src/components/resumes/comments/comment/ResumeCommentReplyForm.tsx b/apps/portal/src/components/resumes/comments/comment/ResumeCommentReplyForm.tsx new file mode 100644 index 00000000..0f2f89e6 --- /dev/null +++ b/apps/portal/src/components/resumes/comments/comment/ResumeCommentReplyForm.tsx @@ -0,0 +1,107 @@ +import type { SubmitHandler } from 'react-hook-form'; +import { useForm } from 'react-hook-form'; +import type { ResumesSection } from '@prisma/client'; +import { Button, TextArea } from '@tih/ui'; + +import { trpc } from '~/utils/trpc'; + +type ResumeCommentEditFormProps = { + parentId: string; + resumeId: string; + section: ResumesSection; + setIsReplyingComment: (value: boolean) => void; +}; + +type IReplyInput = { + description: string; +}; + +export default function ResumeCommentReplyForm({ + parentId, + setIsReplyingComment, + resumeId, + section, +}: ResumeCommentEditFormProps) { + const { + register, + handleSubmit, + setValue, + formState: { errors, isDirty }, + reset, + } = useForm({ + defaultValues: { + description: '', + }, + }); + + const trpcContext = trpc.useContext(); + const commentReplyMutation = trpc.useMutation('resumes.comments.user.reply', { + onSuccess: () => { + // Comment updated, invalidate query to trigger refetch + trpcContext.invalidateQueries(['resumes.comments.list']); + }, + }); + + const onCancel = () => { + reset({ description: '' }); + setIsReplyingComment(false); + }; + + const onSubmit: SubmitHandler = async (data) => { + return commentReplyMutation.mutate( + { + parentId, + resumeId, + section, + ...data, + }, + { + onSuccess: () => { + setIsReplyingComment(false); + }, + }, + ); + }; + + const setFormValue = (value: string) => { + setValue('description', value.trim(), { shouldDirty: true }); + }; + + return ( +
+
+