- {[...Array(category?.total_pages)].map((_, i) => (
-
- ))}
+ {[...Array(category?.total_pages)].map((_, i) => {
+ const pageNum = i + 1;
+ return (
+
+ );
+ })}
diff --git a/src/pages/finance/ui/Finance.tsx b/src/pages/finance/ui/Finance.tsx
index e4f6319..dbf815c 100644
--- a/src/pages/finance/ui/Finance.tsx
+++ b/src/pages/finance/ui/Finance.tsx
@@ -40,28 +40,23 @@ export default function FinancePage({ user }: { user: Role }) {
const [searchParams, setSearchParams] = useSearchParams();
const tabParam = searchParams.get("tab") as "bookings" | "agencies" | null;
const pageParam = Number(searchParams.get("page")) || 1;
+ const filterParam = String(searchParams.get("filter")) || "";
const pageAgencyParam = Number(searchParams.get("page_agency")) || 1;
const [currentPage, setCurrentPage] = useState(pageParam);
const [currentPageAgency, setCurrentPageAgency] = useState(pageAgencyParam);
const [tab, setTab] = useState<"bookings" | "agencies">(
tabParam ?? "bookings",
);
- const [filterStatus, setFilterStatus] = useState<
- | ""
- | "pending_payment"
- | "pending_confirmation"
- | "confirmed"
- | "completed"
- | "cancelled"
- >("");
+ const [filterStatus, setFilterStatus] = useState(filterParam);
useEffect(() => {
setSearchParams({
tab,
page: String(currentPage),
page_agency: String(currentPageAgency),
+ filter: String(filterStatus),
});
- }, [tab, currentPage, currentPageAgency, setSearchParams]);
+ }, [tab, currentPage, currentPageAgency, setSearchParams, filterStatus]);
useEffect(() => {
if (tabParam && tabParam !== tab) {
@@ -69,18 +64,19 @@ export default function FinancePage({ user }: { user: Role }) {
}
}, [tabParam]);
- useEffect(() => {
- setCurrentPage(1);
- setCurrentPageAgency(1);
- }, [filterStatus, tab]);
-
const { data, isLoading, isError, refetch } = useQuery({
queryKey: ["list_order_user", currentPage, filterStatus],
queryFn: () =>
getAllOrder({
page: currentPage,
- page_size: 10,
- order_status: filterStatus,
+ page_size: 12,
+ order_status: filterStatus as
+ | ""
+ | "pending_payment"
+ | "pending_confirmation"
+ | "confirmed"
+ | "completed"
+ | "cancelled",
}),
});
@@ -94,7 +90,7 @@ export default function FinancePage({ user }: { user: Role }) {
queryFn: () =>
getAllOrderAgecy({
page: currentPageAgency,
- page_size: 10,
+ page_size: 12,
}),
});
@@ -277,7 +273,7 @@ export default function FinancePage({ user }: { user: Role }) {
? "bg-blue-600 text-white shadow-md"
: "bg-gray-800 text-gray-300 hover:bg-gray-700"
}`}
- onClick={() =>
+ onClick={() => {
setFilterStatus(
s as
| ""
@@ -286,8 +282,9 @@ export default function FinancePage({ user }: { user: Role }) {
| "confirmed"
| "completed"
| "cancelled",
- )
- }
+ );
+ setCurrentPage(1);
+ }}
>
{s === ""
? t("Barcha bandlovlar")
diff --git a/src/pages/news/ui/News.tsx b/src/pages/news/ui/News.tsx
index 7185720..4f7109b 100644
--- a/src/pages/news/ui/News.tsx
+++ b/src/pages/news/ui/News.tsx
@@ -26,22 +26,31 @@ import {
} from "lucide-react";
import { useState } from "react";
import { useTranslation } from "react-i18next";
-import { useNavigate } from "react-router-dom";
+import { useNavigate, useSearchParams } from "react-router-dom";
import { toast } from "sonner";
const News = () => {
- const [currentPage, setCurrentPage] = useState(1);
+ const [searchParams, setSearchParams] = useSearchParams();
+
+ const initialPage = Number(searchParams.get("page")) || 1;
+ const [page, setPage] = useState(initialPage);
const { t } = useTranslation();
const [deleteId, setDeleteId] = useState
(null);
const queryClient = useQueryClient();
const navigate = useNavigate();
+
+ const updatePage = (newPage: number) => {
+ setPage(newPage);
+ setSearchParams({ page: newPage.toString() });
+ };
+
const {
data: allNews,
isLoading,
isError,
} = useQuery({
- queryKey: ["all_news", currentPage],
- queryFn: () => getAllNews({ page: currentPage, page_size: 10 }),
+ queryKey: ["all_news", page],
+ queryFn: () => getAllNews({ page, page_size: 12 }),
});
const { mutate: deleteMutate, isPending } = useMutation({
@@ -303,37 +312,38 @@ const News = () => {
{/* Pagination */}
-
+
- {[...Array(allNews?.data.data.total_pages)].map((_, i) => (
-
- ))}
+ {[...Array(allNews?.data.data.total_pages)].map((_, i) => {
+ const pageNum = i + 1;
+ return (
+
+ );
+ })}
diff --git a/src/pages/payout-request/ui/PayoutRequest.tsx b/src/pages/payout-request/ui/PayoutRequest.tsx
index 0d1783d..6c5f301 100644
--- a/src/pages/payout-request/ui/PayoutRequest.tsx
+++ b/src/pages/payout-request/ui/PayoutRequest.tsx
@@ -38,6 +38,7 @@ import {
} from "lucide-react";
import { useState } from "react";
import { useTranslation } from "react-i18next";
+import { useSearchParams } from "react-router-dom";
import { toast } from "sonner";
export default function WithdrawRequests({
@@ -53,7 +54,16 @@ export default function WithdrawRequests({
| "user";
}) {
const queryClient = useQueryClient();
- const [currentPage, setCurrentPage] = useState(1);
+ const [searchParams, setSearchParams] = useSearchParams();
+
+ const initialPage = Number(searchParams.get("page")) || 1;
+ const [page, setPage] = useState(initialPage);
+
+ const updatePage = (newPage: number) => {
+ setPage(newPage);
+ setSearchParams({ page: newPage.toString() });
+ };
+
const [statusFilter, setStatusFilter] = useState<
"pending" | "approved" | "cancelled" | ""
>("");
@@ -70,11 +80,11 @@ export default function WithdrawRequests({
const [closeId, setCloseId] = useState
(null);
const { data, isLoading, isError, refetch } = useQuery({
- queryKey: ["withdraw-requests", currentPage, statusFilter],
+ queryKey: ["withdraw-requests", page, statusFilter],
queryFn: () =>
getPayoutList({
- page: currentPage,
- page_size: 10,
+ page,
+ page_size: 20,
status: statusFilter,
}),
});
@@ -178,7 +188,7 @@ export default function WithdrawRequests({
key={tab.value}
onClick={() => {
setStatusFilter(tab.value);
- setCurrentPage(1);
+ updatePage(1);
}}
className={`rounded-xl px-4 py-2 font-medium transition-all ${
statusFilter === tab.value
@@ -360,37 +370,38 @@ export default function WithdrawRequests({
{/* 🔹 PAGINATION */}
-
+
- {[...Array(data?.data.data.total_pages)].map((_, i) => (
-
- ))}
+ {[...Array(data?.data.data.total_pages)].map((_, i) => {
+ const pageNum = i + 1;
+ return (
+
+ );
+ })}
diff --git a/src/pages/site-banner/ui/Banner.tsx b/src/pages/site-banner/ui/Banner.tsx
index 7aabaaa..e03b319 100644
--- a/src/pages/site-banner/ui/Banner.tsx
+++ b/src/pages/site-banner/ui/Banner.tsx
@@ -56,6 +56,7 @@ import {
import { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { useTranslation } from "react-i18next";
+import { useSearchParams } from "react-router-dom";
import { toast } from "sonner";
import { z } from "zod";
@@ -92,15 +93,24 @@ const positions = [
];
const SiteBannerAdmin = () => {
- const [currentPage, setCurrentPage] = useState(1);
+ const [searchParams, setSearchParams] = useSearchParams();
+
+ const initialPage = Number(searchParams.get("page")) || 1;
+ const [page, setPage] = useState(initialPage);
+
+ const updatePage = (newPage: number) => {
+ setPage(newPage);
+ setSearchParams({ page: newPage.toString() });
+ };
+
const {
data: banner,
isLoading,
isError,
refetch,
} = useQuery({
- queryKey: ["all_banner", currentPage],
- queryFn: () => getBanner({ page: currentPage, page_size: 10 }),
+ queryKey: ["all_banner", page],
+ queryFn: () => getBanner({ page, page_size: 20 }),
select(data) {
return data.data.data;
},
@@ -385,37 +395,38 @@ const SiteBannerAdmin = () => {
-
+
- {[...Array(banner?.total_pages)].map((_, i) => (
-
- ))}
+ {[...Array(banner?.total_pages)].map((_, i) => {
+ const pageNum = i + 1;
+ return (
+
+ );
+ })}
diff --git a/src/pages/support/ui/SupportAgency.tsx b/src/pages/support/ui/SupportAgency.tsx
index 5c87a9a..0bed2d3 100644
--- a/src/pages/support/ui/SupportAgency.tsx
+++ b/src/pages/support/ui/SupportAgency.tsx
@@ -15,15 +15,25 @@ import {
DialogTitle,
} from "@/shared/ui/dialog";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
-import { AlertTriangle, Loader2, XIcon } from "lucide-react";
+import {
+ AlertTriangle,
+ ChevronLeft,
+ ChevronRight,
+ Loader2,
+ XIcon,
+} from "lucide-react";
import { useState } from "react";
import { useTranslation } from "react-i18next";
-import { Link } from "react-router-dom";
+import { Link, useSearchParams } from "react-router-dom";
import { toast } from "sonner";
const SupportAgency = () => {
const [query, setQuery] = useState("");
const queryClient = useQueryClient();
+ const [searchParams, setSearchParams] = useSearchParams();
+
+ const initialPage = Number(searchParams.get("page")) || 1;
+ const [page, setPage] = useState(initialPage);
const [openUser, setOpenUser] = useState
(false);
const [user, setUser] = useState<{
status: boolean;
@@ -38,10 +48,15 @@ const SupportAgency = () => {
const { t } = useTranslation();
const [selected, setSelected] = useState(null);
+ const updatePage = (newPage: number) => {
+ setPage(newPage);
+ setSearchParams({ page: newPage.toString() });
+ };
+
const { data, isLoading, isError, refetch } = useQuery({
- queryKey: ["support_agency"],
+ queryKey: ["support_agency", page],
queryFn: () =>
- getSupportAgency({ page: 1, page_size: 10, search: "", status: "" }),
+ getSupportAgency({ page: page, page_size: 12, search: "", status: "" }),
});
const { mutate: updateTours } = useMutation({
@@ -117,7 +132,10 @@ const SupportAgency = () => {
setQuery(e.target.value)}
+ onChange={(e) => {
+ setQuery(e.target.value);
+ updatePage(1);
+ }}
placeholder={t("Qidiruv (ism, email yoki telefon)...")}
className="flex-1 p-2 border rounded-md focus:outline-none focus:ring"
/>
@@ -188,6 +206,43 @@ const SupportAgency = () => {
)}
+
+
+
+ {[...Array(data?.data.data.total_pages)].map((_, i) => {
+ const pageNum = i + 1;
+ return (
+
+ );
+ })}
+
+
+
+
{selected && (
) {
const formData = new FormData();
-
+ const tour = data ? data.data : null;
// Asosiy ma'lumotlar
formData.append("title", value.title);
formData.append("location_name", value.location_name);
@@ -315,7 +315,7 @@ const StepOne = ({
formData.append("hotel_meals_ru", value.hotel_meals_info_ru);
}
formData.append("duration_days", String(value.duration));
- formData.append("rating", String("0.0"));
+ formData.append("rating", tour ? String(tour.rating) : "0.0");
if (value.banner instanceof File) {
formData.append("image_banner", value.banner);
diff --git a/src/pages/tours/ui/Tours.tsx b/src/pages/tours/ui/Tours.tsx
index e565c50..25c496b 100644
--- a/src/pages/tours/ui/Tours.tsx
+++ b/src/pages/tours/ui/Tours.tsx
@@ -37,7 +37,7 @@ import {
} from "lucide-react";
import { useState } from "react";
import { useTranslation } from "react-i18next";
-import { useNavigate } from "react-router-dom";
+import { useNavigate, useSearchParams } from "react-router-dom";
import { toast } from "sonner";
type Role =
@@ -51,15 +51,17 @@ type Role =
const Tours = ({ user }: { user: Role }) => {
const { t } = useTranslation();
- const [page, setPage] = useState(1);
const [deleteId, setDeleteId] = useState
(null);
const [showPopularDialog, setShowPopularDialog] = useState(false);
const navigate = useNavigate();
const queryClient = useQueryClient();
+ const [searchParams, setSearchParams] = useSearchParams();
+ const initialPage = Number(searchParams.get("page")) || 1;
+ const [page, setPage] = useState(initialPage);
const { data, isLoading, isError, refetch } = useQuery({
queryKey: ["all_tours", page],
- queryFn: () => getAllTours({ page: page, page_size: 10 }),
+ queryFn: () => getAllTours({ page, page_size: 10 }),
});
const { data: popularTour } = useQuery({
@@ -110,6 +112,11 @@ const Tours = ({ user }: { user: Role }) => {
setShowPopularDialog(false);
};
+ const updatePage = (newPage: number) => {
+ setPage(newPage);
+ setSearchParams({ page: newPage.toString() });
+ };
+
if (isLoading) {
return (
@@ -343,32 +350,35 @@ const Tours = ({ user }: { user: Role }) => {
- {[...Array(data?.data.data.total_pages)].map((_, i) => (
-
- ))}
+
+ {[...Array(data?.data.data.total_pages)].map((_, i) => {
+ const pageNum = i + 1;
+ return (
+
+ );
+ })}
+
diff --git a/src/pages/tours/ui/ToursSetting.tsx b/src/pages/tours/ui/ToursSetting.tsx
index 7db0b91..ae7076e 100644
--- a/src/pages/tours/ui/ToursSetting.tsx
+++ b/src/pages/tours/ui/ToursSetting.tsx
@@ -25,6 +25,39 @@ import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { useNavigate, useSearchParams } from "react-router-dom";
+// Error Component
+const ErrorDisplay: React.FC<{ message: string; onRetry: () => void }> = ({
+ message,
+ onRetry,
+}) => {
+ const { t } = useTranslation();
+ return (
+
+
+
{message}
+
+
+ );
+};
+
+// Loading Component
+const LoadingDisplay: React.FC<{ message?: string }> = ({ message }) => {
+ const { t } = useTranslation();
+ return (
+
+
+
+ {message || t("Ma'lumotlar yuklanmoqda...")}
+
+
+ );
+};
+
const ToursSetting: React.FC = () => {
const { t } = useTranslation();
const [searchParams] = useSearchParams();
@@ -134,61 +167,12 @@ const ToursSetting: React.FC = () => {
isError: amenitiesError,
refetch: amenitiesRef,
} = useQuery({
- queryKey: ["all_amenities", page, pageSize],
- queryFn: () => getAllAmenities({ page, page_size: pageSize }),
+ queryKey: ["all_amenities", pageAmenities, pageSizeAmenities],
+ queryFn: () =>
+ getAllAmenities({ page: pageAmenities, page_size: pageSizeAmenities }),
select: (res) => res.data.data,
});
- if (
- isLoading ||
- tarifLoad ||
- transportLoad ||
- typeLoad ||
- featureLoad ||
- featureTypeLoad ||
- amenitiesLoad
- ) {
- return (
-
-
-
{t("Ma'lumotlar yuklanmoqda...")}
-
- );
- }
-
- if (
- isError ||
- tarifError ||
- transportError ||
- typeError ||
- featureError ||
- featureTypeError ||
- amenitiesError
- ) {
- return (
-
-
-
- {t("Ma'lumotlarni yuklashda xatolik yuz berdi.")}
-
-
-
- );
- }
-
const handleTabChange = (value: string) => {
setActiveTab(value);
navigate({
@@ -217,52 +201,121 @@ const ToursSetting: React.FC = () => {
-
+ {isLoading ? (
+
+ ) : isError ? (
+
+ ) : (
+
+ )}
+
-
+ {tarifLoad ? (
+
+ ) : tarifError ? (
+
+ ) : (
+
+ )}
+
-
+ {transportLoad ? (
+
+ ) : transportError ? (
+
+ ) : (
+
+ )}
+
-
+ {amenitiesLoad ? (
+
+ ) : amenitiesError ? (
+
+ ) : (
+
+ )}
+
-
+ {typeLoad ? (
+
+ ) : typeError ? (
+
+ ) : (
+
+ )}
+
-
+ {featureLoad ? (
+
+ ) : featureError ? (
+
+ ) : (
+
+ )}
+
-
+ {featureTypeLoad ? (
+
+ ) : featureTypeError ? (
+
+ ) : (
+
+ )}
diff --git a/src/pages/users/ui/User.tsx b/src/pages/users/ui/User.tsx
index bccce0a..7a0a489 100644
--- a/src/pages/users/ui/User.tsx
+++ b/src/pages/users/ui/User.tsx
@@ -18,20 +18,28 @@ import {
} from "lucide-react";
import { useState } from "react";
import { useTranslation } from "react-i18next";
-import { useNavigate } from "react-router-dom";
+import { useNavigate, useSearchParams } from "react-router-dom";
export default function UserList() {
const [searchQuery, setSearchQuery] = useState("");
- const [currentPage, setCurrentPage] = useState(1);
+ const [searchParams, setSearchParams] = useSearchParams();
+
+ const initialPage = Number(searchParams.get("page")) || 1;
+ const [page, setPage] = useState(initialPage);
const usersPerPage = 6;
const { t } = useTranslation();
const navigate = useNavigate();
+ const updatePage = (newPage: number) => {
+ setPage(newPage);
+ setSearchParams({ page: newPage.toString() });
+ };
+
const { data, isLoading, isError, refetch } = useQuery({
- queryKey: ["user_all", currentPage, searchQuery],
+ queryKey: ["user_all", page, searchQuery],
queryFn: () =>
getAllUsers({
- page: currentPage,
+ page,
page_size: usersPerPage,
search: searchQuery,
}),
@@ -119,7 +127,7 @@ export default function UserList() {
value={searchQuery}
onChange={(e) => {
setSearchQuery(e.target.value);
- setCurrentPage(1);
+ updatePage(1);
}}
className="w-full pl-14 pr-4 py-3 bg-slate-700/30 border border-slate-600/50 text-white placeholder-slate-400 rounded-xl focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
/>
@@ -214,41 +222,40 @@ export default function UserList() {
))}
-
+
- {[...Array(data?.data.data.total_pages)].map((_, i) => (
-
- ))}
+ {[...Array(data?.data.data.total_pages)].map((_, i) => {
+ const pageNum = i + 1;
+ return (
+
+ );
+ })}