+
-
-
-
-
+ {cardData.map((card, index) => (
+
);
}
diff --git a/src/features/bookclub/components/FilterSection.tsx b/src/features/bookclub/components/FilterSection.tsx
index e1193ab1..961d46b7 100644
--- a/src/features/bookclub/components/FilterSection.tsx
+++ b/src/features/bookclub/components/FilterSection.tsx
@@ -19,7 +19,7 @@ function FilterSection() {
aria-label="책 검색"
/>
-
로그인
diff --git a/src/features/auth/hooks/useLoginSubmit.ts b/src/features/auth/hooks/useLoginSubmit.ts index 016dad72..6cd2bfc4 100644 --- a/src/features/auth/hooks/useLoginSubmit.ts +++ b/src/features/auth/hooks/useLoginSubmit.ts @@ -17,7 +17,7 @@ export const useLoginSubmit = ( console.log('로그인 성공:', response); reset(); - const returnUrl = searchParams.get('returnUrl') || '/exchange'; + const returnUrl = searchParams.get('returnUrl') || '/bookclub'; router.replace(returnUrl); } catch (error) { handleAuthError(error, setError); diff --git a/src/features/bookclub/components/ClubListSection.tsx b/src/features/bookclub/components/ClubListSection.tsx index 219f6afe..b3af9f86 100644 --- a/src/features/bookclub/components/ClubListSection.tsx +++ b/src/features/bookclub/components/ClubListSection.tsx @@ -1,81 +1,105 @@ -// import { Meeting } from '@/components/card/types'; +'use client'; import Card from '@/components/card/Card'; -import { CardProps } from '@/components/card/types'; +import { useRouter } from 'next/navigation'; -// const mockImgSrc = '/images/profile.png'; +const cardData = [ + { + clubId: 1, + imageUrl: '/images/defaultBookClub.jpg', + imageAlt: '모임 이미지', + title: '독서 모임 1', + location: '서울 강남구', + datetime: '2024-01-20 14:00', + isLiked: false, + current: 3, + max: 8, + isPast: false, + isCanceled: false, + clubStatus: 'pending' as const, + meetingType: 'OFFLINE' as const, + bookClubType: 'FIXED' as const, -// const mockMeeting: Meeting = { -// meetingInfo: { -// title: '을지로에서 만나는 독서 모임', -// category: '자유책', -// location: '을지로 3가', -// datetime: '12/14(토) 오전 10:00', -// }, -// participationStatus: { -// currentParticipants: 17, -// maxParticipants: 20, -// isConfirmed: true, -// confirmedVariant: 'confirmed', -// participants: [ -// { -// src: mockImgSrc, -// alt: '참가자1', -// }, -// { -// src: mockImgSrc, -// alt: '참가자2', -// }, -// { -// src: mockImgSrc, -// alt: '참가자3', -// }, -// ], -// }, -// imageInfo: { -// url: mockImgSrc, -// isLiked: true, -// onLikeClick: () => alert('좋아요를 눌렀습니다!'), -// }, -// isPast: false, -// isCanceled: false, -// actions: { -// onClick: () => alert('카드를 클릭했습니다!'), -// onDelete: () => alert('모임을 삭제했습니다!'), -// }, -// }; + // meetingType: 'FIXED', // 정확한 리터럴 값 설정 + // status: 'pending', + }, + { + clubId: 2, + imageUrl: '/images/defaultBookClub.jpg', + imageAlt: '모임 이미지', + title: '독서 모임 1', + location: '서울 강남구', + datetime: '2024-01-20 14:00', + isLiked: false, + current: 3, + max: 8, + isPast: false, + isCanceled: false, + clubStatus: 'pending' as const, + meetingType: 'OFFLINE' as const, + bookClubType: 'FIXED' as const, -const defaultCardProps: CardProps = { - imageUrl: '/images/profile.png', - imageAlt: '모임 이미지', - title: '독서 모임', - location: '서울 강남구', - datetime: '2024-01-20 14:00', - isLiked: false, - current: 3, - max: 8, - isPast: false, - isCanceled: false, - meetingType: 'FIXED', - status: 'pending', - onLikeClick: () => { - console.log('좋아요 클릭'); + // meetingType: 'FIXED', // 정확한 리터럴 값 설정 + // status: 'pending', }, - onClick: () => { - console.log('카드 클릭'); + { + clubId: 3, + imageUrl: '/images/defaultBookClub.jpg', + imageAlt: '모임 이미지', + title: '독서 모임 1', + location: '서울 강남구', + datetime: '2024-01-20 14:00', + isLiked: false, + current: 3, + max: 8, + isPast: false, + isCanceled: false, + clubStatus: 'pending' as const, + meetingType: 'OFFLINE' as const, + bookClubType: 'FIXED' as const, + + // meetingType: 'FIXED', // 정확한 리터럴 값 설정 + // status: 'pending', }, - onDelete: () => { - console.log('삭제 클릭'); + { + clubId: 4, + imageUrl: '/images/defaultBookClub.jpg', + imageAlt: '모임 이미지', + title: '독서 모임 1', + location: '서울 강남구', + datetime: '2024-01-20 14:00', + isLiked: false, + current: 3, + max: 8, + isPast: false, + isCanceled: false, + clubStatus: 'pending' as const, + meetingType: 'OFFLINE' as const, + bookClubType: 'FIXED' as const, + + // meetingType: 'FIXED', // 정확한 리터럴 값 설정 + // status: 'pending', }, -}; +]; function ClubListSection() { + const router = useRouter(); return (
+ router.push(`/bookclub/${card.clubId}`)}
+ onLikeClick={() => console.log('좋아요 클릭')}
+ onDelete={() => console.log('삭제 클릭')}
+ />
+
+ ))}
+
({
resolver: zodResolver(bookClubSchema),
@@ -19,7 +26,14 @@ export const useBookClubForm = () => {
watch,
} = form;
- const onSubmit = handleSubmit(createBookClub);
+ const onSubmit = handleSubmit(async (data) => {
+ try {
+ await createBookClub(data);
+ setShowSuccessPopup(true);
+ } catch (error) {
+ console.error(error);
+ }
+ });
return {
form,
@@ -31,5 +45,8 @@ export const useBookClubForm = () => {
watch,
onSubmit,
isLoading,
+ showSuccessPopup,
+ handlePopUpClose,
+ handlePopUpConfirm,
};
};
diff --git a/src/features/club-create/hooks/useCreateBookClub.ts b/src/features/club-create/hooks/useCreateBookClub.ts
index 74765377..aa05ae29 100644
--- a/src/features/club-create/hooks/useCreateBookClub.ts
+++ b/src/features/club-create/hooks/useCreateBookClub.ts
@@ -14,7 +14,6 @@ export const useCreateBookClub = () => {
try {
const response = await createBookClub(data);
- alert('북클럽이 성공적으로 생성되었습니다!');
return response;
} catch (error) {
setError('북클럽 생성에 실패했습니다.');
diff --git a/src/features/club-create/hooks/usePopup.ts b/src/features/club-create/hooks/usePopup.ts
new file mode 100644
index 00000000..b4f7a892
--- /dev/null
+++ b/src/features/club-create/hooks/usePopup.ts
@@ -0,0 +1,26 @@
+'use client';
+
+import { useState } from 'react';
+import { useRouter } from 'next/navigation';
+
+export const usePopup = () => {
+ const router = useRouter();
+ const [showSuccessPopup, setShowSuccessPopup] = useState(false);
+
+ const handlePopUpClose = () => {
+ setShowSuccessPopup(true);
+ router.push('/bookclub');
+ };
+
+ const handlePopUpConfirm = () => {
+ setShowSuccessPopup(true);
+ router.push('/bookclub');
+ };
+
+ return {
+ showSuccessPopup,
+ setShowSuccessPopup,
+ handlePopUpClose,
+ handlePopUpConfirm,
+ };
+};
diff --git a/src/features/club-details/components/HeaderSection.tsx b/src/features/club-details/components/HeaderSection.tsx
index 993267c7..c0353318 100644
--- a/src/features/club-details/components/HeaderSection.tsx
+++ b/src/features/club-details/components/HeaderSection.tsx
@@ -39,6 +39,7 @@ function HeaderSection() {
const EXAMPLE_IMAGE = '/images/profile.png';
const defaultCardProps: CardProps = {
+ clubId: 45,
variant: 'detailedClub',
imageUrl: EXAMPLE_IMAGE,
imageAlt: '모임 이미지',
@@ -49,8 +50,9 @@ function HeaderSection() {
current: 3,
max: 8,
isPast: false,
- meetingType: 'FIXED',
- status: 'pending',
+ meetingType: 'OFFLINE',
+ bookClubType: 'FIXED',
+ clubStatus: 'pending',
onClick: () => {},
onLikeClick: () => {
setIsLiked(!isLiked);
@@ -104,7 +106,7 @@ function HeaderSection() {
};
return (
-
+
내가 만든 모임 뷰 ;
}
diff --git a/src/features/profile/components/clubs/JoinedClubList.tsx b/src/features/profile/components/clubs/JoinedClubList.tsx
index 6961689e..3062055c 100644
--- a/src/features/profile/components/clubs/JoinedClubList.tsx
+++ b/src/features/profile/components/clubs/JoinedClubList.tsx
@@ -1,3 +1,257 @@
-export default function JoinedClubList() {
- return ('NEWEST');
const [selectedList, setSelectedList] = useState(
EXCHANGE_TABS[0],
diff --git a/src/features/profile/components/exchange/index.ts b/src/features/profile/components/exchange/index.ts
new file mode 100644
index 00000000..aaaf3d63
--- /dev/null
+++ b/src/features/profile/components/exchange/index.ts
@@ -0,0 +1,4 @@
+export { default as ExchangeContents } from './ExchangeContents';
+export { default as MyRegisteredBooks } from './MyRegisteredBooks';
+export { default as TradeRecords } from './TradeRecords';
+export { default as TradeReviews } from './TradeReviews';
diff --git a/src/features/profile/components/profile/Profile.stories.tsx b/src/features/profile/components/profile/Profile.stories.tsx
index fe17b4b2..d14873ca 100644
--- a/src/features/profile/components/profile/Profile.stories.tsx
+++ b/src/features/profile/components/profile/Profile.stories.tsx
@@ -1,6 +1,6 @@
import type { Meta, StoryObj } from '@storybook/react';
import Profile from './Profile';
-import User from '../../types/user';
+import { User } from '../../types';
const mockUser: User = {
teamId: '1',
diff --git a/src/features/profile/components/profile/Profile.test.tsx b/src/features/profile/components/profile/Profile.test.tsx
index 973cbd3f..dacf4893 100644
--- a/src/features/profile/components/profile/Profile.test.tsx
+++ b/src/features/profile/components/profile/Profile.test.tsx
@@ -1,8 +1,8 @@
import '@testing-library/jest-dom';
import Profile from './Profile';
import { render, screen } from '@testing-library/react';
-import User from '../../types/user';
import userEvent from '@testing-library/user-event';
+import { User } from '../../types';
const mockUser: User = {
teamId: '1',
diff --git a/src/features/profile/components/profile/Profile.tsx b/src/features/profile/components/profile/Profile.tsx
index 85bbd5f1..92c82c70 100644
--- a/src/features/profile/components/profile/Profile.tsx
+++ b/src/features/profile/components/profile/Profile.tsx
@@ -3,14 +3,14 @@
import { useState } from 'react';
import Avatar from '@/components/avatar/Avatar';
import { IcEdit } from '../../../../../public/icons/index';
-import ProfileEditModal from '../ProfileEditModal';
import { ProfileEditData, ProfilePageProps } from '../../types';
+import ProfileEditModal from './ProfileEditModal';
function Profile({ user }: ProfilePageProps) {
const [isModalOpen, setIsModalOpen] = useState(false);
const onSubmitEditProfile = (formData: ProfileEditData) => {
- alert(`name:${formData.name}, companyName:${formData.companyName}`);
+ alert(`name:${formData.name}, companyName:${formData.description}`);
setIsModalOpen(false);
};
@@ -53,7 +53,7 @@ function Profile({ user }: ProfilePageProps) {
{/* 프로필 이미지 */}
diff --git a/src/features/profile/components/ProfileEditModal.tsx b/src/features/profile/components/profile/ProfileEditModal.tsx
similarity index 98%
rename from src/features/profile/components/ProfileEditModal.tsx
rename to src/features/profile/components/profile/ProfileEditModal.tsx
index 4091c7d3..6c67a17b 100644
--- a/src/features/profile/components/ProfileEditModal.tsx
+++ b/src/features/profile/components/profile/ProfileEditModal.tsx
@@ -1,8 +1,8 @@
import { useState } from 'react';
import { useAuthStore } from '@/store/authStore';
import Avatar from '@/components/avatar/Avatar';
-import EditIcon from '../../../../public/icons/EditIcon';
import Modal from '@/components/modal/Modal';
+import { EditIcon } from '../../../../../public/icons';
interface ProfileData {
name: string;
diff --git a/src/features/profile/components/profile/index.ts b/src/features/profile/components/profile/index.ts
new file mode 100644
index 00000000..1792c9cf
--- /dev/null
+++ b/src/features/profile/components/profile/index.ts
@@ -0,0 +1,2 @@
+export { default as ProfileEditModal } from './ProfileEditModal';
+export { default as Profile } from './Profile';
diff --git a/src/features/profile/components/clubs/ClubContents.tsx b/src/features/profile/container/ClubContents.tsx
similarity index 68%
rename from src/features/profile/components/clubs/ClubContents.tsx
rename to src/features/profile/container/ClubContents.tsx
index 6fa42003..6a14885b 100644
--- a/src/features/profile/components/clubs/ClubContents.tsx
+++ b/src/features/profile/container/ClubContents.tsx
@@ -1,29 +1,32 @@
import SortingButton from '@/components/sorting-button/SortingButton';
import { CLUB_TABS, ClubTab } from '@/constants';
import { useState } from 'react';
-import JoinedClubList from './JoinedClubList';
-import MyReviewList from './MyReviewList';
-import HostedClubList from './HostedClubsList';
import Tab from '@/components/tab/Tab';
+import { ProfilePageProps } from '../types';
+import {
+ HostedClubList,
+ JoinedClubList,
+ MyReviewList,
+} from '../components/clubs';
-export default function ClubContents() {
+export default function ClubContents({ user }: ProfilePageProps) {
const [sortBy, setSortBy] = useState('NEWEST');
const [selectedList, setSelectedList] = useState(CLUB_TABS[0]);
const renderList = (selectedList: ClubTab) => {
switch (selectedList) {
case CLUB_TABS[0]:
- return ;
+ return ;
case CLUB_TABS[1]:
- return ;
+ return ;
case CLUB_TABS[2]:
- return ;
+ return ;
}
};
return (
router.push('/bookclub/create')} /> ); diff --git a/src/features/club-create/container/FormContainer.tsx b/src/features/club-create/container/FormContainer.tsx index 25c0d45d..7d03a887 100644 --- a/src/features/club-create/container/FormContainer.tsx +++ b/src/features/club-create/container/FormContainer.tsx @@ -12,6 +12,7 @@ import { ImageField, } from '@/features/club-create/container'; import { useBookClubForm } from '@/features/club-create/hooks'; +import PopUp from '@/components/pop-up/PopUp'; function FormContainer() { const { @@ -23,121 +24,133 @@ function FormContainer() { watch, onSubmit, isLoading, + showSuccessPopup, + handlePopUpClose, + handlePopUpConfirm, } = useBookClubForm(); return ( -
- - + > ); } diff --git a/src/features/club-create/hooks/useBookClubForm.ts b/src/features/club-create/hooks/useBookClubForm.ts index efe44f2c..efc4f1be 100644 --- a/src/features/club-create/hooks/useBookClubForm.ts +++ b/src/features/club-create/hooks/useBookClubForm.ts @@ -1,10 +1,17 @@ import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { BookClubForm, bookClubSchema } from '../types'; -import { useCreateBookClub } from '@/features/club-create/hooks'; +import { useCreateBookClub } from './useCreateBookClub'; +import { usePopup } from './usePopup'; export const useBookClubForm = () => { const { onSubmit: createBookClub, isLoading } = useCreateBookClub(); + const { + setShowSuccessPopup, + showSuccessPopup, + handlePopUpClose, + handlePopUpConfirm, + } = usePopup(); const form = useForm나의 모임 뷰
;
+import Card from '@/components/card/Card';
+import { BookClub, User } from '../../types';
+import { useRouter } from 'next/navigation';
+import { useState } from 'react';
+import { WriteReviewModal } from '../clubs';
+
+interface JoinedClubListProps {
+ user: User | null;
+ sortBy: string | undefined;
+}
+
+const mockJoinedBookClubList: BookClub[] = [
+ {
+ clubId: 1,
+ title: '문학의 밤',
+ description: '다양한 문학 작품을 함께 읽고 토론하는 모임입니다.',
+ meetingType: 'OFFLINE',
+ bookClubType: 'FIXED',
+ targetDate: '2024-01-10',
+ endDate: '2024-12-10',
+ memberLimit: 20,
+ town: '서울',
+ memberCount: 15,
+ isLiked: true,
+ isCanceled: false,
+ imageUrl: '/images/defaultBookClub.jpg',
+ isPast: false,
+ clubStatus: 'confirmed',
+ },
+ {
+ clubId: 2,
+ title: '과학 탐험',
+ description:
+ '최신 과학 서적을 읽고 실험을 통해 배운 내용을 공유하는 모임입니다.',
+ meetingType: 'ONLINE',
+ bookClubType: 'FREE',
+ targetDate: '2024-02-15',
+ endDate: '2024-08-15',
+ memberLimit: 30,
+ town: '부산',
+ memberCount: 25,
+ isLiked: false,
+ isCanceled: false,
+ imageUrl: '/images/defaultBookClub.jpg',
+ isPast: false,
+ clubStatus: 'pending',
+ },
+ {
+ clubId: 3,
+ title: '추리 소설 독서회',
+ description: '추리 소설을 읽고 결말을 예측하며 토론하는 모임입니다.',
+ meetingType: 'OFFLINE',
+ bookClubType: 'FIXED',
+ targetDate: '2024-03-20',
+ endDate: '2024-11-20',
+ memberLimit: 10,
+ town: '대전',
+ memberCount: 8,
+ isLiked: true,
+ isCanceled: false,
+ imageUrl: '/images/defaultBookClub.jpg',
+ isPast: false,
+ clubStatus: 'confirmed',
+ },
+ {
+ clubId: 4,
+ title: '로맨스 북클럽',
+ description: '사랑과 감정을 주제로 한 로맨스 소설을 읽는 모임입니다.',
+ meetingType: 'ONLINE',
+ bookClubType: 'FREE',
+ targetDate: '2024-04-25',
+ endDate: '2024-10-25',
+ memberLimit: 25,
+ town: '인천',
+ memberCount: 20,
+ isLiked: false,
+ isCanceled: true,
+ imageUrl: '/images/defaultBookClub.jpg',
+ isPast: false,
+ clubStatus: 'closed',
+ },
+ {
+ clubId: 5,
+ title: '비즈니스 책 모임',
+ description:
+ '비즈니스 전략과 아이디어를 다룬 책을 읽고 토론하는 모임입니다.',
+ meetingType: 'OFFLINE',
+ bookClubType: 'FIXED',
+ targetDate: '2024-05-30',
+ endDate: '2024-11-30',
+ memberLimit: 15,
+ town: '경기',
+ memberCount: 12,
+ isLiked: true,
+ isCanceled: false,
+ imageUrl: '/images/defaultBookClub.jpg',
+ isPast: true,
+ clubStatus: 'closed',
+ },
+ {
+ clubId: 6,
+ title: '고전 문학',
+ description: '고전 문학 작품을 읽고 그 의미를 되새기는 모임입니다.',
+ meetingType: 'ONLINE',
+ bookClubType: 'FREE',
+ targetDate: '2024-06-05',
+ endDate: '2024-12-05',
+ memberLimit: 18,
+ town: '서울',
+ memberCount: 10,
+ isLiked: true,
+ isCanceled: false,
+ imageUrl: '/images/defaultBookClub.jpg',
+ isPast: false,
+ clubStatus: 'confirmed',
+ },
+ {
+ clubId: 7,
+ title: '환경 보호 독서회',
+ description: '환경과 관련된 주제의 책을 읽고 토론하는 모임입니다.',
+ meetingType: 'OFFLINE',
+ bookClubType: 'FIXED',
+ targetDate: '2024-07-15',
+ endDate: '2024-12-15',
+ memberLimit: 20,
+ town: '대구',
+ memberCount: 17,
+ isLiked: false,
+ isCanceled: false,
+ imageUrl: '/images/defaultBookClub.jpg',
+ isPast: false,
+ clubStatus: 'pending',
+ },
+ {
+ clubId: 8,
+ title: '스타트업 독서 모임',
+ description: '스타트업 관련 책을 읽고 창업 아이디어를 나누는 모임입니다.',
+ meetingType: 'ONLINE',
+ bookClubType: 'FREE',
+ targetDate: '2024-08-10',
+ endDate: '2024-12-10',
+ memberLimit: 10,
+ town: '서울',
+ memberCount: 7,
+ isLiked: true,
+ isCanceled: false,
+ imageUrl: '/images/defaultBookClub.jpg',
+ isPast: false,
+ clubStatus: 'confirmed',
+ },
+ {
+ clubId: 9,
+ title: '디지털 혁명',
+ description: '디지털 시대 혁신적인 책을 읽고 토론하는 모임입니다.',
+ meetingType: 'OFFLINE',
+ bookClubType: 'FIXED',
+ targetDate: '2024-09-05',
+ endDate: '2024-11-05',
+ memberLimit: 30,
+ town: '부산',
+ memberCount: 22,
+ isLiked: false,
+ isCanceled: false,
+ imageUrl: '/images/defaultBookClub.jpg',
+ isPast: false,
+ clubStatus: 'confirmed',
+ },
+ {
+ clubId: 10,
+ title: '인문학 읽기',
+ description: '인문학적 사유를 통해 통찰을 얻는 독서 모임입니다.',
+ meetingType: 'ONLINE',
+ bookClubType: 'FREE',
+ targetDate: '2024-10-12',
+ endDate: '2024-12-12',
+ memberLimit: 20,
+ town: '광주',
+ memberCount: 15,
+ isLiked: true,
+ isCanceled: false,
+ imageUrl: '/images/defaultBookClub.jpg',
+ isPast: false,
+ clubStatus: 'confirmed',
+ },
+];
+
+export default function JoinedClubList({ user, sortBy }: JoinedClubListProps) {
+ console.log(user, sortBy);
+
+ const router = useRouter();
+
+ const [isModalOpen, setIsModalOpen] = useState(false);
+
+ // const bookClubList: BookClub[] = [];
+ const bookClubList = mockJoinedBookClubList;
+ const NO_LIST_MESSAGE =
+ '아직 신청한 모임이 없어요.\n지금 바로 책 모임을 신청해 보세요';
+
+ //카드 컴포넌트 클릭 시 해당 모임 상세페이지로 라우팅
+ const handleCardClick = (clubId: number) => {
+ router.push(`/bookclub/${clubId}`);
+ };
+
+ const handleCancelClick = (clubId: number) => {
+ alert(`${clubId}취소하기`);
+ //TODO: 취소 확인 팝업 표시, API작업 필요
+ };
+
+ const handleDeleteClick = (clubId: number) => {
+ alert(`${clubId}삭제하기`);
+ //TODO: 삭제 확인 팝업 표시, API 작업 필요
+ };
+
+ const onSubmitReview = (rating: number, review: string) => {
+ alert(`점수:${rating} 리뷰:${review}`);
+ //TODO: API 작업 필요
+ setIsModalOpen(false);
+ };
+
+ return (
+
+ setIsModalOpen(false)}
+ onConfirm={(rating, review) => onSubmitReview(rating, review)}
+ />
+ {bookClubList.length === 0 ? (
+
+ );
}
diff --git a/src/features/profile/components/clubs/MyReviewList.tsx b/src/features/profile/components/clubs/MyReviewList.tsx
index 47c32930..75a20e5c 100644
--- a/src/features/profile/components/clubs/MyReviewList.tsx
+++ b/src/features/profile/components/clubs/MyReviewList.tsx
@@ -1,3 +1,12 @@
-export default function MyReviewList() {
+import { User } from '../../types';
+
+interface MyReviewListProps {
+ user: User | null;
+ sortBy: string | undefined;
+}
+
+export default function MyReviewList({ user, sortBy }: MyReviewListProps) {
+ console.log(user);
+ console.log(sortBy);
return
+ {NO_LIST_MESSAGE}
+
+ ) : (
+ bookClubList.map((bookClub, index) => (
+
+ {/* TODO: isCanceled, imageUrl. isPast, status 수정 */}
+ handleCardClick(clubId)}
+ onCancel={(clubId) => handleCancelClick(clubId)}
+ onWriteReview={() => setIsModalOpen(true)}
+ onDelete={(clubId) => handleDeleteClick(clubId)}
+ />
+
+ ))
+ )}
+ 나의 리뷰 뷰
;
}
diff --git a/src/features/profile/components/WriteReviewModal.tsx b/src/features/profile/components/clubs/WriteReviewModal.tsx
similarity index 97%
rename from src/features/profile/components/WriteReviewModal.tsx
rename to src/features/profile/components/clubs/WriteReviewModal.tsx
index 0f2ba14d..b0e989b0 100644
--- a/src/features/profile/components/WriteReviewModal.tsx
+++ b/src/features/profile/components/clubs/WriteReviewModal.tsx
@@ -2,7 +2,7 @@
import React, { useState } from 'react';
import Modal from '@/components/modal/Modal';
-import RatingIcon from '../../../../public/icons/RatingIcon';
+import RatingIcon from '../../../../../public/icons/RatingIcon';
const INITIAL_RATING = 5;
const RATING_RANGE = [1, 2, 3, 4, 5] as const;
diff --git a/src/features/profile/components/clubs/index.ts b/src/features/profile/components/clubs/index.ts
new file mode 100644
index 00000000..abd2d29c
--- /dev/null
+++ b/src/features/profile/components/clubs/index.ts
@@ -0,0 +1,4 @@
+export { default as HostedClubList } from './HostedClubsList';
+export { default as JoinedClubList } from './JoinedClubList';
+export { default as MyReviewList } from './MyReviewList';
+export { default as WriteReviewModal } from './WriteReviewModal';
diff --git a/src/features/profile/components/exchange/ExchangeContents.tsx b/src/features/profile/components/exchange/ExchangeContents.tsx
index b7326c91..f7c2929c 100644
--- a/src/features/profile/components/exchange/ExchangeContents.tsx
+++ b/src/features/profile/components/exchange/ExchangeContents.tsx
@@ -1,12 +1,10 @@
import SortingButton from '@/components/sorting-button/SortingButton';
import { EXCHANGE_TABS, ExchangeTab } from '@/constants';
import { useState } from 'react';
-import TradeRecords from './TradeRecords';
-import MyRegisteredBooks from './MyRegisteredBooks';
-import TradeReviews from './TradeReviews';
+import { MyRegisteredBooks, TradeRecords, TradeReviews } from '../exchange';
import Tab from '@/components/tab/Tab';
-export default function ClubContents() {
+export default function ExchangeContents() {
const [sortBy, setSortBy] = useState
diff --git a/src/features/profile/components/MainContent.tsx b/src/features/profile/container/MainContent.tsx
similarity index 67%
rename from src/features/profile/components/MainContent.tsx
rename to src/features/profile/container/MainContent.tsx
index cb24dd8c..483ebc3b 100644
--- a/src/features/profile/components/MainContent.tsx
+++ b/src/features/profile/container/MainContent.tsx
@@ -2,14 +2,15 @@
import Tab from '@/components/tab/Tab';
import { CONTENT_TABS, ContentTab } from '@/constants';
import { useState } from 'react';
-import ClubContents from './clubs/ClubContents';
-import ExchangeContents from './exchange/ExchangeContents';
+import { ClubContents } from '../container';
+import ExchangeContents from '../components/exchange/ExchangeContents';
+import { ProfilePageProps } from '../types';
-function MainContent() {
+function MainContent({ user }: ProfilePageProps) {
const [selectedTab, setSelectedTab] = useState(CONTENT_TABS[0]);
return (
-
+
{selectedTab === CONTENT_TABS[0] ? (
-
+
) : (
)}
diff --git a/src/features/profile/container/ProfileHeader.tsx b/src/features/profile/container/ProfileHeader.tsx
new file mode 100644
index 00000000..305a9329
--- /dev/null
+++ b/src/features/profile/container/ProfileHeader.tsx
@@ -0,0 +1,14 @@
+import { ProfilePageProps } from '../types';
+import { Profile } from '../components/profile';
+
+export default function ProfileHeader({ user }: ProfilePageProps) {
+ return (
+
-
+
);
}
diff --git a/src/features/profile/container/index.ts b/src/features/profile/container/index.ts
index cb0ff5c3..35ae0bdc 100644
--- a/src/features/profile/container/index.ts
+++ b/src/features/profile/container/index.ts
@@ -1 +1,4 @@
-export {};
+export { default as ClubContents } from './ClubContents';
+export { default as MainContent } from './MainContent';
+export { default as ProfileHeader } from './ProfileHeader';
+export { default as Profile } from './ProfilePage';
diff --git a/src/features/profile/types/index.ts b/src/features/profile/types/index.ts
index c948e72e..c7010aab 100644
--- a/src/features/profile/types/index.ts
+++ b/src/features/profile/types/index.ts
@@ -1,4 +1,13 @@
-import User from './user';
+export interface User {
+ teamId: string;
+ id: number;
+ email: string;
+ name: string;
+ description?: string | null;
+ image?: string | null;
+ createdAt: Date;
+ updatedAt: Date;
+}
export interface ProfilePageProps {
user: User | null;
@@ -6,6 +15,25 @@ export interface ProfilePageProps {
export interface ProfileEditData {
name: string;
- companyName?: string;
+ description?: string;
image?: string | null;
}
+
+//TODO: isCanceled, imageUrl. isPast, status 수정
+export interface BookClub {
+ clubId: number;
+ title: string;
+ description: string;
+ meetingType: 'ONLINE' | 'OFFLINE';
+ bookClubType: 'FREE' | 'FIXED';
+ targetDate: string;
+ endDate: string;
+ memberLimit: number;
+ town: string;
+ memberCount: number;
+ isLiked: boolean;
+ isCanceled: boolean;
+ imageUrl: string;
+ isPast: boolean;
+ clubStatus: 'pending' | 'confirmed' | 'closed';
+}
diff --git a/src/features/profile/types/user.ts b/src/features/profile/types/user.ts
index 2c5c42f5..81ab2bc2 100644
--- a/src/features/profile/types/user.ts
+++ b/src/features/profile/types/user.ts
@@ -1,10 +1,10 @@
-export default interface User {
- teamId: string;
- id: number;
- email: string;
- name: string;
- description?: string | null;
- image?: string | null;
- createdAt: Date;
- updatedAt: Date;
-}
+// export default interface User {
+// teamId: string;
+// id: number;
+// email: string;
+// name: string;
+// description?: string | null;
+// image?: string | null;
+// createdAt: Date;
+// updatedAt: Date;
+// }
diff --git a/src/middleware.ts b/src/middleware.ts
index 1b764c86..91fcba4a 100644
--- a/src/middleware.ts
+++ b/src/middleware.ts
@@ -1,7 +1,7 @@
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
-const AUTH_REQUIRED_PATHS = ['/wish', '/profile'];
+const AUTH_REQUIRED_PATHS = ['/wish', '/profile', '/bookclub/create'];
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
@@ -24,5 +24,5 @@ export function middleware(request: NextRequest) {
}
export const config = {
- matcher: ['/wish', '/profile', '/login'],
+ matcher: ['/wish', '/profile', '/login', '/bookclub/create'],
};
+ {/* TODO: 프로필 페이지가 로그인된 유저의 프로필 페이지와 일치 여부 확인 후 마이페이지 or **님의 페이지 */}
+
+ 마이 페이지
+
+
+
+ );
+}
diff --git a/src/features/profile/components/ProfilePage.tsx b/src/features/profile/container/ProfilePage.tsx
similarity index 72%
rename from src/features/profile/components/ProfilePage.tsx
rename to src/features/profile/container/ProfilePage.tsx
index a010bf05..f246ad0e 100644
--- a/src/features/profile/components/ProfilePage.tsx
+++ b/src/features/profile/container/ProfilePage.tsx
@@ -1,8 +1,7 @@
'use client';
-import MainContent from './MainContent';
-import ProfileHeader from './ProfileHeader';
import { useAuthStore } from '@/store/authStore';
+import { MainContent, ProfileHeader } from '../container';
function ProfilePage() {
const { user } = useAuthStore();
@@ -10,7 +9,7 @@ function ProfilePage() {
return (