From 60002a71696d2b1dfd89e2611b09607622ba238b Mon Sep 17 00:00:00 2001 From: vchikalkin Date: Tue, 22 Jul 2025 12:28:10 +0300 Subject: [PATCH] refactor(orders): add useOrdersInfiniteQuery for improved pagination and add load more button in orders list components --- .../components/orders/orders-list/index.tsx | 41 ++++++++++++++----- apps/web/components/profile/orders-list.tsx | 22 +++++++--- apps/web/hooks/api/orders.ts | 30 +++++++++++++- 3 files changed, 75 insertions(+), 18 deletions(-) diff --git a/apps/web/components/orders/orders-list/index.tsx b/apps/web/components/orders/orders-list/index.tsx index d53916a..6457199 100644 --- a/apps/web/components/orders/orders-list/index.tsx +++ b/apps/web/components/orders/orders-list/index.tsx @@ -2,8 +2,9 @@ import { OrderCard } from '@/components/shared/order-card'; import { useCustomerQuery, useIsMaster } from '@/hooks/api/customers'; -import { useOrdersQuery } from '@/hooks/api/orders'; +import { useOrdersInfiniteQuery } from '@/hooks/api/orders'; import { useDateTimeStore } from '@/stores/datetime'; +import { Button } from '@repo/ui/components/ui/button'; import { getDateUTCRange } from '@repo/utils/datetime-format'; export function ClientsOrdersList() { @@ -14,7 +15,12 @@ export function ClientsOrdersList() { const selectedDate = useDateTimeStore((store) => store.date); const { endOfDay, startOfDay } = getDateUTCRange(selectedDate).day(); - const { data: { orders } = {}, isLoading } = useOrdersQuery( + const { + data: { pages } = {}, + fetchNextPage, + hasNextPage, + isLoading, + } = useOrdersInfiniteQuery( { filters: { slot: { @@ -31,19 +37,23 @@ export function ClientsOrdersList() { }, }, }, - pagination: { - limit: selectedDate ? undefined : 10, - }, }, - Boolean(customer?.documentId) && isMaster, + { enabled: Boolean(customer?.documentId) && isMaster }, ); + const orders = pages?.flatMap((page) => page.orders) ?? []; + if (!orders?.length || isLoading || !isMaster) return null; return (

Записи клиентов

{orders?.map((order) => order && )} + {hasNextPage && ( + + )}
); } @@ -54,7 +64,12 @@ export function OrdersList() { const selectedDate = useDateTimeStore((store) => store.date); const { endOfDay, startOfDay } = getDateUTCRange(selectedDate).day(); - const { data: { orders } = {}, isLoading } = useOrdersQuery( + const { + data: { pages } = {}, + fetchNextPage, + hasNextPage, + isLoading, + } = useOrdersInfiniteQuery( { filters: { client: { @@ -71,13 +86,12 @@ export function OrdersList() { : undefined, }, }, - pagination: { - limit: selectedDate ? undefined : 10, - }, }, - Boolean(customer?.documentId), + { enabled: Boolean(customer?.documentId) }, ); + const orders = pages?.flatMap((page) => page.orders) ?? []; + if (!orders?.length || isLoading) return null; return ( @@ -87,6 +101,11 @@ export function OrdersList() { (order) => order && , )} + {hasNextPage && ( + + )} ); } diff --git a/apps/web/components/profile/orders-list.tsx b/apps/web/components/profile/orders-list.tsx index 75b1ea7..1133a6d 100644 --- a/apps/web/components/profile/orders-list.tsx +++ b/apps/web/components/profile/orders-list.tsx @@ -3,7 +3,8 @@ import { OrderCard } from '../shared/order-card'; import { type ProfileProps } from './types'; import { useCustomerQuery, useIsMaster } from '@/hooks/api/customers'; -import { useOrdersQuery } from '@/hooks/api/orders'; +import { useOrdersInfiniteQuery } from '@/hooks/api/orders'; +import { Button } from '@repo/ui/components/ui/button'; export function ProfileOrdersList({ telegramId }: Readonly) { const { data: { customer } = {} } = useCustomerQuery(); @@ -11,7 +12,12 @@ export function ProfileOrdersList({ telegramId }: Readonly) { const { data: { customer: profile } = {} } = useCustomerQuery({ telegramId }); - const { data: { orders } = {}, isLoading } = useOrdersQuery( + const { + data: { pages } = {}, + fetchNextPage, + hasNextPage, + isLoading, + } = useOrdersInfiniteQuery( { filters: { client: { @@ -27,13 +33,12 @@ export function ProfileOrdersList({ telegramId }: Readonly) { }, }, }, - pagination: { - limit: 5, - }, }, - Boolean(profile?.documentId) && Boolean(customer?.documentId), + { enabled: Boolean(profile?.documentId) && Boolean(customer?.documentId) }, ); + const orders = pages?.flatMap((page) => page.orders) ?? []; + if (!orders?.length || isLoading) return null; return ( @@ -50,6 +55,11 @@ export function ProfileOrdersList({ telegramId }: Readonly) { /> ), )} + {hasNextPage && ( + + )} ); } diff --git a/apps/web/hooks/api/orders.ts b/apps/web/hooks/api/orders.ts index a622f88..d54f22d 100644 --- a/apps/web/hooks/api/orders.ts +++ b/apps/web/hooks/api/orders.ts @@ -1,7 +1,8 @@ +/* eslint-disable unicorn/prevent-abbreviations */ 'use client'; import { createOrder, getOrder, getOrders, updateOrder } from '@/actions/api/orders'; -import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; +import { useInfiniteQuery, useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; export const useOrderQuery = ({ documentId }: Parameters[0]) => useQuery({ @@ -37,6 +38,33 @@ export const useOrdersQuery = (variables: Parameters[0], enabl staleTime: 60 * 1_000, }); +export const useOrdersInfiniteQuery = ( + variables: Omit[0], 'pagination'>, + { enabled = true, pageSize = 5 }, +) => { + const queryFn = ({ pageParam: page = 1 }) => + getOrders({ + ...variables, + pagination: { + page, + pageSize, + }, + }); + + return useInfiniteQuery({ + enabled, + getNextPageParam: (lastPage, _allPages, lastPageParameter) => { + if (!lastPage?.orders?.length) return undefined; + + return lastPageParameter + 1; + }, + initialPageParam: 1, + queryFn, + queryKey: ['orders', variables, 'infinite'], + staleTime: 60 * 1_000, + }); +}; + export const useOrderMutation = ({ documentId, }: Pick[0], 'documentId'>) => {