Skip to content
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
24 changes: 23 additions & 1 deletion src/components/common/Pagination/Pagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export interface PaginationProps {
pageCount: number;
/** 페이지 이동 시 실행할 콜백 */
onPageChange: (page: number) => void;
/** 페이지 버튼에 포인터를 올렸을 때 실행할 콜백 */
onPagePrefetch?: (page: number) => void;
className?: string;
}

Expand Down Expand Up @@ -135,7 +137,13 @@ const getPageItems = (currentPage: number, pageCount: number, rangeSize: number)
return items;
};

const Pagination = ({ currentPage, pageCount, onPageChange, className }: PaginationProps) => {
const Pagination = ({
currentPage,
pageCount,
onPageChange,
onPagePrefetch,
className,
}: PaginationProps) => {
const isLg = useSyncExternalStore(subscribeToXl, getXlSnapshot, getServerSnapshot);

const [openEllipsisIndex, setOpenEllipsisIndex] = useState<number | null>(null);
Expand All @@ -159,6 +167,14 @@ const Pagination = ({ currentPage, pageCount, onPageChange, className }: Paginat
onPageChange(nextPage);
};

const prefetchPage = (page: number) => {
const nextPage = Math.min(Math.max(page, 1), pageCount);

if (nextPage !== currentPage) {
onPagePrefetch?.(nextPage);
}
};

const itemClassName = cn(
"flex items-center justify-center p-10",
isLg ? "size-48 rounded-8" : "size-34 rounded-6",
Expand All @@ -177,6 +193,8 @@ const Pagination = ({ currentPage, pageCount, onPageChange, className }: Paginat
"text-text-secondary enabled:hover:bg-background-hover disabled:text-text-weak transition disabled:cursor-not-allowed",
)}
onClick={() => goToPage(currentPage - 1)}
onPointerEnter={() => prefetchPage(currentPage - 1)}
onFocus={() => prefetchPage(currentPage - 1)}
disabled={isPrevDisabled}
aria-label="이전 페이지"
>
Expand Down Expand Up @@ -208,6 +226,8 @@ const Pagination = ({ currentPage, pageCount, onPageChange, className }: Paginat
: "text-text-weak enabled:hover:bg-background-hover cursor-pointer",
)}
onClick={() => goToPage(item.page)}
onPointerEnter={() => prefetchPage(item.page)}
onFocus={() => prefetchPage(item.page)}
disabled={item.page === currentPage}
aria-label={`${item.page} 페이지`}
aria-current={item.page === currentPage ? "page" : undefined}
Expand Down Expand Up @@ -238,6 +258,8 @@ const Pagination = ({ currentPage, pageCount, onPageChange, className }: Paginat
"text-text-secondary enabled:hover:bg-background-hover disabled:text-text-weak transition disabled:cursor-not-allowed",
)}
onClick={() => goToPage(currentPage + 1)}
onPointerEnter={() => prefetchPage(currentPage + 1)}
onFocus={() => prefetchPage(currentPage + 1)}
disabled={isNextDisabled}
aria-label="다음 페이지"
>
Expand Down
2 changes: 1 addition & 1 deletion src/components/estimate/ReceivedRequestsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import Image from "next/image";
import { FormEvent, useState } from "react";
import { type FormEvent, useState } from "react";

import Checkbox from "@/components/common/Checkbox/Checkbox";
import SelectableChip from "@/components/common/Chip/SelectableChip";
Expand Down
18 changes: 16 additions & 2 deletions src/components/mover/detail/MoverDetailReviews.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use client";

import { useState } from "react";
import { useQueryClient } from "@tanstack/react-query";
import { useCallback, useState } from "react";

import Pagination from "@/components/common/Pagination/Pagination";
import { Text } from "@/components/common/Text";
Expand All @@ -10,7 +11,8 @@ import MoverRatingSummary from "@/components/mover/detail/MoverRatingSummary";
import MoverReviewList from "@/components/mover/detail/MoverReviewList";
import { useMoverReviews } from "@/hooks/useMoverReviews";
import { getApiErrorMessage } from "@/lib/api/getApiErrorMessage";
import { MOVER_REVIEW_PAGE_LIMIT } from "@/lib/api/movers";
import { getMoverReviews, MOVER_REVIEW_PAGE_LIMIT } from "@/lib/api/movers";
import { QUERY_KEYS } from "@/lib/constants/queryKeys";
import type { MoverDetail } from "@/types/moverDetail";

interface MoverDetailReviewsProps {
Expand All @@ -31,6 +33,7 @@ export default function MoverDetailReviews({
ratingDistribution,
}: MoverDetailReviewsProps) {
const [currentPage, setCurrentPage] = useState(1);
const queryClient = useQueryClient();
const { data, isLoading, isError, error, isFetching, refetch } = useMoverReviews(moverId, {
page: currentPage,
});
Expand All @@ -51,6 +54,16 @@ export default function MoverDetailReviews({
// 헤더 개수도 목록 totalCount와 맞춤 (없을 때만 상세 reviewCount fallback)
// 2026.07.30 정슬기 - [수정]
const displayedReviewCount = data?.pagination.totalCount ?? reviewCount;
const prefetchReviewPage = useCallback(
(page: number) => {
void queryClient.prefetchQuery({
queryKey: QUERY_KEYS.REVIEWS.BY_MOVER(moverId, page, MOVER_REVIEW_PAGE_LIMIT),
queryFn: () => getMoverReviews(moverId, { page, limit: MOVER_REVIEW_PAGE_LIMIT }),
});
},
[moverId, queryClient],
);

return (
<section className="flex w-full flex-col gap-24 md:gap-32" aria-labelledby="mover-reviews">
<Text
Expand Down Expand Up @@ -100,6 +113,7 @@ export default function MoverDetailReviews({
currentPage={currentPage}
pageCount={pageCount}
onPageChange={setCurrentPage}
onPagePrefetch={prefetchReviewPage}
className="self-center"
/>
) : null}
Expand Down