Skip to content

Commit

Permalink
[FE] ✨ Feat : 방명록 관련 하위 컴포넌트 임시 구현 (codestates-seb#352)
Browse files Browse the repository at this point in the history
  • Loading branch information
nalsae committed Dec 12, 2023
1 parent 128efd4 commit 7906436
Show file tree
Hide file tree
Showing 3 changed files with 193 additions and 0 deletions.
110 changes: 110 additions & 0 deletions client/src/components/garden/Comment.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
'use client';

import { useParams } from 'next/navigation';
import { useForm } from 'react-hook-form';

import usePostStore from '@/stores/postStore';
import useUserStore from '@/stores/userStore';

import useEditCommentMutation from '@/hooks/mutation/useEditCommentMutation';

import { PostProfile, DateAndControlSection } from '@/components/post';
import CommonButton from '../common/CommonButton';

import { GuestbookDataInfo } from '@/types/data';
import { CommentInputValue } from '@/types/common';

import { COMMENT } from '@/constants/contents';

interface CommentProps {
comment: GuestbookDataInfo | null;
guestbookId: number | null;
}

export default function Comment({ comment, guestbookId }: CommentProps) {
if (!comment || !guestbookId) return null;

const { id } = useParams();

const { editMode, targetId, setEditMode } = usePostStore();
const { userId } = useUserStore();

const { mutate: editComment } = useEditCommentMutation({
guestbookId,
targetId,
});

const {
register,
handleSubmit,
formState: { isSubmitting },
} = useForm<CommentInputValue>({
defaultValues: {
comment: comment.content,
},
});

const isEdit = editMode && String(comment.commentId) === targetId;

const isOwner = userId === String(comment.accountId);

const submitCommentForm = (data: CommentInputValue) => {
editComment(data);
setEditMode(false);
};

return (
<li className="pr-[1rem] mb-8 min-w-[248px] w-full">
<div className="flex justify-between mb-2 relative max-[500px]:items-end">
<PostProfile
userId={comment.guestbookId}
displayName={comment.displayName}
grade={comment.accountGrade}
profileImageUrl={comment.imageUrl}
usage="comment"
/>
<DateAndControlSection
date={new Date(comment?.createdAt)}
isOwner={isOwner}
usage="comment"
ownerId={String(comment.guestbookId)}
targetId={String(comment.guestbookId)}
/>
</div>
<div className="pl-11 max-[550px]:pl-0">
{isEdit ? (
<form onSubmit={handleSubmit(submitCommentForm)}>
<input
autoFocus={true}
className="w-full px-[0.875rem] py-[0.75rem] bg-brown-10 border-2 border-brown-50 rounded-xl text-black-50 text-xs left-3 common-drop-shadow outline-none max-[500px]:py-[0.5rem] max-[500px]:text-[0.5rem]"
{...register('comment', {
maxLength: {
value: COMMENT.maxLength.value,
message: COMMENT.maxLength.errorMessage,
},
})}
/>
{isEdit && (
<div className="flex p-2 justify-end gap-2">
<CommonButton size="sm" type="submit">
수정
</CommonButton>
<CommonButton
size="sm"
type="button"
onClick={() => setEditMode(false)}
disabled={isSubmitting}>
취소
</CommonButton>
</div>
)}
</form>
) : (
<p className="w-full px-[0.875rem] py-[0.75rem] bg-brown-10 border-2 border-brown-50 rounded-xl text-black-50 text-xs left-3 common-drop-shadow max-[500px]:px-[0.6rem] max-[500px]:py-[0.5rem] max-[500px]:text-[0.75rem]">
{comment.content}
</p>
)}
</div>
</li>
);
}
64 changes: 64 additions & 0 deletions client/src/components/garden/CommentForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
'use client';

import { useForm } from 'react-hook-form';
import { motion } from 'framer-motion';
import { ErrorMessage } from '@hookform/error-message';

import useAddGuestbookMutation from '@/hooks/mutation/useAddGuestbookMutation';

import CommentProfileImage from './CommentProfileImage';

import { CommentInputValue } from '@/types/common';

import { COMMENT } from '@/constants/contents';

export default function CommentForm() {
const {
register,
handleSubmit,
reset,
formState: { errors, isSubmitting },
} = useForm<CommentInputValue>();
const { mutate: addGuestbook } = useAddGuestbookMutation();

const submitCommentForm = (data: CommentInputValue) => {
addGuestbook(data);
reset();
};

return (
<form
onSubmit={handleSubmit(submitCommentForm)}
className="relative p-5 w-full h-[90px] flex justify-between items-center gap-3 bg-contain bg-center bg-[url('/assets/img/bg_wood_dark.png')] border-[3px] border-brown-70 rounded-lg shadow-outer/down mb-6 max-[560px]:p-3 max-[560px]:gap-2 max-[560px]:h-[74px]">
<CommentProfileImage />
<input
className="px-[1.125rem] w-full py-[0.6875rem] h-[36px] flex-1 rounded-[50px] text-[0.875rem] leading-[0.875rem] font-normal focus:outline-none shadow-outer/down max-[560px]:px-[0.8rem] max-[560px]:py-[0.4rem] max-[560px]:h-[32px] max-[500px]:text-[0.7rem] "
placeholder="댓글을 입력하세요."
required
{...register('comment', {
maxLength: {
value: COMMENT.maxLength.value,
message: COMMENT.maxLength.errorMessage,
},
})}
/>
<ErrorMessage
errors={errors}
name={'comment'}
render={({ message }) => (
<div className="absolute w-full -bottom-5 text-[0.6rem] leading-3 text-red-50 text-center">
{message}
</div>
)}
/>
<motion.button
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
className="px-[0.6875rem] py-[0.5625rem] bg-contain bg-center bg-[url('/assets/img/bg_wood_light.png')] border-[3px] border-brown-50 rounded-xl text-[1rem] leading-[1rem] font-bold text-brown-40 shadow-outer/down max-[560px]:text-[0.85rem] max-[560px]:px-[0.55rem] max-[560px]:py-[0.5rem] max-[500px]:text-[0.8rem] max-[500px]:px-[0.4rem] max-[500px]:py-[0.3rem]"
type="submit"
disabled={isSubmitting}>
등록
</motion.button>
</form>
);
}
19 changes: 19 additions & 0 deletions client/src/components/garden/CommentProfileImage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import Image from 'next/image';

import useUserStore from '@/stores/userStore';

export default function CommentProfileImage() {
const { profileImageUrl } = useUserStore();
return (
<div className="w-[44px] h-[44px] rounded-[50%] flex justify-center items-center border-brown-10 border-[3px] overflow-hidden shadow-outer/down max-[500px]:hidden">
<Image
src={profileImageUrl || '/assets/img/bg_default_profile.png'}
alt="profile_img"
className="h-full bg-brown-20 object-cover object-center isolate"
width={44}
height={44}
style={{ width: 44, height: 44 }}
/>
</div>
);
}

0 comments on commit 7906436

Please sign in to comment.