diff --git a/src/app/me/[slug]/drafts/page.tsx b/src/app/drafts/[slug]/page.tsx
similarity index 100%
rename from src/app/me/[slug]/drafts/page.tsx
rename to src/app/drafts/[slug]/page.tsx
diff --git a/src/app/me/[slug]/layout.tsx b/src/app/me/[slug]/layout.tsx
new file mode 100644
index 00000000..aab2ccd4
--- /dev/null
+++ b/src/app/me/[slug]/layout.tsx
@@ -0,0 +1,139 @@
+import Header from '@/components/shared/Header';
+import {
+ getHistory,
+ getMemosByUserId,
+ getRankInfoByUserId,
+ getStatsByUserId,
+} from '@/service/me';
+import LayoutWrapper from '@/components/shared/LayoutWrapper';
+import { checkUser, getUserInfo } from '@/service/auth';
+import { cookies } from 'next/headers';
+import { ACCESS_TOKEN, MY_TAG_MAX_COUNT, REFRESH_TOKEN } from '@/utils/const';
+import MeSideBar from '@/components/me/MeSideBar';
+import { getUserTags } from '@/service/tag';
+import MeTagsContainer from '@/components/me/MeTagsContainer';
+import { getFollowers, getFollowings } from '@/service/follow';
+import FollowListModalProvider from '@/context/FollowListModalProvider';
+import FollowListModal from '@/components/me/FollowListModal';
+import { getNotificationsTop30 } from '@/service/notification';
+import { getScoreInfoByUserId } from '@/service/rank';
+import {
+ getCoverletterInfoByUserId,
+ getCoverletterVisibleMode,
+} from '@/service/coverletter';
+import { notFound } from 'next/navigation';
+
+type Props = {
+ children: React.ReactNode;
+ params: {
+ slug: string;
+ };
+};
+
+export default async function MeLayout({ children, params: { slug } }: Props) {
+ const accessToken = cookies().get(ACCESS_TOKEN)?.value;
+ const refreshToken = cookies().get(REFRESH_TOKEN)?.value;
+ const cookie = `${ACCESS_TOKEN}=${accessToken}; ${REFRESH_TOKEN}=${refreshToken}`;
+ const userId = Number(slug);
+
+ const userInfo = await getUserInfo(userId, cookie);
+ if (userInfo.userId === undefined) {
+ notFound();
+ }
+
+ const memosData = getMemosByUserId(userId);
+ const historyData = getHistory(
+ userId,
+ new Date().getFullYear(),
+ new Date().getMonth() + 1,
+ true
+ );
+ const myData = checkUser(cookie);
+ const tagData = getUserTags(slug, MY_TAG_MAX_COUNT);
+ const followingData = getFollowings(slug);
+ const followerData = getFollowers(slug);
+ const userRankData = getRankInfoByUserId(userId);
+ const userStatsData = getStatsByUserId(userId);
+ const userScoreData = getScoreInfoByUserId(userId);
+ const coverletterVisibleModeData = getCoverletterVisibleMode();
+
+ const [
+ history,
+ { id, isLogin, authority },
+ tags,
+ followings,
+ followers,
+ userRankInfo,
+ userStats,
+ { dailyScore },
+ coverletterIsVisible,
+ ] = await Promise.all([
+ historyData,
+ myData,
+ tagData,
+ followingData,
+ followerData,
+ userRankData,
+ userStatsData,
+ userScoreData,
+ coverletterVisibleModeData,
+ ]);
+
+ const myUserInfo = await getUserInfo(id);
+
+ const notifications = isLogin ? await getNotificationsTop30(cookie) : [];
+
+ const isCoverletterCreated = await getCoverletterInfoByUserId(
+ userId,
+ cookie
+ ).then((res) => {
+ if ('code' in res) {
+ return false;
+ }
+ return true;
+ });
+
+ return (
+
+
+
+
+
+
+
+
+
+ {tags.length >= 2 && (
+
+ )}
+ {children}
+
+
+
+
+ );
+}
diff --git a/src/app/me/[slug]/like/layout.tsx b/src/app/me/[slug]/like/layout.tsx
new file mode 100644
index 00000000..928e539e
--- /dev/null
+++ b/src/app/me/[slug]/like/layout.tsx
@@ -0,0 +1,21 @@
+import MeNavigator from '@/components/me/MeNavigator';
+
+type Props = {
+ children: React.ReactNode;
+ params: {
+ slug: string;
+ };
+};
+
+export default async function MeLikeLayout({
+ children,
+ params: { slug },
+}: Props) {
+ const userId = +slug;
+ return (
+
+
+ {children}
+
+ );
+}
diff --git a/src/app/me/[slug]/like/memo/page.tsx b/src/app/me/[slug]/like/memo/page.tsx
new file mode 100644
index 00000000..f4e61f25
--- /dev/null
+++ b/src/app/me/[slug]/like/memo/page.tsx
@@ -0,0 +1,21 @@
+import MeMemosContainer from '@/components/me/MeMemosContainer';
+import MePostCategories from '@/components/me/MePostCategories';
+import { getLikedMemosByUserId } from '@/service/me';
+
+type Props = {
+ params: {
+ slug: string;
+ };
+};
+
+export default async function MeLikedMemoPage({ params: { slug } }: Props) {
+ const userId = +slug;
+ const memos = await getLikedMemosByUserId(userId);
+
+ return (
+ <>
+
+
+ >
+ );
+}
diff --git a/src/app/me/[slug]/like/page.tsx b/src/app/me/[slug]/like/page.tsx
new file mode 100644
index 00000000..2b65ee7d
--- /dev/null
+++ b/src/app/me/[slug]/like/page.tsx
@@ -0,0 +1,21 @@
+import MeMemosContainer from '@/components/me/MeMemosContainer';
+import MePostCategories from '@/components/me/MePostCategories';
+import { getLikedMemosByUserId } from '@/service/me';
+
+type Props = {
+ params: {
+ slug: string;
+ };
+};
+
+export default async function MeLikepage({ params: { slug } }: Props) {
+ const userId = +slug;
+ const memos = await getLikedMemosByUserId(userId);
+
+ return (
+ <>
+
+
+ >
+ );
+}
diff --git a/src/app/me/[slug]/like/question/page.tsx b/src/app/me/[slug]/like/question/page.tsx
new file mode 100644
index 00000000..9d9393b2
--- /dev/null
+++ b/src/app/me/[slug]/like/question/page.tsx
@@ -0,0 +1,29 @@
+import MePostCategories from '@/components/me/MePostCategories';
+import MeQuestionsContainer from '@/components/me/MeQuestionsContainer';
+import { getLikedQuestionsByUserId, getQuestionsByUserId } from '@/service/me';
+
+type Props = {
+ params: {
+ slug: string;
+ };
+};
+
+export default async function MeLikedQuestionPage({ params: { slug } }: Props) {
+ const userId = +slug;
+ const questions = await getLikedQuestionsByUserId(userId);
+
+ return (
+ <>
+
+
+ >
+ );
+}
diff --git a/src/app/me/[slug]/like/series/page.tsx b/src/app/me/[slug]/like/series/page.tsx
new file mode 100644
index 00000000..d6c956fc
--- /dev/null
+++ b/src/app/me/[slug]/like/series/page.tsx
@@ -0,0 +1,25 @@
+import MePostCategories from '@/components/me/MePostCategories';
+import MeSeriesContainer from '@/components/me/MeSeriesContainer';
+import { getLikedSeriesByUserId } from '@/service/me';
+
+type Props = {
+ params: {
+ slug: string;
+ };
+};
+
+export default async function MeLikedSeriesPage({ params: { slug } }: Props) {
+ const userId = +slug;
+ const series = await getLikedSeriesByUserId(userId);
+
+ return (
+ <>
+
+ {' '}
+ >
+ );
+}
diff --git a/src/app/me/[slug]/page.tsx b/src/app/me/[slug]/page.tsx
index cddea564..cc5b7a55 100644
--- a/src/app/me/[slug]/page.tsx
+++ b/src/app/me/[slug]/page.tsx
@@ -1,28 +1,7 @@
-import Header from '@/components/shared/Header';
-import {
- getHistory,
- getMemosByUserId,
- getRankInfoByUserId,
- getStatsByUserId,
-} from '@/service/me';
-import LayoutWrapper from '@/components/shared/LayoutWrapper';
-import { checkUser, getUserInfo } from '@/service/auth';
-import MeMainContainer from '@/components/me/MeMainContainer';
-import { cookies } from 'next/headers';
-import { ACCESS_TOKEN, MY_TAG_MAX_COUNT, REFRESH_TOKEN } from '@/utils/const';
-import MeSideBar from '@/components/me/MeSideBar';
-import { getUserTags } from '@/service/tag';
-import MeTagsContainer from '@/components/me/MeTagsContainer';
-import { getFollowers, getFollowings } from '@/service/follow';
-import FollowListModalProvider from '@/context/FollowListModalProvider';
-import FollowListModal from '@/components/me/FollowListModal';
-import { getNotificationsTop30 } from '@/service/notification';
-import { getScoreInfoByUserId } from '@/service/rank';
-import {
- getCoverletterInfoByUserId,
- getCoverletterVisibleMode,
-} from '@/service/coverletter';
-import { notFound } from 'next/navigation';
+import { getMemosByUserId } from '@/service/me';
+import MeNavigator from '@/components/me/MeNavigator';
+import MePostCategories from '@/components/me/MePostCategories';
+import MeMemosContainer from '@/components/me/MeMemosContainer';
type Props = {
params: {
@@ -31,124 +10,16 @@ type Props = {
};
export default async function MePage({ params: { slug } }: Props) {
- const accessToken = cookies().get(ACCESS_TOKEN)?.value;
- const refreshToken = cookies().get(REFRESH_TOKEN)?.value;
- const cookie = `${ACCESS_TOKEN}=${accessToken}; ${REFRESH_TOKEN}=${refreshToken}`;
const userId = Number(slug);
-
- const userInfo = await getUserInfo(userId, cookie);
- if (userInfo.userId === undefined) {
- notFound();
- }
-
- const memosData = getMemosByUserId(userId);
- const historyData = getHistory(
- userId,
- new Date().getFullYear(),
- new Date().getMonth() + 1,
- true
- );
- const myData = checkUser(cookie);
- const tagData = getUserTags(slug, MY_TAG_MAX_COUNT);
- const followingData = getFollowings(slug);
- const followerData = getFollowers(slug);
- const userRankData = getRankInfoByUserId(userId);
- const userStatsData = getStatsByUserId(userId);
- const userScoreData = getScoreInfoByUserId(userId);
- const coverletterVisibleModeData = getCoverletterVisibleMode();
-
- const [
- memos,
- history,
- { id, isLogin, authority },
- tags,
- followings,
- followers,
- userRankInfo,
- userStats,
- { dailyScore },
- coverletterIsVisible,
- ] = await Promise.all([
- memosData,
- historyData,
- myData,
- tagData,
- followingData,
- followerData,
- userRankData,
- userStatsData,
- userScoreData,
- coverletterVisibleModeData,
- ]);
-
- const myUserInfo = await getUserInfo(id);
-
- const notifications = isLogin ? await getNotificationsTop30(cookie) : [];
-
- const isCoverletterCreated = await getCoverletterInfoByUserId(
- userId,
- cookie
- ).then((res) => {
- if ('code' in res) {
- return false;
- }
- return true;
- });
+ const memos = await getMemosByUserId(userId);
return (
-
-
-
-
-
-
-
-
-
- {tags.length >= 2 && (
-
- )}
-
-
-
-
+
);
}
-
-export async function generateMetadata({ params: { slug } }: Props) {
- const userId = Number(slug);
- const { nickname } = await getUserInfo(userId);
- if (nickname === undefined) {
- notFound();
- }
-
- return {
- title: `${nickname} - 인포럼`,
- description: `${nickname}의 마이페이지입니다.`,
- };
-}
diff --git a/src/app/me/[slug]/post/layout.tsx b/src/app/me/[slug]/post/layout.tsx
new file mode 100644
index 00000000..02f412ef
--- /dev/null
+++ b/src/app/me/[slug]/post/layout.tsx
@@ -0,0 +1,21 @@
+import MeNavigator from '@/components/me/MeNavigator';
+
+type Props = {
+ children: React.ReactNode;
+ params: {
+ slug: string;
+ };
+};
+
+export default async function MePostLayout({
+ children,
+ params: { slug },
+}: Props) {
+ const userId = +slug;
+ return (
+
+
+ {children}
+
+ );
+}
diff --git a/src/app/me/[slug]/post/memo/page.tsx b/src/app/me/[slug]/post/memo/page.tsx
new file mode 100644
index 00000000..6de87884
--- /dev/null
+++ b/src/app/me/[slug]/post/memo/page.tsx
@@ -0,0 +1,21 @@
+import MeMemosContainer from '@/components/me/MeMemosContainer';
+import MePostCategories from '@/components/me/MePostCategories';
+import { getMemosByUserId } from '@/service/me';
+
+type Props = {
+ params: {
+ slug: string;
+ };
+};
+
+export default async function MePostMemoPage({ params: { slug } }: Props) {
+ const userId = +slug;
+ const memos = await getMemosByUserId(userId);
+
+ return (
+ <>
+
+
+ >
+ );
+}
diff --git a/src/app/me/[slug]/post/page.tsx b/src/app/me/[slug]/post/page.tsx
new file mode 100644
index 00000000..5525413d
--- /dev/null
+++ b/src/app/me/[slug]/post/page.tsx
@@ -0,0 +1,21 @@
+import MeMemosContainer from '@/components/me/MeMemosContainer';
+import MePostCategories from '@/components/me/MePostCategories';
+import { getMemosByUserId } from '@/service/me';
+
+type Props = {
+ params: {
+ slug: string;
+ };
+};
+
+export default async function MePostPage({ params: { slug } }: Props) {
+ const userId = +slug;
+ const memos = await getMemosByUserId(userId);
+
+ return (
+ <>
+
+
+ >
+ );
+}
diff --git a/src/app/me/[slug]/post/question/page.tsx b/src/app/me/[slug]/post/question/page.tsx
new file mode 100644
index 00000000..e0971868
--- /dev/null
+++ b/src/app/me/[slug]/post/question/page.tsx
@@ -0,0 +1,29 @@
+import MePostCategories from '@/components/me/MePostCategories';
+import MeQuestionsContainer from '@/components/me/MeQuestionsContainer';
+import { getQuestionsByUserId } from '@/service/me';
+
+type Props = {
+ params: {
+ slug: string;
+ };
+};
+
+export default async function MePostQuestionPage({ params: { slug } }: Props) {
+ const userId = +slug;
+ const questions = await getQuestionsByUserId(userId);
+
+ return (
+ <>
+
+
+ >
+ );
+}
diff --git a/src/app/me/[slug]/post/series/page.tsx b/src/app/me/[slug]/post/series/page.tsx
new file mode 100644
index 00000000..69559af0
--- /dev/null
+++ b/src/app/me/[slug]/post/series/page.tsx
@@ -0,0 +1,25 @@
+import MePostCategories from '@/components/me/MePostCategories';
+import MeSeriesContainer from '@/components/me/MeSeriesContainer';
+import { getSeriesByUserId } from '@/service/me';
+
+type Props = {
+ params: {
+ slug: string;
+ };
+};
+
+export default async function MePostSeriesPage({ params: { slug } }: Props) {
+ const userId = +slug;
+ const series = await getSeriesByUserId(userId);
+
+ return (
+ <>
+
+
+ >
+ );
+}
diff --git a/src/app/me/[slug]/question_answered/page.tsx b/src/app/me/[slug]/question_answered/page.tsx
new file mode 100644
index 00000000..2b62469d
--- /dev/null
+++ b/src/app/me/[slug]/question_answered/page.tsx
@@ -0,0 +1,27 @@
+import { getAnswerdQuestionsByUserId } from '@/service/me';
+import MeNavigator from '@/components/me/MeNavigator';
+import MeQuestionsContainer from '@/components/me/MeQuestionsContainer';
+
+type Props = {
+ params: {
+ slug: string;
+ };
+};
+
+export default async function MeQuestionAnsweredPage({
+ params: { slug },
+}: Props) {
+ const userId = +slug;
+ const questions = await getAnswerdQuestionsByUserId(userId);
+
+ return (
+
+ );
+}
diff --git a/src/components/me/MeMainContainer.tsx b/src/components/me/MeMainContainer.tsx
deleted file mode 100644
index 11037567..00000000
--- a/src/components/me/MeMainContainer.tsx
+++ /dev/null
@@ -1,229 +0,0 @@
-'use client';
-
-import { Memo } from '@/types/memo';
-import MemosGrid from '../memo/MemosGrid';
-import BarBtn from '@/components/shared/btn/BarBtn';
-import { useEffect, useRef, useState } from 'react';
-import {
- getAnswerdQuestionsByUserId,
- getLikedMemosByUserId,
- getLikedQuestionsByUserId,
- getLikedSeriesByUserId,
- getMemosByUserId,
- getQuestionsByUserId,
- getSeriesByUserId,
-} from '@/service/me';
-import CategoryBtn from '../shared/btn/CategoryBtn';
-import { Question } from '@/types/question';
-import QuestionsList from '../question/QuestionsList';
-import { Series } from '@/types/series';
-import SeriesGrid from '../series/SeriesGrid';
-import useObserver from '@/hooks/useObserver';
-
-type Props = {
- memos: Memo[];
- userId: number;
-};
-
-type BigCategory = 'my' | 'answered' | 'liked';
-type PostType = 'memo' | 'question' | 'series';
-
-export default function MeMainContainer({ memos, userId }: Props) {
- const [memoData, setMemoData] = useState(memos);
- const [questionData, setQuestionData] = useState([]);
- const [seriesData, setSeriesData] = useState([]);
- const [selectedBigCategory, setSelectedBigCategory] =
- useState('my');
- const [selectedPostType, setSelectedPostType] = useState('memo');
- const [pageNum, setPageNum] = useState(0);
- const [isEnd, setIsEnd] = useState(false);
- const [isLoading, setIsLoading] = useState(false);
- const isInitialMount = useRef(true);
-
- const handleClick = async (type: BigCategory) => {
- if (type === selectedBigCategory) return;
- setIsLoading(true);
- setPageNum(0);
- setIsEnd(false);
- if (type === 'answered') {
- const questions = await getAnswerdQuestionsByUserId(userId);
- setQuestionData(questions);
- } else {
- const memos =
- type === 'my'
- ? await getMemosByUserId(userId)
- : await getLikedMemosByUserId(userId);
- setMemoData(memos);
- setSelectedPostType('memo');
- }
- setIsLoading(false);
- setSelectedBigCategory(type);
- };
-
- const handlePostCategotyClick = async (type: PostType) => {
- if (type === selectedPostType) return;
- setIsLoading(true);
- setPageNum(0);
- setIsEnd(false);
- let data;
- switch (type) {
- case 'memo':
- data =
- selectedBigCategory === 'my'
- ? await getMemosByUserId(userId)
- : await getLikedMemosByUserId(userId);
- setMemoData(data);
- break;
- case 'question':
- data =
- selectedBigCategory === 'my'
- ? await getQuestionsByUserId(userId)
- : await getLikedQuestionsByUserId(userId);
- setQuestionData(data);
- break;
- case 'series':
- data =
- selectedBigCategory === 'my'
- ? await getSeriesByUserId(userId)
- : await getLikedSeriesByUserId(userId);
- setSeriesData(data);
- break;
- default:
- throw new Error('알맞은 타입이 아님');
- }
- setIsLoading(false);
- setSelectedPostType(type);
- };
-
- const fetchPosts = () => {
- if (isLoading || isEnd) return;
- setIsLoading(true);
- if (selectedBigCategory === 'answered') {
- getAnswerdQuestionsByUserId(userId, pageNum)
- .then((questions) => {
- setIsLoading(false);
- if (!questions.length) setIsEnd(true);
- else setQuestionData([...questionData, ...questions]);
- })
- .catch(() => setIsLoading(false));
- } else {
- let data;
- switch (selectedPostType) {
- case 'memo':
- data =
- selectedBigCategory === 'my'
- ? getMemosByUserId(userId, pageNum)
- : getLikedMemosByUserId(userId, pageNum);
- data
- .then((memos) => {
- setIsLoading(false);
- if (!memos.length) setIsEnd(true);
- else {
- setMemoData([...memoData, ...memos]);
- }
- })
- .catch(() => setIsLoading(false));
- break;
- case 'question':
- data =
- selectedBigCategory === 'my'
- ? getQuestionsByUserId(userId, pageNum)
- : getLikedQuestionsByUserId(userId, pageNum);
- data
- .then((questions) => {
- setIsLoading(false);
- if (!questions.length) setIsEnd(true);
- else {
- setQuestionData([...questionData, ...questions]);
- }
- })
- .catch(() => setIsLoading(false));
- break;
- case 'series':
- data =
- selectedBigCategory === 'my'
- ? getSeriesByUserId(userId, pageNum)
- : getLikedSeriesByUserId(userId, pageNum);
- data
- .then((seriesArray) => {
- setIsLoading(false);
- if (!seriesArray.length) setIsEnd(true);
- else {
- setSeriesData([...seriesData, ...seriesArray]);
- }
- })
- .catch(() => setIsLoading(false));
- break;
- default:
- throw new Error('알맞은 타입이 아님');
- }
- }
- };
-
- useEffect(() => {
- if (isInitialMount.current) {
- isInitialMount.current = false;
- } else {
- fetchPosts();
- }
- }, [pageNum]);
-
- const onIntersect: IntersectionObserverCallback = ([entry]) => {
- if (isEnd || isLoading) return;
- entry.isIntersecting && setPageNum(pageNum + 1);
- };
-
- const { setTarget } = useObserver({ onIntersect });
-
- return (
-
-
- handleClick('my')}
- isSelected={selectedBigCategory === 'my'}
- />
- handleClick('answered')}
- isSelected={selectedBigCategory === 'answered'}
- />
- handleClick('liked')}
- isSelected={selectedBigCategory === 'liked'}
- />
-
- {selectedBigCategory !== 'answered' && (
-
- handlePostCategotyClick('memo')}
- isSelected={selectedPostType === 'memo'}
- />
- handlePostCategotyClick('question')}
- isSelected={selectedPostType === 'question'}
- />
- handlePostCategotyClick('series')}
- isSelected={selectedPostType === 'series'}
- />
-
- )}
- {selectedBigCategory !== 'answered' && selectedPostType === 'memo' && (
-
- )}
- {(selectedBigCategory === 'answered' ||
- selectedPostType === 'question') && (
-
- )}
- {selectedBigCategory !== 'answered' && selectedPostType === 'series' && (
-
- )}
- {isEnd ? <>> :
}
-
- );
-}
diff --git a/src/components/me/MeMemosContainer.tsx b/src/components/me/MeMemosContainer.tsx
new file mode 100644
index 00000000..8391b11e
--- /dev/null
+++ b/src/components/me/MeMemosContainer.tsx
@@ -0,0 +1,31 @@
+'use client';
+
+import { useInfinityScroll } from '@/hooks/useInfinityScroll';
+import MemosGrid from '../memo/MemosGrid';
+import { Memo } from '@/types/memo';
+import { getLikedMemosByUserId, getMemosByUserId } from '@/service/me';
+
+type Props = {
+ memos: Memo[];
+ userId: number;
+ bigCategory: 'post' | 'like';
+};
+
+export default function MeMemosContainer({
+ memos,
+ userId,
+ bigCategory,
+}: Props) {
+ const [data, isEnd, setTarget] = useInfinityScroll(memos, (pageNum) =>
+ bigCategory === 'post'
+ ? getMemosByUserId(userId, pageNum)
+ : getLikedMemosByUserId(userId, pageNum)
+ );
+
+ return (
+ <>
+
+ {isEnd ? <>> : }
+ >
+ );
+}
diff --git a/src/components/me/MeNavigator.tsx b/src/components/me/MeNavigator.tsx
new file mode 100644
index 00000000..0603f190
--- /dev/null
+++ b/src/components/me/MeNavigator.tsx
@@ -0,0 +1,28 @@
+import BarLink from '../shared/BarLink';
+
+type Props = {
+ userId: number;
+ type: 'post' | 'like' | 'question_answered';
+};
+
+export default function MeNavigator({ userId, type }: Props) {
+ return (
+
+ );
+}
diff --git a/src/components/me/MePostCategories.tsx b/src/components/me/MePostCategories.tsx
new file mode 100644
index 00000000..58df4952
--- /dev/null
+++ b/src/components/me/MePostCategories.tsx
@@ -0,0 +1,33 @@
+import CategoryLink from '../shared/CategoryLink';
+
+type Props = {
+ userId: number;
+ selected: 'memo' | 'question' | 'series';
+ bigCategory: 'post' | 'like';
+};
+
+export default function MePostCategories({
+ userId,
+ selected,
+ bigCategory,
+}: Props) {
+ return (
+
+
+
+
+
+ );
+}
diff --git a/src/components/me/MeQuestionsContainer.tsx b/src/components/me/MeQuestionsContainer.tsx
new file mode 100644
index 00000000..95ca1ae7
--- /dev/null
+++ b/src/components/me/MeQuestionsContainer.tsx
@@ -0,0 +1,40 @@
+'use client';
+
+import { useInfinityScroll } from '@/hooks/useInfinityScroll';
+import {
+ getAnswerdQuestionsByUserId,
+ getLikedQuestionsByUserId,
+ getQuestionsByUserId,
+} from '@/service/me';
+import { Question } from '@/types/question';
+import QuestionsList from '@/components/question/QuestionsList';
+
+type Props = {
+ questions: Question[];
+ userId: number;
+ bigCategory: 'post' | 'like' | 'answered';
+};
+
+export default function MeQuestionsContainer({
+ questions,
+ userId,
+ bigCategory,
+}: Props) {
+ const [data, isEnd, setTarget] = useInfinityScroll(questions, (pageNum) => {
+ switch (bigCategory) {
+ case 'post':
+ return getQuestionsByUserId(userId, pageNum);
+ case 'like':
+ return getLikedQuestionsByUserId(userId, pageNum);
+ case 'answered':
+ return getAnswerdQuestionsByUserId(userId, pageNum);
+ }
+ });
+
+ return (
+ <>
+
+ {isEnd ? <>> : }
+ >
+ );
+}
diff --git a/src/components/me/MeSeriesContainer.tsx b/src/components/me/MeSeriesContainer.tsx
new file mode 100644
index 00000000..e45a6b55
--- /dev/null
+++ b/src/components/me/MeSeriesContainer.tsx
@@ -0,0 +1,31 @@
+'use client';
+
+import { useInfinityScroll } from '@/hooks/useInfinityScroll';
+import { getLikedSeriesByUserId, getSeriesByUserId } from '@/service/me';
+import { Series } from '@/types/series';
+import SeriesGrid from '@/components/series/SeriesGrid';
+
+type Props = {
+ seriesArr: Series[];
+ userId: number;
+ bigCategory: 'post' | 'like';
+};
+
+export default function MeSeriesContainer({
+ seriesArr,
+ userId,
+ bigCategory,
+}: Props) {
+ const [data, isEnd, setTarget] = useInfinityScroll(seriesArr, (pageNum) =>
+ bigCategory === 'post'
+ ? getSeriesByUserId(userId, pageNum)
+ : getLikedSeriesByUserId(userId, pageNum)
+ );
+
+ return (
+ <>
+
+ {isEnd ? <>> : }
+ >
+ );
+}
diff --git a/src/components/memo/MemosContainer.tsx b/src/components/memo/MemosContainer.tsx
index 42bf693a..583f25a5 100644
--- a/src/components/memo/MemosContainer.tsx
+++ b/src/components/memo/MemosContainer.tsx
@@ -3,11 +3,9 @@
import { Memo } from '@/types/memo';
import { Orderby } from '@/types';
import MemosGrid from './MemosGrid';
-import { useEffect, useRef, useState } from 'react';
import { getMemos } from '@/service/memos';
-import useObserver from '@/hooks/useObserver';
-import { MEMO_NUMBER_PER_PAGE_FOR_INFINITY_SCROLL } from '@/utils/const';
import CategoryLink from '../shared/CategoryLink';
+import { useInfinityScroll } from '@/hooks/useInfinityScroll';
type Props = {
memos: Memo[];
@@ -15,42 +13,9 @@ type Props = {
};
export default function MemosContainer({ memos, type }: Props) {
- const [memoData, setMemodata] = useState(memos);
- const [pageNum, setPageNum] = useState(1);
- const [isEnd, setIsEnd] = useState(false);
- const [isLoading, setIsLoading] = useState(false);
- const isInitialMount = useRef(true);
-
- const fetchMemos = () => {
- if (isLoading || isEnd) return;
- setIsLoading(true);
- getMemos('month', type, pageNum, MEMO_NUMBER_PER_PAGE_FOR_INFINITY_SCROLL)
- .then((data) => {
- setIsLoading(false);
- if (!data.length) setIsEnd(true);
- else {
- setMemodata([...memoData, ...data]);
- }
- })
- .catch(() => {
- setIsLoading(false);
- });
- };
-
- useEffect(() => {
- if (isInitialMount.current) {
- isInitialMount.current = false;
- } else {
- fetchMemos();
- }
- }, [pageNum]);
-
- const onIntersect: IntersectionObserverCallback = ([entry]) => {
- if (isEnd || isLoading) return;
- entry.isIntersecting && setPageNum(pageNum + 1);
- };
-
- const { setTarget } = useObserver({ onIntersect });
+ const [data, isEnd, setTarget] = useInfinityScroll(memos, (pageNum) =>
+ getMemos('month', type, pageNum)
+ );
return (
@@ -68,7 +33,7 @@ export default function MemosContainer({ memos, type }: Props) {
isSelected={type === 'hot'}
/>
-
+
{isEnd ? <>> : }
);
diff --git a/src/components/shared/BarLink.tsx b/src/components/shared/BarLink.tsx
new file mode 100644
index 00000000..9402d896
--- /dev/null
+++ b/src/components/shared/BarLink.tsx
@@ -0,0 +1,22 @@
+import Link from 'next/link';
+
+type Props = {
+ text: string;
+ isSelected: boolean;
+ href: string;
+};
+
+export default function BarLink({ text, isSelected, href }: Props) {
+ return (
+
+ {text}
+
+ );
+}
diff --git a/src/components/shared/Header.tsx b/src/components/shared/Header.tsx
index 599a17af..c9acc819 100644
--- a/src/components/shared/Header.tsx
+++ b/src/components/shared/Header.tsx
@@ -291,7 +291,7 @@ export default function Header({
className="p-2 px-3 tracking-wider hover:bg-gray-200"
onClick={() => {
checkUser().then((data) =>
- router.push(`/me/${data.id}/drafts`)
+ router.push(`/drafts/${data.id}`)
);
setIsActive(false);
}}
diff --git a/src/hooks/useInfinityScroll.ts b/src/hooks/useInfinityScroll.ts
new file mode 100644
index 00000000..1f57918a
--- /dev/null
+++ b/src/hooks/useInfinityScroll.ts
@@ -0,0 +1,51 @@
+import { Dispatch, SetStateAction, useEffect, useRef, useState } from 'react';
+import useObserver from '@/hooks/useObserver';
+
+export const useInfinityScroll = (
+ initialData: T[],
+ fn: (c: number) => Promise
+): [
+ data: T[],
+ isEnd: boolean,
+ setTarget: Dispatch>
+] => {
+ const [data, setData] = useState(initialData);
+ const [pageNum, setPageNum] = useState(1);
+ const [isEnd, setIsEnd] = useState(false);
+ const [isLoading, setIsLoading] = useState(false);
+ const isInitialMount = useRef(true);
+
+ const fetchData = () => {
+ if (isLoading || isEnd) return;
+ setIsLoading(true);
+
+ fn(pageNum)
+ .then((item) => {
+ setIsLoading(false);
+ if (!item.length) setIsEnd(true);
+ else {
+ setData([...data, ...item]);
+ }
+ })
+ .catch(() => {
+ setIsLoading(false);
+ });
+ };
+
+ useEffect(() => {
+ if (isInitialMount.current) {
+ isInitialMount.current = false;
+ } else {
+ fetchData();
+ }
+ }, [pageNum]);
+
+ const onIntersect: IntersectionObserverCallback = ([entry]) => {
+ if (isEnd || isLoading) return;
+ entry.isIntersecting && setPageNum(pageNum + 1);
+ };
+
+ const { setTarget } = useObserver({ onIntersect });
+
+ return [data, isEnd, setTarget];
+};