diff --git a/package-lock.json b/package-lock.json index ebe27e49..36ce19e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,4 +1,3 @@ - { "name": "codeit3-fe", "version": "0.1.0", diff --git a/src/app/profile/page.tsx b/src/app/profile/page.tsx index 673f3881..de681fd0 100644 --- a/src/app/profile/page.tsx +++ b/src/app/profile/page.tsx @@ -1,4 +1,4 @@ -import ProfilePage from '@/features/profile/components/ProfilePage'; +import ProfilePage from '@/features/profile/container/ProfilePage'; import React from 'react'; const Profile = () => { diff --git a/src/components/card/Card.tsx b/src/components/card/Card.tsx index 2f8308d1..05e28876 100644 --- a/src/components/card/Card.tsx +++ b/src/components/card/Card.tsx @@ -200,6 +200,7 @@ function Card(props: CardProps) { case 'defaultClub': default: { const { + clubId, imageUrl, imageAlt, title, @@ -211,10 +212,11 @@ function Card(props: CardProps) { max, isPast, isCanceled, - meetingType, + // meetingType, + bookClubType, onClick, onDelete, - status, + clubStatus, } = props as DefaultClubCard & { variant: 'defaultClub' }; return ( @@ -227,11 +229,14 @@ function Card(props: CardProps) { onLikeClick={onLikeClick} /> - + onClick(clubId)} + className="justify-between" + >
{title} - +
{location} @@ -246,7 +251,7 @@ function Card(props: CardProps) { max={max} isPast={isPast} /> - +
- {isCanceled && } + {isCanceled && onDelete()} />} ); } case 'participatedClub': { const { + clubId, imageUrl, imageAlt, - isLiked, - onLikeClick, + // isLiked, + // onLikeClick, isCanceled, onClick, onDelete, - status, - meetingType, + clubStatus, + // meetingType, + bookClubType, title, location, datetime, @@ -283,17 +290,20 @@ function Card(props: CardProps) { - + onClick(clubId)} + className="justify-between" + >
- +
- +
{title} @@ -324,7 +334,7 @@ function Card(props: CardProps) { lightColor="gray-normal-01" onClick={(e) => { e.stopPropagation(); - onCancel(); + onCancel(clubId); }} className="w-full" /> @@ -332,18 +342,20 @@ function Card(props: CardProps) {
- {isCanceled && } + {isCanceled && onDelete(clubId)} />} ); } case 'hostedClub': { const { + clubId, imageUrl, imageAlt, onClick, - status, - meetingType, + clubStatus, + // meetingType, + bookClubType, isPast, title, location, @@ -355,11 +367,14 @@ function Card(props: CardProps) { return (
- + onClick(clubId)} + className="justify-between" + >
- - + +
{title} @@ -413,6 +428,7 @@ function Card(props: CardProps) { case 'detailedClub': { const { + clubId, imageUrl, imageAlt, title, @@ -420,12 +436,13 @@ function Card(props: CardProps) { datetime, isLiked, onLikeClick, - meetingType, + // meetingType, + bookClubType, current, max, isPast, host, - status, + clubStatus, participants, onClick, isHost, @@ -542,13 +559,13 @@ function Card(props: CardProps) { /> onClick(clubId)} + className="justify-between" >
{title} - +
{location} @@ -574,7 +591,7 @@ function Card(props: CardProps) { ))}
- +
{renderCardContent()} diff --git a/src/components/card/ClubCard.stories.tsx b/src/components/card/ClubCard.stories.tsx index f5164924..7e66b561 100644 --- a/src/components/card/ClubCard.stories.tsx +++ b/src/components/card/ClubCard.stories.tsx @@ -13,9 +13,9 @@ const meta = { control: 'select', options: ['FREE', 'FIXED'], }, - status: { + clubStatus: { control: 'select', - options: ['completed', 'scheduled', 'pending', 'confirmed', 'closed'], + options: ['pending', 'confirmed', 'closed'], }, }, tags: ['autodocs'], @@ -28,12 +28,14 @@ const baseArgs = { // ClubCard 기본 인터페이스의 속성들 imageUrl: 'https://picsum.photos/400/300', imageAlt: '모임 이미지', + clubId: 45, title: '을지로 독서 모임', location: '을지로 3가', datetime: '12/14(토) 오전 10:00', - meetingType: 'FREE' as const, + meetingType: 'OFFLINE' as const, + bookClubType: 'FREE' as const, isPast: false, - status: 'confirmed' as const, + clubStatus: 'confirmed' as const, onClick: () => alert('카드 클릭!'), } as const; diff --git a/src/components/card/types/clubCard.ts b/src/components/card/types/clubCard.ts index 5298db4b..a71972af 100644 --- a/src/components/card/types/clubCard.ts +++ b/src/components/card/types/clubCard.ts @@ -4,15 +4,17 @@ interface ClubCard { imageAlt?: string; // 모임 정보 + clubId: number; title: string; location: string; datetime: string; - meetingType: 'FREE' | 'FIXED'; + meetingType: 'ONLINE' | 'OFFLINE'; + bookClubType: 'FREE' | 'FIXED'; isPast: boolean; // 지난 모임인지 아닌지 - status: 'completed' | 'scheduled' | 'pending' | 'confirmed' | 'closed'; // 개설 현황 + clubStatus: 'pending' | 'confirmed' | 'closed'; // 개설 현황 // 액션 (카드 클릭시 라우터 처리 등) - onClick: () => void; + onClick: (clubId: number) => void; } interface DefaultClubCard extends ClubCard { @@ -31,16 +33,16 @@ interface DefaultClubCard extends ClubCard { interface ParticipatedClubCard extends ClubCard { // 찜 정보 - isLiked: boolean; - onLikeClick: () => void; + // isLiked: boolean; + // onLikeClick: () => void; // 취소 정보 (블러) isCanceled: boolean; - onDelete: () => void; + onDelete: (clubId: number) => void; // 버튼 액션 onWriteReview: () => void; // 리뷰 작성 - onCancel: () => void; // 모임 취소 + onCancel: (clubId: number) => void; // 모임 취소 } interface HostedClubCard extends ClubCard { diff --git a/src/components/pop-up-button/PopUpButton.tsx b/src/components/pop-up-button/PopUpButton.tsx new file mode 100644 index 00000000..e60fb587 --- /dev/null +++ b/src/components/pop-up-button/PopUpButton.tsx @@ -0,0 +1,23 @@ +const THEME_COLOR = { + cancel: 'border border-orange-600 bg-white text-orange-600 mr-[8px]', + confirm: 'bg-orange-600 text-white', +}; + +interface PopUpButtonProps { + isConfirm: boolean; + // onClick: ( + // event: MouseEvent | MouseEvent, + // ) => void; +} + +function PopUpButton({ isConfirm }: PopUpButtonProps) { + return ( + + ); +} + +export default PopUpButton; diff --git a/src/features/bookclub/components/ClubListSection.tsx b/src/features/bookclub/components/ClubListSection.tsx index c8ab13b6..8dc0f48b 100644 --- a/src/features/bookclub/components/ClubListSection.tsx +++ b/src/features/bookclub/components/ClubListSection.tsx @@ -3,81 +3,98 @@ import Card from '@/components/card/Card'; import { useRouter } from 'next/navigation'; -function ClubListSection() { - const router = useRouter(); +const cardData = [ + { + clubId: 1, + imageUrl: '/images/profile.png', + 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', + }, + { + clubId: 2, + imageUrl: '/images/profile.png', + 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', + }, + { + clubId: 3, + imageUrl: '/images/profile.png', + 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 cardData = [ - { - id: 1, - imageUrl: '/images/profile.png', - imageAlt: '모임 이미지', - title: '독서 모임 1', - location: '서울 강남구', - datetime: '2024-01-20 14:00', - isLiked: false, - current: 3, - max: 8, - isPast: false, - isCanceled: false, - // meetingType: 'FIXED', // 정확한 리터럴 값 설정 - // status: 'pending', - }, - { - id: 2, - imageUrl: '/images/profile.png', - imageAlt: '모임 이미지', - title: '독서 모임 1', - location: '서울 강남구', - datetime: '2024-01-20 14:00', - isLiked: false, - current: 3, - max: 8, - isPast: false, - isCanceled: false, - // meetingType: 'FIXED', // 정확한 리터럴 값 설정 - // status: 'pending', - }, - { - id: 3, - imageUrl: '/images/profile.png', - imageAlt: '모임 이미지', - title: '독서 모임 1', - location: '서울 강남구', - datetime: '2024-01-20 14:00', - isLiked: false, - current: 3, - max: 8, - isPast: false, - isCanceled: false, - // meetingType: 'FIXED', // 정확한 리터럴 값 설정 - // status: 'pending', - }, - { - id: 4, - imageUrl: '/images/profile.png', - imageAlt: '모임 이미지', - title: '독서 모임 1', - location: '서울 강남구', - datetime: '2024-01-20 14:00', - isLiked: false, - current: 3, - max: 8, - isPast: false, - isCanceled: false, - // meetingType: 'FIXED', // 정확한 리터럴 값 설정 - // status: 'pending', - }, - ]; + // meetingType: 'FIXED', // 정확한 리터럴 값 설정 + // status: 'pending', + }, + { + clubId: 4, + imageUrl: '/images/profile.png', + 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 (
{cardData.map((card, index) => (
router.push(`/bookclub/${card.id}`)} + // // meetingType={'FIXED' as 'FIXED'} + // // status="pending" + // {...card} + variant="defaultClub" + onClick={() => router.push(`/bookclub/${card.clubId}`)} onLikeClick={() => console.log('좋아요 클릭')} onDelete={() => console.log('삭제 클릭')} /> diff --git a/src/features/club-details/components/HeaderSection.tsx b/src/features/club-details/components/HeaderSection.tsx index 993267c7..91b0bd6f 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); diff --git a/src/features/profile/components/clubs/HostedClubsList.tsx b/src/features/profile/components/clubs/HostedClubsList.tsx index 17650279..20efa5ab 100644 --- a/src/features/profile/components/clubs/HostedClubsList.tsx +++ b/src/features/profile/components/clubs/HostedClubsList.tsx @@ -1,3 +1,12 @@ -export default function HostedClubList() { +import { User } from '../../types'; + +interface HostedClubListProps { + user: User | null; + sortBy: string | undefined; +} + +export default function HostedClubList({ user, sortBy }: HostedClubListProps) { + console.log(user); + console.log(sortBy); return
내가 만든 모임 뷰
; } diff --git a/src/features/profile/components/clubs/JoinedClubList.tsx b/src/features/profile/components/clubs/JoinedClubList.tsx index 6961689e..53fac703 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
나의 모임 뷰
; +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/profile.png', + 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/profile.png', + 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/profile.png', + 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/profile.png', + 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/profile.png', + 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/profile.png', + 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/profile.png', + 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/profile.png', + 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/profile.png', + 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/profile.png', + 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 ? ( +
+ {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/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
나의 리뷰 뷰
; } 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('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 76% rename from src/features/profile/components/clubs/ClubContents.tsx rename to src/features/profile/container/ClubContents.tsx index 6fa42003..4cebfe34 100644 --- a/src/features/profile/components/clubs/ClubContents.tsx +++ b/src/features/profile/container/ClubContents.tsx @@ -1,23 +1,26 @@ 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 ; } }; diff --git a/src/features/profile/components/MainContent.tsx b/src/features/profile/container/MainContent.tsx similarity index 68% rename from src/features/profile/components/MainContent.tsx rename to src/features/profile/container/MainContent.tsx index cb24dd8c..d9602ce9 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 ( +
+ {/* TODO: 프로필 페이지가 로그인된 유저의 프로필 페이지와 일치 여부 확인 후 마이페이지 or **님의 페이지 */} + + 마이 페이지 + + +
+ ); +} diff --git a/src/features/profile/components/ProfilePage.tsx b/src/features/profile/container/ProfilePage.tsx similarity index 56% rename from src/features/profile/components/ProfilePage.tsx rename to src/features/profile/container/ProfilePage.tsx index a010bf05..b5417318 100644 --- a/src/features/profile/components/ProfilePage.tsx +++ b/src/features/profile/container/ProfilePage.tsx @@ -1,16 +1,15 @@ '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(); 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; +// }