added tour

This commit is contained in:
Samandar Turgunboyev
2025-10-27 12:54:47 +05:00
parent eca7370833
commit a9e99f9755
10 changed files with 405 additions and 217 deletions

View File

@@ -1,5 +1,6 @@
"use client";
import { getAllFaq, getAllFaqCategory } from "@/pages/faq/lib/api";
import { Button } from "@/shared/ui/button";
import {
Dialog,
@@ -21,7 +22,6 @@ import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectLabel,
SelectTrigger,
SelectValue,
@@ -37,63 +37,13 @@ import {
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/shared/ui/tabs";
import { Textarea } from "@/shared/ui/textarea";
import { zodResolver } from "@hookform/resolvers/zod";
import { useQuery } from "@tanstack/react-query";
import { Pencil, PlusCircle, Trash2 } from "lucide-react";
import { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { useTranslation } from "react-i18next";
import z from "zod";
type FaqType = {
id: number;
category: string;
question: string;
answer: string;
};
const categories = [
{ value: "umumiy", label: "Umumiy" },
{ value: "tolov", label: "Tolov" },
{ value: "hujjatlar", label: "Hujjatlar" },
{ value: "sugurta", label: "Sugurta" },
];
const initialFaqs: FaqType[] = [
{
id: 1,
category: "umumiy",
question: "Sayohatni bron qilish uchun qanday tolov usullari mavjud?",
answer:
"Biz kredit karta, Payme, Click, va naqd tolovni qabul qilamiz. Tolovlar xavfsiz va ishonchli tizim orqali amalga oshiriladi.",
},
{
id: 2,
category: "umumiy",
question: "Sayohatni bekor qilsam, pul qaytariladimi?",
answer:
"Ha, ammo bu bron qilingan turdagi sayohatga bogliq. Bazi sayohatlar uchun 24 soat oldin bekor qilsangiz, toliq qaytariladi.",
},
{
id: 3,
category: "hujjatlar",
question: "Pasport muddati tugasa sayohat qilish mumkinmi?",
answer:
"Yoq, pasport muddati kamida 6 oy amal qilishi kerak. Aks holda, mamlakatga kirish rad etiladi.",
},
{
id: 4,
category: "sugurta",
question: "Sayohat davomida sugurta kerakmi?",
answer:
"Ha, biz barcha mijozlarga sayohat sugurtasini tavsiya qilamiz. Bu favqulodda holatlarda yordam beradi.",
},
{
id: 5,
category: "tolov",
question: "Tolovni bosqichma-bosqich amalga oshirish mumkinmi?",
answer: "Ha, ayrim yonalishlar uchun bosqichli tolov mavjud.",
},
];
const faqForm = z.object({
categories: z.string().min(1, { message: "Majburiy maydon" }),
title: z.string().min(1, { message: "Majburiy maydon" }),
@@ -101,14 +51,36 @@ const faqForm = z.object({
});
const Faq = () => {
const [faqs, setFaqs] = useState<FaqType[]>(initialFaqs);
const [activeTab, setActiveTab] = useState("umumiy");
const { t } = useTranslation();
const [openModal, setOpenModal] = useState(false);
const [editFaq, setEditFaq] = useState<FaqType | null>(null);
const [deleteId, setDeleteId] = useState<number | null>(null);
const { data: category } = useQuery({
queryKey: ["all_faqcategory"],
queryFn: () => {
return getAllFaqCategory({ page: 1, page_size: 99 });
},
select(data) {
return data.data.data.results;
},
});
const { data: faq } = useQuery({
queryKey: ["all_faq"],
queryFn: () => {
return getAllFaq({ page: 1, page_size: 99 });
},
select(data) {
return data.data.data.results;
},
});
const [activeTab, setActiveTab] = useState<string>("");
const filteredFaqs = faqs.filter((faq) => faq.category === activeTab);
useEffect(() => {
if (category) {
setActiveTab(String(category[0].id));
}
}, [category]);
const [deleteId, setDeleteId] = useState<number | null>(null);
const [editFaq, setEditFaq] = useState<any | null>(null);
const [openModal, setOpenModal] = useState(false);
const form = useForm<z.infer<typeof faqForm>>({
resolver: zodResolver(faqForm),
@@ -123,18 +95,12 @@ const Faq = () => {
console.log(value);
}
const handleEdit = (faq: FaqType) => {
const handleEdit = (faq: number) => {
setEditFaq(faq);
setOpenModal(true);
form.setValue("answer", faq.answer);
form.setValue("title", faq.question);
form.setValue("categories", faq.category);
};
const handleDelete = () => {
if (deleteId) {
setFaqs((prev) => prev.filter((faq) => faq.id !== deleteId));
setDeleteId(null);
}
};
@@ -164,70 +130,73 @@ const Faq = () => {
</div>
{/* Tabs */}
<Tabs value={activeTab} onValueChange={setActiveTab}>
<TabsList className="flex flex-wrap gap-2">
{categories.map((cat) => (
<TabsTrigger key={cat.value} value={cat.value}>
{cat.label}
<Tabs value={activeTab} onValueChange={setActiveTab} className="w-full">
<TabsList className="flex flex-wrap gap-2 mb-4">
{category?.map((cat) => (
<TabsTrigger key={cat.id} value={String(cat.id)}>
{cat.name}
</TabsTrigger>
))}
</TabsList>
<TabsContent value={activeTab} className="mt-4">
{filteredFaqs.length > 0 ? (
<div className="border rounded-md overflow-hidden shadow-sm">
<Table>
<TableHeader>
<TableRow>
<TableHead className="w-[50px] text-center">#</TableHead>
<TableHead>{t("Savol")}</TableHead>
<TableHead>{t("Javob")}</TableHead>
<TableHead className="w-[120px] text-center">
{t("Amallar")}
</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{filteredFaqs.map((faq, index) => (
<TableRow key={faq.id}>
<TableCell className="text-center font-medium">
{index + 1}
</TableCell>
<TableCell className="font-medium">
{faq.question}
</TableCell>
<TableCell className="text-foreground">
{faq.answer.length > 80
? faq.answer.slice(0, 80) + "..."
: faq.answer}
</TableCell>
<TableCell className="flex justify-center gap-2">
<Button
variant="outline"
size="icon"
onClick={() => handleEdit(faq)}
>
<Pencil className="w-4 h-4" />
</Button>
<Button
variant="destructive"
size="icon"
onClick={() => setDeleteId(faq.id)}
>
<Trash2 className="w-4 h-4" />
</Button>
</TableCell>
{/* Tabs content */}
{category?.map((cat) => (
<TabsContent key={cat.id} value={String(cat.id)}>
{faq && faq?.length > 0 ? (
<div className="border rounded-md overflow-hidden shadow-sm">
<Table>
<TableHeader>
<TableRow>
<TableHead className="w-[50px] text-center">#</TableHead>
<TableHead>{t("Savol")}</TableHead>
<TableHead>{t("Javob")}</TableHead>
<TableHead className="w-[120px] text-center">
{t("Amallar")}
</TableHead>
</TableRow>
))}
</TableBody>
</Table>
</div>
) : (
<p className="text-gray-500 text-sm mt-4">
{t("Bu bolimda savollar yoq.")}
</p>
)}
</TabsContent>
</TableHeader>
<TableBody>
{faq.map((faq, index) => (
<TableRow key={faq.id}>
<TableCell className="text-center font-medium">
{index + 1}
</TableCell>
<TableCell className="font-medium">
{faq.title}
</TableCell>
<TableCell className="text-foreground">
{faq.text.length > 80
? faq.text.slice(0, 80) + "..."
: faq.text}
</TableCell>
<TableCell className="flex justify-center gap-2">
<Button
variant="outline"
size="icon"
onClick={() => handleEdit(faq.id)}
>
<Pencil className="w-4 h-4" />
</Button>
<Button
variant="destructive"
size="icon"
onClick={() => setDeleteId(faq.id)}
>
<Trash2 className="w-4 h-4" />
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
) : (
<p className="text-gray-500 text-sm mt-4 text-center">
{t("Bu bolimda savollar yoq.")}
</p>
)}
</TabsContent>
))}
</Tabs>
<Dialog open={openModal} onOpenChange={setOpenModal}>
@@ -257,11 +226,11 @@ const Faq = () => {
<SelectContent className="border-gray-700 text-white">
<SelectGroup>
<SelectLabel>{t("Kategoriyalar")}</SelectLabel>
{categories.map((cat) => (
{/* {categories.map((cat) => (
<SelectItem key={cat.value} value={cat.value}>
{cat.label}
</SelectItem>
))}
))} */}
</SelectGroup>
</SelectContent>
</Select>