first commit
This commit is contained in:
346
src/pages/faq/ui/Faq.tsx
Normal file
346
src/pages/faq/ui/Faq.tsx
Normal file
@@ -0,0 +1,346 @@
|
||||
"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;
|
||||
Reference in New Issue
Block a user