- 0 ? reviewImages[0].imgUrl : keydeukImg)}
+ 0 ? reviewImages[0].imgUrl : keydeukImg)}
alt='키보드 이미지'
- fill
- onError={() => setClickedImage('')}
- className={cn('selected-image-wrapper')}
- sizes='(max-width: 1200px) 100%'
- priority
- placeholder={IMAGE_BLUR.placeholder}
- blurDataURL={IMAGE_BLUR.blurDataURL}
+ width={493}
+ height={reviewImages.length > 1 ? 536 : 604}
/>
{reviewImages.length > 1 && (
@@ -281,12 +296,17 @@ export default function PostCardDetailModal({ cardId, onClose, isMine, commentCo
{title}
{content}
@@ -299,7 +319,11 @@ export default function PostCardDetailModal({ cardId, onClose, isMine, commentCo
key={comment.id}
cardId={cardId}
commentData={comment}
- ref={lastCommentId === comment.id ? lastCommentRef : null}
+ ref={setCommentRefType(comment.id)}
+ onOpenPopOver={handleOpenCommentPopOver}
+ onClosePopOver={handleCloseCommentPopOver}
+ isOpenedPopOver={clickedPopOverCommentId === comment.id}
+ onOpenProfileCard={handleOpenCommentProfileCard}
/>
))}
{isCommentLoading && }
diff --git a/src/app/community/_components/SortDropdown.module.scss b/src/app/community/_components/SortDropdown.module.scss
new file mode 100644
index 00000000..60d77ccb
--- /dev/null
+++ b/src/app/community/_components/SortDropdown.module.scss
@@ -0,0 +1,4 @@
+.container {
+ width: min-content;
+ margin-left: auto;
+}
diff --git a/src/app/community/_components/SortDropdown.tsx b/src/app/community/_components/SortDropdown.tsx
index 0b0766f0..7d400b57 100644
--- a/src/app/community/_components/SortDropdown.tsx
+++ b/src/app/community/_components/SortDropdown.tsx
@@ -1,14 +1,21 @@
'use client';
+import classNames from 'classnames/bind';
import { useRouter } from 'next/navigation';
import { useState } from 'react';
+import { useQueryClient } from '@tanstack/react-query';
import { Dropdown } from '@/components';
import { COMMUNITY_REVIEW_SORT_OPTIONS } from '@/constants/dropdownOptions';
+import styles from './SortDropdown.module.scss';
+
+const cn = classNames.bind(styles);
+
export default function SortDropdown() {
const [selectedOption, setSelectedOption] = useState(COMMUNITY_REVIEW_SORT_OPTIONS[0].label);
const router = useRouter();
+ const queryClient = useQueryClient();
const updateQuery = (queryValue: string) => {
const query = new URLSearchParams(window.location.search);
@@ -23,14 +30,19 @@ export default function SortDropdown() {
return;
}
updateQuery(queryValue);
+ queryClient.invalidateQueries({
+ queryKey: ['postCardsList'],
+ });
};
return (
-
option.label)}
- sizeVariant='xs'
- onChange={handleDropdownChange}
- value={selectedOption}
- />
+
+ option.label)}
+ sizeVariant='xs'
+ onChange={handleDropdownChange}
+ value={selectedOption}
+ />
+
);
}
diff --git a/src/app/community/_components/UserProfileCard.module.scss b/src/app/community/_components/UserProfileCard.module.scss
new file mode 100644
index 00000000..7fe918be
--- /dev/null
+++ b/src/app/community/_components/UserProfileCard.module.scss
@@ -0,0 +1,82 @@
+.user-detail-profile-card {
+ display: flex;
+ position: absolute;
+ z-index: $zindex-popover;
+ top: 6rem;
+ left: 0;
+ width: 45rem;
+ height: 15rem;
+ padding: 1rem;
+ animation: fade-in 0.5s cubic-bezier(0.39, 0.575, 0.565, 1) both;
+ border: 0.2rem solid $gray-20;
+ border-radius: 1rem;
+ background-color: white;
+ box-shadow: 0 0 1.5rem 0 rgb(0 0 0 / 35%);
+ gap: 1rem;
+}
+
+.loading-div {
+ @include flex-center;
+}
+
+.above-profile {
+ top: -16rem;
+}
+
+.display-none {
+ display: none;
+}
+
+.profile-image {
+ position: relative;
+ width: 12rem;
+ height: 100%;
+ overflow: hidden;
+ border-radius: 0.8rem;
+ background-color: $gray-10;
+ object-fit: cover;
+}
+
+.info-wrapper {
+ @include flex-column(0.2rem);
+
+ height: 100%;
+ padding-left: 1rem;
+ border-left: 0.2rem solid $gray-20;
+}
+
+.info-wrapper p {
+ @include pretendard-14-400;
+
+ & > strong {
+ @include pretendard-14-600;
+ }
+}
+
+.info-wrapper .nickname {
+ @include pretendard-20-700;
+}
+
+.not-found-text {
+ @include pretendard-20-700;
+}
+
+@keyframes fade-in {
+ 0% {
+ opacity: 0;
+ }
+
+ 100% {
+ opacity: 1;
+ }
+}
+
+@keyframes fade-out {
+ 0% {
+ opacity: 1;
+ }
+
+ 100% {
+ opacity: 0;
+ }
+}
diff --git a/src/app/community/_components/UserProfileCard.tsx b/src/app/community/_components/UserProfileCard.tsx
new file mode 100644
index 00000000..b88a7c43
--- /dev/null
+++ b/src/app/community/_components/UserProfileCard.tsx
@@ -0,0 +1,87 @@
+'use client';
+
+import classNames from 'classnames/bind';
+import { forwardRef, useEffect, useState } from 'react';
+import { useQuery, useQueryClient } from '@tanstack/react-query';
+import Image from 'next/image';
+
+import { getOthersInfo } from '@/api/usersAPI';
+import { SpinLoading, keydeukProfileImg } from '@/public/index';
+
+import styles from './UserProfileCard.module.scss';
+
+const cn = classNames.bind(styles);
+
+interface UserProfileCardProps {
+ isOpenProfileCard: boolean;
+ userId: number;
+ positionTop?: number;
+}
+export default forwardRef(function UserProfileCard(
+ { isOpenProfileCard, userId, positionTop },
+ ref,
+) {
+ const {
+ data: userInfo,
+ refetch,
+ isFetching,
+ } = useQuery({
+ queryKey: ['clickedUserInfo'],
+ queryFn: () => getOthersInfo(userId),
+ enabled: false,
+ });
+ const queryClient = useQueryClient();
+
+ const [isAboveProfile, setIsAboveProfile] = useState(false);
+
+ useEffect(() => {
+ const VIEWPORT_HEIGHT = window.innerHeight;
+
+ if (isOpenProfileCard && positionTop && positionTop > VIEWPORT_HEIGHT / 2) {
+ setIsAboveProfile(true);
+ }
+ }, [isOpenProfileCard, positionTop, isAboveProfile]);
+
+ useEffect(() => {
+ queryClient.removeQueries({ queryKey: ['clickedUserInfo'] });
+ refetch();
+ }, [userId, refetch, isOpenProfileCard, queryClient]);
+
+ return positionTop && positionTop === 0 ? null : (
+ e.stopPropagation()}
+ >
+ {isFetching ? (
+
+ ) : (
+ <>
+
+
+
+
+
{userInfo?.nickname || '사용자를 찾을 수 없습니다.'}
+
+ email: {userInfo?.email}
+
+
+ birthday: {userInfo?.birth}
+
+
+ phone: {userInfo?.phone}
+
+
+ gender: {userInfo?.gender}
+
+
+ >
+ )}
+
+ );
+});
diff --git a/src/app/community/_components/WritePostButton.tsx b/src/app/community/_components/WritePostButton.tsx
index ba8aa756..245016fe 100644
--- a/src/app/community/_components/WritePostButton.tsx
+++ b/src/app/community/_components/WritePostButton.tsx
@@ -11,33 +11,53 @@ import Dialog from '@/components/Dialog/Dialog';
import { ROUTER } from '@/constants/route';
import WriteEditModal from '@/components/WriteEditModal/WriteEditModal';
import type { PostCardDetailModalCustomKeyboardType } from '@/types/CommunityTypes';
+import type { Users } from '@/types/userType';
import { getCustomOrderList } from '@/api/communityAPI';
-import styles from './WritePostButton.module.scss';
+import SignInModal from '@/components/SignInModal/SignInModal';
import OrderListModal from './OrderListModal';
+import styles from './WritePostButton.module.scss';
+
const cn = classNames.bind(styles);
+interface UserDataType {
+ data: Users;
+ status: string;
+ message: string;
+}
+
export default function WritePostButton() {
const queryClient = useQueryClient();
const router = useRouter();
const [isOpenOrderListModal, setIsOpenOrderListModal] = useState(false);
+ const [isOpenSignInModal, setIsOpenSignInModal] = useState(false);
const [isOpenReviewModal, setIsOpenReviewModal] = useState(false);
const [selectedOrder, setSelectedOrder] = useState(null);
- const { data: orderListData } = useQuery({
+ const { data: orderListData, refetch: refetchCustomOrderList } = useQuery({
queryKey: ['orderList'],
queryFn: getCustomOrderList,
+ enabled: false,
});
- const handleClickProductList = (i: number) => {
- setSelectedOrder(orderListData.data[i]);
- };
+ const handleClickButton = () => {
+ const userData = queryClient.getQueryData(['userData']);
+ queryClient.invalidateQueries({ queryKey: ['orderList'] });
+
+ if (!userData?.data) {
+ setIsOpenSignInModal(true);
+ return;
+ }
- const openOrderListModal = () => {
+ refetchCustomOrderList();
setIsOpenOrderListModal(true);
};
+ const handleClickProductList = (i: number) => {
+ setSelectedOrder(orderListData.data[i]);
+ };
+
const closeOrderListModal = () => {
setIsOpenOrderListModal(false);
};
@@ -60,7 +80,14 @@ export default function WritePostButton() {
return (
-
);
}
diff --git a/src/app/community/layout.module.scss b/src/app/community/layout.module.scss
index 6cbbe838..1d84c216 100644
--- a/src/app/community/layout.module.scss
+++ b/src/app/community/layout.module.scss
@@ -1,8 +1,7 @@
.container {
width: 100%;
- height: 100vh;
- padding: 12.8rem 12rem 0;
- overflow: auto;
+ height: max-content;
+ padding: 12.8rem 12rem;
}
.filter-write-button-wrapper {
diff --git a/src/app/community/layout.tsx b/src/app/community/layout.tsx
index 690ef12a..4619c66b 100644
--- a/src/app/community/layout.tsx
+++ b/src/app/community/layout.tsx
@@ -14,12 +14,12 @@ interface CommunityLayoutProps {
export default async function CommunityLayout({ children }: CommunityLayoutProps) {
return (
diff --git a/src/app/my-info/(account)/my-posts/_components/MyPostsEmptyCase.module.scss b/src/app/my-info/(account)/my-posts/_components/MyPostsEmptyCase.module.scss
new file mode 100644
index 00000000..ffa8d6f4
--- /dev/null
+++ b/src/app/my-info/(account)/my-posts/_components/MyPostsEmptyCase.module.scss
@@ -0,0 +1,9 @@
+.container {
+ @include flex-center;
+ @include pretendard-20-600;
+
+ flex-direction: column;
+ gap: 3rem;
+ height: 70vh;
+ color: $gray-30;
+}
diff --git a/src/app/my-info/(account)/my-posts/_components/MyPostsEmptyCase.tsx b/src/app/my-info/(account)/my-posts/_components/MyPostsEmptyCase.tsx
new file mode 100644
index 00000000..03a064e6
--- /dev/null
+++ b/src/app/my-info/(account)/my-posts/_components/MyPostsEmptyCase.tsx
@@ -0,0 +1,26 @@
+import classNames from 'classnames/bind';
+import { NoReviewIcon } from '@/public/index';
+
+import { Button } from '@/components';
+import Link from 'next/link';
+
+import styles from './MyPostsEmptyCase.module.scss';
+
+const cn = classNames.bind(styles);
+
+export default function MyPostsEmptyCase() {
+ return (
+
+ 내 게시글이 없어요!
+
+ 다른 게시글 구경하러가기
+
+
+ );
+}
diff --git a/src/app/my-info/(account)/my-posts/page.tsx b/src/app/my-info/(account)/my-posts/page.tsx
index 56affb4e..22c17995 100644
--- a/src/app/my-info/(account)/my-posts/page.tsx
+++ b/src/app/my-info/(account)/my-posts/page.tsx
@@ -6,6 +6,7 @@ import { MyInfoEmptyCase } from '../../_components';
import MyPostCardList from './_components/MyPostCardList';
import styles from './page.module.scss';
+import MyPostsEmptyCase from './_components/MyPostsEmptyCase';
const cn = classNames.bind(styles);
@@ -28,6 +29,10 @@ export default async function MyPostsPage({ searchParams }: MyPostsPageProps) {
const data = await getMyPosts(initialParams);
+ if (!data) {
+ return ;
+ }
+
const { content, ...rest } = data;
return (
diff --git a/src/components/Buttons/HeartButton/HeartButton.tsx b/src/components/Buttons/HeartButton/HeartButton.tsx
index 0650ad89..76e15e3e 100644
--- a/src/components/Buttons/HeartButton/HeartButton.tsx
+++ b/src/components/Buttons/HeartButton/HeartButton.tsx
@@ -181,7 +181,6 @@ export default function HeartButton({ id, usage, isLiked, likeCount }: HeartButt
)}