-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor : article 페이지 리팩토링 & 기존 검색페이지 파일 삭제 (#338)
* remove: delete searchPage before refactoring * refactor: implement FilteredData component * refactor: implement RenderArticles for newest and subscribed articles * fix: edit searchPage type * refactor: add topButton in articlePage * fix: move on top obejct and delete return * fix: comfrim type of HEADER_LABEL and label in HeaderProps * fix: rename type
- Loading branch information
Showing
14 changed files
with
275 additions
and
329 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { ReactNode } from 'react'; | ||
import { useNavigate } from 'react-router-dom'; | ||
import SubButton from '@/components/SubButton'; | ||
|
||
type FailedMessageProps = { | ||
path: string; | ||
label: string; | ||
children: ReactNode; | ||
}; | ||
|
||
const FailedMessage = ({ path, label, children }: FailedMessageProps) => { | ||
const navigate = useNavigate(); | ||
|
||
return ( | ||
<div className="flex flex-col items-center justify-center w-full h-full text-center font-Cafe24SurroundAir"> | ||
<span className="mb-4">{children}</span> | ||
<SubButton label={label} color="blue" type="outline" onClick={() => navigate(path)} /> | ||
</div> | ||
); | ||
}; | ||
|
||
export default FailedMessage; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import { AiOutlineArrowUp } from 'react-icons/ai'; | ||
import { BsFire } from 'react-icons/bs'; | ||
import { MdStars } from 'react-icons/md'; | ||
import { Header } from '@/components'; | ||
import BottomNavigation from '@/components/BottomNavigation'; | ||
import Tabs from '@/components/Tabs'; | ||
import useScrollToTop from '@/hooks/useScrollToTop'; | ||
import RenderHottestArticles from '@/pages/ArticlesPage/RenderHottestArticles'; | ||
import RenderArticles from '../RenderArticles'; | ||
|
||
const ArticlesPage = () => { | ||
const { ref: scrollRef, showScrollToTopButton, scrollToTop } = useScrollToTop(); | ||
|
||
return ( | ||
<Tabs defaultValue="newest"> | ||
<section className="max-w-[25.875rem] mx-auto h-screen w-screen flex flex-col relative overflow-hidden"> | ||
<header className="flex flex-col pt-[2.75rem] gap-5"> | ||
<div className="pl-7 pr-7"> | ||
<Header label="news" type="search" path="/search" /> | ||
</div> | ||
<Tabs.List> | ||
<Tabs.Tab value="newest">최신의</Tabs.Tab> | ||
<Tabs.Tab value="hottest"> | ||
<BsFire className="w-[1.3rem] h-[1.3rem]" /> | ||
뜨거운 | ||
</Tabs.Tab> | ||
<Tabs.Tab value="subscribed"> | ||
<MdStars className="w-[1.5rem] h-[1.5rem]" /> | ||
구독한 | ||
</Tabs.Tab> | ||
</Tabs.List> | ||
</header> | ||
<article ref={scrollRef} className="flex-grow overflow-y-auto"> | ||
<Tabs.Panel value="newest"> | ||
<RenderArticles type="newest" /> | ||
</Tabs.Panel> | ||
<Tabs.Panel value="hottest"> | ||
<RenderHottestArticles /> | ||
</Tabs.Panel> | ||
<Tabs.Panel value="subscribed"> | ||
<RenderArticles type="subscribed" /> | ||
</Tabs.Panel> | ||
<button | ||
onClick={scrollToTop} | ||
disabled={!showScrollToTopButton} | ||
className={`absolute p-2 flex items-center justify-center text-white w-[3.5rem] h-[3.5rem] bg-cooled-blue drop-shadow-[0_0.25rem_0.25rem_rgba(0,0,0,0.25)] transition-opacity duration-300 ease-in-out ${ | ||
showScrollToTopButton ? 'opacity-100' : 'opacity-0 pointer-events-none' | ||
} rounded-full bottom-24 right-4`} | ||
aria-label="위로 가기" | ||
> | ||
<AiOutlineArrowUp className="w-[1.5rem] h-[1.5rem]" /> | ||
</button> | ||
</article> | ||
<div className="flex justify-center flex-none w-full"> | ||
<BottomNavigation currentPage="/news" /> | ||
</div> | ||
</section> | ||
</Tabs> | ||
); | ||
}; | ||
|
||
export default ArticlesPage; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import Loader from '@/components/Loader'; | ||
import SearchSkeleton from '@/components/SearchSkeleton'; | ||
import useAuthQuery from '@/hooks/useAuthQuery'; | ||
import InfiniteScroll from '@/pages/ArticlesPage/InfiniteScroll.tsx'; | ||
import FilteredData from '@/shared/components/FilteredData'; | ||
import FailedMessage from '../FailedMessage.tsx'; | ||
import useFetchArticles from '../useFetchArticles'; | ||
|
||
type RenderArticlesProps = { | ||
type: 'newest' | 'subscribed'; | ||
}; | ||
|
||
const RenderArticles = ({ type }: RenderArticlesProps) => { | ||
const { | ||
userQuery: { data: user }, | ||
} = useAuthQuery(); | ||
|
||
const followingUsersIds = Array.from(new Set(user?.following.map((user) => user.user))); | ||
|
||
const { data, isLoading, isFetching, fetchNextPage, hasNextPage } = useFetchArticles({ | ||
type, | ||
followingUsersIds, | ||
}); | ||
|
||
if (isLoading) { | ||
return <SearchSkeleton SkeletonType="title" />; | ||
} | ||
|
||
if (type === 'subscribed') { | ||
if (!user) { | ||
return ( | ||
<FailedMessage path="/login" label="로그인"> | ||
로그인이 필요합니다. <br /> | ||
로그인 페이지로 이동하시겠습니까? | ||
</FailedMessage> | ||
); | ||
} else if (!followingUsersIds.length) { | ||
return ( | ||
<FailedMessage path="/search" label="구독하기"> | ||
앗 구독한 글들이 없습니다. <br /> | ||
다른 사용자를 팔로우하러 가시겠습니까? | ||
</FailedMessage> | ||
) | ||
} | ||
} | ||
|
||
return ( | ||
<> | ||
<FilteredData type="article" data={data?.pages.flat()} /> | ||
{isFetching ? ( | ||
<div className="flex justify-center"> | ||
<Loader /> | ||
</div> | ||
) : ( | ||
<InfiniteScroll fetchData={fetchNextPage} canFetchMore={hasNextPage} /> | ||
)} | ||
</> | ||
); | ||
}; | ||
|
||
export default RenderArticles; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { useInfiniteQuery } from '@tanstack/react-query'; | ||
import { fetchAllPosts, fetchUserPosts } from '@/api/Post'; | ||
|
||
type useFetchArticlesProps = { | ||
type: 'newest' | 'subscribed'; | ||
followingUsersIds: string[]; | ||
}; | ||
|
||
const ARTICLES_LIMIT = { | ||
newest: 10, | ||
subscribed: 3, | ||
}; | ||
|
||
const QUERY_KEY = { | ||
newest: 'newestArticles', | ||
subscribed: 'followingArticles', | ||
}; | ||
|
||
const useFetchArticles = ({ type, followingUsersIds }: useFetchArticlesProps) => { | ||
|
||
|
||
const FETCH_API = { | ||
newest: async ({ pageParam = 0 }) => { | ||
return await fetchAllPosts({ offset: pageParam, limit: ARTICLES_LIMIT[type] }); | ||
}, | ||
subscribed: async ({ pageParam = 0 }) => { | ||
const newArticles = await Promise.all( | ||
followingUsersIds.map((user) => | ||
fetchUserPosts({ offset: pageParam, limit: ARTICLES_LIMIT[type], authorId: user }), | ||
), | ||
); | ||
return newArticles.flat(); | ||
}, | ||
}; | ||
|
||
const { data, fetchNextPage, hasNextPage, isLoading, isFetching } = useInfiniteQuery( | ||
[QUERY_KEY[type]], | ||
FETCH_API[type], | ||
{ | ||
getNextPageParam: (lastPage, pages) => lastPage.length < ARTICLES_LIMIT[type] ? undefined : pages.length * ARTICLES_LIMIT[type] | ||
|
||
}, | ||
); | ||
|
||
return { | ||
data, | ||
fetchNextPage, | ||
hasNextPage, | ||
isLoading, | ||
isFetching, | ||
}; | ||
}; | ||
|
||
export default useFetchArticles; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.