import { useEffect, useState } from 'react' import { db, type FeedbackDimension, type FeedbackCategory, type FeedbackCriterionItem, type AssignmentType, type PhaseTemplate } from '../db' export default function FeedbackStructureConfig() { const [dimensions, setDimensions] = useState([]) const [categories, setCategories] = useState([]) const [items, setItems] = useState([]) const [assignmentTypes, setAssignmentTypes] = useState([]) const [expanded, setExpanded] = useState>(new Set()) const [expandedCat, setExpandedCat] = useState>(new Set()) const [showCatalogs, setShowCatalogs] = useState(false) const [phaseTemplates, setPhaseTemplates] = useState([]) const [showTypeConfig, setShowTypeConfig] = useState(false) const [expandedType, setExpandedType] = useState(null) const [newTypeName, setNewTypeName] = useState('') const [newPhase, setNewPhase] = useState>({}) const [typeError, setTypeError] = useState>({}) // Neue Einträge const [newDimName, setNewDimName] = useState('') const [newCatName, setNewCatName] = useState>({}) const [newItemName, setNewItemName] = useState>({}) const load = async () => { const [dims, cats, itms, types, phases] = await Promise.all([ db.feedbackDimensions.orderBy('order').toArray(), db.feedbackCategories.orderBy('order').toArray(), db.feedbackCriterionItems.orderBy('order').toArray(), db.assignmentTypes.toArray(), db.phaseTemplates.toArray(), ]) setDimensions(dims) setCategories(cats) setItems(itms) setAssignmentTypes(types) setPhaseTemplates(phases) } useEffect(() => { load() }, []) // ── Dimensionen ─────────────────────────────────────────────────────────── const addDimension = async () => { if (!newDimName.trim()) return const maxOrder = dimensions.reduce((m, d) => Math.max(m, d.order), 0) const id = await db.feedbackDimensions.add({ name: newDimName.trim(), order: maxOrder + 1 }) setNewDimName('') await load() setExpanded(prev => new Set([...prev, id])) } const updateDimension = async (id: number, name: string) => { await db.feedbackDimensions.update(id, { name }) setDimensions(prev => prev.map(d => d.id === id ? { ...d, name } : d)) } const deleteDimension = async (id: number) => { const cats = await db.feedbackCategories.where('dimensionId').equals(id).toArray() for (const cat of cats) { await db.feedbackCriterionItems.where('categoryId').equals(cat.id!).delete() } await db.feedbackCategories.where('dimensionId').equals(id).delete() await db.feedbackDimensions.delete(id) await load() } const moveDim = async (dim: FeedbackDimension, dir: -1 | 1) => { const sorted = [...dimensions].sort((a, b) => a.order - b.order) const idx = sorted.findIndex(d => d.id === dim.id) const other = sorted[idx + dir] if (!other) return await db.feedbackDimensions.update(dim.id!, { order: other.order }) await db.feedbackDimensions.update(other.id!, { order: dim.order }) await load() } // ── Kategorien ──────────────────────────────────────────────────────────── const addCategory = async (dimId: number) => { const name = newCatName[dimId]?.trim() if (!name) return const dimCats = categories.filter(c => c.dimensionId === dimId) const maxOrder = dimCats.reduce((m, c) => Math.max(m, c.order), 0) const id = await db.feedbackCategories.add({ dimensionId: dimId, name, order: maxOrder + 1 }) setNewCatName(prev => ({ ...prev, [dimId]: '' })) await load() setExpandedCat(prev => new Set([...prev, id])) } const updateCategory = async (id: number, name: string) => { await db.feedbackCategories.update(id, { name }) setCategories(prev => prev.map(c => c.id === id ? { ...c, name } : c)) } const deleteCategory = async (id: number) => { await db.feedbackCriterionItems.where('categoryId').equals(id).delete() await db.feedbackCategories.delete(id) await load() } // ── Kriterium-Items ─────────────────────────────────────────────────────── const addItem = async (catId: number) => { const name = newItemName[catId]?.trim() if (!name) return const catItems = items.filter(i => i.categoryId === catId) const maxOrder = catItems.reduce((m, i) => Math.max(m, i.order), 0) await db.feedbackCriterionItems.add({ categoryId: catId, name, order: maxOrder + 1 }) setNewItemName(prev => ({ ...prev, [catId]: '' })) await load() } const updateItem = async (id: number, name: string) => { await db.feedbackCriterionItems.update(id, { name }) setItems(prev => prev.map(i => i.id === id ? { ...i, name } : i)) } const deleteItem = async (id: number) => { await db.feedbackCriterionItems.delete(id) setItems(prev => prev.filter(i => i.id !== id)) } const updateItemWeight = async (id: number, weight: number) => { await db.feedbackCriterionItems.update(id, { weight }) setItems(prev => prev.map(i => i.id === id ? { ...i, weight } : i)) } const toggleCatalogCategory = async (type: AssignmentType, catId: number) => { const current = type.criteriaIds ?? [] const next = current.includes(catId) ? current.filter(id => id !== catId) : [...current, catId] await db.assignmentTypes.update(type.id!, { criteriaIds: next }) setAssignmentTypes(prev => prev.map(t => t.id === type.id ? { ...t, criteriaIds: next } : t)) } // ── AssignmentType CRUD ─────────────────────────────────────────────────── const addAssignmentType = async () => { if (!newTypeName.trim()) return await db.assignmentTypes.add({ name: newTypeName.trim(), defaultPhaseKeys: [] }) setNewTypeName('') await load() } const updateAssignmentTypeName = async (id: number, name: string) => { await db.assignmentTypes.update(id, { name }) setAssignmentTypes(prev => prev.map(t => t.id === id ? { ...t, name } : t)) } const deleteAssignmentType = async (id: number) => { const count = await db.assignments.where('assignmentTypeId').equals(id).count() if (count > 0) { setTypeError(prev => ({ ...prev, [id]: `Kann nicht gelöscht werden – ${count} Assignment(s) verwenden diesen Typ.` })) return } await db.phaseTemplates.where('assignmentTypeId').equals(id).delete() await db.assignmentTypes.delete(id) setTypeError(prev => { const n = { ...prev }; delete n[id]; return n }) await load() } // ── PhaseTemplate CRUD ──────────────────────────────────────────────────── const addPhaseTemplate = async (typeId: number) => { const p = newPhase[typeId] if (!p?.label.trim()) return const existing = phaseTemplates.filter(t => t.assignmentTypeId === typeId) await db.phaseTemplates.add({ assignmentTypeId: typeId, phaseKey: p.label.trim().toLowerCase().replace(/\s+/g, '_'), label: p.label.trim(), withWhom: p.withWhom, isRepeatable: p.isRepeatable, hasConversation: p.hasConversation, hasAssessment: p.hasAssessment, criteriaIds: [], order: existing.length + 1, }) setNewPhase(prev => ({ ...prev, [typeId]: { label: '', withWhom: 'lead', isRepeatable: false, hasConversation: false, hasAssessment: false } })) await load() } const updatePhaseTemplate = async (id: number, fields: Partial) => { await db.phaseTemplates.update(id, fields) setPhaseTemplates(prev => prev.map(t => t.id === id ? { ...t, ...fields } : t)) } const deletePhaseTemplate = async (id: number) => { await db.phaseTemplates.delete(id) setPhaseTemplates(prev => prev.filter(t => t.id !== id)) } const sorted = [...dimensions].sort((a, b) => a.order - b.order) return (

Feedback-Dimensionen & Kategorien

{/* Neue Dimension */}
setNewDimName(e.target.value)} onKeyDown={e => e.key === 'Enter' && addDimension()} />
{/* Dimensionen */} {sorted.map((dim, di) => { const isOpen = expanded.has(dim.id!) const dimCats = [...categories].filter(c => c.dimensionId === dim.id).sort((a, b) => a.order - b.order) return (
{/* Dimension-Header */}
updateDimension(dim.id!, e.target.value)} />
{isOpen && (
{dimCats.map(cat => { const isCatOpen = expandedCat.has(cat.id!) const catItems = [...items].filter(i => i.categoryId === cat.id).sort((a, b) => a.order - b.order) return (
updateCategory(cat.id!, e.target.value)} />
{isCatOpen && (
{catItems.map(item => (
· updateItem(item.id!, e.target.value)} />
))}
setNewItemName(p => ({ ...p, [cat.id!]: e.target.value }))} onKeyDown={e => e.key === 'Enter' && addItem(cat.id!)} />
)}
) })} {/* Neue Kategorie */}
setNewCatName(p => ({ ...p, [dim.id!]: e.target.value }))} onKeyDown={e => e.key === 'Enter' && addCategory(dim.id!)} />
)}
) })}
) }