booking
This commit is contained in:
@@ -28,6 +28,12 @@ export interface UserOrderData {
|
|||||||
tour_name: string;
|
tour_name: string;
|
||||||
}[];
|
}[];
|
||||||
total_income: string;
|
total_income: string;
|
||||||
|
awaiting_payments: string;
|
||||||
|
awaiting_payments_count: string;
|
||||||
|
confirmed_order: string;
|
||||||
|
pending_confirmation: string;
|
||||||
|
completed_order: string;
|
||||||
|
cancelled_order: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,32 +8,177 @@ import { Button } from "@/shared/ui/button";
|
|||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import {
|
import {
|
||||||
AlertTriangle,
|
AlertTriangle,
|
||||||
|
CheckCircle,
|
||||||
|
ChevronLeft,
|
||||||
|
ChevronRight,
|
||||||
|
Clock,
|
||||||
CreditCard,
|
CreditCard,
|
||||||
DollarSign,
|
DollarSign,
|
||||||
Eye,
|
Eye,
|
||||||
Hotel,
|
|
||||||
Loader2,
|
Loader2,
|
||||||
MapPin,
|
MapPin,
|
||||||
Plane,
|
Plane,
|
||||||
TrendingUp,
|
TrendingUp,
|
||||||
Users,
|
Users,
|
||||||
|
XCircle,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Link } from "react-router-dom";
|
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() {
|
export default function FinancePage() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
const [tab, setTab] = useState<"bookings" | "agencies">("bookings");
|
const [tab, setTab] = useState<"bookings" | "agencies">("bookings");
|
||||||
const [filterStatus, setFilterStatus] = useState<
|
const [filterStatus, setFilterStatus] = useState<
|
||||||
"all" | "paid" | "pending" | "cancelled" | "refunded"
|
"all" | "paid" | "pending" | "cancelled" | "refunded"
|
||||||
>("all");
|
>("all");
|
||||||
|
|
||||||
const { data, isLoading, isError, refetch } = useQuery({
|
const { data, isLoading, isError, refetch } = useQuery({
|
||||||
queryKey: ["list_order_user"],
|
queryKey: ["list_order_user", currentPage],
|
||||||
queryFn: () => getAllOrder({ page: 1, page_size: 10 }),
|
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: <DollarSign className="text-green-400 w-6 h-6" />,
|
||||||
|
color: "text-green-400",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("Kutilayotgan to‘lovlar"),
|
||||||
|
value: data?.data.data.results.awaiting_payments ?? "0",
|
||||||
|
description: t("Tasdiqlash kutilmoqda"),
|
||||||
|
icon: <TrendingUp className="text-yellow-400 w-6 h-6" />,
|
||||||
|
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: <Clock className="text-orange-400 w-6 h-6" />,
|
||||||
|
color: "text-orange-400",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("Tasdiqlangan buyurtmalar"),
|
||||||
|
value: data?.data.data.results.confirmed_order ?? "0",
|
||||||
|
description: t("Tasdiqlangan bandlovlar soni"),
|
||||||
|
icon: <CreditCard className="text-blue-400 w-6 h-6" />,
|
||||||
|
color: "text-blue-400",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("Kutilayotgan tasdiqlar"),
|
||||||
|
value: data?.data.data.results.pending_confirmation ?? "0",
|
||||||
|
description: t("Hali tasdiqlanmagan bandlovlar"),
|
||||||
|
icon: <Clock className="text-purple-400 w-6 h-6" />,
|
||||||
|
color: "text-purple-400",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("Yakunlangan buyurtmalar"),
|
||||||
|
value: data?.data.data.results.completed_order ?? "0",
|
||||||
|
description: t("Muvaffaqiyatli yakunlangan buyurtmalar"),
|
||||||
|
icon: <CheckCircle className="text-emerald-400 w-6 h-6" />,
|
||||||
|
color: "text-emerald-400",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("Bekor qilingan buyurtmalar"),
|
||||||
|
value: data?.data.data.results.cancelled_order ?? "0",
|
||||||
|
description: t("Bekor qilingan bandlovlar soni"),
|
||||||
|
icon: <XCircle className="text-red-400 w-6 h-6" />,
|
||||||
|
color: "text-red-400",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const getStatusBadge = (status: OrderStatus["order_status"]) => {
|
const getStatusBadge = (status: OrderStatus["order_status"]) => {
|
||||||
const base =
|
const base =
|
||||||
"px-3 py-1 rounded-full text-sm font-medium inline-flex items-center gap-2";
|
"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 (
|
return (
|
||||||
<div className="min-h-screen w-full bg-gray-900 text-gray-100">
|
<div className="min-h-screen w-full bg-gray-900 text-gray-100">
|
||||||
<div className="w-[90%] mx-auto py-6">
|
<div className="w-[90%] mx-auto py-6">
|
||||||
@@ -201,70 +366,24 @@ export default function FinancePage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Stats */}
|
{/* Stats */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
<div className="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-6 mb-8">
|
||||||
<div className="bg-gray-800 p-6 rounded-xl shadow flex flex-col justify-between">
|
{stats.map((item, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
className="bg-gray-800 p-6 rounded-xl shadow flex flex-col justify-between transition-all hover:scale-[1.02]"
|
||||||
|
>
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<p className="text-gray-400 font-medium">
|
<p className="text-gray-400 font-medium">{item.title}</p>
|
||||||
{t("Jami daromad")}
|
{item.icon}
|
||||||
</p>
|
|
||||||
<DollarSign className="text-green-400 w-6 h-6" />
|
|
||||||
</div>
|
</div>
|
||||||
<p className="text-2xl font-bold text-green-400 mt-3">
|
<p className={`text-2xl font-bold mt-3 ${item.color}`}>
|
||||||
{/* {formatPrice(totalRevenue, true)} */}
|
{Number(item.value).toLocaleString()}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-sm text-gray-500 mt-1">
|
<p className="text-sm text-gray-500 mt-1">
|
||||||
{t("Yakunlangan bandlovlardan")}
|
{item.description}
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="bg-gray-800 p-6 rounded-xl shadow flex flex-col justify-between">
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<p className="text-gray-400 font-medium">
|
|
||||||
{t("Kutilayotgan to‘lovlar")}
|
|
||||||
</p>
|
|
||||||
<TrendingUp className="text-yellow-400 w-6 h-6" />
|
|
||||||
</div>
|
|
||||||
<p className="text-2xl font-bold text-yellow-400 mt-3">
|
|
||||||
{/* {formatPrice(pendingRevenue, true)} */}
|
|
||||||
</p>
|
|
||||||
<p className="text-sm text-gray-500 mt-1">
|
|
||||||
{t("Tasdiqlash kutilmoqda")}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="bg-gray-800 p-6 rounded-xl shadow flex flex-col justify-between">
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<p className="text-gray-400 font-medium">
|
|
||||||
{t("Tasdiqlangan bandlovlar")}
|
|
||||||
</p>
|
|
||||||
<CreditCard className="text-blue-400 w-6 h-6" />
|
|
||||||
</div>
|
|
||||||
<p className="text-2xl font-bold text-blue-400 mt-3">
|
|
||||||
{/* {
|
|
||||||
filteredPurchases.filter((p) => p.paymentStatus === "paid")
|
|
||||||
.length
|
|
||||||
} */}
|
|
||||||
</p>
|
|
||||||
<p className="text-sm text-gray-500 mt-1">
|
|
||||||
{t("Tasdiqlangan bandlovlar")}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="bg-gray-800 p-6 rounded-xl shadow flex flex-col justify-between">
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<p className="text-gray-400 font-medium">
|
|
||||||
{t("Kutilayotgan bandlovlar")}
|
|
||||||
</p>
|
|
||||||
<Hotel className="text-purple-400 w-6 h-6" />
|
|
||||||
</div>
|
|
||||||
<p className="text-2xl font-bold text-purple-400 mt-3">
|
|
||||||
{/* {
|
|
||||||
filteredPurchases.filter(
|
|
||||||
(p) => p.paymentStatus === "pending",
|
|
||||||
).length
|
|
||||||
} */}
|
|
||||||
</p>
|
|
||||||
<p className="text-sm text-gray-500 mt-1">
|
|
||||||
{t("Kutilayotgan to‘lovlar")}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Booking Cards */}
|
{/* Booking Cards */}
|
||||||
@@ -321,10 +440,45 @@ export default function FinancePage() {
|
|||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex justify-end gap-2 mt-5">
|
||||||
|
<button
|
||||||
|
disabled={currentPage === 1}
|
||||||
|
onClick={() => setCurrentPage((p) => Math.max(p - 1, 1))}
|
||||||
|
className="p-2 rounded-lg border border-slate-600 text-slate-300 hover:bg-slate-700/50 disabled:opacity-50 disabled:cursor-not-allowed transition-all hover:border-slate-500"
|
||||||
|
>
|
||||||
|
<ChevronLeft className="w-5 h-5" />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{[...Array(data?.data.data.total_pages)].map((_, i) => (
|
||||||
|
<button
|
||||||
|
key={i}
|
||||||
|
onClick={() => setCurrentPage(i + 1)}
|
||||||
|
className={`px-4 py-2 rounded-lg border transition-all font-medium ${
|
||||||
|
currentPage === i + 1
|
||||||
|
? "bg-gradient-to-r from-blue-600 to-cyan-600 border-blue-500 text-white shadow-lg shadow-cyan-500/50"
|
||||||
|
: "border-slate-600 text-slate-300 hover:bg-slate-700/50 hover:border-slate-500"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{i + 1}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<button
|
||||||
|
disabled={currentPage === data?.data.data.total_pages}
|
||||||
|
onClick={() =>
|
||||||
|
setCurrentPage((p) =>
|
||||||
|
Math.min(p + 1, data ? data?.data.data.total_pages : 0),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
className="p-2 rounded-lg border border-slate-600 text-slate-300 hover:bg-slate-700/50 disabled:opacity-50 disabled:cursor-not-allowed transition-all hover:border-slate-500"
|
||||||
|
>
|
||||||
|
<ChevronRight className="w-5 h-5" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* {tab === "agencies" && (
|
{tab === "agencies" && (
|
||||||
<>
|
<>
|
||||||
<h2 className="text-xl font-bold mb-6">Partner Agencies</h2>
|
<h2 className="text-xl font-bold mb-6">Partner Agencies</h2>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
@@ -380,7 +534,7 @@ export default function FinancePage() {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)} */}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -61,11 +61,12 @@ export default function FinanceDetailUser() {
|
|||||||
};
|
};
|
||||||
}) => updateDetailOrder({ body, id }),
|
}) => updateDetailOrder({ body, id }),
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
|
queryClient.refetchQueries({ queryKey: ["detail_order"] });
|
||||||
|
queryClient.refetchQueries({ queryKey: ["list_order_user"] });
|
||||||
toast.success(t("Status muvaffaqiyatli yangilandi"), {
|
toast.success(t("Status muvaffaqiyatli yangilandi"), {
|
||||||
richColors: true,
|
richColors: true,
|
||||||
position: "top-center",
|
position: "top-center",
|
||||||
});
|
});
|
||||||
queryClient.invalidateQueries({ queryKey: ["detail_order"] });
|
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: () => {
|
||||||
toast.error(t("Statusni yangilashda xatolik yuz berdi"), {
|
toast.error(t("Statusni yangilashda xatolik yuz berdi"), {
|
||||||
|
|||||||
@@ -89,32 +89,6 @@ const SupportTours = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isLoading) {
|
|
||||||
return (
|
|
||||||
<div className="flex flex-col items-center justify-center min-h-screen bg-slate-900 text-white gap-4 w-full">
|
|
||||||
<Loader2 className="w-10 h-10 animate-spin text-cyan-400" />
|
|
||||||
<p className="text-slate-400">{t("Ma'lumotlar yuklanmoqda...")}</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isError) {
|
|
||||||
return (
|
|
||||||
<div className="flex flex-col items-center justify-center min-h-screen bg-slate-900 w-full text-center text-white gap-4">
|
|
||||||
<AlertTriangle className="w-10 h-10 text-red-500" />
|
|
||||||
<p className="text-lg">
|
|
||||||
{t("Ma'lumotlarni yuklashda xatolik yuz berdi.")}
|
|
||||||
</p>
|
|
||||||
<Button
|
|
||||||
onClick={() => refetch()}
|
|
||||||
className="bg-gradient-to-r from-blue-600 to-cyan-600 text-white rounded-lg px-5 py-2 hover:opacity-90"
|
|
||||||
>
|
|
||||||
{t("Qayta urinish")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-gray-900 text-gray-100 p-6 space-y-6 w-full">
|
<div className="min-h-screen bg-gray-900 text-gray-100 p-6 space-y-6 w-full">
|
||||||
<h1 className="text-3xl font-bold tracking-tight mb-4 text-white">
|
<h1 className="text-3xl font-bold tracking-tight mb-4 text-white">
|
||||||
@@ -141,8 +115,29 @@ const SupportTours = () => {
|
|||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
{isError ? (
|
||||||
{/* Cards */}
|
<div className="flex flex-col items-center justify-center min-h-screen bg-slate-900 w-full text-center text-white gap-4">
|
||||||
|
<AlertTriangle className="w-10 h-10 text-red-500" />
|
||||||
|
<p className="text-lg">
|
||||||
|
{t("Ma'lumotlarni yuklashda xatolik yuz berdi.")}
|
||||||
|
</p>
|
||||||
|
<Button
|
||||||
|
onClick={() => refetch()}
|
||||||
|
className="bg-gradient-to-r from-blue-600 to-cyan-600 text-white rounded-lg px-5 py-2 hover:opacity-90"
|
||||||
|
>
|
||||||
|
{t("Qayta urinish")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{isLoading ? (
|
||||||
|
<div className="flex flex-col items-center justify-center min-h-screen bg-slate-900 text-white gap-4 w-full">
|
||||||
|
<Loader2 className="w-10 h-10 animate-spin text-cyan-400" />
|
||||||
|
<p className="text-slate-400">
|
||||||
|
{t("Ma'lumotlar yuklanmoqda...")}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
<div className="grid gap-5 sm:grid-cols-3 lg:grid-cols-3">
|
<div className="grid gap-5 sm:grid-cols-3 lg:grid-cols-3">
|
||||||
{data && data.data.data.results.length === 0 ? (
|
{data && data.data.data.results.length === 0 ? (
|
||||||
<div className="col-span-full flex flex-col items-center justify-center min-h-[50vh] w-full text-center text-white gap-4">
|
<div className="col-span-full flex flex-col items-center justify-center min-h-[50vh] w-full text-center text-white gap-4">
|
||||||
@@ -211,6 +206,9 @@ const SupportTours = () => {
|
|||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Detail Modal */}
|
{/* Detail Modal */}
|
||||||
<Dialog open={!!selected} onOpenChange={() => setSelected(null)}>
|
<Dialog open={!!selected} onOpenChange={() => setSelected(null)}>
|
||||||
|
|||||||
Reference in New Issue
Block a user