product delete and user search

This commit is contained in:
Samandar Turgunboyev
2026-01-28 13:26:15 +05:00
parent 10dbf1593b
commit a48a9318c8
11 changed files with 477 additions and 326 deletions

View File

@@ -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>