diff --git a/src/pages/finance/lib/type.ts b/src/pages/finance/lib/type.ts index df51f29..64a41ee 100644 --- a/src/pages/finance/lib/type.ts +++ b/src/pages/finance/lib/type.ts @@ -28,6 +28,12 @@ export interface UserOrderData { tour_name: string; }[]; total_income: string; + awaiting_payments: string; + awaiting_payments_count: string; + confirmed_order: string; + pending_confirmation: string; + completed_order: string; + cancelled_order: string; }; }; } diff --git a/src/pages/finance/ui/Finance.tsx b/src/pages/finance/ui/Finance.tsx index a48c835..44bdf13 100644 --- a/src/pages/finance/ui/Finance.tsx +++ b/src/pages/finance/ui/Finance.tsx @@ -8,32 +8,177 @@ import { Button } from "@/shared/ui/button"; import { useQuery } from "@tanstack/react-query"; import { AlertTriangle, + CheckCircle, + ChevronLeft, + ChevronRight, + Clock, CreditCard, DollarSign, Eye, - Hotel, Loader2, MapPin, Plane, TrendingUp, Users, + XCircle, } from "lucide-react"; import { useState } from "react"; import { useTranslation } from "react-i18next"; import { Link } from "react-router-dom"; +type Purchase = { + id: number; + userName: string; + userPhone: string; + tourName: string; + tourId: number; + agencyName: string; + agencyId: number; + destination: string; + travelDate: string; + amount: number; + paymentStatus: "paid" | "pending" | "cancelled" | "refunded"; + purchaseDate: string; +}; + +const mockPurchases: Purchase[] = [ + { + id: 1, + userName: "Aziza Karimova", + userPhone: "+998 90 123 45 67", + tourName: "Dubai Luxury Tour", + tourId: 1, + agencyName: "Silk Road Travel", + agencyId: 1, + destination: "Dubai, UAE", + travelDate: "2025-11-10", + amount: 1500000, + paymentStatus: "paid", + purchaseDate: "2025-10-10", + }, + { + id: 2, + userName: "Sardor Rahimov", + userPhone: "+998 91 234 56 78", + tourName: "Bali Adventure Package", + tourId: 2, + agencyName: "Silk Road Travel", + agencyId: 1, + destination: "Bali, Indonesia", + travelDate: "2025-11-15", + amount: 1800000, + paymentStatus: "paid", + purchaseDate: "2025-10-12", + }, + { + id: 3, + userName: "Nilufar Toshmatova", + userPhone: "+998 93 345 67 89", + tourName: "Dubai Luxury Tour", + tourId: 1, + agencyName: "Silk Road Travel", + agencyId: 1, + destination: "Dubai, UAE", + travelDate: "2025-11-20", + amount: 1500000, + paymentStatus: "pending", + purchaseDate: "2025-10-14", + }, + { + id: 4, + userName: "Jamshid Alimov", + userPhone: "+998 94 456 78 90", + tourName: "Istanbul Express Tour", + tourId: 3, + agencyName: "Orient Express", + agencyId: 3, + destination: "Istanbul, Turkey", + travelDate: "2025-11-05", + amount: 1200000, + paymentStatus: "cancelled", + purchaseDate: "2025-10-08", + }, + { + id: 5, + userName: "Madina Yusupova", + userPhone: "+998 97 567 89 01", + tourName: "Paris Romantic Getaway", + tourId: 4, + agencyName: "Euro Travels", + agencyId: 2, + destination: "Paris, France", + travelDate: "2025-12-01", + amount: 2200000, + paymentStatus: "paid", + purchaseDate: "2025-10-16", + }, +]; + export default function FinancePage() { const { t } = useTranslation(); + const [currentPage, setCurrentPage] = useState(1); const [tab, setTab] = useState<"bookings" | "agencies">("bookings"); const [filterStatus, setFilterStatus] = useState< "all" | "paid" | "pending" | "cancelled" | "refunded" >("all"); const { data, isLoading, isError, refetch } = useQuery({ - queryKey: ["list_order_user"], - queryFn: () => getAllOrder({ page: 1, page_size: 10 }), + queryKey: ["list_order_user", currentPage], + queryFn: () => getAllOrder({ page: currentPage, page_size: 10 }), }); + const stats = [ + { + title: t("Jami daromad"), + value: data?.data.data.results.total_income ?? "0", + description: t("Yakunlangan bandlovlardan"), + icon: , + color: "text-green-400", + }, + { + title: t("Kutilayotgan to‘lovlar"), + value: data?.data.data.results.awaiting_payments ?? "0", + description: t("Tasdiqlash kutilmoqda"), + icon: , + color: "text-yellow-400", + }, + { + title: t("Kutilayotgan to‘lovlar soni"), + value: data?.data.data.results.awaiting_payments_count ?? "0", + description: t("To‘lov kutilayotgan buyurtmalar soni"), + icon: , + color: "text-orange-400", + }, + { + title: t("Tasdiqlangan buyurtmalar"), + value: data?.data.data.results.confirmed_order ?? "0", + description: t("Tasdiqlangan bandlovlar soni"), + icon: , + color: "text-blue-400", + }, + { + title: t("Kutilayotgan tasdiqlar"), + value: data?.data.data.results.pending_confirmation ?? "0", + description: t("Hali tasdiqlanmagan bandlovlar"), + icon: , + color: "text-purple-400", + }, + { + title: t("Yakunlangan buyurtmalar"), + value: data?.data.data.results.completed_order ?? "0", + description: t("Muvaffaqiyatli yakunlangan buyurtmalar"), + icon: , + color: "text-emerald-400", + }, + { + title: t("Bekor qilingan buyurtmalar"), + value: data?.data.data.results.cancelled_order ?? "0", + description: t("Bekor qilingan bandlovlar soni"), + icon: , + color: "text-red-400", + }, + ]; + const getStatusBadge = (status: OrderStatus["order_status"]) => { const base = "px-3 py-1 rounded-full text-sm font-medium inline-flex items-center gap-2"; @@ -120,6 +265,26 @@ export default function FinancePage() { ); } + const agencies = Array.from( + new Set(mockPurchases.map((p) => p.agencyId)), + ).map((id) => { + const agencyPurchases = mockPurchases.filter((p) => p.agencyId === id); + return { + id, + name: agencyPurchases[0].agencyName, + totalPaid: agencyPurchases + .filter((p) => p.paymentStatus === "paid") + .reduce((sum, p) => sum + p.amount, 0), + pending: agencyPurchases + .filter((p) => p.paymentStatus === "pending") + .reduce((sum, p) => sum + p.amount, 0), + purchaseCount: agencyPurchases.length, + destinations: Array.from( + new Set(agencyPurchases.map((p) => p.destination)), + ), + }; + }); + return (
@@ -201,70 +366,24 @@ export default function FinancePage() {
{/* Stats */} -
-
-
-

- {t("Jami daromad")} +

+ {stats.map((item, index) => ( +
+
+

{item.title}

+ {item.icon} +
+

+ {Number(item.value).toLocaleString()}

- -
-

- {/* {formatPrice(totalRevenue, true)} */} -

-

- {t("Yakunlangan bandlovlardan")} -

-
-
-
-

- {t("Kutilayotgan to‘lovlar")} +

+ {item.description}

-
-

- {/* {formatPrice(pendingRevenue, true)} */} -

-

- {t("Tasdiqlash kutilmoqda")} -

-
-
-
-

- {t("Tasdiqlangan bandlovlar")} -

- -
-

- {/* { - filteredPurchases.filter((p) => p.paymentStatus === "paid") - .length - } */} -

-

- {t("Tasdiqlangan bandlovlar")} -

-
-
-
-

- {t("Kutilayotgan bandlovlar")} -

- -
-

- {/* { - filteredPurchases.filter( - (p) => p.paymentStatus === "pending", - ).length - } */} -

-

- {t("Kutilayotgan to‘lovlar")} -

-
+ ))}
{/* Booking Cards */} @@ -321,10 +440,45 @@ export default function FinancePage() {
))}
+
+ + + {[...Array(data?.data.data.total_pages)].map((_, i) => ( + + ))} + + +
)} - {/* {tab === "agencies" && ( + {tab === "agencies" && ( <>

Partner Agencies

@@ -380,7 +534,7 @@ export default function FinancePage() { ))}
- )} */} + )}
); diff --git a/src/pages/finance/ui/FinanceDetailUsers.tsx b/src/pages/finance/ui/FinanceDetailUsers.tsx index 7853f40..2f91d9e 100644 --- a/src/pages/finance/ui/FinanceDetailUsers.tsx +++ b/src/pages/finance/ui/FinanceDetailUsers.tsx @@ -61,11 +61,12 @@ export default function FinanceDetailUser() { }; }) => updateDetailOrder({ body, id }), onSuccess: () => { + queryClient.refetchQueries({ queryKey: ["detail_order"] }); + queryClient.refetchQueries({ queryKey: ["list_order_user"] }); toast.success(t("Status muvaffaqiyatli yangilandi"), { richColors: true, position: "top-center", }); - queryClient.invalidateQueries({ queryKey: ["detail_order"] }); }, onError: () => { toast.error(t("Statusni yangilashda xatolik yuz berdi"), { diff --git a/src/pages/support/ui/SupportTours.tsx b/src/pages/support/ui/SupportTours.tsx index 9b5170c..d689008 100644 --- a/src/pages/support/ui/SupportTours.tsx +++ b/src/pages/support/ui/SupportTours.tsx @@ -89,32 +89,6 @@ const SupportTours = () => { }); }; - if (isLoading) { - return ( -
- -

{t("Ma'lumotlar yuklanmoqda...")}

-
- ); - } - - if (isError) { - return ( -
- -

- {t("Ma'lumotlarni yuklashda xatolik yuz berdi.")} -

- -
- ); - } - return (

@@ -141,76 +115,100 @@ const SupportTours = () => { ))}

