Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: 마이페이지 api 연결 #171

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions co-kkiri/src/components/domains/myPage/InvitedTeamList.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import SectionTitle from "../manage/SectionTitle";
import styled from "styled-components";
import DESIGN_TOKEN from "@/styles/tokens";
import { InvitedTeam } from "@/lib/api/myPage/type";
import { InvitedTeamListApiResponseDto } from "@/lib/api/myPage/type";

interface InvitedTeamListProps {
teamList: InvitedTeam[];
teamList: InvitedTeamListApiResponseDto["data"];
count: number;
}

Expand Down
13 changes: 8 additions & 5 deletions co-kkiri/src/components/domains/myPage/ScrapList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@ import Card from "@/components/commons/Card";
import styled from "styled-components";
import DESIGN_TOKEN from "@/styles/tokens";

interface ScrapListProps extends MyScrapApiResponseDto {}

export default function ScrapList({ scrapList }: ScrapListProps) {
const count = scrapList.filter((scrap) => scrap.isScraped).length;
interface ScrapListProps {
data: MyScrapApiResponseDto["data"];
}
export default function ScrapList({ data }: ScrapListProps) {
const count = data.filter((scrap) => scrap.isScraped).length;

return (
<Container>
<SectionTitle title="스터디/프로젝트 스크랩 목록" count={count} type="cardList" />
<Wrapper>
{scrapList?.map((scrap) => {
{data.map((scrap) => {
return scrap.isScraped && <Card key={scrap.postId} page="studyList" cardData={scrap} />;
})}
</Wrapper>
Expand All @@ -26,7 +27,9 @@ const { mediaQueries } = DESIGN_TOKEN;
const Container = styled.div`
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 2rem;
width: 100%;
`;

const Wrapper = styled.div`
Expand Down
52 changes: 43 additions & 9 deletions co-kkiri/src/components/domains/myPage/UserInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,49 @@
import ToggleButton from "@/components/commons/ToggleButton";
import UserProfileCard from "@/components/commons/UserProfileCard";
import { UserInfoApiResponseDto } from "@/lib/api/myPage/type";
import { deleteUser, editVisibleProfileStatus, getVisibleProfileStatus } from "@/lib/api/myPage";
import { UserInfoApiResponseDto, VisibleProfileStatusApiRequestDto } from "@/lib/api/myPage/type";
import DESIGN_TOKEN from "@/styles/tokens";
import { useState } from "react";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { Navigate, useNavigate } from "react-router-dom";
import styled from "styled-components";

interface UserInfoProps {
user: UserInfoApiResponseDto;
visibleProfile: VisibleProfileStatusApiRequestDto;
}

export default function UserInfo({ user }: UserInfoProps) {
const [isChecked, setIsChecked] = useState(user.isVisibleProfile);
export default function UserInfo({ user, visibleProfile }: UserInfoProps) {
const queryClient = useQueryClient();
const navigate = useNavigate();
const editVisibleProfile = useMutation({
mutationFn: (data: VisibleProfileStatusApiRequestDto) => editVisibleProfileStatus(data),
onSuccess: () => {
queryClient.invalidateQueries();
},
onError: (error) => {
console.error(error);
},
});

const handleIsVisibleProfile = () => {
setIsChecked(!isChecked);
const deleteUserMutation = useMutation({
mutationFn: () => deleteUser(),
onSuccess: () => {
queryClient.invalidateQueries();
// navigate("/");
console.log("요청 성공");
// 콘솔은 잘 찍히는데 왜 회원 탈퇴가 안될까~
},
onError: (error) => {
console.error(error);
},
});

const handleEditVisibleProfile = () => {
editVisibleProfile.mutate({ isVisibleProfile: !visibleProfile.isVisibleProfile });
};

const handleDeleteUser = () => {
deleteUserMutation.mutate();
};

return (
Expand All @@ -22,17 +52,21 @@ export default function UserInfo({ user }: UserInfoProps) {
nickname={user.nickname}
position={user.position}
career={user.career}
stacks={user.stacks}
stacks={user.stack}
score={40}
introduce={user.introduce}
link={user.link}
cardType="mypage"
/>
<Box>
<Scout>
<ToggleButton content="스카우트 동의" onChange={handleIsVisibleProfile} isChecked={isChecked} />
<ToggleButton
content="스카우트 동의"
onChange={() => handleEditVisibleProfile()}
isChecked={visibleProfile.isVisibleProfile}
/>
</Scout>
<DeleteUser>회원 탈퇴하기</DeleteUser>
<DeleteUser onClick={handleDeleteUser}>회원 탈퇴하기</DeleteUser>
</Box>
</Container>
);
Expand Down
2 changes: 1 addition & 1 deletion co-kkiri/src/lib/api/address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export const myPageAddress = {
//patch
visibleProfile: "/my-page/visible-profile",
//delete
myPage: "/my-page",
myPage: "/my-page/info",
};

export const teamAddress = {
Expand Down
13 changes: 10 additions & 3 deletions co-kkiri/src/lib/api/myPage/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { myPageAddress } from "../address";
import { apiRequest } from "../axios";
import {
InvitedTeamListApiRequestDto,
InvitedTeamListApiResponseDto,
MyScrapApiRequestDto,
MyScrapApiResponseDto,
UserInfoApiResponseDto,
UserInfoEditApiRequestDto,
Expand All @@ -15,11 +17,16 @@ export const getUserInfo = (): Promise<UserInfoApiResponseDto> => apiRequest("ge
export const editUserInfo = (data: UserInfoEditApiRequestDto) => apiRequest("patch", myPageAddress.userInfo, data);

/** 초대된 팀 목록 가져오기 */
export const getInvitedTeamList = (): Promise<InvitedTeamListApiResponseDto> =>
apiRequest("get", myPageAddress.inviteList);
export const getInvitedTeamList = (qs: InvitedTeamListApiRequestDto): Promise<InvitedTeamListApiResponseDto> =>
apiRequest("get", myPageAddress.inviteList, null, qs);

/** 스크랩 목록 가져오기 */
export const getScrapList = (): Promise<MyScrapApiResponseDto> => apiRequest("get", myPageAddress.scrapList);
export const getScrapList = (qs: MyScrapApiRequestDto): Promise<MyScrapApiResponseDto> =>
apiRequest("get", myPageAddress.scrapList, null, qs);

/** 프로필 공개 여부 가져오기 */
export const getVisibleProfileStatus = (): Promise<VisibleProfileStatusApiRequestDto> =>
apiRequest("get", myPageAddress.visibleProfile);

/** 프로필 공개 여부 수정하기 */
export const editVisibleProfileStatus = (data: VisibleProfileStatusApiRequestDto) =>
Expand Down
32 changes: 27 additions & 5 deletions co-kkiri/src/lib/api/myPage/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,34 @@ export type UserInfoApiResponseDto = {
position: string;
career: number;
introduce: string;
stacks: string[];
stack: string[];
link: string;
isVisibleProfile: boolean;
};

//마이 페이지 초대된 팀 목록
export type InvitedTeam = {
type InvitedTeam = {
teamInviteId: number;
postTitle: string;
};

type PageMeta = {
page: number;
take: number; // 가져올 갯수
totalCount: number; // 전체 갯수
pageCount: number; // 페이지 갯수
hasPreviousPage: boolean; // 이전 페이지가 있는지
hasNextPage: boolean; // 다음 페이지가 있는지
};

export type InvitedTeamListApiResponseDto = {
inviteList: InvitedTeam[];
data: InvitedTeam[];
meta: PageMeta;
};

export type InvitedTeamListApiRequestDto = {
order: "ASC" | "DESC"; // 정렬 순서, ASC: 옛날순, DESC: 최신순
page: number; // 요청할 페이지
take: number;
};

// 마이 페이지 스크랩 목록
Expand All @@ -39,7 +54,14 @@ export type MyScrap = {
};

export type MyScrapApiResponseDto = {
scrapList: MyScrap[];
data: MyScrap[];
meta: PageMeta;
};

export type MyScrapApiRequestDto = {
order: "ASC" | "DESC"; // 정렬 순서, ASC: 옛날순, DESC: 최신순
page: number; // 요청할 페이지
take: number;
};

// 마이 페이지 유저 정보 수정
Expand Down
56 changes: 9 additions & 47 deletions co-kkiri/src/pages/Manage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,85 +2,47 @@ import MemberList from "@/components/domains/manage/MemberList";
import * as S from "./styled";
import AppliedList from "@/components/domains/manage/AppliedList";
import { getAppliedMemberList, getStudyManagement } from "@/lib/api/post";
import { useEffect, useState } from "react";
import { AppliedMemberListApiResponseDto, StudyManagementApiResponseDto } from "@/lib/api/post/type";
import { StudyManagementApiResponseDto } from "@/lib/api/post/type";
import { getTeamMember } from "@/lib/api/teamMember";
import { TeamMemberApiResponseDto } from "@/lib/api/teamMember/type";
import { useQuery } from "@tanstack/react-query";

interface ManageProps {
postId: StudyManagementApiResponseDto["postId"];
}

export default function Manage({ postId }: ManageProps) {
const [detailInfo, setDetailInfo] = useState<StudyManagementApiResponseDto>();
const [appliedMemberList, setAppliedMemberList] = useState<
AppliedMemberListApiResponseDto["data"] | null | undefined
>();
const [memberList, setMemberList] = useState<TeamMemberApiResponseDto["data"] | null | undefined>();

const {
data: detailInfoData,
error,
isError,
} = useQuery({
const { data: detailInfo, error } = useQuery({
queryKey: ["management", postId],
queryFn: () => getStudyManagement(postId),
});
const {
data: appliedMemberListData,
error: appliedMemberListError,
isError: isAppliedMemberListError,
} = useQuery({
const { data: appliedMemberList, error: appliedMemberListError } = useQuery({
queryKey: ["appliedMemberList", postId],
queryFn: () => getAppliedMemberList(postId, { order: "DESC", page: 1, take: 100 }),
});
const {
data: memberListData,
error: memberListError,
isError: isMemberListError,
} = useQuery({
const { data: memberList, error: memberListError } = useQuery({
queryKey: ["memberList", postId],
queryFn: () => getTeamMember(postId, { order: "DESC", page: 1, take: 5 }),
});

if (isError) {
if (error) {
console.error(error);
}

if (isAppliedMemberListError) {
if (appliedMemberListError) {
console.error(appliedMemberListError);
}

if (isMemberListError) {
if (memberListError) {
console.error(memberListError);
}

useEffect(() => {
if (detailInfoData) {
setDetailInfo(detailInfoData);
}
}, [detailInfoData]);

useEffect(() => {
if (appliedMemberListData) {
setAppliedMemberList(appliedMemberListData.data);
}
}, [appliedMemberListData]);

useEffect(() => {
if (memberListData) {
setMemberList(memberListData.data);
}
}, [memberListData]);

return (
<S.Container>
<S.Box>
{detailInfo && <S.DetailSection detailInfo={detailInfo} />}
<S.ListSection>
<AppliedList detailInfo={appliedMemberList} />
<MemberList detailInfo={memberList} />
{appliedMemberList && <AppliedList detailInfo={appliedMemberList.data} />}
{memberList && <MemberList detailInfo={memberList.data} />}
</S.ListSection>
{detailInfo && <S.ButtonSection buttonType={detailInfo.status} isLeader={detailInfo.isLeader} />}
</S.Box>
Expand Down
56 changes: 47 additions & 9 deletions co-kkiri/src/pages/MyPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,65 @@ import UserInfo from "@/components/domains/myPage/UserInfo";
import TagList from "@/components/domains/myPage/TagList";
import InvitedTeamList from "@/components/domains/myPage/InvitedTeamList";
import ScrapList from "@/components/domains/myPage/ScrapList";
import { invitedTeamList } from "@/lib/mock/myPage/invitedTeam";
import { myScrapList } from "@/lib/mock/myPage/myScrap";
import { userProfileInfoData } from "@/lib/mock/myPage/userProfileInfo";
import { useQuery } from "@tanstack/react-query";
import { getInvitedTeamList, getScrapList, getUserInfo, getVisibleProfileStatus } from "@/lib/api/myPage";

export default function MyPage() {
const profileInfo = userProfileInfoData.result.userProfileInfo;
const teamList = invitedTeamList.result.inviteList;
const scrapList = myScrapList.result.scrapList;
const { data: userInfo, error: userInfoError } = useQuery({
queryKey: ["info"],
queryFn: () => getUserInfo(),
retry: false,
});

// 리뷰는 아직 API 명세 안나옴.

const { data: invitedTeamList, error: invitedTeamListError } = useQuery({
queryKey: ["invite/list"],
queryFn: () => getInvitedTeamList({ order: "DESC", page: 1, take: 100 }),
retry: false,
});

const { data: scrapList, error: scrapListError } = useQuery({
queryKey: ["/my-page/scrap/list"],
queryFn: () => getScrapList({ order: "DESC", page: 1, take: 100 }),
retry: false,
});

const { data: visibleProfile, error: visibleProfileError } = useQuery({
queryKey: ["my-page/visigle-profile"],
queryFn: () => getVisibleProfileStatus(),
retry: false,
});

if (userInfoError) {
console.error(userInfoError);
}

if (invitedTeamListError) {
console.error(invitedTeamListError);
}

if (scrapListError) {
console.error(scrapListError);
}

if (visibleProfileError) {
console.error(visibleProfileError);
}

return (
<S.Container>
<S.Box>
<S.Wrapper>
<UserInfo user={profileInfo} />
{userInfo && visibleProfile && <UserInfo user={userInfo} visibleProfile={visibleProfile} />}
<S.Lists>
<TagList />
<InvitedTeamList count={teamList.length} teamList={teamList} />
{invitedTeamList && <InvitedTeamList count={invitedTeamList.data.length} teamList={invitedTeamList.data} />}
</S.Lists>
</S.Wrapper>
<ScrapList scrapList={scrapList} />
{scrapList && <ScrapList data={scrapList.data} />}
</S.Box>
{/* {userInfoError && <AuthModal onClose={handleModal} />} */}
</S.Container>
);
}
Loading