-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feat] 커뮤니티 카드 컴포넌트 구현 #79
The head ref may contain hidden characters: "29-feat-\uCEE4\uBBA4\uB2C8\uD2F0-\uCE74\uB4DC-\uCEF4\uD3EC\uB10C\uD2B8-\uAD6C\uD604"
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM !
export default function PostCard({ cardData }: PostCardProps) { | ||
const [isPostModalOpen, setIsPostModalOpen] = useState(false); | ||
const handleClickPostModal = () => { | ||
setIsPostModalOpen(true); | ||
}; | ||
const handleClosePostModal = () => { | ||
setIsPostModalOpen(false); | ||
}; | ||
const { | ||
user_nickname: nickname, | ||
created_at: createdAt, | ||
title, | ||
image, | ||
good_count: goodCount, | ||
comment_count: commentCount, | ||
} = cardData; | ||
const nowDate = new Date(); | ||
const createdDate = new Date(createdAt); | ||
const timeToString = calculateTimeDifference(createdDate, nowDate); | ||
|
||
return ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
export default function PostCard({ cardData }: PostCardProps) { | |
const [isPostModalOpen, setIsPostModalOpen] = useState(false); | |
const handleClickPostModal = () => { | |
setIsPostModalOpen(true); | |
}; | |
const handleClosePostModal = () => { | |
setIsPostModalOpen(false); | |
}; | |
const { | |
user_nickname: nickname, | |
created_at: createdAt, | |
title, | |
image, | |
good_count: goodCount, | |
comment_count: commentCount, | |
} = cardData; | |
const nowDate = new Date(); | |
const createdDate = new Date(createdAt); | |
const timeToString = calculateTimeDifference(createdDate, nowDate); | |
return ( | |
export default function PostCard({ cardData }: PostCardProps) { | |
const [isPostModalOpen, setIsPostModalOpen] = useState(false); | |
const { | |
user_nickname: nickname, | |
created_at: createdAt, | |
title, | |
image, | |
good_count: goodCount, | |
comment_count: commentCount, | |
} = cardData; | |
const nowDate = new Date(); | |
const createdDate = new Date(createdAt); | |
const timeToString = calculateTimeDifference(createdDate, nowDate); | |
const handleClickPostModal = () => { | |
setIsPostModalOpen(true); | |
}; | |
const handleClosePostModal = () => { | |
setIsPostModalOpen(false); | |
}; | |
return ( |
import 구문 정리해주신것처럼 함수 안에서도
이런식의 구분이 들어가면 더 읽기 좋을거같아요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
훨씬 보기 편하군여,, 이런 부분도 신경써야겠어요 😃
<div className={cn('container')} onClick={handleContainerClick}> | ||
<div className={cn('icon-and-count')}> | ||
<LikeButton isChecked={isChecked} onClick={handleLikeButtonClick} /> | ||
<p id={cn('count')}>{goodCount > 99 ? '99+' : goodCount}</p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
99라는 숫자는 상수로 선언해도 좋을거같네요
padding: 2rem 0; | ||
border-radius: 0.8rem; | ||
background-color: #111; | ||
color: #fff; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
변수로 사용 부탁드립니다
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
어멋 이 파일 삭제했는데 제 브랜치에 남아있었나봐요,, 좀 전에 만든거라,,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이건 여러곳에서 사용 가능할거같은데
회원정보 변경
부분에 들어갈 경우까지 고려해서 범용 컴포넌트로 만드시면 좋을거같아요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 작업 완료했슴다 나중에 한번 더 pr 리뷰 부탁드려도 될까용가리
<div className={cn('image-div')}> | ||
{profile ? ( | ||
<Image src={profile} alt='프로필 이미지' width={64} height={64} /> | ||
) : ( | ||
<Image src={defaultImage} alt='기본 이미지' width={39} height={36} /> | ||
)} | ||
</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://velog.io/@yung315/nextimage-Error-handling
state와 onError을 사용하면 더 간결하게 사용 가능합니다
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오 대박 Image 태그에 onError 속성이 있다니 맵소사
좋은 정보 증말 감사해요 😊
type ProfileImageProp = { | ||
profileImage: StaticImageData | string | null; | ||
width?: number; | ||
height?: number; | ||
isEditable?: boolean; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
interface로 변경 부탁드려요
alt='프로필 이미지' | ||
width={width} | ||
height={height} | ||
className={cn('profile-image')} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Image 태그에 className이 적용되나요..?
이건 컴포넌트로 만들어진 태그라 props에서 해당 요소를 받아주는지 잘 모르겠네요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오 신기하게 전 됐어요~!! border-radius 넣어줫는데 잘 적용됐어요!!!!
return ( | ||
<label htmlFor='profileInput' className={cn({ label: isEditable })}> | ||
<div className={cn('profile-image-wrapper')}> | ||
<Image |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Image태그에서 layoutShift를 방지하고 싶으면 placeholder='blur'처리까지 넣어주시는게 좋아요
적용하시면 페이지 로딩시 이미지 요소가 있는 위치는 스켈레톤으로 처리 됩니다.
https://haruisshort.tistory.com/302
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오오오 이미지에 아주 빠싹하시네여 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저 이 부분 적용하려했는데 제가 사용하는 부분은 동적인 부분이라 추가적인 설정들이 많이 필요하더라구요,,, 하다가 포기,,,🥺 일단 이 부분 보류하고 추후에 설정해봐도 괜찮을까용?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
넵넵 merge되면 제가 한번 살펴볼게요 동적 이미지에서의 스켈레톤처리가 최적화에서 가장 크게작용합니다
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
네네넹 감사합니도로도로~!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
굿잡~~ 진행도 빠르고 수정도 빠르고 흡수력이 정말 좋으신거 같아용~! 고생하셨슴당~!~!
<p id={cn('user-name')}>{nickname}</p> | ||
<p id={cn('sub-info')}>{timeAgo}</p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
지난번에도 보였던거 같은데 id를 사용하신이유가 무엇일까용??
그리고 id 는 그냥 id = 'user-name'으로 쓰는게 맞지 않을까용?(사실 모르는데 좀 이상하다고 느껴집니다!!) cn 자체가 classname의 줄임말이라서??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오옹오!!!! 구러네요오오오 좀 약간 속에 있는 요소들을 id로 쓰는데className이랑은 안어울리겠네욤,,수정하겠슴니다!!!
요즘은 영은님이 알려주신 그 단축키써서 클래스이름으로만 씁니동,, 그래도 id는 최대한 className으로 써보도록,, 명심하겠슴당
<AuthorCard nickname={nickname} timeAgo={timeToString} /> | ||
<div className={cn('keyboard-image-wrapper')}> | ||
<Image src={ContentImage} className={cn('keyboard-image')} alt='키보드 이미지' /> | ||
{image.length > 1 && <p id={cn('image-count')}>{image.length}</p>} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
진짜 굳이굳이 말하자면 1도 상수처리?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
넹넹넹넹 !!!! 수정하겟슴니다다닷
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
수정안하셔도 됩니둥~~
@@ -44,7 +44,7 @@ export default function ImageInput() { | |||
))} | |||
{selectedImageFile.length < 4 && ( | |||
<label htmlFor='imageInput' className={cn('label-input')}> | |||
<CarmeraIcon /> | |||
<CarmeraIcon fill='#999999' width={46} height={40} /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
동적으로 바뀌는거 아니니까 파일에서 fill 설정해도 되지 않을까 싶습니다?!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이거 ProfileImage 컴포넌트에서도 사용해서 이렇게 했어요오잇
const { | ||
user_nickname: nickname, | ||
created_at: createdAt, | ||
title, | ||
image, | ||
good_count: goodCount, | ||
comment_count: commentCount, | ||
} = cardData; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
와아우~ 저도 써먹어야겠슴다~!!! 나이스하당!!!!!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
야하오 ~
const [isChecked, setIsChecked] = useState(false); | ||
|
||
const handleContainerClick = (e: MouseEvent<HTMLDivElement>) => { | ||
e.stopPropagation(); | ||
}; | ||
|
||
const handleLikeButtonClick = () => { | ||
setIsChecked((prev) => !prev); | ||
}; | ||
return ( | ||
<div className={cn('container')} onClick={handleContainerClick}> | ||
<div className={cn('icon-and-count')}> | ||
<LikeButton isChecked={isChecked} onClick={handleLikeButtonClick} /> | ||
<p id={cn('count')}>{goodCount > MAX_COUNT ? '99+' : goodCount}</p> | ||
</div> | ||
<div className={cn('icon-and-count')}> | ||
<CommentIcon /> | ||
<p id={cn('count')}>{commentCount > MAX_COUNT ? '99+' : commentCount}</p> | ||
</div> | ||
</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
요기는 예진님 버튼 나오면 변경해야 할거 같아요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
깔끔하네용 고생하셨습니다!!👍buttons 폴더만 한번 확인 부탁드려요~~
display: flex; | ||
flex-direction: column; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
여기도 mixin 써주셔도 좋을 것 같아용!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오호옹 넹넹넹!!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오오오잉 이친구들 안지워졌을까용???
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이게,,,제 컴퓨터가 아주 이상해여오,, 충돌인가 에러가 나서 지웠다가 다시 깔았더니 이렇게 소문자로 들어가부렸네요,, 방금도 대소문자랑 싸우고 왔슴니도,, 제 컴퓨터만 증말 왜이럴까요호,,
이 문제가 저인 것 같아서 일단 제가 해결하고 머지해보도록 하겟씁니더,,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
수고하셨습니다!
import myProfileImage from '@/public/images/myProfile.jpeg'; | ||
import ShowMoreIcon from '@/public/svgs/verticalTripleDot.svg'; | ||
|
||
import ProfileImage from '../../../components/ProfileImage/ProfileImage'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이렇게 depth가 깊을 때는 @/로 하는 게 더 좋을 것 같습니다
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오오옹 넹넹!! 자동완성 import 가 저렇게 되었나보네여,, push 하기 전에 확인 꼭꼭 하도록 하겠슴니당!
src/libs/calculateDate.ts
Outdated
if (days > 0) { | ||
return `${days}일 전`; | ||
} else if (hours > 0) { | ||
return `${hours}시간 전`; | ||
} else if (minutes > 0) { | ||
return `${minutes}분 전`; | ||
} else { | ||
return '방금 전'; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return이 있어서 else는 안 붙여도 될 것 같습니다
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오오오 넹네엔ㅇ!
🚀 작업 내용
📝 참고 사항
🖼️ 스크린샷
🚨 관련 이슈 (이슈 번호)
✅ 체크리스트