- - {/* Cards */} -
- {data && data.data.data.results.length === 0 ? ( -
-

{t("Natija topilmadi")}

-
- ) : ( - data?.data.data.results.map((req) => ( - - -
- - - {req.name} - + {isError ? ( +
+ +

+ {t("Ma'lumotlarni yuklashda xatolik yuz berdi.")} +

+ +
+ ) : ( + <> + {isLoading ? ( +
+ +

+ {t("Ma'lumotlar yuklanmoqda...")} +

+
+ ) : ( +
+ {data && data.data.data.results.length === 0 ? ( +
+

{t("Natija topilmadi")}

- - - {req.status === "pending" ? t("Kutilmoqda") : t("done")} - - - - - {req.travel_agency !== null ? ( - - {t("Agentlikka tegishli")} - - ) : ( - - {t("Sayt bo'yicha")} - - )} -
- - {formatPhone(req.phone_number)} -
-
- - -
-
- - )) - )} -
+ +
+ + + {req.name} + +
+ + + {req.status === "pending" ? t("Kutilmoqda") : t("done")} + +
+ + + {req.travel_agency !== null ? ( + + {t("Agentlikka tegishli")} + + ) : ( + + {t("Sayt bo'yicha")} + + )} +
+ + {formatPhone(req.phone_number)} +
+
+ + +
+
+ + )) + )} +
+ )} + + )} {/* Detail Modal */} setSelected(null)}>