Redo header and remove column selector

This commit is contained in:
2024-12-21 18:59:46 -05:00
parent 350523c51c
commit 9ffec2ad15

View File

@@ -58,14 +58,6 @@ const ProductGrid = ({
direction: "desc",
});
const [searchQuery, setSearchQuery] = useState("");
const [columnVisibility, setColumnVisibility] = useState({
image: true,
name: true,
totalQuantity: true,
totalRevenue: true,
orderCount: true,
price: true,
});
useEffect(() => {
fetchProducts();
@@ -210,11 +202,20 @@ const ProductGrid = ({
)}
</div>
<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
value={selectedTimeRange}
onValueChange={handleTimeRangeChange}
>
<SelectTrigger className="w-[180px] h-9">
<SelectTrigger className="w-[120px] h-9">
<SelectValue placeholder="Select time range" />
</SelectTrigger>
<SelectContent>
@@ -270,53 +271,7 @@ const ProductGrid = ({
</CardHeader>
<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="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)]">
<div className="h-full">
{loading && !products.length ? (
<LoadingState />
) : error ? (
@@ -337,84 +292,72 @@ const ProductGrid = ({
<table className="w-full">
<thead>
<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" />
)}
{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">
<button
onClick={() => handleSort("name")}
className={cn(
"inline-flex items-center justify-start w-full px-2 py-1 text-sm font-medium transition-colors rounded-md",
sorting.column === "name"
? "bg-primary text-primary-foreground"
: "hover:bg-accent hover:text-accent-foreground"
)}
>
Product
</button>
</th>
)}
{columnVisibility.totalQuantity && (
<th className="p-1.5 font-medium text-center sticky top-0 bg-white dark:bg-background z-10 border-b">
<button
onClick={() => handleSort("totalQuantity")}
className={cn(
"inline-flex items-center justify-center w-full px-2 py-1 text-sm font-medium transition-colors rounded-md",
sorting.column === "totalQuantity"
? "bg-primary text-primary-foreground"
: "hover:bg-accent hover:text-accent-foreground"
)}
>
Sold
</button>
</th>
)}
{columnVisibility.totalRevenue && (
<th className="p-1.5 font-medium text-center sticky top-0 bg-white dark:bg-background z-10 border-b">
<button
onClick={() => handleSort("totalRevenue")}
className={cn(
"inline-flex items-center justify-center w-full px-2 py-1 text-sm font-medium transition-colors rounded-md",
sorting.column === "totalRevenue"
? "bg-primary text-primary-foreground"
: "hover:bg-accent hover:text-accent-foreground"
)}
>
Rev
</button>
</th>
)}
{columnVisibility.orderCount && (
<th className="p-1.5 font-medium text-center sticky top-0 bg-white dark:bg-background z-10 border-b">
<button
onClick={() => handleSort("orderCount")}
className={cn(
"inline-flex items-center justify-center w-full px-2 py-1 text-sm font-medium transition-colors rounded-md",
sorting.column === "orderCount"
? "bg-primary text-primary-foreground"
: "hover:bg-accent hover:text-accent-foreground"
)}
>
Orders
</button>
</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">
<button
onClick={() => handleSort("price")}
className={cn(
"inline-flex items-center justify-center w-full px-2 py-1 text-sm font-medium transition-colors rounded-md",
sorting.column === "price"
? "bg-primary text-primary-foreground"
: "hover:bg-accent hover:text-accent-foreground"
)}
>
Price
</button>
</th>
)}
<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 min-w-[200px] border-b">
<button
onClick={() => handleSort("name")}
className={cn(
"inline-flex items-center justify-start w-full px-2 py-1 text-sm font-medium transition-colors rounded-md",
sorting.column === "name"
? "bg-primary text-primary-foreground"
: "hover:bg-accent hover:text-accent-foreground"
)}
>
Product
</button>
</th>
<th className="p-1.5 font-medium text-center sticky top-0 bg-white dark:bg-background z-10 border-b">
<button
onClick={() => handleSort("totalQuantity")}
className={cn(
"inline-flex items-center justify-center w-full px-2 py-1 text-sm font-medium transition-colors rounded-md",
sorting.column === "totalQuantity"
? "bg-primary text-primary-foreground"
: "hover:bg-accent hover:text-accent-foreground"
)}
>
Sold
</button>
</th>
<th className="p-1.5 font-medium text-center sticky top-0 bg-white dark:bg-background z-10 border-b">
<button
onClick={() => handleSort("totalRevenue")}
className={cn(
"inline-flex items-center justify-center w-full px-2 py-1 text-sm font-medium transition-colors rounded-md",
sorting.column === "totalRevenue"
? "bg-primary text-primary-foreground"
: "hover:bg-accent hover:text-accent-foreground"
)}
>
Rev
</button>
</th>
<th className="p-1.5 font-medium text-center sticky top-0 bg-white dark:bg-background z-10 border-b">
<button
onClick={() => handleSort("orderCount")}
className={cn(
"inline-flex items-center justify-center w-full px-2 py-1 text-sm font-medium transition-colors rounded-md",
sorting.column === "orderCount"
? "bg-primary text-primary-foreground"
: "hover:bg-accent hover:text-accent-foreground"
)}
>
Orders
</button>
</th>
<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
onClick={() => handleSort("price")}
className={cn(
"inline-flex items-center justify-center w-full px-2 py-1 text-sm font-medium transition-colors rounded-md",
sorting.column === "price"
? "bg-primary text-primary-foreground"
: "hover:bg-accent hover:text-accent-foreground"
)}
>
Price
</button>
</th>
</tr>
</thead>
<tbody className="divide-y divide-gray-200 dark:divide-gray-800">
@@ -423,54 +366,42 @@ const ProductGrid = ({
key={product.id}
className="hover:bg-muted/50 transition-colors"
>
{columnVisibility.image && (
<td className="p-1 align-middle w-[50px]">
{product.ImgThumb && (
<img
src={product.ImgThumb}
alt=""
width={50}
height={50}
className="rounded bg-muted"
onError={(e) => (e.target.style.display = "none")}
/>
)}
</td>
)}
{columnVisibility.name && (
<td className="p-1 align-middle min-w-[200px]">
<div className="flex flex-col min-w-0">
<a
href={`https://backend.acherryontop.com/product/${product.id}`}
target="_blank"
rel="noopener noreferrer"
className="text-sm hover:underline line-clamp-2 text-gray-900 dark:text-gray-100"
>
{product.name}
</a>
</div>
</td>
)}
{columnVisibility.totalQuantity && (
<td className="p-1 align-middle text-center text-sm font-medium">
{product.totalQuantity}
</td>
)}
{columnVisibility.totalRevenue && (
<td className="p-1 align-middle text-center text-emerald-600 dark:text-emerald-400 text-sm font-medium">
${product.totalRevenue.toFixed(2)}
</td>
)}
{columnVisibility.orderCount && (
<td className="p-1 align-middle text-center text-muted-foreground text-sm">
{product.orderCount}
</td>
)}
{columnVisibility.price && (
<td className="p-1 align-middle text-center hidden md:table-cell text-sm">
${product.price.toFixed(2)}
</td>
)}
<td className="p-1 align-middle w-[50px]">
{product.ImgThumb && (
<img
src={product.ImgThumb}
alt=""
width={50}
height={50}
className="rounded bg-muted"
onError={(e) => (e.target.style.display = "none")}
/>
)}
</td>
<td className="p-1 align-middle min-w-[200px]">
<div className="flex flex-col min-w-0">
<a
href={`https://backend.acherryontop.com/product/${product.id}`}
target="_blank"
rel="noopener noreferrer"
className="text-sm hover:underline line-clamp-2 text-gray-900 dark:text-gray-100"
>
{product.name}
</a>
</div>
</td>
<td className="p-1 align-middle text-center text-sm font-medium">
{product.totalQuantity}
</td>
<td className="p-1 align-middle text-center text-emerald-600 dark:text-emerald-400 text-sm font-medium">
${product.totalRevenue.toFixed(2)}
</td>
<td className="p-1 align-middle text-center text-muted-foreground text-sm">
{product.orderCount}
</td>
<td className="p-1 align-middle text-center hidden md:table-cell text-sm">
${product.price.toFixed(2)}
</td>
</tr>
))}
</tbody>