api ulandi

This commit is contained in:
Samandar Turgunboyev
2025-10-25 18:42:01 +05:00
parent 1a08775451
commit 05b752daf2
84 changed files with 11179 additions and 3724 deletions

View File

@@ -0,0 +1,351 @@
import {
hotelFeatureCreate,
hotelFeatureDelete,
hotelFeatureDetail,
hotelFeatureUpdate,
} from "@/pages/tours/lib/api";
import { FeatureColumns } from "@/pages/tours/lib/column";
import type { HotelFeatures } from "@/pages/tours/lib/type";
import { Button } from "@/shared/ui/button";
import { Dialog, DialogContent } from "@/shared/ui/dialog";
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/shared/ui/form";
import { Input } from "@/shared/ui/input";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/shared/ui/table";
import RealPagination from "@/widgets/real-pagination/ui/RealPagination";
import { zodResolver } from "@hookform/resolvers/zod";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import {
flexRender,
getCoreRowModel,
useReactTable,
} from "@tanstack/react-table";
import { Loader, PlusIcon } from "lucide-react";
import { useEffect, useState, type Dispatch, type SetStateAction } from "react";
import { useForm } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";
import z from "zod";
const formSchema = z.object({
name: z.string().min(1, { message: "Majburiy maydon" }),
name_ru: z.string().min(1, { message: "Majburiy maydon" }),
});
const FeaturesTable = ({
data,
page,
pageSize,
setActiveTab,
setFeatureId,
}: {
page: number;
pageSize: number;
setActiveTab: Dispatch<SetStateAction<string>>;
setFeatureId: Dispatch<SetStateAction<number | null>>;
data:
| {
links: {
previous: string;
next: string;
};
total_items: number;
total_pages: number;
page_size: number;
current_page: number;
results: HotelFeatures[];
}
| undefined;
}) => {
const { t } = useTranslation();
const [open, setOpen] = useState<boolean>(false);
const [editId, setEditId] = useState<number | null>(null);
const queryClient = useQueryClient();
const [types, setTypes] = useState<"edit" | "create">("create");
const handleEdit = (id: number) => {
setTypes("edit");
setOpen(true);
setEditId(id);
};
const { data: badgeDetail } = useQuery({
queryKey: ["detail_feature", editId],
queryFn: () => hotelFeatureDetail({ id: editId! }),
enabled: !!editId,
});
const { mutate: deleteMutate } = useMutation({
mutationFn: ({ id }: { id: number }) => hotelFeatureDelete({ id }),
onSuccess: () => {
queryClient.refetchQueries({ queryKey: ["detail_feature"] });
queryClient.refetchQueries({ queryKey: ["all_feature"] });
setOpen(false);
form.reset();
},
onError: () => {
toast.error(t("Xatolik yuz berdi"), {
position: "top-center",
richColors: true,
});
},
});
const handleDelete = (id: number) => {
deleteMutate({ id });
};
const columns = FeatureColumns(
handleEdit,
handleDelete,
t,
setActiveTab,
setFeatureId,
);
const { mutate: create, isPending } = useMutation({
mutationFn: ({
body,
}: {
body: {
hotel_feature_type_name: string;
hotel_feature_type_name_ru: string;
};
}) => hotelFeatureCreate({ body }),
onSuccess: () => {
queryClient.refetchQueries({ queryKey: ["detail_feature"] });
queryClient.refetchQueries({ queryKey: ["all_feature"] });
setOpen(false);
form.reset();
},
onError: () => {
toast.error(t("Xatolik yuz berdi"), {
position: "top-center",
richColors: true,
});
},
});
const { mutate: update, isPending: updatePending } = useMutation({
mutationFn: ({
body,
id,
}: {
id: number;
body: {
hotel_feature_type_name: string;
hotel_feature_type_name_ru: string;
};
}) => hotelFeatureUpdate({ body, id }),
onSuccess: () => {
queryClient.refetchQueries({ queryKey: ["detail_feature"] });
queryClient.refetchQueries({ queryKey: ["all_feature"] });
setOpen(false);
form.reset();
},
onError: () => {
toast.error(t("Xatolik yuz berdi"), {
position: "top-center",
richColors: true,
});
},
});
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
name: "",
name_ru: "",
},
});
useEffect(() => {
if (badgeDetail) {
form.setValue("name", badgeDetail.data.data.hotel_feature_type_name);
form.setValue(
"name_ru",
badgeDetail.data.data.hotel_feature_type_name_ru,
);
}
}, [editId, badgeDetail]);
function onSubmit(values: z.infer<typeof formSchema>) {
if (types === "create") {
create({
body: {
hotel_feature_type_name: values.name,
hotel_feature_type_name_ru: values.name_ru,
},
});
} else if (types === "edit" && editId) {
update({
id: editId,
body: {
hotel_feature_type_name: values.name,
hotel_feature_type_name_ru: values.name_ru,
},
});
}
}
const table = useReactTable({
data: data?.results ?? [],
columns,
getCoreRowModel: getCoreRowModel(),
manualPagination: true,
pageCount: data?.total_pages ?? 0,
state: {
pagination: {
pageIndex: page - 1,
pageSize: pageSize,
},
},
});
return (
<>
<div className="flex justify-end">
<Button
variant="default"
onClick={() => {
setOpen(true);
setTypes("create");
form.reset();
}}
>
<PlusIcon className="mr-2" />
{t("Qoshish")}
</Button>
</div>
<div className="border border-gray-700 rounded-md overflow-hidden mt-4">
<Table key={data?.current_page}>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext(),
)}
</TableHead>
))}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<TableRow key={row.id}>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext(),
)}
</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell
colSpan={columns.length}
className="h-24 text-center text-gray-400"
>
{t("Ma'lumot topilmadi")}
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
<RealPagination
table={table}
totalPages={data?.total_pages}
namePage="pageFeature"
namePageSize="pageSizeFeature"
/>
<Dialog open={open} onOpenChange={setOpen}>
<DialogContent>
<p className="text-xl">
{types === "create" ? t("Saqlash") : t("Tahrirlash")}
</p>
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-6 p-2"
>
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormLabel>{t("Nomi")}</FormLabel>
<FormControl>
<Input placeholder={t("Nomi")} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="name_ru"
render={({ field }) => (
<FormItem>
<FormLabel>{t("Nomi (ru)")}</FormLabel>
<FormControl>
<Input placeholder={t("Nomi (ru)")} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<div className="flex justify-end gap-4">
<Button
type="button"
onClick={() => setOpen(false)}
className="border-slate-600 text-white hover:bg-gray-600 bg-gray-600"
>
{t("Bekor qilish")}
</Button>
<Button type="submit">
{isPending || updatePending ? (
<Loader className="animate-spin" />
) : types === "create" ? (
t("Saqlash")
) : (
t("Tahrirlash")
)}
</Button>
</div>
</form>
</Form>
</DialogContent>
</Dialog>
</>
);
};
export default FeaturesTable;