update
This commit is contained in:
@@ -10,13 +10,9 @@ import { useState } from "react";
|
||||
|
||||
const CategoriesList = () => {
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [search, setSearch] = useState("");
|
||||
const [editingDistrict, setEditingDistrict] = useState<CategoryItem | null>(
|
||||
null,
|
||||
);
|
||||
|
||||
const { data, isLoading, isError } = useQuery({
|
||||
queryKey: ["categories", currentPage, search],
|
||||
queryKey: ["categories", currentPage],
|
||||
queryFn: () =>
|
||||
categories_api.list({
|
||||
page: currentPage,
|
||||
@@ -42,14 +38,7 @@ const CategoriesList = () => {
|
||||
<div className="flex flex-col md:flex-row justify-between items-start md:items-center mb-4 gap-4">
|
||||
<h1 className="text-2xl font-bold">Kategoriyalar ro‘yxati</h1>
|
||||
|
||||
<FilterCategory
|
||||
dialogOpen={dialogOpen}
|
||||
setDialogOpen={setDialogOpen}
|
||||
editing={editingDistrict}
|
||||
setEditing={setEditingDistrict}
|
||||
search={search}
|
||||
setSearch={setSearch}
|
||||
/>
|
||||
<FilterCategory />
|
||||
</div>
|
||||
|
||||
<TableDistrict
|
||||
@@ -58,7 +47,6 @@ const CategoriesList = () => {
|
||||
dialogOpen={dialogOpen}
|
||||
isLoading={isLoading}
|
||||
setDialogOpen={setDialogOpen}
|
||||
setEditingDistrict={setEditingDistrict}
|
||||
handleDelete={handleDelete}
|
||||
currentPage={currentPage}
|
||||
/>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { categories_api } from "@/features/districts/lib/api";
|
||||
import type { CategoryItem } from "@/features/plans/lib/data";
|
||||
import { Button } from "@/shared/ui/button";
|
||||
import {
|
||||
@@ -9,11 +8,8 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/shared/ui/dialog";
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import type { AxiosError } from "axios";
|
||||
import { Loader2, Trash, X } from "lucide-react";
|
||||
import { X } from "lucide-react";
|
||||
import { type Dispatch, type SetStateAction } from "react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
interface Props {
|
||||
opneDelete: boolean;
|
||||
@@ -22,32 +18,25 @@ interface Props {
|
||||
discrit: CategoryItem | null;
|
||||
}
|
||||
|
||||
const DeleteDiscrit = ({
|
||||
opneDelete,
|
||||
setOpenDelete,
|
||||
setDiscritDelete,
|
||||
discrit,
|
||||
}: Props) => {
|
||||
const queryClient = useQueryClient();
|
||||
const DeleteDiscrit = ({ opneDelete, setOpenDelete, discrit }: Props) => {
|
||||
// const { mutate: deleteDiscrict, isPending } = useMutation({
|
||||
// mutationFn: (id: string) => categories_api.delete(id),
|
||||
|
||||
const { mutate: deleteDiscrict, isPending } = useMutation({
|
||||
mutationFn: (id: string) => categories_api.delete(id),
|
||||
|
||||
onSuccess: () => {
|
||||
queryClient.refetchQueries({ queryKey: ["categories"] });
|
||||
toast.success(`Kategoriya o'chirildi`);
|
||||
setOpenDelete(false);
|
||||
setDiscritDelete(null);
|
||||
},
|
||||
onError: (err: AxiosError) => {
|
||||
const errMessage = err.response?.data as { message: string };
|
||||
const messageText = errMessage.message;
|
||||
toast.error(messageText || "Xatolik yuz berdi", {
|
||||
richColors: true,
|
||||
position: "top-center",
|
||||
});
|
||||
},
|
||||
});
|
||||
// onSuccess: () => {
|
||||
// queryClient.refetchQueries({ queryKey: ["categories"] });
|
||||
// toast.success(`Kategoriya o'chirildi`);
|
||||
// setOpenDelete(false);
|
||||
// setDiscritDelete(null);
|
||||
// },
|
||||
// onError: (err: AxiosError) => {
|
||||
// const errMessage = err.response?.data as { message: string };
|
||||
// const messageText = errMessage.message;
|
||||
// toast.error(messageText || "Xatolik yuz berdi", {
|
||||
// richColors: true,
|
||||
// position: "top-center",
|
||||
// });
|
||||
// },
|
||||
// });
|
||||
|
||||
return (
|
||||
<Dialog open={opneDelete} onOpenChange={setOpenDelete}>
|
||||
@@ -55,7 +44,7 @@ const DeleteDiscrit = ({
|
||||
<DialogHeader>
|
||||
<DialogTitle>Kategoriyani o'chirish</DialogTitle>
|
||||
<DialogDescription className="text-md font-semibold">
|
||||
Siz rostan ham {discrit?.name_uz} kategoriyani o'chirmoqchimisiz
|
||||
Siz rostan ham {discrit?.name} kategoriyani o'chirmoqchimisiz
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter>
|
||||
@@ -66,10 +55,7 @@ const DeleteDiscrit = ({
|
||||
<X />
|
||||
Bekor qilish
|
||||
</Button>
|
||||
<Button
|
||||
variant={"destructive"}
|
||||
onClick={() => discrit && deleteDiscrict(discrit.id)}
|
||||
>
|
||||
{/*<Button variant={"destructive"}>
|
||||
{isPending ? (
|
||||
<Loader2 className="animate-spin" />
|
||||
) : (
|
||||
@@ -78,7 +64,7 @@ const DeleteDiscrit = ({
|
||||
O'chirish
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</Button>*/}
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
@@ -25,7 +25,6 @@ interface Props {
|
||||
isError: boolean;
|
||||
handleDelete: (user: CategoryItem) => void;
|
||||
setDialogOpen: Dispatch<SetStateAction<boolean>>;
|
||||
setEditingDistrict: Dispatch<SetStateAction<CategoryItem | null>>;
|
||||
dialogOpen: boolean;
|
||||
currentPage: number;
|
||||
}
|
||||
|
||||
@@ -49,29 +49,26 @@ const AddedPlan = ({ initialValues, setDialogOpen }: Props) => {
|
||||
const form = useForm<z.infer<typeof createPlanFormData>>({
|
||||
resolver: zodResolver(createPlanFormData),
|
||||
defaultValues: {
|
||||
name_uz: initialValues?.name_uz || "",
|
||||
name_ru: initialValues?.name_ru || "",
|
||||
description_uz: initialValues?.description_uz || "",
|
||||
description_ru: initialValues?.description_ru || "",
|
||||
category_id: initialValues?.category || "",
|
||||
unity_id: initialValues?.unity || "",
|
||||
price: initialValues?.price || 0,
|
||||
quantity_left: initialValues?.quantity_left || 0,
|
||||
min_quantity: initialValues?.min_quantity || 0,
|
||||
is_active: initialValues?.is_active || false,
|
||||
name_uz: "",
|
||||
name_ru: "",
|
||||
description_uz: "",
|
||||
description_ru: "",
|
||||
category_id: "",
|
||||
unity_id: "",
|
||||
price: 0,
|
||||
quantity_left: 0,
|
||||
min_quantity: 0,
|
||||
is_active: false,
|
||||
images: [],
|
||||
article: initialValues?.article || "",
|
||||
brand: initialValues?.brand || "",
|
||||
code: initialValues?.code || "",
|
||||
manufacturer: initialValues?.manufacturer || "",
|
||||
volume: initialValues?.volume || "",
|
||||
article: "",
|
||||
brand: "",
|
||||
code: "",
|
||||
manufacturer: "",
|
||||
volume: "",
|
||||
},
|
||||
});
|
||||
const [openUser, setOpenUser] = useState<boolean>(false);
|
||||
const [openUnity, setOpenUnity] = useState<boolean>(false);
|
||||
const [initialImages, setInitialImages] = useState(
|
||||
initialValues?.images || [],
|
||||
);
|
||||
|
||||
const { mutate, isPending } = useMutation({
|
||||
mutationFn: (body: FormData) => plans_api.create(body),
|
||||
@@ -132,7 +129,6 @@ const AddedPlan = ({ initialValues, setDialogOpen }: Props) => {
|
||||
return data.data;
|
||||
},
|
||||
});
|
||||
const [removedImageIds, setRemovedImageIds] = useState<string[]>([]);
|
||||
|
||||
const onSubmit = (data: z.infer<typeof createPlanFormData>) => {
|
||||
const formData = new FormData();
|
||||
@@ -159,8 +155,7 @@ const AddedPlan = ({ initialValues, setDialogOpen }: Props) => {
|
||||
}
|
||||
|
||||
if (initialValues) {
|
||||
removedImageIds.map((e) => formData.append("delete_images", e));
|
||||
updated({ body: formData, id: initialValues.id });
|
||||
updated({ body: formData, id: initialValues.id.toString() });
|
||||
} else {
|
||||
mutate(formData);
|
||||
}
|
||||
@@ -260,9 +255,8 @@ const AddedPlan = ({ initialValues, setDialogOpen }: Props) => {
|
||||
!field.value && "text-muted-foreground",
|
||||
)}
|
||||
>
|
||||
{selectedUser &&
|
||||
typeof selectedUser.name_uz === "string"
|
||||
? selectedUser.name_uz
|
||||
{selectedUser && typeof selectedUser.name === "string"
|
||||
? selectedUser.name
|
||||
: "Kategoriyani tanlang"}
|
||||
</Button>
|
||||
</FormControl>
|
||||
@@ -297,7 +291,7 @@ const AddedPlan = ({ initialValues, setDialogOpen }: Props) => {
|
||||
: "opacity-0",
|
||||
)}
|
||||
/>
|
||||
{u.name_uz}
|
||||
{u.name}
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
@@ -589,10 +583,10 @@ const AddedPlan = ({ initialValues, setDialogOpen }: Props) => {
|
||||
<FormControl>
|
||||
<div className="space-y-3">
|
||||
{/* Agar initialValues'dan rasm bo'lsa ko'rsatish */}
|
||||
{initialValues?.image && !field.value && (
|
||||
{initialValues?.images && !field.value && (
|
||||
<div className="relative w-full h-48 border rounded-xl overflow-hidden">
|
||||
<img
|
||||
src={API_URLS.BASE_URL + initialValues.image}
|
||||
src={API_URLS.BASE_URL + initialValues.images[0].image}
|
||||
alt="Mavjud rasm"
|
||||
className="w-full h-full object-contain"
|
||||
/>
|
||||
@@ -619,7 +613,7 @@ const AddedPlan = ({ initialValues, setDialogOpen }: Props) => {
|
||||
>
|
||||
<Upload className="size-10 text-muted-foreground" />
|
||||
<p className="text-muted-foreground text-lg">
|
||||
{field.value || initialValues?.image
|
||||
{field.value || initialValues?.images
|
||||
? "Yangi rasm tanlash"
|
||||
: "Rasm tanlang"}
|
||||
</p>
|
||||
@@ -652,48 +646,6 @@ const AddedPlan = ({ initialValues, setDialogOpen }: Props) => {
|
||||
<FormLabel>Qo'shimcha rasmlar</FormLabel>
|
||||
<FormControl>
|
||||
<div className="space-y-3">
|
||||
{initialImages.length > 0 && (
|
||||
<div>
|
||||
<p className="text-sm text-gray-600 mb-2">
|
||||
Mavjud rasmlar:
|
||||
</p>
|
||||
<div className="grid grid-cols-7 gap-2 mb-3">
|
||||
{initialImages.map((img, idx) => (
|
||||
<div
|
||||
key={idx}
|
||||
className="relative border rounded-xl overflow-hidden"
|
||||
>
|
||||
<img
|
||||
src={API_URLS.BASE_URL + img.image}
|
||||
alt={`existing-${idx}`}
|
||||
className="h-14 w-14 object-cover"
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
const removed = initialImages[idx].id;
|
||||
setRemovedImageIds([
|
||||
...removedImageIds,
|
||||
removed,
|
||||
]);
|
||||
const updated = initialImages.filter(
|
||||
(_, i) => i !== idx,
|
||||
);
|
||||
setInitialImages(updated);
|
||||
}}
|
||||
className="absolute z-[99999] top-1 right-1 bg-red-500 hover:bg-red-600 text-white rounded-full cursor-pointer flex items-center justify-center w-4 h-4"
|
||||
>
|
||||
<XIcon className="size-3" />
|
||||
</Button>
|
||||
<div className="absolute bottom-0 left-0 right-0 bg-blue-500/80 text-white text-[10px] text-center py-0.5">
|
||||
Mavjud
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* FILE INPUT */}
|
||||
<Input
|
||||
type="file"
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { plans_api } from "@/features/plans/lib/api";
|
||||
import type { Product } from "@/features/plans/lib/data";
|
||||
import { Button } from "@/shared/ui/button";
|
||||
import {
|
||||
@@ -9,11 +8,8 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/shared/ui/dialog";
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import type { AxiosError } from "axios";
|
||||
import { Loader2, Trash, X } from "lucide-react";
|
||||
import { X } from "lucide-react";
|
||||
import type { Dispatch, SetStateAction } from "react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
interface Props {
|
||||
opneDelete: boolean;
|
||||
@@ -22,33 +18,7 @@ interface Props {
|
||||
planDelete: Product | null;
|
||||
}
|
||||
|
||||
const DeletePlan = ({
|
||||
opneDelete,
|
||||
setOpenDelete,
|
||||
planDelete,
|
||||
setPlanDelete,
|
||||
}: Props) => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const { mutate: deleteUser, isPending } = useMutation({
|
||||
mutationFn: (id: string) => plans_api.delete(id),
|
||||
|
||||
onSuccess: () => {
|
||||
queryClient.refetchQueries({ queryKey: ["product_list"] });
|
||||
toast.success(`Mahsulot o'chirildi`);
|
||||
setOpenDelete(false);
|
||||
setPlanDelete(null);
|
||||
},
|
||||
onError: (err: AxiosError) => {
|
||||
const errMessage = err.response?.data as { message: string };
|
||||
const messageText = errMessage.message;
|
||||
toast.error(messageText || "Xatolik yuz berdi", {
|
||||
richColors: true,
|
||||
position: "top-center",
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const DeletePlan = ({ opneDelete, setOpenDelete }: Props) => {
|
||||
return (
|
||||
<Dialog open={opneDelete} onOpenChange={setOpenDelete}>
|
||||
<DialogContent>
|
||||
@@ -66,19 +36,6 @@ const DeletePlan = ({
|
||||
<X />
|
||||
Bekor qilish
|
||||
</Button>
|
||||
<Button
|
||||
variant={"destructive"}
|
||||
onClick={() => planDelete && deleteUser(planDelete.id)}
|
||||
>
|
||||
{isPending ? (
|
||||
<Loader2 className="animate-spin" />
|
||||
) : (
|
||||
<>
|
||||
<Trash />
|
||||
O'chirish
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
Reference in New Issue
Block a user