From 6d318329454e7c603d81c364a031d8095cd72d82 Mon Sep 17 00:00:00 2001 From: A_jin <77830408+ppochaco@users.noreply.github.com> Date: Sat, 17 Aug 2024 03:37:01 +0900 Subject: [PATCH] [Refactor] create board (#178) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit close #167 * :recycle: Refactor(create-board): error-boundary 로직 수정 related to: #169 * :recycle: Refactor: 페이지네이션 버튼 공통 컴포넌트로 분리 * :truck: Rename: table content 컴포넌트 위치 이동 * :truck: Rename(board): 활동 게시판 페이지 구조 수정 related to: #167 * :sparkles: Feat(board): 활동 게시글 불러오기 추가 related to: #167 * :recycle: Refactor: post table 공통 컴포넌트로 분리 * :lipstick: Design(board): 활동 게시글 테이블 UI 추가 related to: #167 --- .../_components/ActivityErrorFallback.tsx | 19 ++++-- .../_components/ActivitySection/index.tsx | 2 +- .../BoardPaginationButton/index.tsx | 68 ------------------- .../_components/BoardSection/index.tsx | 26 ++++--- .../_components/CreateBoardButton/index.tsx | 10 ++- .../_components/ActivityPostSection/index.tsx | 53 +++++++++++++++ .../_components/BoardContent/index.tsx | 28 -------- .../BoardHero/BoardDetail/index.tsx | 0 .../{BoardContent => }/BoardHero/index.tsx | 0 .../CreatePostButton/index.tsx | 0 .../CreateActivityPostForm/index.tsx | 3 + .../[activityId]/boards/[boardId]/page.tsx | 23 +++++-- .../[semesterName]/[activityId]/layout.tsx | 4 +- .../_components/EventPostSection/index.tsx | 9 ++- .../index.tsx | 6 +- .../Table/PostTable}/index.tsx | 11 ++- .../components/ReactQueryClientProvider.tsx | 4 +- src/service/data/activity.ts | 4 +- src/service/data/post.ts | 24 ++++++- src/service/server/post/index.ts | 67 ++++++++++++++++-- 20 files changed, 212 insertions(+), 149 deletions(-) delete mode 100644 src/app/(main)/activity/[semesterName]/[activityId]/_components/BoardSection/BoardPaginationButton/index.tsx create mode 100644 src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/_components/ActivityPostSection/index.tsx delete mode 100644 src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/_components/BoardContent/index.tsx rename src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/_components/{BoardContent => }/BoardHero/BoardDetail/index.tsx (100%) rename src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/_components/{BoardContent => }/BoardHero/index.tsx (100%) rename src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/_components/{BoardContent => }/CreatePostButton/index.tsx (100%) rename src/components/{Table/TablePaginationButton => PaginationButtons}/index.tsx (91%) rename src/{app/(main)/event/board/_components/EventPostSection/EventPostTable => components/Table/PostTable}/index.tsx (88%) diff --git a/src/app/(main)/activity/[semesterName]/[activityId]/_components/ActivityErrorFallback.tsx b/src/app/(main)/activity/[semesterName]/[activityId]/_components/ActivityErrorFallback.tsx index 62e71dd..14dbb56 100644 --- a/src/app/(main)/activity/[semesterName]/[activityId]/_components/ActivityErrorFallback.tsx +++ b/src/app/(main)/activity/[semesterName]/[activityId]/_components/ActivityErrorFallback.tsx @@ -1,5 +1,7 @@ 'use client' +import { useEffect } from 'react' + import { usePathname, useRouter } from 'next/navigation' import { Button } from '@/components/ui/button' @@ -15,13 +17,16 @@ const ActivityErrorFallback = ({ const pathName = usePathname() const router = useRouter() - if (error?.message === DATA_ERROR_MESSAGES.ACTIVITY_NOT_FOUND) { - const semesterName = getSemesterNameFromPath(pathName) - const currentSemester = useCurrentSemester(semesterName) - const {} = useGetActivities(Number(currentSemester.semesterId)) + const semesterName = getSemesterNameFromPath(pathName) + const currentSemester = useCurrentSemester(semesterName) + + useGetActivities(Number(currentSemester.semesterId)) - resetErrorBoundary() - } + useEffect(() => { + if (error?.message === DATA_ERROR_MESSAGES.ACTIVITY_NOT_FOUND) { + resetErrorBoundary() + } + }, [error]) return (
@@ -30,7 +35,7 @@ const ActivityErrorFallback = ({ - +
) diff --git a/src/app/(main)/activity/[semesterName]/[activityId]/_components/ActivitySection/index.tsx b/src/app/(main)/activity/[semesterName]/[activityId]/_components/ActivitySection/index.tsx index 9267a41..b5c0886 100644 --- a/src/app/(main)/activity/[semesterName]/[activityId]/_components/ActivitySection/index.tsx +++ b/src/app/(main)/activity/[semesterName]/[activityId]/_components/ActivitySection/index.tsx @@ -13,7 +13,7 @@ export const ActivitySection = ({ semesterId, activityId, }: ActivitySectionProps) => { - const { data: activities, status } = useGetActivities(semesterId) + const { data: activities } = useGetActivities(semesterId) const currentActivity = useCurrentActivity(semesterId, activityId) if (!activities?.length) return
활동이 없습니다.
diff --git a/src/app/(main)/activity/[semesterName]/[activityId]/_components/BoardSection/BoardPaginationButton/index.tsx b/src/app/(main)/activity/[semesterName]/[activityId]/_components/BoardSection/BoardPaginationButton/index.tsx deleted file mode 100644 index 4bde7ce..0000000 --- a/src/app/(main)/activity/[semesterName]/[activityId]/_components/BoardSection/BoardPaginationButton/index.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import { Dispatch, SetStateAction } from 'react' - -import { - Pagination, - PaginationButton, - PaginationContent, - PaginationItem, - PaginationNext, - PaginationPrevious, -} from '@/components/ui/pagination' -import { BoardsResponse } from '@/service/server/board' - -type BoardPaginationButtonProps = { - boardData?: BoardsResponse - currentPage: number - setCurrentPage: Dispatch> -} - -export const BoardPaginationButton = ({ - boardData, - currentPage, - setCurrentPage, -}: BoardPaginationButtonProps) => { - if (!boardData) return null - - const pages = createPageNumber(boardData.pageInfo.totalPages) - - return ( - - - - { - e.preventDefault() - setCurrentPage((old) => Math.max(old - 1, 0)) - }} - disabled={currentPage === 0} - /> - - {pages.map((page) => ( - - setCurrentPage(page - 1)} - isActive={currentPage + 1 === page} - > - {page} - - - ))} - - { - e.preventDefault() - setCurrentPage((old) => (boardData.nextPageToken ? old + 1 : old)) - }} - disabled={currentPage === boardData.pageInfo.totalPages - 1} - /> - - - - ) -} - -const createPageNumber = (totalPages: number) => { - return Array.from({ length: totalPages }, (_, index) => index + 1) -} diff --git a/src/app/(main)/activity/[semesterName]/[activityId]/_components/BoardSection/index.tsx b/src/app/(main)/activity/[semesterName]/[activityId]/_components/BoardSection/index.tsx index 29dadee..f00f3ae 100644 --- a/src/app/(main)/activity/[semesterName]/[activityId]/_components/BoardSection/index.tsx +++ b/src/app/(main)/activity/[semesterName]/[activityId]/_components/BoardSection/index.tsx @@ -1,20 +1,26 @@ 'use client' -import { useEffect, useState } from 'react' +import { useEffect } from 'react' +import { useSearchParams } from 'next/navigation' + +import { PaginationButtons } from '@/components/PaginationButtons' import { queryClient } from '@/service/components/ReactQueryClientProvider' import { useGetBoardsPaging } from '@/service/data/boards' import { getBoardsPaging } from '@/service/server/board' import { BoardList } from './BoardList/indext' -import { BoardPaginationButton } from './BoardPaginationButton' type BoardSectionProps = { activityId: number } export const BoardSection = ({ activityId }: BoardSectionProps) => { - const [page, setPage] = useState(0) + const searchParams = useSearchParams() + const params = new URLSearchParams(searchParams) + + const page = + Number(params.get('page')) > 0 ? Number(params.get('page')) - 1 : 0 const { data, status, isPlaceholderData } = useGetBoardsPaging({ activityId: activityId, @@ -24,12 +30,8 @@ export const BoardSection = ({ activityId }: BoardSectionProps) => { useEffect(() => { if (!isPlaceholderData && data?.nextPageToken) { queryClient.prefetchQuery({ - queryKey: ['boards', activityId, page + 1], - queryFn: () => - getBoardsPaging({ - activityId: activityId, - page: page + 1, - }), + queryKey: ['boards', activityId, page], + queryFn: () => getBoardsPaging({ activityId, page }), }) } }, [data, isPlaceholderData, page, queryClient]) @@ -40,11 +42,7 @@ export const BoardSection = ({ activityId }: BoardSectionProps) => { return (
- +
) } diff --git a/src/app/(main)/activity/[semesterName]/[activityId]/_components/CreateBoardButton/index.tsx b/src/app/(main)/activity/[semesterName]/[activityId]/_components/CreateBoardButton/index.tsx index cadbaca..098f9bd 100644 --- a/src/app/(main)/activity/[semesterName]/[activityId]/_components/CreateBoardButton/index.tsx +++ b/src/app/(main)/activity/[semesterName]/[activityId]/_components/CreateBoardButton/index.tsx @@ -1,3 +1,5 @@ +import { useEffect, useState } from 'react' + import { usePathname, useRouter } from 'next/navigation' import { Button } from '@/components/ui/button' @@ -6,14 +8,20 @@ import { useMyInfoStore } from '@/store/myInfo' export const CreateBoardButton = () => { const pathName = usePathname() const router = useRouter() + const { role } = useMyInfoStore((state) => state.getMyInfo()) + const [disabled, setDisabled] = useState(true) + + useEffect(() => { + setDisabled(!(role === '해구르르' || role === '팀장')) + }, []) return (
diff --git a/src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/_components/ActivityPostSection/index.tsx b/src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/_components/ActivityPostSection/index.tsx new file mode 100644 index 0000000..124d149 --- /dev/null +++ b/src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/_components/ActivityPostSection/index.tsx @@ -0,0 +1,53 @@ +import { useEffect } from 'react' + +import { useSearchParams } from 'next/navigation' + +import { PaginationButtons } from '@/components/PaginationButtons' +import { PostTable } from '@/components/Table/PostTable' +import { queryClient } from '@/service/components/ReactQueryClientProvider' +import { useGetActivityPostsPaging } from '@/service/data/post' +import { getActivityPostsPaging } from '@/service/server/post' + +type ActivityPostSectionProps = { + boardId: number +} + +export const ActivityPostSection = ({ boardId }: ActivityPostSectionProps) => { + const searchParams = useSearchParams() + const params = new URLSearchParams(searchParams) + + const page = + Number(params.get('page')) > 0 ? Number(params.get('page')) - 1 : 0 + + const { data, status, isPlaceholderData } = useGetActivityPostsPaging({ + boardId, + page, + }) + + useEffect(() => { + if (!isPlaceholderData && data?.nextPageToken) { + queryClient.prefetchQuery({ + queryKey: ['posts', boardId, page], + queryFn: () => getActivityPostsPaging({ boardId, page }), + }) + } + }, [data, isPlaceholderData, page, queryClient]) + + if (status === 'pending') + return
loading...
+ + if (!data) { + return
게시글이 없습니다.
+ } + + return ( +
+ + +
+ ) +} diff --git a/src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/_components/BoardContent/index.tsx b/src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/_components/BoardContent/index.tsx deleted file mode 100644 index a45c2ef..0000000 --- a/src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/_components/BoardContent/index.tsx +++ /dev/null @@ -1,28 +0,0 @@ -'use client' - -import { useBoardDetail } from '@/service/data/boards' - -import { BoardHero } from './BoardHero' -import { CreatePostButton } from './CreatePostButton' - -type BoardPageProps = { - boardId: number - activityId: number -} - -export const BoardContent = ({ boardId, activityId }: BoardPageProps) => { - const { data: boardDetail, status } = useBoardDetail({ - activityId, - boardId, - }) - - if (status === 'pending') return
loading...
- if (!boardDetail) return
게시판 정보가 없습니다.
- - return ( -
- - -
- ) -} diff --git a/src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/_components/BoardContent/BoardHero/BoardDetail/index.tsx b/src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/_components/BoardHero/BoardDetail/index.tsx similarity index 100% rename from src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/_components/BoardContent/BoardHero/BoardDetail/index.tsx rename to src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/_components/BoardHero/BoardDetail/index.tsx diff --git a/src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/_components/BoardContent/BoardHero/index.tsx b/src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/_components/BoardHero/index.tsx similarity index 100% rename from src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/_components/BoardContent/BoardHero/index.tsx rename to src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/_components/BoardHero/index.tsx diff --git a/src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/_components/BoardContent/CreatePostButton/index.tsx b/src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/_components/CreatePostButton/index.tsx similarity index 100% rename from src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/_components/BoardContent/CreatePostButton/index.tsx rename to src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/_components/CreatePostButton/index.tsx diff --git a/src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/create-post/_components/CreateActivityPostForm/index.tsx b/src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/create-post/_components/CreateActivityPostForm/index.tsx index 0ba02b7..bbe5666 100644 --- a/src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/create-post/_components/CreateActivityPostForm/index.tsx +++ b/src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/create-post/_components/CreateActivityPostForm/index.tsx @@ -10,6 +10,7 @@ import { usePathname, useRouter } from 'next/navigation' import { CreatePostForm } from '@/components/CreatePostForm' import { useToast } from '@/components/ui/use-toast' import { CreateActivityPost, CreateActivityPostSchema } from '@/schema/post' +import { queryClient } from '@/service/components/ReactQueryClientProvider' import { createActivityPostAction } from '@/service/server/post/create-post' type CreateActivityPostFormProps = { @@ -51,7 +52,9 @@ export const CreateActivityPostForm = ({ title: result.data.message, duration: 3000, }) + queryClient.invalidateQueries({ queryKey: ['posts', boardId, 0] }) router.push(basePath) + return } diff --git a/src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/page.tsx b/src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/page.tsx index e05c0da..b994e8b 100644 --- a/src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/page.tsx +++ b/src/app/(main)/activity/[semesterName]/[activityId]/boards/[boardId]/page.tsx @@ -1,6 +1,10 @@ 'use client' -import { BoardContent } from './_components/BoardContent' +import { useBoardDetail } from '@/service/data/boards' + +import { ActivityPostSection } from './_components/ActivityPostSection' +import { BoardHero } from './_components/BoardHero' +import { CreatePostButton } from './_components/CreatePostButton' type BoardPageParams = { params: { @@ -10,11 +14,20 @@ type BoardPageParams = { } const BoardPage = ({ params }: BoardPageParams) => { + const { data: boardDetail, status } = useBoardDetail({ + activityId: Number(params.activityId), + boardId: Number(params.boardId), + }) + + if (status === 'pending') return
loading...
+ if (!boardDetail) return
게시판 정보가 없습니다.
+ return ( - +
+ + + +
) } diff --git a/src/app/(main)/activity/[semesterName]/[activityId]/layout.tsx b/src/app/(main)/activity/[semesterName]/[activityId]/layout.tsx index 4cd1f31..03f5b08 100644 --- a/src/app/(main)/activity/[semesterName]/[activityId]/layout.tsx +++ b/src/app/(main)/activity/[semesterName]/[activityId]/layout.tsx @@ -8,7 +8,9 @@ const ActivityLayout = ({ children }: { children: ReactNode }) => { return ( loading...
} + suspenseFallback={ +
loading...
+ } > {children} diff --git a/src/app/(main)/event/board/_components/EventPostSection/index.tsx b/src/app/(main)/event/board/_components/EventPostSection/index.tsx index b6172d4..87938da 100644 --- a/src/app/(main)/event/board/_components/EventPostSection/index.tsx +++ b/src/app/(main)/event/board/_components/EventPostSection/index.tsx @@ -4,13 +4,12 @@ import { useEffect } from 'react' import { useSearchParams } from 'next/navigation' -import { TablePaginationButton } from '@/components/Table/TablePaginationButton' +import { PaginationButtons } from '@/components/PaginationButtons' +import { PostTable } from '@/components/Table/PostTable' import { queryClient } from '@/service/components/ReactQueryClientProvider' import { useGetPostsPaging } from '@/service/data/post' import { getPostsPaging } from '@/service/server/post' -import { EventPostTable } from './EventPostTable' - export const EventPostSection = () => { const postType = 'EVENT' @@ -43,12 +42,12 @@ export const EventPostSection = () => { return (
- - +
) } diff --git a/src/components/Table/TablePaginationButton/index.tsx b/src/components/PaginationButtons/index.tsx similarity index 91% rename from src/components/Table/TablePaginationButton/index.tsx rename to src/components/PaginationButtons/index.tsx index 2dfe5a1..3e0a3e7 100644 --- a/src/components/Table/TablePaginationButton/index.tsx +++ b/src/components/PaginationButtons/index.tsx @@ -11,13 +11,13 @@ import { } from '@/components/ui/pagination' import { Paging } from '@/service/types/paging' -type TablePaginationButtonProps = { +type PaginationButtonsProps = { data: T } -export const TablePaginationButton = ({ +export const PaginationButtons = ({ data, -}: TablePaginationButtonProps) => { +}: PaginationButtonsProps) => { const pages = createPageNumber(data.pageInfo.totalPages) const searchParams = useSearchParams() diff --git a/src/app/(main)/event/board/_components/EventPostSection/EventPostTable/index.tsx b/src/components/Table/PostTable/index.tsx similarity index 88% rename from src/app/(main)/event/board/_components/EventPostSection/EventPostTable/index.tsx rename to src/components/Table/PostTable/index.tsx index 03af712..8d6d4ca 100644 --- a/src/app/(main)/event/board/_components/EventPostSection/EventPostTable/index.tsx +++ b/src/components/Table/PostTable/index.tsx @@ -6,20 +6,17 @@ import { useReactTable, } from '@tanstack/react-table' -import { TableContent } from '@/components/Table/TableContent' import { Post } from '@/types/post' -type EventPostTableProps = { +import { TableContent } from '../TableContent' + +type PostTableProps = { posts: Post[] pageNumber: number pageSize: number } -export const EventPostTable = ({ - posts, - pageNumber, - pageSize, -}: EventPostTableProps) => { +export const PostTable = ({ posts, pageNumber, pageSize }: PostTableProps) => { if (!posts?.length) return
게시글이 없습니다.
diff --git a/src/service/components/ReactQueryClientProvider.tsx b/src/service/components/ReactQueryClientProvider.tsx index 381506d..4c761e5 100644 --- a/src/service/components/ReactQueryClientProvider.tsx +++ b/src/service/components/ReactQueryClientProvider.tsx @@ -7,8 +7,10 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query' export const queryClient = new QueryClient({ defaultOptions: { queries: { - retry: 0, + retry: 1, staleTime: 1000 * 60 * 3, + refetchOnMount: false, + refetchOnWindowFocus: false, }, }, }) diff --git a/src/service/data/activity.ts b/src/service/data/activity.ts index 96a75fb..2f62522 100644 --- a/src/service/data/activity.ts +++ b/src/service/data/activity.ts @@ -1,4 +1,6 @@ -import { queryOptions, useQuery, useSuspenseQuery } from '@tanstack/react-query' +'use client' + +import { queryOptions, useSuspenseQuery } from '@tanstack/react-query' import { DATA_ERROR_MESSAGES } from '@/constant/errorMessage' import { queryClient } from '@/service/components/ReactQueryClientProvider' diff --git a/src/service/data/post.ts b/src/service/data/post.ts index 6f4678b..9af7c8d 100644 --- a/src/service/data/post.ts +++ b/src/service/data/post.ts @@ -1,6 +1,28 @@ import { keepPreviousData, useQuery } from '@tanstack/react-query' -import { getPostsPaging, getPostsSlider } from '@/service/server/post' +import { + getActivityPostsPaging, + getPostsPaging, + getPostsSlider, +} from '@/service/server/post' + +type ActivityPostParams = { + boardId: number + page: number + size?: number +} + +export const useGetActivityPostsPaging = ({ + boardId, + page, + size = 10, +}: ActivityPostParams) => { + return useQuery({ + queryKey: ['posts', boardId, page], + queryFn: () => getActivityPostsPaging({ boardId, page, size }), + placeholderData: keepPreviousData, + }) +} type PostsParams = { postType: 'EVENT' | 'NOTICE' diff --git a/src/service/server/post/index.ts b/src/service/server/post/index.ts index 7e9a9b7..15a56f5 100644 --- a/src/service/server/post/index.ts +++ b/src/service/server/post/index.ts @@ -3,12 +3,6 @@ import { AUTHORIZATION_API, BACKEND_API } from '@/service/config' import { PagaingRaw, Paging } from '@/service/types/paging' import { Post, PostSlider } from '@/types/post' -type PostsPagingRequestParams = { - postType: 'NOTICE' | 'EVENT' - page?: number - size?: number -} - interface PostsPaingResponseRaw extends PagaingRaw { content: Post[] } @@ -17,6 +11,67 @@ export interface PostsResponse extends Paging { posts: Post[] } +type ActivityPostsPagingRequestParams = { + boardId: number + page?: number + size?: number +} + +export const getActivityPostsPaging = async ( + params: ActivityPostsPagingRequestParams, +): Promise => { + const response = await BACKEND_API.get( + getActivityPostsPath(params), + ) + + const { data } = response + + const posts = data.content.map((post) => { + const formatCreateDate = formatDateDistanceFromToday( + new Date(post.postCreateDate), + ) + + if (!formatCreateDate) return post + + return { + ...post, + postCreateDate: formatCreateDate, + } + }) + + return { + posts, + nextPageToken: + data.pageable.pageNumber !== data.totalPages + ? (data.pageable.pageNumber + 1).toString() + : undefined, + pageInfo: { + totalPages: data.totalPages, + totalElements: data.totalElements, + pageSize: data.pageable.pageSize, + }, + } +} + +const getActivityPostsPath = ({ + boardId, + page, + size, +}: ActivityPostsPagingRequestParams) => { + const params = new URLSearchParams() + + if (page) params.append('page', page.toString()) + if (size) params.append('size', size.toString()) + + return `/boards/${boardId}/posts?${params.toString()}` +} + +type PostsPagingRequestParams = { + postType: 'NOTICE' | 'EVENT' + page?: number + size?: number +} + export const getPostsPaging = async ( params: PostsPagingRequestParams, ): Promise => {