feat(admin): add product dependencies and clean up labels
All checks were successful
Staging Build / build (push) Successful in 2m43s
All checks were successful
Staging Build / build (push) Successful in 2m43s
- Add addProductDependency and removeProductDependency actions - Create DependencyPopover and integrate in live editor UI - Render green requirements and red exclusions badges - Remove technical parentheses from category checkbox labels
This commit is contained in:
@@ -2,9 +2,10 @@
|
||||
|
||||
import { useState, useTransition } from 'react'
|
||||
import { Category, Product, ProductModule } from '@/lib/types'
|
||||
import { updateProduct, createProduct, updateCategory, createCategory, deleteProduct, deleteCategory } from '@/lib/actions/products'
|
||||
import { updateProduct, createProduct, updateCategory, createCategory, deleteProduct, deleteCategory, addProductDependency, removeProductDependency } from '@/lib/actions/products'
|
||||
import { InlineInput } from './components/inline-input'
|
||||
import { ModulePopover } from './components/module-popover'
|
||||
import { DependencyPopover } from './components/dependency-popover'
|
||||
import { Trash2 } from 'lucide-react'
|
||||
|
||||
export function WysiwygAdminClient({
|
||||
@@ -60,6 +61,14 @@ export function WysiwygAdminClient({
|
||||
})
|
||||
}
|
||||
|
||||
const getDependencyName = (depId: string) => {
|
||||
const matchedProduct = products.find(p => p.id === depId)
|
||||
if (matchedProduct) return matchedProduct.name
|
||||
const matchedModule = allModules.find(m => m.id === depId)
|
||||
if (matchedModule) return `${matchedModule.name} (Modul)`
|
||||
return depId
|
||||
}
|
||||
|
||||
// Filterung der Kategorien nach aktivem Modus
|
||||
const filteredCategories = categories.filter(cat =>
|
||||
mode === 'purchase' ? cat.show_in_kauf : cat.show_in_abo
|
||||
@@ -181,7 +190,7 @@ export function WysiwygAdminClient({
|
||||
onChange={(e) => handleCategoryToggle(cat.id, { is_required: e.target.checked })}
|
||||
className="rounded border-white/10 bg-white/5 text-primary focus:ring-0 focus:ring-offset-0"
|
||||
/>
|
||||
<span>Pflichtauswahl (is_required)</span>
|
||||
<span>Pflichtauswahl</span>
|
||||
</label>
|
||||
<label className="flex items-center gap-2 cursor-pointer select-none">
|
||||
<input
|
||||
@@ -190,7 +199,7 @@ export function WysiwygAdminClient({
|
||||
onChange={(e) => handleCategoryToggle(cat.id, { allow_multiselect: e.target.checked })}
|
||||
className="rounded border-white/10 bg-white/5 text-primary focus:ring-0 focus:ring-offset-0"
|
||||
/>
|
||||
<span>Mehrfachauswahl (allow_multiselect)</span>
|
||||
<span>Mehrfachauswahl</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -274,6 +283,84 @@ export function WysiwygAdminClient({
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Requirements */}
|
||||
<div className="space-y-1">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-[10px] uppercase tracking-wider text-slate-500 font-semibold block">Benötigt:</span>
|
||||
<DependencyPopover
|
||||
currentProductId={prod.id}
|
||||
assignedIds={prod.requirements || []}
|
||||
allProducts={products}
|
||||
allModules={allModules}
|
||||
onAddDependency={async (depId) => {
|
||||
const newReqs = [...(prod.requirements || []), depId]
|
||||
setProducts(products.map(p => p.id === prod.id ? { ...p, requirements: newReqs } : p))
|
||||
await addProductDependency(prod.id, 'requirements', depId)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{(prod.requirements || []).length > 0 ? (
|
||||
(prod.requirements || []).map((reqId) => (
|
||||
<span key={reqId} className="inline-flex items-center gap-1 px-2 py-0.5 rounded text-[10px] bg-green-500/10 text-green-400 border border-green-500/20 font-medium animate-fade-in">
|
||||
{getDependencyName(reqId)}
|
||||
<button
|
||||
onClick={async () => {
|
||||
const newReqs = (prod.requirements || []).filter(id => id !== reqId)
|
||||
setProducts(products.map(p => p.id === prod.id ? { ...p, requirements: newReqs } : p))
|
||||
await removeProductDependency(prod.id, 'requirements', reqId)
|
||||
}}
|
||||
className="text-green-600 hover:text-green-400 font-bold transition-colors ml-0.5"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
</span>
|
||||
))
|
||||
) : (
|
||||
<span className="text-[10px] text-slate-500 italic">Keine Anforderungen</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Exclusions */}
|
||||
<div className="space-y-1">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-[10px] uppercase tracking-wider text-slate-500 font-semibold block">Schließt aus:</span>
|
||||
<DependencyPopover
|
||||
currentProductId={prod.id}
|
||||
assignedIds={prod.exclusions || []}
|
||||
allProducts={products}
|
||||
allModules={allModules}
|
||||
onAddDependency={async (depId) => {
|
||||
const newExcs = [...(prod.exclusions || []), depId]
|
||||
setProducts(products.map(p => p.id === prod.id ? { ...p, exclusions: newExcs } : p))
|
||||
await addProductDependency(prod.id, 'exclusions', depId)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{(prod.exclusions || []).length > 0 ? (
|
||||
(prod.exclusions || []).map((exId) => (
|
||||
<span key={exId} className="inline-flex items-center gap-1 px-2 py-0.5 rounded text-[10px] bg-red-500/10 text-red-400 border border-red-500/20 font-medium animate-fade-in">
|
||||
{getDependencyName(exId)}
|
||||
<button
|
||||
onClick={async () => {
|
||||
const newExcs = (prod.exclusions || []).filter(id => id !== exId)
|
||||
setProducts(products.map(p => p.id === prod.id ? { ...p, exclusions: newExcs } : p))
|
||||
await removeProductDependency(prod.id, 'exclusions', exId)
|
||||
}}
|
||||
className="text-red-600 hover:text-red-400 font-bold transition-colors ml-0.5"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
</span>
|
||||
))
|
||||
) : (
|
||||
<span className="text-[10px] text-slate-500 italic">Keine Ausschlüsse</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Modul hinzufügen Popover */}
|
||||
|
||||
Reference in New Issue
Block a user