Skip to content

Commit

Permalink
Merge pull request #85 from Mogazoa-team20/feat/myPage
Browse files Browse the repository at this point in the history
[#35] 마이페이지 유저 상호작용 데이터 무한스크롤 추가
  • Loading branch information
yeeZinu authored Jun 19, 2024
2 parents 7409b22 + 3cbf627 commit 80eb85e
Show file tree
Hide file tree
Showing 34 changed files with 331 additions and 199 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
display: flex;
flex-direction: column;
gap: 40px;
padding: 40px;
width: 360px;
padding: 40px;

@include respond-to(mobile) {
width: minmax(320px, calc(100% - 40px));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
.container {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
align-items: center;
width: 100%;

.title {
color: $gray-200;

@include font-normal;
@include text-normal;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
@import "@/styles/_index";

.container {
width: 56px;
height: 56px;
display: flex;
justify-content: center;
align-items: center;
@include rounded-full;
justify-content: center;
width: 56px;
height: 56px;
background-color: transparent;
border: 1px solid $gray-300;

@include rounded-full;
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
.button {
width: auto;
padding: 21px;

@include text-lg;

@include respond-to(tablet) {
@include text-normal;

padding: 18px;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@
.signInButton {
width: auto;
padding: 21px;

@include text-lg;

@include respond-to(tablet) {
@include text-normal;

padding: 18px;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@
.signUpButton {
width: auto;
padding: 21px;

@include text-lg;

@include respond-to(tablet) {
@include text-normal;

padding: 18px;
}
}
Expand Down
16 changes: 0 additions & 16 deletions src/app/(userpage)/mypage/page.tsx

This file was deleted.

5 changes: 0 additions & 5 deletions src/app/(userpage)/page.tsx

This file was deleted.

22 changes: 11 additions & 11 deletions src/app/(userpage)/types.tsx → src/app/(userpage)/types.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
export type UserDetail = {
updatedAt: Date;
createdAt: Date;
teamId: string;
image: string;
description: string;
nickname: string;
id: number;
nickname: string;
description: string;
image: string;
createdAt: string;
updatedAt: string;
teamId: string;
isFollowing: boolean;
followersCount: number;
followeesCount: number;
reviewCount: number;
averageRating: number;
mostFavoriteCategory: {
name: string;
id: number;
};
averageRating: number;
reviewCount: number;
followeesCount: number;
followersCount: number;
isFollowing: boolean;
};

export type UserProduct = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ type FollowListProps = {
};

export default function FollowList({ followData }: FollowListProps) {
console.log(followData);

return (
<div className={cn(styles.container)}>
{followData.list.map((item) => (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useQuery } from "@tanstack/react-query";
import Image from "next/image";
import { useSession } from "next-auth/react";
import React, { useEffect, useState } from "react";
import React from "react";
import { UserProduct } from "@/app/(userpage)/types";
import Modal from "@/components/Modal/Modal";
import cn from "@/utils/classNames";
Expand All @@ -18,31 +19,26 @@ type ModalProps = {

export default function FollowModal({ isModalState, setIsModalState, followState }: ModalProps) {
const { data: session } = useSession();
const [followData, setFollowData] = useState<UserProduct>();
const userId = session?.user.id;
const ACCESS_TOKEN = session?.accessToken ?? "";

const httpClient = new HttpClient(process.env.NEXT_PUBLIC_BASE_URL!);

const handleData = async () => {
if (session && followState) {
const userId = session.user.id;
const ACCESS_TOKEN = session.accessToken;
setFollowData(
await httpClient.get(`users/${userId}/${followState}`, {
headers: { Authorization: ACCESS_TOKEN },
cache: "no-cache",
}),
);
}
};

useEffect(() => {
handleData();
}, [followState]);
const { data } = useQuery({
queryKey: ["followData", followState],
queryFn: async () => {
const res = httpClient.get<UserProduct>(`users/${userId}/${followState}`, {
headers: { Authorization: ACCESS_TOKEN },
cache: "no-cache",
});
return res;
},
});

const handleClose = () => setIsModalState(false);
return (
<>
{followData !== undefined && isModalState && (
{data !== undefined && isModalState && (
<Modal onClose={handleClose}>
<div className={cn(styles.container)}>
<div
Expand All @@ -59,10 +55,10 @@ export default function FollowModal({ isModalState, setIsModalState, followState
/>
</div>
<h1>nickname님{followState === "followees" ? "이" : "을"} 팔로우 하는 유저</h1>
{followData.list.length < 1 ? (
{data.list.length < 1 ? (
<div className={cn(styles.noFollowBox)}>팔로우하는 유저가 없어요</div>
) : (
<FollowList followData={followData} />
<FollowList followData={data} />
)}
</div>
</Modal>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@

.container {
display: flex;
flex-direction: column;
gap: 20px;
align-items: center;
justify-content: center;
width: 100%;
}

.profile {
width: 80%;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React, { useState } from "react";
import Button from "@/components/Button/Button";
import Modal from "@/components/Modal/Modal";
import cn from "@/utils/classNames";
import styles from "./MyProfileButton.module.scss";

export default function MyProfileButton() {
const [isModal, setIsModal] = useState(false);
const handleClose = () => setIsModal(false);
const handleOpen = () => setIsModal(true);

return (
<div className={cn(styles.container)}>
{isModal && (
<Modal onClose={handleClose}>
<div className={styles.profileEdit}>모달 테스트</div>
</Modal>
)}
<Button
styleType='primary'
onClick={handleOpen}
className={styles.profile}
>
프로필 수정
</Button>
<Button
styleType='tertiary'
className={styles.profile}
>
로그아웃
</Button>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
"use client";

import { useInfiniteQuery } from "@tanstack/react-query";
import { useRouter } from "next/navigation";
import { useSession } from "next-auth/react";
import React, { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { useInView } from "react-intersection-observer";
import { Dropdown } from "@/components/Dropdown";
import { ORDER, DROPDOWN } from "@/components/Dropdown/constants";
import useWindowSize from "@/hooks/useWindowSize";
import { ProductType, ProductsResponseType } from "@/types/global";
import cn from "@/utils/classNames";
import HttpClient from "@/utils/httpClient";
import styles from "./UserActivityList.module.scss";
// eslint-disable-next-line no-restricted-imports
import TabButton from "../TabButton/TabButton";
// eslint-disable-next-line no-restricted-imports
import UserProductList from "../UserProductList/UserProductList";

export default function UserActivityList() {
const router = useRouter();
const [selectedButton, setSelectedButton] = useState<string>("reviewed");
const { data: session } = useSession();
const { width } = useWindowSize();
const { control, watch } = useForm({ mode: "onBlur" });

const { ref, inView } = useInView({
threshold: 0.5,
});

const httpClient = new HttpClient(process.env.NEXT_PUBLIC_BASE_URL!);
const userId = session?.user.id;
const ACCESS_TOKEN = session?.accessToken ?? "";

const querySelectButton = (value: string) => {
const params = new URLSearchParams();
params.set("order", value);

return params.toString();
};

const {
data: userProductData,
fetchNextPage,
hasNextPage,
} = useInfiniteQuery({
queryKey: ["userProductData", selectedButton],
queryFn: async ({ pageParam }) => {
const res = await httpClient.get<ProductsResponseType>(
`users/${userId}/${selectedButton}-products?cursor=${pageParam}`,
{
headers: { Authorization: ACCESS_TOKEN },
cache: "no-cache",
},
);
return res;
},
select: (data): ProductType[] => data.pages.map((page) => page.list).flat(),
initialPageParam: 0,
getNextPageParam: (lastPage) => lastPage.nextCursor ?? undefined,
});

const selectTab = ORDER.PROFILE.filter((i) => i.value === selectedButton) ?? "reviewed";

useEffect(() => {
if (width <= 1023 && watch("select") === "") {
setSelectedButton("reviewed");
}
if (width <= 1023 && watch("select") !== "") {
setSelectedButton(watch("select"));
}

router.push(`${userId}/?${querySelectButton(selectedButton)}`);
}, [selectedButton, watch("select")]);

useEffect(() => {
if (inView && hasNextPage) {
fetchNextPage();
}
}, [inView, fetchNextPage, hasNextPage]);

const onSelectButtonHandler = (value: string) => {
setSelectedButton(value);
};

return (
<div className={cn(styles.container)}>
{width > 1023 ? (
<TabButton
onSelectButton={onSelectButtonHandler}
button={selectedButton}
/>
) : (
<div>
<Dropdown
items={ORDER.PROFILE}
control={control}
name='select'
variant={DROPDOWN.ORDER}
placeholder={
ORDER.PROFILE[0].option !== selectTab[0].option ? selectTab[0].option : ORDER.PROFILE[0].option
}
/>
</div>
)}
{userProductData && (
<UserProductList
list={userProductData}
lastRef={ref}
/>
)}
</div>
);
}
Loading

0 comments on commit 80eb85e

Please sign in to comment.