From 39f5b8ca3c36e8436f15f4d672680ec1f78ce7eb Mon Sep 17 00:00:00 2001 From: Samandar Turgunboyev Date: Thu, 30 Oct 2025 18:28:17 +0500 Subject: [PATCH] booking --- src/pages/faq/ui/Faq.tsx | 55 +++++- src/pages/finance/lib/api.ts | 7 + src/pages/finance/ui/Finance.tsx | 62 ++++--- src/pages/seo/lib/types.ts | 30 ++-- src/pages/seo/ui/Seo.tsx | 140 ++++++++++++++- src/pages/site-page/lib/api.ts | 18 +- src/pages/site-page/lib/types.ts | 4 + src/pages/site-page/ui/PolicyCrud.tsx | 130 +++++++++++--- src/pages/site-page/ui/SitePage.tsx | 179 ++++++++++++++++---- src/pages/support/ui/SupportTours.tsx | 64 ++++++- src/pages/tour-settings/lib/api.ts | 4 + src/pages/tour-settings/lib/types.ts | 4 + src/pages/tour-settings/ui/TourSettings.tsx | 68 +++++++- 13 files changed, 650 insertions(+), 115 deletions(-) diff --git a/src/pages/faq/ui/Faq.tsx b/src/pages/faq/ui/Faq.tsx index b1e4c70..72efba4 100644 --- a/src/pages/faq/ui/Faq.tsx +++ b/src/pages/faq/ui/Faq.tsx @@ -44,6 +44,7 @@ import { useQueryClient, } from "@tanstack/react-query"; import { + ChevronLeft, ChevronRight, Loader2, Pencil, @@ -66,6 +67,7 @@ const faqForm = z.object({ const Faq = () => { const [activeTab, setActiveTab] = useState(""); + const [currentPage, setCurrentPage] = useState(1); const { t } = useTranslation(); const [openModal, setOpenModal] = useState(false); const [editFaq, setEditFaq] = useState(null); @@ -94,17 +96,24 @@ const Faq = () => { initialPageParam: 1, }); - // Barcha kategoriyalarni birlashtirib olish + useEffect(() => { + setCurrentPage(1); + }, [activeTab]); + const category = categoryData?.pages.flatMap((page) => page.data.data.results) ?? []; const { data: faq } = useQuery({ - queryKey: ["all_faq", activeTab], + queryKey: ["all_faq", activeTab, currentPage], queryFn: () => { - return getAllFaq({ page: 1, page_size: 10, category: Number(activeTab) }); + return getAllFaq({ + page: currentPage, + page_size: 10, + category: Number(activeTab), + }); }, select(data) { - return data.data.data.results; + return data.data.data; }, enabled: !!activeTab, }); @@ -323,7 +332,7 @@ const Faq = () => { {/* Tabs content */} {category.map((cat) => ( - {faq && faq?.length > 0 ? ( + {faq && faq?.results.length > 0 ? (
@@ -337,7 +346,7 @@ const Faq = () => { - {faq.map((faq, index) => ( + {faq.results.map((faq, index) => ( {index + 1} @@ -380,6 +389,40 @@ const Faq = () => { ))} +
+ + + {[...Array(faq?.total_pages)].map((_, i) => ( + + ))} + + +
+ diff --git a/src/pages/finance/lib/api.ts b/src/pages/finance/lib/api.ts index e94e376..9d7d1b8 100644 --- a/src/pages/finance/lib/api.ts +++ b/src/pages/finance/lib/api.ts @@ -9,6 +9,13 @@ import type { AxiosResponse } from "axios"; const getAllOrder = async (params: { page: number; page_size: number; + order_status: + | "pending_payment" + | "pending_confirmation" + | "cancelled" + | "confirmed" + | "completed" + | ""; }): Promise> => { const res = await httpClient.get(USER_ORDERS, { params }); return res; diff --git a/src/pages/finance/ui/Finance.tsx b/src/pages/finance/ui/Finance.tsx index 44bdf13..2599c1b 100644 --- a/src/pages/finance/ui/Finance.tsx +++ b/src/pages/finance/ui/Finance.tsx @@ -22,7 +22,7 @@ import { Users, XCircle, } from "lucide-react"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { Link } from "react-router-dom"; @@ -119,12 +119,26 @@ export default function FinancePage() { const [currentPage, setCurrentPage] = useState(1); const [tab, setTab] = useState<"bookings" | "agencies">("bookings"); const [filterStatus, setFilterStatus] = useState< - "all" | "paid" | "pending" | "cancelled" | "refunded" - >("all"); + | "" + | "pending_payment" + | "pending_confirmation" + | "confirmed" + | "completed" + | "cancelled" + >(""); + + useEffect(() => { + setCurrentPage(1); + }, [filterStatus]); const { data, isLoading, isError, refetch } = useQuery({ - queryKey: ["list_order_user", currentPage], - queryFn: () => getAllOrder({ page: currentPage, page_size: 10 }), + queryKey: ["list_order_user", currentPage, filterStatus], + queryFn: () => + getAllOrder({ + page: currentPage, + page_size: 10, + order_status: filterStatus, + }), }); const stats = [ @@ -333,7 +347,14 @@ export default function FinancePage() { <> {/* Filter */}
- {["all", "paid", "pending", "cancelled", "refunded"].map((s) => ( + {[ + "", + "pending_payment", + "pending_confirmation", + "confirmed", + "completed", + "cancelled", + ].map((s) => ( ))}
diff --git a/src/pages/seo/lib/types.ts b/src/pages/seo/lib/types.ts index a614055..7404c02 100644 --- a/src/pages/seo/lib/types.ts +++ b/src/pages/seo/lib/types.ts @@ -9,17 +9,15 @@ export interface AllSeoData { total_pages: number; page_size: number; current_page: number; - results: [ - { - id: number; - title: string; - description: string; - keywords: string; - og_title: string; - og_description: string; - og_image: string; - }, - ]; + results: { + id: number; + title: string; + description: string; + keywords: string; + og_title: string; + og_description: string; + og_image: string; + }[]; }; } @@ -28,10 +26,20 @@ export interface DetailSeoData { data: { id: number; title: string; + title_uz: string; + title_ru: string; description: string; + description_uz: string; + description_ru: string; keywords: string; + keywords_uz: string; + keywords_ru: string; og_title: string; + og_title_uz: string; + og_title_ru: string; og_description: string; + og_description_uz: string; + og_description_ru: string; og_image: string; }; } diff --git a/src/pages/seo/ui/Seo.tsx b/src/pages/seo/ui/Seo.tsx index 8389477..f65f449 100644 --- a/src/pages/seo/ui/Seo.tsx +++ b/src/pages/seo/ui/Seo.tsx @@ -24,20 +24,30 @@ import { toast } from "sonner"; type SeoData = { title: string; + title_ru: string; description: string; + description_ru: string; keywords: string; + keywords_ru: string; ogTitle: string; + ogTitle_ru: string; ogDescription: string; + ogDescription_ru: string; ogImage: File | null | string; }; export default function Seo() { const [formData, setFormData] = useState({ title: "", + title_ru: "", description: "", + description_ru: "", keywords: "", + keywords_ru: "", ogTitle: "", + ogTitle_ru: "", ogDescription: "", + ogDescription_ru: "", ogImage: null, }); const { t } = useTranslation(); @@ -52,6 +62,11 @@ export default function Seo() { }); setFormData({ description: "", + description_ru: "", + keywords_ru: "", + ogDescription_ru: "", + ogTitle_ru: "", + title_ru: "", keywords: "", ogDescription: "", ogImage: null, @@ -80,6 +95,11 @@ export default function Seo() { setEdit(null); setFormData({ description: "", + description_ru: "", + keywords_ru: "", + ogDescription_ru: "", + ogTitle_ru: "", + title_ru: "", keywords: "", ogDescription: "", ogImage: null, @@ -104,6 +124,11 @@ export default function Seo() { setEdit(null); setFormData({ description: "", + description_ru: "", + keywords_ru: "", + ogDescription_ru: "", + ogTitle_ru: "", + title_ru: "", keywords: "", ogDescription: "", ogImage: null, @@ -170,12 +195,17 @@ export default function Seo() { useEffect(() => { if (detailSeo) { setFormData({ - description: detailSeo.description, - keywords: detailSeo.keywords, - ogDescription: detailSeo.og_description, + description: detailSeo.description_uz, + keywords: detailSeo.keywords_uz, + ogDescription: detailSeo.og_description_uz, ogImage: detailSeo.og_image, - ogTitle: detailSeo.og_title, - title: detailSeo.title, + ogTitle: detailSeo.og_title_uz, + title: detailSeo.title_uz, + description_ru: detailSeo.description_ru, + keywords_ru: detailSeo.keywords_ru, + ogDescription_ru: detailSeo.og_description_ru, + ogTitle_ru: detailSeo.og_title_ru, + title_ru: detailSeo.title_ru, }); setImagePreview(detailSeo.og_image || null); } @@ -184,10 +214,15 @@ export default function Seo() { const handleSave = () => { const form = new FormData(); form.append("title", formData.title); + form.append("title_ru", formData.title_ru); form.append("description", formData.description); + form.append("description_ru", formData.description_ru); form.append("keywords", formData.keywords); + form.append("keywords_ru", formData.keywords_ru); form.append("og_title", formData.ogTitle); + form.append("og_title_ru", formData.ogTitle_ru); form.append("og_description", formData.ogDescription); + form.append("og_description_ru", formData.ogDescription_ru); // faqat File bo‘lsa qo‘shamiz if (formData.ogImage instanceof File) { @@ -250,6 +285,29 @@ export default function Seo() { +
+ + +
+ {isValidTitle && ( + + )} + {getTitleLength() > 0 && !isValidTitle && ( + + )} +
+
+ {/* Description */}
+
+ +