From 46f640a7e0c2026c7629f0cd4cd01f7f4758bbe5 Mon Sep 17 00:00:00 2001 From: Fringg Date: Sat, 7 Mar 2026 07:04:56 +0300 Subject: [PATCH] fix: add pagination to campaigns list The campaigns page was fetching only the first 50 items with no way to load more. Switched from useQuery to useInfiniteQuery with a "Load more" button so all campaigns are accessible. --- src/locales/en.json | 1 + src/locales/ru.json | 1 + src/pages/AdminCampaigns.tsx | 36 ++++++++++++++++++++++++++++++++---- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/src/locales/en.json b/src/locales/en.json index a5065b9..5f7347f 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -2031,6 +2031,7 @@ "subtitle": "Manage advertising links", "createButton": "Create", "noData": "No ad campaigns", + "loadMore": "Load more", "bonusType": { "balance": "Balance", "subscription": "Subscription", diff --git a/src/locales/ru.json b/src/locales/ru.json index 4ddc25a..341951f 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -2545,6 +2545,7 @@ "subtitle": "Управление рекламными ссылками", "createButton": "Создать", "noData": "Нет рекламных кампаний", + "loadMore": "Загрузить ещё", "bonusType": { "balance": "Баланс", "subscription": "Подписка", diff --git a/src/pages/AdminCampaigns.tsx b/src/pages/AdminCampaigns.tsx index d6eae21..2d298f0 100644 --- a/src/pages/AdminCampaigns.tsx +++ b/src/pages/AdminCampaigns.tsx @@ -1,12 +1,14 @@ import { useState } from 'react'; import { useNavigate } from 'react-router'; -import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; +import { useInfiniteQuery, useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import i18n from '../i18n'; import { campaignsApi, CampaignListItem, CampaignBonusType } from '../api/campaigns'; import { PlusIcon, EditIcon, TrashIcon, CheckIcon, XIcon, ChartIcon } from '../components/icons'; import { usePlatform } from '../platform/hooks/usePlatform'; +const PAGE_SIZE = 50; + // Bonus type labels and colors const bonusTypeConfig: Record< CampaignBonusType, @@ -69,9 +71,20 @@ export default function AdminCampaigns() { const [deleteConfirm, setDeleteConfirm] = useState(null); // Queries - const { data: campaignsData, isLoading } = useQuery({ + const { + data: campaignsData, + isLoading, + hasNextPage, + fetchNextPage, + isFetchingNextPage, + } = useInfiniteQuery({ queryKey: ['admin-campaigns'], - queryFn: () => campaignsApi.getCampaigns(true), + queryFn: ({ pageParam = 0 }) => campaignsApi.getCampaigns(true, pageParam, PAGE_SIZE), + initialPageParam: 0, + getNextPageParam: (lastPage, allPages) => { + const loaded = allPages.reduce((sum, p) => sum + p.campaigns.length, 0); + return loaded < lastPage.total ? loaded : undefined; + }, }); const { data: overview } = useQuery({ @@ -96,7 +109,7 @@ export default function AdminCampaigns() { }, }); - const campaigns = campaignsData?.campaigns || []; + const campaigns = campaignsData?.pages.flatMap((p) => p.campaigns) ?? []; return (
@@ -261,6 +274,21 @@ export default function AdminCampaigns() {
))} + + {/* Load more */} + {hasNextPage && ( + + )} )}