From 3e4256013fbbf84115f41dc5c24f474085fc1528 Mon Sep 17 00:00:00 2001 From: zzzzzuuuuu Date: Thu, 15 Jan 2026 22:43:44 +0900 Subject: [PATCH 01/12] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=BD=98=EC=86=94=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entities/management/ui/Schedule.tsx | 4 ---- src/features/management/model/useSchedule.ts | 1 - src/pages/ManagementPage/management.tsx | 1 - 3 files changed, 6 deletions(-) diff --git a/src/entities/management/ui/Schedule.tsx b/src/entities/management/ui/Schedule.tsx index ce28bded..1c79da50 100644 --- a/src/entities/management/ui/Schedule.tsx +++ b/src/entities/management/ui/Schedule.tsx @@ -44,10 +44,6 @@ export const Schedule = ({ const { isOpen, setIsOpen, toggle } = useToggle(); - useEffect(() => { - console.log('팀 스케줄? ', schedule); - }, [schedule]); - useEffect(() => { if (members?.length && selectedMembers.length === 0) { setSelectedMembers(members); diff --git a/src/features/management/model/useSchedule.ts b/src/features/management/model/useSchedule.ts index 6b71f9cc..35940bf5 100644 --- a/src/features/management/model/useSchedule.ts +++ b/src/features/management/model/useSchedule.ts @@ -64,7 +64,6 @@ export const useSchedule = ( }; const submit = () => { - console.log('등록된 시간:', weeklyTimes); onSubmit?.(weeklyTimes); setShowRegister(false); }; diff --git a/src/pages/ManagementPage/management.tsx b/src/pages/ManagementPage/management.tsx index a5f134f5..f074fa75 100644 --- a/src/pages/ManagementPage/management.tsx +++ b/src/pages/ManagementPage/management.tsx @@ -61,7 +61,6 @@ export function ManagementPage() { } const transformedMySchedule = transformScheduleData(mySchedule); const transformedPartialSchedule = transformScheduleData(partialSchedule); - console.log(schedule, transformedPartialSchedule); return ( From 8253a1d79be52cc889311074d5a083c0fc2fee89 Mon Sep 17 00:00:00 2001 From: zzzzzuuuuu Date: Mon, 19 Jan 2026 22:41:20 +0900 Subject: [PATCH 02/12] =?UTF-8?q?feat:=20=EB=A7=88=EC=9D=B4=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=ED=8F=AC=ED=8A=B8=ED=8F=B4=EB=A6=AC?= =?UTF-8?q?=EC=98=A4=20=EB=A9=94=EB=89=B4=20=EB=B0=8F=20=EB=9D=BC=EC=9A=B0?= =?UTF-8?q?=ED=84=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/routes/paths.ts | 5 +++++ src/app/routes/routes.tsx | 5 +++++ src/pages/MyPage/portfolio.tsx | 3 +++ src/shared/assets/mypage/portfolio.svg | 3 +++ 4 files changed, 16 insertions(+) create mode 100644 src/pages/MyPage/portfolio.tsx create mode 100644 src/shared/assets/mypage/portfolio.svg diff --git a/src/app/routes/paths.ts b/src/app/routes/paths.ts index 075a6e19..6807b064 100644 --- a/src/app/routes/paths.ts +++ b/src/app/routes/paths.ts @@ -1,4 +1,5 @@ import MypageNoticeIcon from '@/shared/assets/mypage/loudspeaker.svg?react'; +import MypagePortfolio from '@/shared/assets/mypage/portfolio.svg?react'; import MypageTermOfServiceIcon from '@/shared/assets/mypage/term-of-service.svg?react'; import MypageProfileIcon from '@/shared/assets/mypage/update-profile.svg?react'; import FixedMemoList from '@/widgets/memo/FixedMemoList'; @@ -29,6 +30,7 @@ export const ROUTE_SEGMENTS = { MEMO_EDIT: 'edit/:memoId', MY_PAGE: 'mypage', MY_PAGE_PROFILE: 'mypage/profile', + MY_PAGE_PORTFOLIO: 'mypage/portfolio', NOTICE: 'notice', END: 'end', } as const; @@ -66,6 +68,8 @@ export const PATHS = { MY_PAGE: (teamId: number) => `${basePath(teamId)}/${ROUTE_SEGMENTS.MY_PAGE}`, PROFILE: (teamId: number) => `${basePath(teamId)}/${ROUTE_SEGMENTS.MY_PAGE_PROFILE}`, + PORTFOLIO: (teamId: number) => + `${basePath(teamId)}/${ROUTE_SEGMENTS.MY_PAGE_PORTFOLIO}`, /* 공지사항 페이지 */ NOTICE: (teamId: number) => `${basePath(teamId)}/${ROUTE_SEGMENTS.NOTICE}`, @@ -114,6 +118,7 @@ export const mainRoutes: RouteConfig[] = [ export const mypageRoutes: RouteConfig[] = [ { label: '프로필 수정', to: PATHS.PROFILE, icon: MypageProfileIcon }, + { label: '포트폴리오', to: PATHS.PORTFOLIO, icon: MypagePortfolio }, { label: '공지사항', to: PATHS.NOTICE, icon: MypageNoticeIcon }, { label: '이용약관 및 개인정보처리방침', diff --git a/src/app/routes/routes.tsx b/src/app/routes/routes.tsx index 77ec6668..f473aa65 100644 --- a/src/app/routes/routes.tsx +++ b/src/app/routes/routes.tsx @@ -11,6 +11,7 @@ import MakeTeamPage from '@/pages/MakeTeamPage/make-team'; import { ManagementPage } from '@/pages/ManagementPage'; import { ExtraMemoPage, RedirectToRootFolder } from '@/pages/MemoPage'; import { MyPage } from '@/pages/MyPage'; +import Portfolio from '@/pages/MyPage/portfolio.tsx'; import ProfilePage from '@/pages/MyPage/profile'; import NoticePage from '@/pages/NoticePage/notice'; import Redirect from '@/pages/RedirectPage/redirect'; @@ -87,6 +88,10 @@ export default function AppRoutes() { path={ROUTE_SEGMENTS.MY_PAGE_PROFILE} element={} /> + } + /> {/* 공지 페이지 */} } /> diff --git a/src/pages/MyPage/portfolio.tsx b/src/pages/MyPage/portfolio.tsx new file mode 100644 index 00000000..f833fcbe --- /dev/null +++ b/src/pages/MyPage/portfolio.tsx @@ -0,0 +1,3 @@ +export default function Portfolio() { + return
안녕
; +} diff --git a/src/shared/assets/mypage/portfolio.svg b/src/shared/assets/mypage/portfolio.svg new file mode 100644 index 00000000..83eefaaf --- /dev/null +++ b/src/shared/assets/mypage/portfolio.svg @@ -0,0 +1,3 @@ + + + From 054ea4fd9e7bb1c46942e86a4719888a3d004c0d Mon Sep 17 00:00:00 2001 From: zzzzzuuuuu Date: Mon, 19 Jan 2026 23:50:15 +0900 Subject: [PATCH 03/12] =?UTF-8?q?feat:=20=ED=94=84=EB=A1=9C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=20=EC=B9=B4=EB=93=9C=20UI=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entities/mypage/ui/ProjectCard.tsx | 78 ++++++++++++++++++++++++++ src/shared/assets/common/arrow.svg | 4 +- 2 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 src/entities/mypage/ui/ProjectCard.tsx diff --git a/src/entities/mypage/ui/ProjectCard.tsx b/src/entities/mypage/ui/ProjectCard.tsx new file mode 100644 index 00000000..9d032a68 --- /dev/null +++ b/src/entities/mypage/ui/ProjectCard.tsx @@ -0,0 +1,78 @@ +import styled from 'styled-components'; +import ArrowIcon from '@/shared/assets/common/arrow.svg?react'; + +interface ProjectCardProps { + id: number; + name: string; + duration: string; + selected: boolean; + onSelect: (id: number) => void; +} + +export function ProjectCard({ + id, + name, + duration, + selected, + onSelect, +}: ProjectCardProps) { + return ( + onSelect(id)}> + + {name} + {duration} + + + + + + ); +} + +const CardContainer = styled.div<{ $selected: boolean }>` + display: flex; + justify-content: space-between; + align-items: center; + width: 487px; + height: 64px; + border-radius: 7px; + border: 1px solid + ${({ $selected, theme }) => + $selected ? theme.colors.mainBlue : theme.colors.lightGray}; + padding: 0 16px; + + background: ${({ $selected, theme }) => + $selected ? theme.colors.background : 'white'}; +`; + +const ProjectName = styled.div` + display: flex; + align-items: center; + gap: 10px; +`; + +const Name = styled.p<{ $selected: boolean }>` + font-size: 16px; + font-weight: ${({ $selected }) => ($selected ? 700 : 500)}; + color: ${({ theme }) => theme.colors.black}; +`; + +const Duration = styled.p` + font-size: 12px; + font-weight: 400; + color: ${({ theme }) => theme.colors.gray}; +`; + +const ArrowWrapper = styled.div` + width: 24px; + height: 24px; + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; +`; diff --git a/src/shared/assets/common/arrow.svg b/src/shared/assets/common/arrow.svg index bb043561..5817e5cb 100644 --- a/src/shared/assets/common/arrow.svg +++ b/src/shared/assets/common/arrow.svg @@ -1,3 +1,3 @@ - - + + \ No newline at end of file From 5b76ea5622fa62152ef7f61d06520263c0fb5cb7 Mon Sep 17 00:00:00 2001 From: zzzzzuuuuu Date: Mon, 19 Jan 2026 23:55:43 +0900 Subject: [PATCH 04/12] =?UTF-8?q?feat:=20=ED=94=84=EB=A1=9C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20UI=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/MyPage/portfolio.tsx | 26 ++++++++++++++- src/widgets/mypage/ui/ProjectList.tsx | 48 +++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/widgets/mypage/ui/ProjectList.tsx diff --git a/src/pages/MyPage/portfolio.tsx b/src/pages/MyPage/portfolio.tsx index f833fcbe..5992e67a 100644 --- a/src/pages/MyPage/portfolio.tsx +++ b/src/pages/MyPage/portfolio.tsx @@ -1,3 +1,27 @@ +import styled from 'styled-components'; +import MypageHeader from '@/widgets/mypage/MypageHeader.tsx'; +import { ProjectList } from '@/widgets/mypage/ui/ProjectList.tsx'; + export default function Portfolio() { - return
안녕
; + return ( + + 포트폴리오 + + + + + + ); } + +const Container = styled.div` + width: 100%; + height: 100vh; +`; + +const ContentWrapper = styled.div` + display: flex; + flex-direction: column; + width: 75%; + margin: 46px 0 0 10%; +`; diff --git a/src/widgets/mypage/ui/ProjectList.tsx b/src/widgets/mypage/ui/ProjectList.tsx new file mode 100644 index 00000000..b6d6472e --- /dev/null +++ b/src/widgets/mypage/ui/ProjectList.tsx @@ -0,0 +1,48 @@ +import { useState } from 'react'; +import styled from 'styled-components'; +import { ProjectCard } from '@/entities/mypage/ui/ProjectCard.tsx'; + +const MOCK_PROJECTS = [ + { + id: 1, + name: '팀매니저 ver.1', + duration: '2024.07 ~ 2024.08', + }, + { + id: 2, + name: '팀매니저 ver.2', + duration: '2024.09 ~ ing', + }, +]; + +export function ProjectList() { + const [selectedProjectId, setSelectedProjectId] = useState( + MOCK_PROJECTS[0].id, + ); + return ( + + {MOCK_PROJECTS.map((project) => ( + + ))} + + ); +} + +const ListContainer = styled.div` + display: flex; + flex-direction: column; + align-items: center; + width: 534px; + height: 562px; + padding: 24px 0; + gap: 20px; + background: white; + border-radius: 10px; +`; From 4c7f9664e51933085c245cb596aec451e575c30f Mon Sep 17 00:00:00 2001 From: zzzzzuuuuu Date: Tue, 20 Jan 2026 23:21:55 +0900 Subject: [PATCH 05/12] =?UTF-8?q?feat:=20=ED=83=9C=EA=B7=B8=20=EA=B3=B5?= =?UTF-8?q?=ED=86=B5=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/shared/ui/Tag/Tag.tsx | 34 ++++++++++++++++++++++++++++++++++ src/shared/ui/Tag/index.ts | 1 + 2 files changed, 35 insertions(+) create mode 100644 src/shared/ui/Tag/Tag.tsx create mode 100644 src/shared/ui/Tag/index.ts diff --git a/src/shared/ui/Tag/Tag.tsx b/src/shared/ui/Tag/Tag.tsx new file mode 100644 index 00000000..f63e5607 --- /dev/null +++ b/src/shared/ui/Tag/Tag.tsx @@ -0,0 +1,34 @@ +import styled from 'styled-components'; + +interface TagProps { + text: string; + variant?: 'default' | 'primary'; +} + +export function Tag({ text }: TagProps) { + return ( + + {text} + + ); +} + +const TagBox = styled.div` + max-width: 80px; + height: 28px; + display: flex; + justify-content: center; + align-items: center; + padding: 5px 8px; + border-radius: 3px; + background: ${({ theme }) => theme.colors.background}; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +`; + +const TagText = styled.span` + font-size: 12px; + font-weight: 500; + color: ${({ theme }) => theme.colors.mainBlue}; +`; diff --git a/src/shared/ui/Tag/index.ts b/src/shared/ui/Tag/index.ts new file mode 100644 index 00000000..ba2338b7 --- /dev/null +++ b/src/shared/ui/Tag/index.ts @@ -0,0 +1 @@ +export { Tag } from './Tag'; From e2b4256ac40ae4c88059c9f611ae4b7d02e1c3c4 Mon Sep 17 00:00:00 2001 From: zzzzzuuuuu Date: Tue, 20 Jan 2026 23:22:31 +0900 Subject: [PATCH 06/12] =?UTF-8?q?feat:=20=ED=94=84=EB=A1=9C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=20=EC=A0=95=EB=B3=B4=20section=20UI=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entities/mypage/ui/ProjectInfoSection.tsx | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/entities/mypage/ui/ProjectInfoSection.tsx diff --git a/src/entities/mypage/ui/ProjectInfoSection.tsx b/src/entities/mypage/ui/ProjectInfoSection.tsx new file mode 100644 index 00000000..133a7511 --- /dev/null +++ b/src/entities/mypage/ui/ProjectInfoSection.tsx @@ -0,0 +1,52 @@ +import styled from 'styled-components'; +import { Tag } from '@/shared/ui/Tag/Tag.tsx'; + +interface ProjectInfoSectionProps { + id: number; + title: string; + tags: string[]; +} + +export function ProjectInfoSection({ + id, + title, + tags, +}: ProjectInfoSectionProps) { + return ( + + {title} + + + {tags.map((tag) => ( + + ))} + + + ); +} + +const Container = styled.div` + display: flex; + flex-direction: column; + width: 480px; + gap: 4px; +`; + +const Title = styled.div` + width: 100%; + height: 18px; + display: flex; + align-items: center; + font-size: 12px; + font-weight: 600; + color: ${({ theme }) => theme.colors.black}; +`; + +const TagContainer = styled.div` + width: 100%; + height: 44px; + display: flex; + align-items: center; + gap: 7px; + border-bottom: 1px solid ${({ theme }) => theme.colors.silver}; +`; From 7a6ee88e3d6097e34a2c0209d0ec1ea1ab1a0e8f Mon Sep 17 00:00:00 2001 From: zzzzzuuuuu Date: Wed, 21 Jan 2026 13:30:49 +0900 Subject: [PATCH 07/12] =?UTF-8?q?chore:=20=ED=94=84=EB=A1=9C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=20=EB=AA=A9=EC=97=85=EB=8D=B0=EC=9D=B4=ED=84=B0=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../portfolio/model/portfolio.mock.ts | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/entities/portfolio/model/portfolio.mock.ts diff --git a/src/entities/portfolio/model/portfolio.mock.ts b/src/entities/portfolio/model/portfolio.mock.ts new file mode 100644 index 00000000..3e217f82 --- /dev/null +++ b/src/entities/portfolio/model/portfolio.mock.ts @@ -0,0 +1,30 @@ +export const MOCK_PROJECTS = [ + { + id: 1, + name: '팀매니저 ver.1', + duration: '2024.07 ~ 2024.08', + }, + { + id: 2, + name: '팀매니저 ver.2', + duration: '2024.09 ~ ing', + }, +]; + +export const projectInfoMock = [ + { + id: 1, + title: '프로젝트 카테고리', + tags: ['팀매니저', '팀프로젝트'], + }, + { + id: 2, + title: '프로젝트 멤버', + tags: ['지유', '안지유'], + }, + { + id: 3, + title: '나의 역할', + tags: ['개발자', '프론트엔드'], + }, +]; From a8ec31c3d07041be1aef00fdfd404592c07d5aaf Mon Sep 17 00:00:00 2001 From: zzzzzuuuuu Date: Wed, 21 Jan 2026 13:31:40 +0900 Subject: [PATCH 08/12] =?UTF-8?q?refactor:=20=ED=94=84=EB=A1=9C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=20=EB=AA=A9=EC=97=85=EB=8D=B0=EC=9D=B4=ED=84=B0=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{mypage => portfolio}/ui/ProjectCard.tsx | 0 .../ui/ProjectInfoSection.tsx | 8 ++--- .../{mypage => portfolio}/ui/ProjectList.tsx | 34 ++++++++----------- 3 files changed, 16 insertions(+), 26 deletions(-) rename src/entities/{mypage => portfolio}/ui/ProjectCard.tsx (100%) rename src/entities/{mypage => portfolio}/ui/ProjectInfoSection.tsx (86%) rename src/widgets/{mypage => portfolio}/ui/ProjectList.tsx (50%) diff --git a/src/entities/mypage/ui/ProjectCard.tsx b/src/entities/portfolio/ui/ProjectCard.tsx similarity index 100% rename from src/entities/mypage/ui/ProjectCard.tsx rename to src/entities/portfolio/ui/ProjectCard.tsx diff --git a/src/entities/mypage/ui/ProjectInfoSection.tsx b/src/entities/portfolio/ui/ProjectInfoSection.tsx similarity index 86% rename from src/entities/mypage/ui/ProjectInfoSection.tsx rename to src/entities/portfolio/ui/ProjectInfoSection.tsx index 133a7511..146b1e22 100644 --- a/src/entities/mypage/ui/ProjectInfoSection.tsx +++ b/src/entities/portfolio/ui/ProjectInfoSection.tsx @@ -7,18 +7,14 @@ interface ProjectInfoSectionProps { tags: string[]; } -export function ProjectInfoSection({ - id, - title, - tags, -}: ProjectInfoSectionProps) { +export function ProjectInfoSection({ title, tags }: ProjectInfoSectionProps) { return ( {title} {tags.map((tag) => ( - + ))} diff --git a/src/widgets/mypage/ui/ProjectList.tsx b/src/widgets/portfolio/ui/ProjectList.tsx similarity index 50% rename from src/widgets/mypage/ui/ProjectList.tsx rename to src/widgets/portfolio/ui/ProjectList.tsx index b6d6472e..08f8e524 100644 --- a/src/widgets/mypage/ui/ProjectList.tsx +++ b/src/widgets/portfolio/ui/ProjectList.tsx @@ -1,34 +1,28 @@ -import { useState } from 'react'; import styled from 'styled-components'; -import { ProjectCard } from '@/entities/mypage/ui/ProjectCard.tsx'; +import { MOCK_PROJECTS } from '@/entities/portfolio/model/portfolio.mock.ts'; +import { ProjectCard } from '@/entities/portfolio/ui/ProjectCard.tsx'; -const MOCK_PROJECTS = [ - { - id: 1, - name: '팀매니저 ver.1', - duration: '2024.07 ~ 2024.08', - }, - { - id: 2, - name: '팀매니저 ver.2', - duration: '2024.09 ~ ing', - }, -]; +interface ProjectListProps { + projects: typeof MOCK_PROJECTS; + selectedProjectId: number; + onSelectProject: (id: number) => void; +} -export function ProjectList() { - const [selectedProjectId, setSelectedProjectId] = useState( - MOCK_PROJECTS[0].id, - ); +export function ProjectList({ + projects, + selectedProjectId, + onSelectProject, +}: ProjectListProps) { return ( - {MOCK_PROJECTS.map((project) => ( + {projects.map((project) => ( ))} From 6bac5b787e766dfd88b212e80cad37a5627be0b4 Mon Sep 17 00:00:00 2001 From: zzzzzuuuuu Date: Wed, 21 Jan 2026 13:44:10 +0900 Subject: [PATCH 09/12] =?UTF-8?q?feat:=20=ED=94=84=EB=A1=9C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=20=EC=84=B8=EB=B6=80=EC=82=AC=ED=95=AD=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=A0=9C=EC=99=B8=ED=95=9C=20UI=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entities/portfolio/ui/ProjectTitle.tsx | 45 +++++++++++++++++++++ src/pages/MyPage/portfolio.tsx | 37 ++++++++++++++--- src/widgets/portfolio/ui/ProjectDetail.tsx | 46 ++++++++++++++++++++++ 3 files changed, 123 insertions(+), 5 deletions(-) create mode 100644 src/entities/portfolio/ui/ProjectTitle.tsx create mode 100644 src/widgets/portfolio/ui/ProjectDetail.tsx diff --git a/src/entities/portfolio/ui/ProjectTitle.tsx b/src/entities/portfolio/ui/ProjectTitle.tsx new file mode 100644 index 00000000..77a2ef3f --- /dev/null +++ b/src/entities/portfolio/ui/ProjectTitle.tsx @@ -0,0 +1,45 @@ +import styled from 'styled-components'; + +interface ProjectTitleProps { + title: string; + duration: string; +} + +export function ProjectTitle({ title, duration }: ProjectTitleProps) { + return ( + + + {title} + {duration} + + + ); +} + +const Container = styled.div` + width: 480px; + height: 34px; + display: flex; + border-bottom: 1px solid ${({ theme }) => theme.colors.silver}; +`; + +const TitleContainer = styled.div` + width: 230px; + height: 27px; + gap: 19px; + display: flex; + align-items: center; +`; + +const Title = styled.p` + font-size: 18px; + font-weight: 700; + color: ${({ theme }) => theme.colors.black}; + margin: 4.5px 0; +`; + +const Duration = styled.p` + font-size: 12px; + font-weight: 400; + color: ${({ theme }) => theme.colors.darkGray}; +`; diff --git a/src/pages/MyPage/portfolio.tsx b/src/pages/MyPage/portfolio.tsx index 5992e67a..25bb6260 100644 --- a/src/pages/MyPage/portfolio.tsx +++ b/src/pages/MyPage/portfolio.tsx @@ -1,27 +1,54 @@ +import { useState } from 'react'; import styled from 'styled-components'; +import { + MOCK_PROJECTS, + projectInfoMock, +} from '@/entities/portfolio/model/portfolio.mock.ts'; import MypageHeader from '@/widgets/mypage/MypageHeader.tsx'; -import { ProjectList } from '@/widgets/mypage/ui/ProjectList.tsx'; +import { ProjectDetail } from '@/widgets/portfolio/ui/ProjectDetail.tsx'; +import { ProjectList } from '@/widgets/portfolio/ui/ProjectList.tsx'; export default function Portfolio() { + const [selectedProjectId, setSelectedProjectId] = useState( + MOCK_PROJECTS[0].id, + ); + + const selectedProject = MOCK_PROJECTS.find( + (project) => project.id === selectedProjectId, + ); + return ( 포트폴리오 - + + {selectedProject && ( + + )} ); } const Container = styled.div` + display: flex; + flex-direction: column; width: 100%; height: 100vh; `; const ContentWrapper = styled.div` display: flex; - flex-direction: column; - width: 75%; - margin: 46px 0 0 10%; + width: 95%; + margin: 46px 0 74px 5%; + gap: 20px; `; diff --git a/src/widgets/portfolio/ui/ProjectDetail.tsx b/src/widgets/portfolio/ui/ProjectDetail.tsx new file mode 100644 index 00000000..1b96fe9f --- /dev/null +++ b/src/widgets/portfolio/ui/ProjectDetail.tsx @@ -0,0 +1,46 @@ +import styled from 'styled-components'; +import { ProjectInfoSection } from '@/entities/portfolio/ui/ProjectInfoSection.tsx'; +import { ProjectTitle } from '@/entities/portfolio/ui/ProjectTitle.tsx'; + +interface ProjectDetailProps { + projectName: string; + projectDuration: string; + projectInfo: { + id: number; + title: string; + tags: string[]; + }[]; +} + +export function ProjectDetail({ + projectName, + projectDuration, + projectInfo, +}: ProjectDetailProps) { + return ( + + + {projectInfo.map((item) => ( + + ))} +
공유했던 파일
+
+ ); +} + +const DetailContainer = styled.div` + display: flex; + flex-direction: column; + align-items: center; + width: 534px; + height: 562px; + padding: 24px 0; + gap: 20px; + background: white; + border-radius: 10px; +`; From 5971f37dcdd3be6e0305be69f7da0743b4b733d6 Mon Sep 17 00:00:00 2001 From: zzzzzuuuuu Date: Thu, 22 Jan 2026 22:53:15 +0900 Subject: [PATCH 10/12] =?UTF-8?q?feat:=20=ED=8F=AC=ED=8A=B8=ED=8F=B4?= =?UTF-8?q?=EB=A6=AC=EC=98=A4=20=ED=94=84=EB=A1=9C=EC=A0=9D=ED=8A=B8=20?= =?UTF-8?q?=EB=AF=B8=EC=A1=B4=EC=9E=AC=20=EB=B0=8F=20=EB=AF=B8=EC=84=A0?= =?UTF-8?q?=ED=83=9D=20=EC=83=81=ED=83=9C=20=EB=B6=84=EA=B8=B0=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entities/portfolio/ui/ProjectCard.tsx | 2 +- src/pages/MyPage/portfolio.tsx | 30 +++++++++-------- src/widgets/portfolio/ui/ProjectDetail.tsx | 39 +++++++++++++++++++--- src/widgets/portfolio/ui/ProjectList.tsx | 27 ++++++++++++++- 4 files changed, 78 insertions(+), 20 deletions(-) diff --git a/src/entities/portfolio/ui/ProjectCard.tsx b/src/entities/portfolio/ui/ProjectCard.tsx index 9d032a68..7f1645ee 100644 --- a/src/entities/portfolio/ui/ProjectCard.tsx +++ b/src/entities/portfolio/ui/ProjectCard.tsx @@ -45,6 +45,7 @@ const CardContainer = styled.div<{ $selected: boolean }>` ${({ $selected, theme }) => $selected ? theme.colors.mainBlue : theme.colors.lightGray}; padding: 0 16px; + cursor: pointer; background: ${({ $selected, theme }) => $selected ? theme.colors.background : 'white'}; @@ -74,5 +75,4 @@ const ArrowWrapper = styled.div` display: flex; justify-content: center; align-items: center; - cursor: pointer; `; diff --git a/src/pages/MyPage/portfolio.tsx b/src/pages/MyPage/portfolio.tsx index 25bb6260..75bbff74 100644 --- a/src/pages/MyPage/portfolio.tsx +++ b/src/pages/MyPage/portfolio.tsx @@ -9,13 +9,18 @@ import { ProjectDetail } from '@/widgets/portfolio/ui/ProjectDetail.tsx'; import { ProjectList } from '@/widgets/portfolio/ui/ProjectList.tsx'; export default function Portfolio() { - const [selectedProjectId, setSelectedProjectId] = useState( - MOCK_PROJECTS[0].id, + const projects = MOCK_PROJECTS; + const [selectedProjectId, setSelectedProjectId] = useState( + null, ); - const selectedProject = MOCK_PROJECTS.find( - (project) => project.id === selectedProjectId, - ); + // 프로젝트 존재 여부 + const hasProjects = projects.length > 0; + + const selectedProject = + selectedProjectId === null + ? null + : (projects.find((project) => project.id === selectedProjectId) ?? null); return ( @@ -23,17 +28,16 @@ export default function Portfolio() { - {selectedProject && ( - - )} + ); diff --git a/src/widgets/portfolio/ui/ProjectDetail.tsx b/src/widgets/portfolio/ui/ProjectDetail.tsx index 1b96fe9f..e8a88d49 100644 --- a/src/widgets/portfolio/ui/ProjectDetail.tsx +++ b/src/widgets/portfolio/ui/ProjectDetail.tsx @@ -1,10 +1,14 @@ import styled from 'styled-components'; import { ProjectInfoSection } from '@/entities/portfolio/ui/ProjectInfoSection.tsx'; import { ProjectTitle } from '@/entities/portfolio/ui/ProjectTitle.tsx'; +import { ContainerText, Wrapper } from '@/widgets/portfolio/ui/ProjectList.tsx'; interface ProjectDetailProps { - projectName: string; - projectDuration: string; + hasProjects: boolean; + selectedProject: { + name: string; + duration: string; + } | null; projectInfo: { id: number; title: string; @@ -13,13 +17,38 @@ interface ProjectDetailProps { } export function ProjectDetail({ - projectName, - projectDuration, + hasProjects, + selectedProject, projectInfo, }: ProjectDetailProps) { + // 프로젝트가 아예 없을 때 + if (!hasProjects) { + return ( + + + 아직 확인할 프로젝트가 없습니다. + + + ); + } + + // 프로젝트는 존재, 선택 전 + if (!selectedProject) { + return ( + + + 프로젝트를 클릭해 확인할 수 있습니다. + + + ); + } + return ( - + {projectInfo.map((item) => ( void; } export function ProjectList({ projects, + hasProjects, selectedProjectId, onSelectProject, }: ProjectListProps) { + if (!hasProjects) { + return ( + + + 아직 끝난 프로젝트가 없습니다. + + + ); + } return ( {projects.map((project) => ( @@ -40,3 +51,17 @@ const ListContainer = styled.div` background: white; border-radius: 10px; `; + +export const Wrapper = styled.div` + width: 100%; + height: 100vh; + display: flex; + justify-content: center; + align-items: center; +`; + +export const ContainerText = styled.div` + font-size: 16px; + font-weight: 500; + color: ${({ theme }) => theme.colors.black}; +`; From 0b29e062c2d7b16be55c30b745bbd1903e8d4f97 Mon Sep 17 00:00:00 2001 From: zzzzzuuuuu Date: Thu, 22 Jan 2026 22:55:29 +0900 Subject: [PATCH 11/12] =?UTF-8?q?feat:=20=ED=94=84=EB=A1=9C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=20=EC=84=A0=ED=83=9D=20=ED=86=A0=EA=B8=80=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/MyPage/portfolio.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/pages/MyPage/portfolio.tsx b/src/pages/MyPage/portfolio.tsx index 75bbff74..8d434486 100644 --- a/src/pages/MyPage/portfolio.tsx +++ b/src/pages/MyPage/portfolio.tsx @@ -22,6 +22,10 @@ export default function Portfolio() { ? null : (projects.find((project) => project.id === selectedProjectId) ?? null); + const handleSelectProject = (projectId: number) => { + setSelectedProjectId((prev) => (prev === projectId ? null : projectId)); + }; + return ( 포트폴리오 @@ -31,7 +35,7 @@ export default function Portfolio() { projects={projects} hasProjects={hasProjects} selectedProjectId={selectedProjectId} - onSelectProject={setSelectedProjectId} + onSelectProject={handleSelectProject} /> Date: Fri, 23 Jan 2026 22:06:47 +0900 Subject: [PATCH 12/12] =?UTF-8?q?feat:=20=ED=8F=AC=ED=8A=B8=ED=8F=B4?= =?UTF-8?q?=EB=A6=AC=EC=98=A4=20=EC=8A=A4=EC=BC=88=EB=A0=88=ED=86=A4=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/MyPage/portfolio.tsx | 43 ++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/src/pages/MyPage/portfolio.tsx b/src/pages/MyPage/portfolio.tsx index 8d434486..752b656e 100644 --- a/src/pages/MyPage/portfolio.tsx +++ b/src/pages/MyPage/portfolio.tsx @@ -1,9 +1,10 @@ -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import styled from 'styled-components'; import { MOCK_PROJECTS, projectInfoMock, } from '@/entities/portfolio/model/portfolio.mock.ts'; +import Skeleton from '@/shared/components/skeleton/Skeleton.tsx'; import MypageHeader from '@/widgets/mypage/MypageHeader.tsx'; import { ProjectDetail } from '@/widgets/portfolio/ui/ProjectDetail.tsx'; import { ProjectList } from '@/widgets/portfolio/ui/ProjectList.tsx'; @@ -13,6 +14,8 @@ export default function Portfolio() { const [selectedProjectId, setSelectedProjectId] = useState( null, ); + // TODO: API 연동 후 isPending으로 변경 + const [isLoading, setIsLoading] = useState(true); // 프로젝트 존재 여부 const hasProjects = projects.length > 0; @@ -26,22 +29,38 @@ export default function Portfolio() { setSelectedProjectId((prev) => (prev === projectId ? null : projectId)); }; + useEffect(() => { + const timer = setTimeout(() => { + setIsLoading(false); + }, 800); + return () => clearTimeout(timer); + }, []); + return ( 포트폴리오 - - + {isLoading ? ( + <> + + + + ) : ( + <> + + + + )} );