diff --git a/apps/web/app/layout.tsx b/apps/web/app/layout.tsx
index 6660bbb1..6fe8ac34 100644
--- a/apps/web/app/layout.tsx
+++ b/apps/web/app/layout.tsx
@@ -41,9 +41,11 @@ function RootLayout({
-
-
-
+
+
+
+
+
{children}
@@ -62,8 +64,12 @@ const Applayout = styled.div`
overflow: hidden;
height: calc(100svh - 55px);
${media.medium} {
- padding-top: 37px;
+ padding-top: 34px;
}
`;
+const Stars = styled.div`
+ height: 6px;
+`;
+
export default RootLayout;
diff --git a/apps/web/components/my/MbtiSelect.tsx b/apps/web/app/my/components/MbtiSelect.tsx
similarity index 100%
rename from apps/web/components/my/MbtiSelect.tsx
rename to apps/web/app/my/components/MbtiSelect.tsx
diff --git a/apps/web/components/my/TabContainer.tsx b/apps/web/app/my/components/TabContainer.tsx
similarity index 100%
rename from apps/web/components/my/TabContainer.tsx
rename to apps/web/app/my/components/TabContainer.tsx
diff --git a/apps/web/app/my/components/UserInfoContainer.tsx b/apps/web/app/my/components/UserInfoContainer.tsx
new file mode 100644
index 00000000..1dbddaf0
--- /dev/null
+++ b/apps/web/app/my/components/UserInfoContainer.tsx
@@ -0,0 +1,87 @@
+import ImageUploadButton from "components/common/ImageUploadButton";
+import { useGetUserInfo } from "hooks/useGetUserInfo";
+import Path from "lib/Path";
+import Link from "next/link";
+import { Gender } from "types/user";
+import styled, { css } from "styled-components";
+import { media } from "@chooz/ui/styles/media";
+
+function UserInfoContainer() {
+ const { data: userInfo } = useGetUserInfo();
+
+ if (!userInfo) return <>>;
+
+ const { gender, username, age, mbti } = userInfo;
+
+ return (
+ <>
+
+
+
+
+
+ <>
+ {gender === Gender.MALE ? "남" : "여"}
+
+ {age}
+
+ {mbti}
+ >
+
+ {username}
+
+ 프로필 수정
+
+
+ >
+ );
+}
+
+const AddImageButtonWrapper = styled.div`
+ float: left;
+`;
+
+const Profile = styled.div`
+ display: flex;
+ flex-direction: column;
+ padding-left: 17px;
+
+ ${media.medium} {
+ padding-left: 28px;
+ }
+`;
+
+const UserInfo = styled.span`
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+ width: 86px;
+ background-color: ${({ theme }) => theme.palette.background.black};
+ border-radius: 4px;
+`;
+
+const Divider = styled.div`
+ width: 1px;
+ height: 8px;
+ margin: 0 4px;
+ background-color: ${({ theme }) => theme.palette.ink.base};
+`;
+
+const Nickname = styled.span`
+ margin-top: 8px;
+ ${({ theme }) => css`
+ ${theme.textStyle.Title_Small};
+ color: ${theme.palette.ink.lighter};
+ `};
+`;
+
+const ProfileModifyButton = styled.button`
+ width: 71px;
+ height: 30px;
+ border: 1px solid ${({ theme }) => theme.palette.border.light};
+ border-radius: 4px;
+ margin-top: 25px;
+`;
+
+export default UserInfoContainer;
diff --git a/apps/web/app/my/components/VoteCountContainer.tsx b/apps/web/app/my/components/VoteCountContainer.tsx
new file mode 100644
index 00000000..b50e4df4
--- /dev/null
+++ b/apps/web/app/my/components/VoteCountContainer.tsx
@@ -0,0 +1,44 @@
+import styled from "styled-components";
+import useGetVoteCount from "../services/useGetVoteCount";
+
+function VoteCountContainer() {
+ const voteCountList = useGetVoteCount();
+
+ return (
+
+ {voteCountList.map(({ voteTypeText, count }) => {
+ return (
+
+ {count}
+ {voteTypeText}
+
+ );
+ })}
+
+ );
+}
+
+const Container = styled.section`
+ display: flex;
+ flex-direction: row;
+ justify-content: space-evenly;
+ width: 100%;
+ margin-top: 24px;
+`;
+
+const VoteType = styled.div`
+ display: flex;
+ flex-direction: column;
+`;
+
+const VoteCount = styled.span`
+ ${({ theme }) => theme.textStyle.Title_Large};
+ font-family: NeoDunggeunmo, Pretendard Variable, -apple-system, BlinkMacSystemFont, system-ui,
+ Roboto, "Helvetica Neue";
+`;
+
+const VoteTypeText = styled.span`
+ color: ${({ theme }) => theme.palette.ink.light};
+`;
+
+export default VoteCountContainer;
diff --git a/apps/web/components/my/VoteItemDesktop.tsx b/apps/web/app/my/components/VoteItemDesktop.tsx
similarity index 98%
rename from apps/web/components/my/VoteItemDesktop.tsx
rename to apps/web/app/my/components/VoteItemDesktop.tsx
index 40531fbe..3cf48ff4 100644
--- a/apps/web/components/my/VoteItemDesktop.tsx
+++ b/apps/web/app/my/components/VoteItemDesktop.tsx
@@ -5,10 +5,10 @@ import { timeDataProcessing } from "lib/utils/timeDataProcessing";
import Image from "next/image";
import { AIcon, BIcon } from "public/icons";
import styled, { css } from "styled-components";
-import { MyPageVote } from "types/vote";
+import { MyVote } from "types/vote";
interface Props {
- vote: MyPageVote;
+ vote: MyVote;
}
function VoteItemDesktop({ vote }: Props) {
diff --git a/apps/web/components/my/VoteItemMobile.tsx b/apps/web/app/my/components/VoteItemMobile.tsx
similarity index 98%
rename from apps/web/components/my/VoteItemMobile.tsx
rename to apps/web/app/my/components/VoteItemMobile.tsx
index 766e540f..b3960e3e 100644
--- a/apps/web/components/my/VoteItemMobile.tsx
+++ b/apps/web/app/my/components/VoteItemMobile.tsx
@@ -7,10 +7,10 @@ import { timeDataProcessing } from "lib/utils/timeDataProcessing";
import Image from "next/image";
import { AIcon, BIcon, BookmarkIcon } from "public/icons";
import styled, { css } from "styled-components";
-import { MyPageVote } from "types/vote";
+import { MyVote } from "types/my";
interface Props {
- vote: MyPageVote;
+ vote: MyVote;
}
function VoteItemMobile({ vote }: Props) {
diff --git a/apps/web/components/my/VoteList.tsx b/apps/web/app/my/components/VoteList.tsx
similarity index 80%
rename from apps/web/components/my/VoteList.tsx
rename to apps/web/app/my/components/VoteList.tsx
index afbdb4f0..07336189 100644
--- a/apps/web/components/my/VoteList.tsx
+++ b/apps/web/app/my/components/VoteList.tsx
@@ -1,11 +1,11 @@
import { media } from "@chooz/ui/styles/media";
import styled from "styled-components";
-import { MyPageVote } from "types/vote";
+import { MyVote } from "types/vote";
import VoteItemDesktop from "./VoteItemDesktop";
import VoteItemMobile from "./VoteItemMobile";
interface Props {
- voteList: MyPageVote[];
+ voteList: MyVote[];
}
function VoteList({ voteList }: Props) {
@@ -14,12 +14,12 @@ function VoteList({ voteList }: Props) {
return (
<>
- {voteList.map((vote: MyPageVote, index: number) => (
+ {voteList.map((vote: MyVote, index: number) => (
))}
- {voteList.map((vote: MyPageVote, index: number) => (
+ {voteList.map((vote: MyVote, index: number) => (
))}
diff --git a/apps/web/app/my/edit/page.tsx b/apps/web/app/my/edit/page.tsx
index 3f149242..56765915 100644
--- a/apps/web/app/my/edit/page.tsx
+++ b/apps/web/app/my/edit/page.tsx
@@ -2,8 +2,7 @@
import { Button, transitions } from "@chooz/ui";
import ImageUploadButton from "components/common/ImageUploadButton";
-import MbtiSelect from "components/my/MbtiSelect";
-import TabContainer from "components/my/TabContainer";
+import MbtiSelect from "app/my/components/MbtiSelect";
import { useGetUserInfo } from "hooks/useGetUserInfo";
import { uploadProfileImageAPI } from "lib/apis/upload";
import { updateUserInfo } from "lib/apis/user";
@@ -18,6 +17,7 @@ import styled, { css } from "styled-components";
import { media } from "styles/media";
import { Gender } from "types/user";
import { IMAGE_CATEGORY_LIST } from "types/vote";
+import TabContainer from "../components/TabContainer";
function ProfileEditPage() {
const router = useRouter();
diff --git a/apps/web/app/my/page.tsx b/apps/web/app/my/page.tsx
index 70f3878c..af741b50 100644
--- a/apps/web/app/my/page.tsx
+++ b/apps/web/app/my/page.tsx
@@ -1,83 +1,33 @@
"use client";
import { media } from "@chooz/ui/styles/media";
-import { useQuery } from "@tanstack/react-query";
-import ImageUploadButton from "components/common/ImageUploadButton";
-import TabContainer from "components/my/TabContainer";
-import VoteList from "components/my/VoteList";
-import { useGetUserInfo } from "hooks/useGetUserInfo";
-import { getVoteCount, VoteListType } from "lib/apis/user";
import { MY_PAGE_VOTE_TYPE } from "lib/constants";
-import Path from "lib/Path";
-import { reactQueryKeys } from "lib/queryKeys";
-import Link from "next/link";
import { useState } from "react";
-import useInfiniteMyPageVoteListService from "services/useInfiniteMyPageVoteListService";
import styled, { css } from "styled-components";
-import { Gender } from "types/user";
+import TabContainer from "./components/TabContainer";
+import VoteList from "./components/VoteList";
+import CountVoteContainer from "./components/VoteCountContainer";
+import { MyVoteListType } from "types/my";
+import useInfiniteMyVoteListService from "./services/useInfiniteMyPageVoteListService";
+import UserInfoContainer from "./components/UserInfoContainer";
function MyPage() {
- const [selectedTab, setSelectedTab] = useState("created");
+ const [selectedTab, setSelectedTab] = useState("created");
const onClickSelectedTab = (e: React.MouseEvent) => {
- setSelectedTab(e.currentTarget.value as VoteListType);
+ setSelectedTab(e.currentTarget.value as MyVoteListType);
};
- const loadVoteCount = () => {
- const { data } = useQuery(reactQueryKeys.myPageVoteCount(), getVoteCount);
- return { data };
- };
-
- const { voteList, subscribe } = useInfiniteMyPageVoteListService({
+ const { voteList, subscribe } = useInfiniteMyVoteListService({
size: 7,
voteType: selectedTab,
});
- const { data: userInfo } = useGetUserInfo();
- const { data: voteCount } = loadVoteCount();
-
- if (!userInfo) return 데이터 없음
;
- if (!voteCount) return 데이터 없음
;
-
- const { gender, username, age, mbti } = userInfo;
- const { countCreatedVote, countParticipatedVote, countBookmarkedVote } = voteCount;
-
return (
-
-
-
-
-
- <>
- {gender === Gender.MALE ? "남" : "여"}
-
- {age}
-
- {mbti}
- >
-
- {username}
-
- 프로필 수정
-
-
- {/* @TODO api 연결하면 map 사용 */}
-
-
- {countCreatedVote}
- 작성한 투표
-
-
- {countParticipatedVote}
- 참여한 투표
-
-
- {countBookmarkedVote}
- 북마크 투표
-
-
+
+
theme.palette.background.black};
- border-radius: 4px;
-`;
-
-const Divider = styled.div`
- width: 1px;
- height: 8px;
- margin: 0 4px;
- background-color: ${({ theme }) => theme.palette.ink.base};
-`;
-
-const Nickname = styled.span`
- margin-top: 8px;
- ${({ theme }) => css`
- ${theme.textStyle.Title_Small};
- color: ${theme.palette.ink.lighter};
- `};
-`;
-
-const ProfileModifyButton = styled.button`
- width: 71px;
- height: 30px;
- border: 1px solid ${({ theme }) => theme.palette.border.light};
- border-radius: 4px;
- margin-top: 25px;
-`;
-
-const NumberOfVoteSection = styled.section`
- display: flex;
- flex-direction: row;
- justify-content: space-evenly;
- width: 100%;
- margin-top: 24px;
-`;
-
-const NumberOfVoteContainer = styled.div`
- display: flex;
- flex-direction: column;
-`;
-
-const NumberOfVote = styled.span`
- ${({ theme }) => theme.textStyle.Title_Large};
- font-family: NeoDunggeunmo, Pretendard Variable, -apple-system, BlinkMacSystemFont, system-ui,
- Roboto, "Helvetica Neue";
-`;
-
-const NumberOfVoteText = styled.span`
- color: ${({ theme }) => theme.palette.ink.light};
-`;
-
const TabContainerWrapper = styled.div`
position: relative;
top: -8px;
diff --git a/apps/web/app/my/services/useGetVoteCount.ts b/apps/web/app/my/services/useGetVoteCount.ts
new file mode 100644
index 00000000..0585b5ee
--- /dev/null
+++ b/apps/web/app/my/services/useGetVoteCount.ts
@@ -0,0 +1,28 @@
+import { useQuery } from "@tanstack/react-query";
+import { getVoteCount } from "lib/apis/my";
+import { reactQueryKeys } from "lib/queryKeys";
+
+function useGetVoteCount() {
+ const { data } = useQuery(reactQueryKeys.myVoteCount(), getVoteCount);
+
+ const { countCreatedVote, countParticipatedVote, countBookmarkedVote } = data || {};
+
+ const voteCountList = [
+ {
+ voteTypeText: "작성한 투표",
+ count: countCreatedVote,
+ },
+ {
+ voteTypeText: "참여한 투표",
+ count: countParticipatedVote,
+ },
+ {
+ voteTypeText: "북마크 투표",
+ count: countBookmarkedVote,
+ },
+ ];
+
+ return voteCountList;
+}
+
+export default useGetVoteCount;
diff --git a/apps/web/services/useInfiniteMyPageVoteListService.ts b/apps/web/app/my/services/useInfiniteMyPageVoteListService.ts
similarity index 70%
rename from apps/web/services/useInfiniteMyPageVoteListService.ts
rename to apps/web/app/my/services/useInfiniteMyPageVoteListService.ts
index df3da206..fef61a18 100644
--- a/apps/web/services/useInfiniteMyPageVoteListService.ts
+++ b/apps/web/app/my/services/useInfiniteMyPageVoteListService.ts
@@ -1,16 +1,16 @@
import { useInfiniteQuery } from "@tanstack/react-query";
import { useInfiniteScroll } from "hooks/useInfiniteScroll";
-import { getMyPageVoteList, GetMyPageVoteListRequest } from "lib/apis/user";
+import { getMyVoteList, GetMyVoteListRequest } from "lib/apis/my";
import { reactQueryKeys } from "lib/queryKeys";
-type Params = Omit;
+type Params = Omit;
// @Todo infinite service 합칠 수 있는 방법 고민하기
-export default function useInfiniteMyPageVoteListService(params: Params) {
+export default function useInfiniteMyVoteListService(params: Params) {
const { data, fetchNextPage } = useInfiniteQuery(
reactQueryKeys.voteList([params.voteType]),
- ({ pageParam }) => getMyPageVoteList({ ...params, page: pageParam?.page || 0 }),
+ ({ pageParam }) => getMyVoteList({ ...params, page: pageParam?.page || 0 }),
{
getNextPageParam: ({ last, number }) => {
if (last) return undefined;
diff --git a/apps/web/lib/apis/my.ts b/apps/web/lib/apis/my.ts
new file mode 100644
index 00000000..22ee9461
--- /dev/null
+++ b/apps/web/lib/apis/my.ts
@@ -0,0 +1,52 @@
+import apiClient from "lib/apis/apiClient";
+import { MyVote, MyVoteListType } from "types/my";
+
+export interface GetMyVoteListRequest {
+ page: number;
+ size: number;
+ voteType: MyVoteListType;
+}
+
+interface GetMyVoteListResponse {
+ content: MyVote[];
+ empty: boolean;
+ first: boolean;
+ last: boolean;
+ number: number;
+ numberOfElements: number;
+ size: number;
+}
+
+export const getMyVoteList = async ({ page, size, voteType }: GetMyVoteListRequest) => {
+ const response = await apiClient.get("api/user/mypage", {
+ params: {
+ page,
+ size,
+ voteType,
+ },
+ });
+ return response.data;
+};
+
+interface GetVoteCountResponse {
+ countCreatedVote: number;
+ countParticipatedVote: number;
+ countBookmarkedVote: number;
+}
+
+export const getVoteCount = async () => {
+ const response = await apiClient.get("api/user/mypage/count");
+ return response.data;
+};
+
+interface UpdateUserInfoRequest {
+ nickname: string;
+ // image: string;
+ mbti: string;
+ categoryList: string[];
+}
+
+export const updateUserInfo = async (updateUserInfoRequest: UpdateUserInfoRequest) => {
+ const response = await apiClient.patch("api/user/mypage/edit", updateUserInfoRequest);
+ return response.data;
+};
diff --git a/apps/web/lib/apis/user.ts b/apps/web/lib/apis/user.ts
index d19925d9..5feacf7d 100644
--- a/apps/web/lib/apis/user.ts
+++ b/apps/web/lib/apis/user.ts
@@ -1,5 +1,5 @@
import { GetUserInfoResponse } from "types/user";
-import { CategoryNameType, MyPageVote } from "types/vote";
+import { CategoryNameType } from "types/vote";
import apiClient from "./apiClient";
interface AddInfoRequest {
@@ -30,55 +30,3 @@ export const getUserInfo = async () => {
const response = await apiClient.get("api/oauth/login");
return response.data;
};
-
-export type VoteListType = "created" | "participated" | "bookmarked";
-
-export interface GetMyPageVoteListRequest {
- page: number;
- size: number;
- voteType: VoteListType;
-}
-interface GetMyPageVoteListResponse {
- content: MyPageVote[];
- empty: boolean;
- first: boolean;
- last: boolean;
- number: number;
- numberOfElements: number;
- size: number;
-}
-
-// @Note api 경로에 따라 분리하는 게 맞나, 도메인에 따라 분리하는 게 맞나
-export const getMyPageVoteList = async ({ page, size, voteType }: GetMyPageVoteListRequest) => {
- const response = await apiClient.get("api/user/mypage", {
- params: {
- page,
- size,
- voteType,
- },
- });
- return response.data;
-};
-
-interface GetVoteCountResponse {
- countCreatedVote: number;
- countParticipatedVote: number;
- countBookmarkedVote: number;
-}
-
-export const getVoteCount = async () => {
- const response = await apiClient.get("api/user/mypage/count");
- return response.data;
-};
-
-interface UpdateUserInfoRequest {
- nickname: string;
- // image: string;
- mbti: string;
- categoryList: string[];
-}
-
-export const updateUserInfo = async (updateUserInfoRequest: UpdateUserInfoRequest) => {
- const response = await apiClient.patch("api/user/mypage/edit", updateUserInfoRequest);
- return response.data;
-};
diff --git a/apps/web/lib/queryKeys.ts b/apps/web/lib/queryKeys.ts
index ad0f070c..86327b7c 100644
--- a/apps/web/lib/queryKeys.ts
+++ b/apps/web/lib/queryKeys.ts
@@ -1,6 +1,6 @@
+import { MyVoteListType } from "types/my";
import { Agetype } from "types/user";
import { GenderType } from "types/vote";
-import { VoteListType } from "./apis/user";
export const queryKeys = {
USER_INFO: "userInfo" as const,
@@ -12,8 +12,8 @@ export const queryKeys = {
DETAIL_ANALYSIS: "analysisByVoteId" as const,
DETAIL_FILTERED_ANALYSIS: "filteredAnalysisByVoteId" as const,
VOTING_CHECK: "votingCheck" as const,
- MY_PAGE_VOTE_LIST: "myPageVoteList" as const,
- MY_PAGE_VOTE_COUNT: "myPageVoteCount" as const,
+ MY_VOTE_LIST: "myVoteList" as const,
+ MY_VOTE_COUNT: "myVoteCount" as const,
};
export const reactQueryKeys = {
@@ -34,6 +34,6 @@ export const reactQueryKeys = {
detailFilterdAnalysis: (id: number, mbti: string, gender: string, age: string) =>
[queryKeys.DETAIL_FILTERED_ANALYSIS, id, mbti, gender, age] as const,
votingCheck: (id: number) => [queryKeys.VOTING_CHECK, id] as const,
- myPageVoteList: (params: VoteListType) => [queryKeys.MY_PAGE_VOTE_LIST, ...params] as const,
- myPageVoteCount: () => [queryKeys.MY_PAGE_VOTE_COUNT] as const,
+ myVoteList: (params: MyVoteListType) => [queryKeys.MY_VOTE_LIST, ...params] as const,
+ myVoteCount: () => [queryKeys.MY_VOTE_COUNT] as const,
};
diff --git a/apps/web/types/my.ts b/apps/web/types/my.ts
new file mode 100644
index 00000000..ebc3b8fc
--- /dev/null
+++ b/apps/web/types/my.ts
@@ -0,0 +1,7 @@
+import { Vote } from "./vote";
+
+export interface MyVote extends Vote {
+ countComment: number;
+}
+
+export type MyVoteListType = "created" | "participated" | "bookmarked";
diff --git a/apps/web/types/vote.ts b/apps/web/types/vote.ts
index 2de101ed..546540ab 100644
--- a/apps/web/types/vote.ts
+++ b/apps/web/types/vote.ts
@@ -58,10 +58,6 @@ export interface Vote {
imageB: string | null;
}
-export interface MyPageVote extends Vote {
- countComment: number;
-}
-
export type AorB = "A" | "B";
export type Voting = PostVotingRequest;