feat: add sort by category button to products list view
All checks were successful
Staging Build / build (push) Successful in 2m20s
All checks were successful
Staging Build / build (push) Successful in 2m20s
This commit is contained in:
@@ -11,14 +11,15 @@ import {
|
|||||||
} from '@/components/ui/table'
|
} from '@/components/ui/table'
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
|
||||||
import { Badge } from '@/components/ui/badge'
|
import { Badge } from '@/components/ui/badge'
|
||||||
import { Edit2, Trash2, Layers } from 'lucide-react'
|
import { Edit2, Trash2, Layers, ArrowUpDown } from 'lucide-react'
|
||||||
import { Button } from '@/components/ui/button'
|
import { Button } from '@/components/ui/button'
|
||||||
import { deleteProduct } from '@/lib/actions/products'
|
import { deleteProduct } from '@/lib/actions/products'
|
||||||
import { useState, useEffect } from 'react'
|
import { useState, useEffect, useMemo } from 'react'
|
||||||
import { CreateProductDialog } from './create-product-dialog'
|
import { CreateProductDialog } from './create-product-dialog'
|
||||||
|
|
||||||
export function ProductList({ initialProducts, categories }: { initialProducts: Product[], categories: Category[] }) {
|
export function ProductList({ initialProducts, categories }: { initialProducts: Product[], categories: Category[] }) {
|
||||||
const [products, setProducts] = useState(initialProducts)
|
const [products, setProducts] = useState(initialProducts)
|
||||||
|
const [isSortedByCategory, setIsSortedByCategory] = useState(false)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setProducts(initialProducts)
|
setProducts(initialProducts)
|
||||||
@@ -31,13 +32,46 @@ export function ProductList({ initialProducts, categories }: { initialProducts:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const toggleSortByCategory = () => {
|
||||||
|
setIsSortedByCategory(!isSortedByCategory)
|
||||||
|
}
|
||||||
|
|
||||||
|
const displayedProducts = useMemo(() => {
|
||||||
|
if (!isSortedByCategory) return products
|
||||||
|
|
||||||
|
return [...products].sort((a, b) => {
|
||||||
|
const orderA = a.category?.sort_order ?? 9999
|
||||||
|
const orderB = b.category?.sort_order ?? 9999
|
||||||
|
if (orderA !== orderB) return orderA - orderB
|
||||||
|
|
||||||
|
const catA = a.category?.name || ''
|
||||||
|
const catB = b.category?.name || ''
|
||||||
|
if (catA !== catB) return catA.localeCompare(catB)
|
||||||
|
|
||||||
|
return a.name.localeCompare(b.name)
|
||||||
|
})
|
||||||
|
}, [products, isSortedByCategory])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="bg-white dark:bg-slate-900/50 border border-slate-200 dark:border-white/10 shadow-sm overflow-hidden text-slate-900 dark:text-white">
|
<Card className="bg-white dark:bg-slate-900/50 border border-slate-200 dark:border-white/10 shadow-sm overflow-hidden text-slate-900 dark:text-white">
|
||||||
<CardHeader>
|
<CardHeader className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
|
||||||
<CardTitle>Produktübersicht</CardTitle>
|
<div>
|
||||||
<CardDescription className="text-slate-500 dark:text-slate-400">
|
<CardTitle>Produktübersicht</CardTitle>
|
||||||
Alle konfigurierten Software-Lösungen und Erweiterungen.
|
<CardDescription className="text-slate-500 dark:text-slate-400">
|
||||||
</CardDescription>
|
Alle konfigurierten Software-Lösungen und Erweiterungen.
|
||||||
|
</CardDescription>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
onClick={toggleSortByCategory}
|
||||||
|
className={`border-slate-200 dark:border-white/10 hover:bg-slate-100 dark:hover:bg-white/10 text-slate-700 dark:text-white ${
|
||||||
|
isSortedByCategory ? 'bg-primary/10 border-primary text-primary hover:bg-primary/20 dark:bg-primary/20 dark:border-primary dark:text-primary-foreground' : ''
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<ArrowUpDown className="w-4 h-4 mr-2" />
|
||||||
|
{isSortedByCategory ? 'Kategoriesortierung aktiv' : 'Nach Kategorien sortieren'}
|
||||||
|
</Button>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Table>
|
<Table>
|
||||||
@@ -51,7 +85,7 @@ export function ProductList({ initialProducts, categories }: { initialProducts:
|
|||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{products.map((product) => (
|
{displayedProducts.map((product) => (
|
||||||
<TableRow key={product.id} className="border-slate-100 dark:border-white/5 hover:bg-slate-50 dark:hover:bg-white/5 transition-colors">
|
<TableRow key={product.id} className="border-slate-100 dark:border-white/5 hover:bg-slate-50 dark:hover:bg-white/5 transition-colors">
|
||||||
<TableCell className="font-medium text-slate-900 dark:text-white">
|
<TableCell className="font-medium text-slate-900 dark:text-white">
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
@@ -103,7 +137,7 @@ export function ProductList({ initialProducts, categories }: { initialProducts:
|
|||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
))}
|
||||||
{products.length === 0 && (
|
{displayedProducts.length === 0 && (
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell colSpan={5} className="text-center py-10 text-slate-500 dark:text-slate-400">
|
<TableCell colSpan={5} className="text-center py-10 text-slate-500 dark:text-slate-400">
|
||||||
Keine Produkte gefunden. Erstellen Sie Ihr erstes Produkt!
|
Keine Produkte gefunden. Erstellen Sie Ihr erstes Produkt!
|
||||||
|
|||||||
Reference in New Issue
Block a user