product delete and user search
This commit is contained in:
@@ -1,8 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import type { Product } from "@/features/plans/lib/data";
|
||||
import { API_URLS } from "@/shared/config/api/URLs";
|
||||
import { Button } from "@/shared/ui/button";
|
||||
import { Checkbox } from "@/shared/ui/checkbox";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -11,18 +10,24 @@ import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/shared/ui/table";
|
||||
import { Eye, Loader2 } from "lucide-react";
|
||||
import { Eye, Loader2, Trash2 } from "lucide-react";
|
||||
import type { Dispatch, SetStateAction } from "react";
|
||||
|
||||
interface Props {
|
||||
products: Product[] | [];
|
||||
isLoading: boolean;
|
||||
isFetching: boolean;
|
||||
setIsAllPagesSelected: Dispatch<SetStateAction<boolean>>;
|
||||
isError: boolean;
|
||||
setEditingProduct: Dispatch<SetStateAction<Product | null>>;
|
||||
setDetailOpen: Dispatch<SetStateAction<boolean>>;
|
||||
setDialogOpen: Dispatch<SetStateAction<boolean>>;
|
||||
handleDelete: (product: Product) => void;
|
||||
selectedProducts: number[];
|
||||
setSelectedProducts: Dispatch<SetStateAction<number[]>>;
|
||||
handleBulkDelete: () => void;
|
||||
totalCount?: number;
|
||||
handleSelectAllPages: () => void;
|
||||
isAllPagesSelected: boolean;
|
||||
}
|
||||
|
||||
const ProductTable = ({
|
||||
@@ -31,7 +36,14 @@ const ProductTable = ({
|
||||
isFetching,
|
||||
isError,
|
||||
setEditingProduct,
|
||||
setIsAllPagesSelected,
|
||||
setDetailOpen,
|
||||
selectedProducts,
|
||||
setSelectedProducts,
|
||||
handleBulkDelete,
|
||||
totalCount = 0,
|
||||
handleSelectAllPages,
|
||||
isAllPagesSelected,
|
||||
}: Props) => {
|
||||
if (isLoading || isFetching) {
|
||||
return (
|
||||
@@ -49,11 +61,83 @@ const ProductTable = ({
|
||||
);
|
||||
}
|
||||
|
||||
const currentPageIds = products.map((p) => p.id);
|
||||
|
||||
const isAllSelected =
|
||||
isAllPagesSelected ||
|
||||
(products.length > 0 &&
|
||||
currentPageIds.every((id) => selectedProducts.includes(id)));
|
||||
|
||||
const isSomeSelected =
|
||||
currentPageIds.some((id) => selectedProducts.includes(id)) &&
|
||||
!currentPageIds.every((id) => selectedProducts.includes(id));
|
||||
|
||||
const handleSelectAll = (checked: boolean) => {
|
||||
if (checked) {
|
||||
setSelectedProducts(
|
||||
Array.from(new Set([...selectedProducts, ...currentPageIds])),
|
||||
);
|
||||
} else {
|
||||
setSelectedProducts(
|
||||
selectedProducts.filter((id) => !currentPageIds.includes(id)),
|
||||
);
|
||||
if (isAllPagesSelected) setIsAllPagesSelected(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSelectProduct = (productId: number, checked: boolean) => {
|
||||
if (checked) setSelectedProducts([...selectedProducts, productId]);
|
||||
else setSelectedProducts(selectedProducts.filter((id) => id !== productId));
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex-1 overflow-auto">
|
||||
{selectedProducts.length > 0 && (
|
||||
<div className="mb-4 space-y-2">
|
||||
<div className="flex items-center justify-between bg-blue-50 p-4 rounded-lg border border-blue-200">
|
||||
<span className="text-sm font-medium text-blue-900">
|
||||
{isAllPagesSelected
|
||||
? `Barcha ${totalCount} ta mahsulot tanlandi`
|
||||
: `${selectedProducts.length} ta mahsulot tanlandi`}
|
||||
</span>
|
||||
<div className="flex gap-2">
|
||||
{!isAllPagesSelected && totalCount > products.length && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={handleSelectAllPages}
|
||||
className="cursor-pointer border-blue-500 text-blue-700 hover:bg-blue-100"
|
||||
>
|
||||
Barcha {totalCount} ta mahsulotni tanlash
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
size="sm"
|
||||
variant="destructive"
|
||||
onClick={handleBulkDelete}
|
||||
className="cursor-pointer"
|
||||
>
|
||||
<Trash2 className="h-4 w-4 mr-2" />
|
||||
Tanlanganlarni o'chirish
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="w-[50px]">
|
||||
<Checkbox
|
||||
checked={isAllSelected}
|
||||
onCheckedChange={handleSelectAll}
|
||||
aria-label="Barchasini tanlash"
|
||||
className={
|
||||
isSomeSelected ? "data-[state=checked]:bg-blue-500" : ""
|
||||
}
|
||||
/>
|
||||
</TableHead>
|
||||
<TableHead>ID</TableHead>
|
||||
<TableHead>Rasmi</TableHead>
|
||||
<TableHead>Nomi</TableHead>
|
||||
@@ -61,54 +145,37 @@ const ProductTable = ({
|
||||
<TableHead className="text-end">Harakatlar</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
|
||||
<TableBody>
|
||||
{products.map((product, index) => {
|
||||
const isSelected = selectedProducts.includes(product.id);
|
||||
return (
|
||||
<TableRow key={product.id}>
|
||||
<TableCell>{index + 1}</TableCell>
|
||||
{product.images.length > 0 ? (
|
||||
<TableCell>
|
||||
<img
|
||||
src={API_URLS.BASE_URL + product.images[0].image}
|
||||
alt={product.name}
|
||||
className="w-16 h-16 object-cover rounded"
|
||||
/>
|
||||
</TableCell>
|
||||
) : (
|
||||
<TableCell>
|
||||
<img
|
||||
src={"/logo.png"}
|
||||
alt={product.name}
|
||||
className="w-10 h-10 object-cover rounded"
|
||||
/>
|
||||
</TableCell>
|
||||
)}
|
||||
<TableCell>{product.name}</TableCell>
|
||||
<TableRow
|
||||
key={product.id}
|
||||
className={isSelected ? "bg-blue-50" : ""}
|
||||
>
|
||||
<TableCell>
|
||||
{product.short_name && product.short_name.slice(0, 15)}...
|
||||
</TableCell>
|
||||
{/* <TableCell
|
||||
className={clsx(
|
||||
product.is_active ? "text-green-600" : "text-red-600",
|
||||
)}
|
||||
>
|
||||
<Select
|
||||
value={product.is_active ? "true" : "false"}
|
||||
onValueChange={(value) =>
|
||||
handleStatusChange(product.id, value as "true" | "false")
|
||||
<Checkbox
|
||||
checked={isSelected}
|
||||
onCheckedChange={(checked) =>
|
||||
handleSelectProduct(product.id, checked as boolean)
|
||||
}
|
||||
>
|
||||
<SelectTrigger className="w-[180px]">
|
||||
<SelectValue placeholder="Holati" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="true">Faol</SelectItem>
|
||||
<SelectItem value="false">Nofaol</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</TableCell> */}
|
||||
|
||||
aria-label={`${product.name} tanlash`}
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell>{index + 1}</TableCell>
|
||||
<TableCell>
|
||||
<img
|
||||
src={
|
||||
product.images.length > 0
|
||||
? API_URLS.BASE_URL + product.images[0].image
|
||||
: "/logo.png"
|
||||
}
|
||||
alt={product.name}
|
||||
className="w-16 h-16 object-cover rounded"
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell>{product.name}</TableCell>
|
||||
<TableCell>{product.short_name?.slice(0, 15)}...</TableCell>
|
||||
<TableCell className="space-x-2 text-right">
|
||||
<Button
|
||||
size="sm"
|
||||
@@ -120,37 +187,10 @@ const ProductTable = ({
|
||||
>
|
||||
<Eye className="h-4 w-4" />
|
||||
</Button>
|
||||
|
||||
{/*<Button
|
||||
size="sm"
|
||||
className="bg-blue-500 text-white hover:bg-blue-600"
|
||||
onClick={() => {
|
||||
setEditingProduct(product);
|
||||
setDialogOpen(true);
|
||||
}}
|
||||
>
|
||||
<Edit className="h-4 w-4" />
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
size="sm"
|
||||
variant="destructive"
|
||||
onClick={() => handleDelete(product)}
|
||||
>
|
||||
<Trash className="h-4 w-4" />
|
||||
</Button>*/}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
})}
|
||||
|
||||
{products.length === 0 && (
|
||||
<TableRow>
|
||||
<TableCell colSpan={8} className="text-center text-gray-500">
|
||||
Mahsulotlar topilmadi
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user