347 lines
11 KiB
TypeScript
347 lines
11 KiB
TypeScript
"use client";
|
||
|
||
import { Button } from "@/shared/ui/button";
|
||
import {
|
||
Dialog,
|
||
DialogContent,
|
||
DialogFooter,
|
||
DialogHeader,
|
||
DialogTitle,
|
||
} from "@/shared/ui/dialog";
|
||
import {
|
||
Form,
|
||
FormControl,
|
||
FormField,
|
||
FormItem,
|
||
FormMessage,
|
||
} from "@/shared/ui/form";
|
||
import { Input } from "@/shared/ui/input";
|
||
import { Label } from "@/shared/ui/label";
|
||
import {
|
||
Select,
|
||
SelectContent,
|
||
SelectGroup,
|
||
SelectItem,
|
||
SelectLabel,
|
||
SelectTrigger,
|
||
SelectValue,
|
||
} from "@/shared/ui/select";
|
||
import {
|
||
Table,
|
||
TableBody,
|
||
TableCell,
|
||
TableHead,
|
||
TableHeader,
|
||
TableRow,
|
||
} from "@/shared/ui/table";
|
||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/shared/ui/tabs";
|
||
import { Textarea } from "@/shared/ui/textarea";
|
||
import { zodResolver } from "@hookform/resolvers/zod";
|
||
import { Pencil, PlusCircle, Trash2 } from "lucide-react";
|
||
import { useEffect, useState } from "react";
|
||
import { useForm } from "react-hook-form";
|
||
import z from "zod";
|
||
|
||
type FaqType = {
|
||
id: number;
|
||
category: string;
|
||
question: string;
|
||
answer: string;
|
||
};
|
||
|
||
const categories = [
|
||
{ value: "umumiy", label: "Umumiy" },
|
||
{ value: "tolov", label: "To‘lov" },
|
||
{ value: "hujjatlar", label: "Hujjatlar" },
|
||
{ value: "sugurta", label: "Sug‘urta" },
|
||
];
|
||
|
||
const initialFaqs: FaqType[] = [
|
||
{
|
||
id: 1,
|
||
category: "umumiy",
|
||
question: "Sayohatni bron qilish uchun qanday to‘lov usullari mavjud?",
|
||
answer:
|
||
"Biz kredit karta, Payme, Click, va naqd to‘lovni qabul qilamiz. To‘lovlar 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 bog‘liq. Ba’zi sayohatlar uchun 24 soat oldin bekor qilsangiz, to‘liq qaytariladi.",
|
||
},
|
||
{
|
||
id: 3,
|
||
category: "hujjatlar",
|
||
question: "Pasport muddati tugasa sayohat qilish mumkinmi?",
|
||
answer:
|
||
"Yo‘q, pasport muddati kamida 6 oy amal qilishi kerak. Aks holda, mamlakatga kirish rad etiladi.",
|
||
},
|
||
{
|
||
id: 4,
|
||
category: "sugurta",
|
||
question: "Sayohat davomida sug‘urta kerakmi?",
|
||
answer:
|
||
"Ha, biz barcha mijozlarga sayohat sug‘urtasini tavsiya qilamiz. Bu favqulodda holatlarda yordam beradi.",
|
||
},
|
||
{
|
||
id: 5,
|
||
category: "tolov",
|
||
question: "To‘lovni bosqichma-bosqich amalga oshirish mumkinmi?",
|
||
answer: "Ha, ayrim yo‘nalishlar uchun bosqichli to‘lov mavjud.",
|
||
},
|
||
];
|
||
|
||
const faqForm = z.object({
|
||
categories: z.string().min(1, { message: "Majburiy maydon" }),
|
||
title: z.string().min(1, { message: "Majburiy maydon" }),
|
||
answer: z.string().min(1, { message: "Majburiy maydon" }),
|
||
});
|
||
|
||
const Faq = () => {
|
||
const [faqs, setFaqs] = useState<FaqType[]>(initialFaqs);
|
||
const [activeTab, setActiveTab] = useState("umumiy");
|
||
const [openModal, setOpenModal] = useState(false);
|
||
const [editFaq, setEditFaq] = useState<FaqType | null>(null);
|
||
const [deleteId, setDeleteId] = useState<number | null>(null);
|
||
|
||
const filteredFaqs = faqs.filter((faq) => faq.category === activeTab);
|
||
|
||
const form = useForm<z.infer<typeof faqForm>>({
|
||
resolver: zodResolver(faqForm),
|
||
defaultValues: {
|
||
answer: "",
|
||
categories: "",
|
||
title: "",
|
||
},
|
||
});
|
||
|
||
function onSubmit(value: z.infer<typeof faqForm>) {
|
||
console.log(value);
|
||
}
|
||
|
||
const handleEdit = (faq: FaqType) => {
|
||
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);
|
||
}
|
||
};
|
||
|
||
useEffect(() => {
|
||
if (!openModal) {
|
||
form.reset();
|
||
setEditFaq(null);
|
||
}
|
||
}, [openModal, form]);
|
||
|
||
return (
|
||
<div className="p-6 space-y-6 w-full">
|
||
{/* Header */}
|
||
<div className="flex items-center justify-between">
|
||
<h1 className="text-2xl font-semibold">FAQ (Savol va javoblar)</h1>
|
||
<Button
|
||
className="gap-2"
|
||
onClick={() => {
|
||
setEditFaq(null);
|
||
setOpenModal(true);
|
||
}}
|
||
>
|
||
<PlusCircle className="w-4 h-4" /> Yangi qo‘shish
|
||
</Button>
|
||
</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}
|
||
</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>Savol</TableHead>
|
||
<TableHead>Javob</TableHead>
|
||
<TableHead className="w-[120px] text-center">
|
||
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>
|
||
</TableRow>
|
||
))}
|
||
</TableBody>
|
||
</Table>
|
||
</div>
|
||
) : (
|
||
<p className="text-gray-500 text-sm mt-4">
|
||
Bu bo‘limda savollar yo‘q.
|
||
</p>
|
||
)}
|
||
</TabsContent>
|
||
</Tabs>
|
||
|
||
<Dialog open={openModal} onOpenChange={setOpenModal}>
|
||
<DialogContent className="sm:max-w-[500px] bg-gray-900">
|
||
<DialogHeader>
|
||
<DialogTitle>
|
||
{editFaq ? "FAQni tahrirlash" : "Yangi FAQ qo‘shish"}
|
||
</DialogTitle>
|
||
</DialogHeader>
|
||
|
||
<Form {...form}>
|
||
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
|
||
<FormField
|
||
control={form.control}
|
||
name="categories"
|
||
render={({ field }) => (
|
||
<FormItem>
|
||
<Label className="text-md">Kategoriya</Label>
|
||
<FormControl>
|
||
<Select
|
||
onValueChange={field.onChange}
|
||
value={field.value}
|
||
>
|
||
<SelectTrigger className="w-full !h-12 border-gray-700 text-white">
|
||
<SelectValue placeholder="Kategoriya tanlang" />
|
||
</SelectTrigger>
|
||
<SelectContent className="border-gray-700 text-white">
|
||
<SelectGroup>
|
||
<SelectLabel>Kategoriyalar</SelectLabel>
|
||
{categories.map((cat) => (
|
||
<SelectItem key={cat.value} value={cat.value}>
|
||
{cat.label}
|
||
</SelectItem>
|
||
))}
|
||
</SelectGroup>
|
||
</SelectContent>
|
||
</Select>
|
||
</FormControl>
|
||
<FormMessage />
|
||
</FormItem>
|
||
)}
|
||
/>
|
||
<FormField
|
||
control={form.control}
|
||
name="title"
|
||
render={({ field }) => (
|
||
<FormItem>
|
||
<Label className="text-md">Savol</Label>
|
||
<FormControl>
|
||
<Input
|
||
placeholder="Savol"
|
||
{...field}
|
||
className="h-12 !text-md bg-gray-800 border-gray-700 text-white"
|
||
/>
|
||
</FormControl>
|
||
<FormMessage />
|
||
</FormItem>
|
||
)}
|
||
/>
|
||
<FormField
|
||
control={form.control}
|
||
name="answer"
|
||
render={({ field }) => (
|
||
<FormItem>
|
||
<Label className="text-md">Javob</Label>
|
||
<FormControl>
|
||
<Textarea
|
||
placeholder="Javob"
|
||
{...field}
|
||
className="min-h-48 max-h-56 !text-md bg-gray-800 border-gray-700 text-white"
|
||
/>
|
||
</FormControl>
|
||
<FormMessage />
|
||
</FormItem>
|
||
)}
|
||
/>
|
||
<div className="flex justify-between">
|
||
<Button
|
||
type="button"
|
||
onClick={() => {
|
||
setOpenModal(false);
|
||
form.reset();
|
||
}}
|
||
className="bg-gray-600 px-5 py-5 hover:bg-gray-700 text-white mt-4 cursor-pointer"
|
||
>
|
||
Bekor qilish
|
||
</Button>
|
||
<Button
|
||
type="submit"
|
||
className="bg-blue-600 px-5 py-5 hover:bg-blue-700 text-white mt-4 cursor-pointer"
|
||
>
|
||
{/* {isEditMode ? "Yangilikni saqlash" : "Keyingisi"} */}
|
||
Qo'shish
|
||
</Button>
|
||
</div>
|
||
</form>
|
||
</Form>
|
||
</DialogContent>
|
||
</Dialog>
|
||
|
||
<Dialog open={!!deleteId} onOpenChange={() => setDeleteId(null)}>
|
||
<DialogContent className="sm:max-w-[400px]">
|
||
<DialogHeader>
|
||
<DialogTitle>Haqiqatan ham o‘chirmoqchimisiz?</DialogTitle>
|
||
</DialogHeader>
|
||
<DialogFooter>
|
||
<Button variant="outline" onClick={() => setDeleteId(null)}>
|
||
Bekor qilish
|
||
</Button>
|
||
<Button variant="destructive" onClick={handleDelete}>
|
||
O‘chirish
|
||
</Button>
|
||
</DialogFooter>
|
||
</DialogContent>
|
||
</Dialog>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default Faq;
|