Redo header and remove column selector
This commit is contained in:
@@ -58,14 +58,6 @@ const ProductGrid = ({
|
|||||||
direction: "desc",
|
direction: "desc",
|
||||||
});
|
});
|
||||||
const [searchQuery, setSearchQuery] = useState("");
|
const [searchQuery, setSearchQuery] = useState("");
|
||||||
const [columnVisibility, setColumnVisibility] = useState({
|
|
||||||
image: true,
|
|
||||||
name: true,
|
|
||||||
totalQuantity: true,
|
|
||||||
totalRevenue: true,
|
|
||||||
orderCount: true,
|
|
||||||
price: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchProducts();
|
fetchProducts();
|
||||||
@@ -210,11 +202,20 @@ const ProductGrid = ({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
|
<div className="relative hidden sm:block">
|
||||||
|
<Search className="absolute left-2 top-2.5 h-4 w-4 text-muted-foreground" />
|
||||||
|
<Input
|
||||||
|
placeholder="Search products..."
|
||||||
|
value={searchQuery}
|
||||||
|
onChange={(e) => setSearchQuery(e.target.value)}
|
||||||
|
className="pl-8 h-9 w-[200px]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<Select
|
<Select
|
||||||
value={selectedTimeRange}
|
value={selectedTimeRange}
|
||||||
onValueChange={handleTimeRangeChange}
|
onValueChange={handleTimeRangeChange}
|
||||||
>
|
>
|
||||||
<SelectTrigger className="w-[180px] h-9">
|
<SelectTrigger className="w-[120px] h-9">
|
||||||
<SelectValue placeholder="Select time range" />
|
<SelectValue placeholder="Select time range" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
@@ -270,53 +271,7 @@ const ProductGrid = ({
|
|||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
||||||
<CardContent className="p-6 pt-0 flex-1 overflow-hidden -mt-1">
|
<CardContent className="p-6 pt-0 flex-1 overflow-hidden -mt-1">
|
||||||
<div className="flex items-center justify-between mb-4 mt-1">
|
<div className="h-full">
|
||||||
<div className="relative max-w-sm">
|
|
||||||
<Search className="absolute left-2 top-2.5 h-4 w-4 text-muted-foreground" />
|
|
||||||
<Input
|
|
||||||
placeholder="Search products..."
|
|
||||||
value={searchQuery}
|
|
||||||
onChange={(e) => setSearchQuery(e.target.value)}
|
|
||||||
className="pl-8 h-9"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<DropdownMenu modal={false}>
|
|
||||||
<DropdownMenuTrigger asChild>
|
|
||||||
<Button variant="outline" size="sm" className="ml-auto h-9 hover:bg-muted/50 focus:ring-1 focus:ring-ring/30">
|
|
||||||
<Settings2 className="mr-2 h-4 w-4" />
|
|
||||||
View
|
|
||||||
</Button>
|
|
||||||
</DropdownMenuTrigger>
|
|
||||||
<DropdownMenuContent
|
|
||||||
align="end"
|
|
||||||
className="w-[150px] mt-2 border-border/40"
|
|
||||||
sideOffset={5}
|
|
||||||
>
|
|
||||||
<DropdownMenuLabel>Toggle columns</DropdownMenuLabel>
|
|
||||||
<DropdownMenuSeparator className="bg-border/40" />
|
|
||||||
{Object.entries(columnVisibility).map(([column, isVisible]) => (
|
|
||||||
<DropdownMenuCheckboxItem
|
|
||||||
key={column}
|
|
||||||
className="capitalize"
|
|
||||||
checked={isVisible}
|
|
||||||
onCheckedChange={(value) =>
|
|
||||||
setColumnVisibility(prev => ({
|
|
||||||
...prev,
|
|
||||||
[column]: value
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{column === 'totalQuantity' ? 'Sold' :
|
|
||||||
column === 'totalRevenue' ? 'Revenue' :
|
|
||||||
column === 'orderCount' ? 'Orders' :
|
|
||||||
column}
|
|
||||||
</DropdownMenuCheckboxItem>
|
|
||||||
))}
|
|
||||||
</DropdownMenuContent>
|
|
||||||
</DropdownMenu>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="h-[calc(100%-3.5rem)]">
|
|
||||||
{loading && !products.length ? (
|
{loading && !products.length ? (
|
||||||
<LoadingState />
|
<LoadingState />
|
||||||
) : error ? (
|
) : error ? (
|
||||||
@@ -337,10 +292,7 @@ const ProductGrid = ({
|
|||||||
<table className="w-full">
|
<table className="w-full">
|
||||||
<thead>
|
<thead>
|
||||||
<tr className="hover:bg-transparent">
|
<tr className="hover:bg-transparent">
|
||||||
{columnVisibility.image && (
|
|
||||||
<th className="p-1.5 text-left font-medium sticky top-0 bg-white dark:bg-background z-10 w-[50px] min-w-[50px] border-b" />
|
<th className="p-1.5 text-left font-medium sticky top-0 bg-white dark:bg-background z-10 w-[50px] min-w-[50px] border-b" />
|
||||||
)}
|
|
||||||
{columnVisibility.name && (
|
|
||||||
<th className="p-1.5 text-left font-medium sticky top-0 bg-white dark:bg-background z-10 min-w-[200px] border-b">
|
<th className="p-1.5 text-left font-medium sticky top-0 bg-white dark:bg-background z-10 min-w-[200px] border-b">
|
||||||
<button
|
<button
|
||||||
onClick={() => handleSort("name")}
|
onClick={() => handleSort("name")}
|
||||||
@@ -354,8 +306,6 @@ const ProductGrid = ({
|
|||||||
Product
|
Product
|
||||||
</button>
|
</button>
|
||||||
</th>
|
</th>
|
||||||
)}
|
|
||||||
{columnVisibility.totalQuantity && (
|
|
||||||
<th className="p-1.5 font-medium text-center sticky top-0 bg-white dark:bg-background z-10 border-b">
|
<th className="p-1.5 font-medium text-center sticky top-0 bg-white dark:bg-background z-10 border-b">
|
||||||
<button
|
<button
|
||||||
onClick={() => handleSort("totalQuantity")}
|
onClick={() => handleSort("totalQuantity")}
|
||||||
@@ -369,8 +319,6 @@ const ProductGrid = ({
|
|||||||
Sold
|
Sold
|
||||||
</button>
|
</button>
|
||||||
</th>
|
</th>
|
||||||
)}
|
|
||||||
{columnVisibility.totalRevenue && (
|
|
||||||
<th className="p-1.5 font-medium text-center sticky top-0 bg-white dark:bg-background z-10 border-b">
|
<th className="p-1.5 font-medium text-center sticky top-0 bg-white dark:bg-background z-10 border-b">
|
||||||
<button
|
<button
|
||||||
onClick={() => handleSort("totalRevenue")}
|
onClick={() => handleSort("totalRevenue")}
|
||||||
@@ -384,8 +332,6 @@ const ProductGrid = ({
|
|||||||
Rev
|
Rev
|
||||||
</button>
|
</button>
|
||||||
</th>
|
</th>
|
||||||
)}
|
|
||||||
{columnVisibility.orderCount && (
|
|
||||||
<th className="p-1.5 font-medium text-center sticky top-0 bg-white dark:bg-background z-10 border-b">
|
<th className="p-1.5 font-medium text-center sticky top-0 bg-white dark:bg-background z-10 border-b">
|
||||||
<button
|
<button
|
||||||
onClick={() => handleSort("orderCount")}
|
onClick={() => handleSort("orderCount")}
|
||||||
@@ -399,8 +345,6 @@ const ProductGrid = ({
|
|||||||
Orders
|
Orders
|
||||||
</button>
|
</button>
|
||||||
</th>
|
</th>
|
||||||
)}
|
|
||||||
{columnVisibility.price && (
|
|
||||||
<th className="p-1.5 font-medium text-center sticky top-0 bg-white dark:bg-background z-10 hidden md:table-cell border-b">
|
<th className="p-1.5 font-medium text-center sticky top-0 bg-white dark:bg-background z-10 hidden md:table-cell border-b">
|
||||||
<button
|
<button
|
||||||
onClick={() => handleSort("price")}
|
onClick={() => handleSort("price")}
|
||||||
@@ -414,7 +358,6 @@ const ProductGrid = ({
|
|||||||
Price
|
Price
|
||||||
</button>
|
</button>
|
||||||
</th>
|
</th>
|
||||||
)}
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody className="divide-y divide-gray-200 dark:divide-gray-800">
|
<tbody className="divide-y divide-gray-200 dark:divide-gray-800">
|
||||||
@@ -423,7 +366,6 @@ const ProductGrid = ({
|
|||||||
key={product.id}
|
key={product.id}
|
||||||
className="hover:bg-muted/50 transition-colors"
|
className="hover:bg-muted/50 transition-colors"
|
||||||
>
|
>
|
||||||
{columnVisibility.image && (
|
|
||||||
<td className="p-1 align-middle w-[50px]">
|
<td className="p-1 align-middle w-[50px]">
|
||||||
{product.ImgThumb && (
|
{product.ImgThumb && (
|
||||||
<img
|
<img
|
||||||
@@ -436,8 +378,6 @@ const ProductGrid = ({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
)}
|
|
||||||
{columnVisibility.name && (
|
|
||||||
<td className="p-1 align-middle min-w-[200px]">
|
<td className="p-1 align-middle min-w-[200px]">
|
||||||
<div className="flex flex-col min-w-0">
|
<div className="flex flex-col min-w-0">
|
||||||
<a
|
<a
|
||||||
@@ -450,27 +390,18 @@ const ProductGrid = ({
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
)}
|
|
||||||
{columnVisibility.totalQuantity && (
|
|
||||||
<td className="p-1 align-middle text-center text-sm font-medium">
|
<td className="p-1 align-middle text-center text-sm font-medium">
|
||||||
{product.totalQuantity}
|
{product.totalQuantity}
|
||||||
</td>
|
</td>
|
||||||
)}
|
|
||||||
{columnVisibility.totalRevenue && (
|
|
||||||
<td className="p-1 align-middle text-center text-emerald-600 dark:text-emerald-400 text-sm font-medium">
|
<td className="p-1 align-middle text-center text-emerald-600 dark:text-emerald-400 text-sm font-medium">
|
||||||
${product.totalRevenue.toFixed(2)}
|
${product.totalRevenue.toFixed(2)}
|
||||||
</td>
|
</td>
|
||||||
)}
|
|
||||||
{columnVisibility.orderCount && (
|
|
||||||
<td className="p-1 align-middle text-center text-muted-foreground text-sm">
|
<td className="p-1 align-middle text-center text-muted-foreground text-sm">
|
||||||
{product.orderCount}
|
{product.orderCount}
|
||||||
</td>
|
</td>
|
||||||
)}
|
|
||||||
{columnVisibility.price && (
|
|
||||||
<td className="p-1 align-middle text-center hidden md:table-cell text-sm">
|
<td className="p-1 align-middle text-center hidden md:table-cell text-sm">
|
||||||
${product.price.toFixed(2)}
|
${product.price.toFixed(2)}
|
||||||
</td>
|
</td>
|
||||||
)}
|
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
Reference in New Issue
Block a user