import { useState, useEffect } from 'react' import { Save, Plus, Edit2, Trash2, X } from 'lucide-react' import { api } from '../utils/api' export default function AdminFeaturesPage() { const [loading, setLoading] = useState(true) const [error, setError] = useState('') const [success, setSuccess] = useState('') const [features, setFeatures] = useState([]) const [editingId, setEditingId] = useState(null) const [showAddForm, setShowAddForm] = useState(false) const [formData, setFormData] = useState({ id: '', name: '', category: 'data', description: '', unit: 'count', limit_type: 'count', default_limit: '', reset_period: 'never', visible_in_admin: true, sort_order: 50, active: true }) useEffect(() => { loadFeatures() }, []) async function loadFeatures() { try { setLoading(true) const data = await api.listFeatures() setFeatures(data) setError('') } catch (e) { setError(e.message) } finally { setLoading(false) } } function resetForm() { setFormData({ id: '', name: '', category: 'data', description: '', unit: 'count', limit_type: 'count', default_limit: '', reset_period: 'never', visible_in_admin: true, sort_order: 50, active: true }) setEditingId(null) setShowAddForm(false) } function startEdit(feature) { setFormData({ id: feature.id, name: feature.name, category: feature.category, description: feature.description || '', unit: feature.unit || 'count', limit_type: feature.limit_type, default_limit: feature.default_limit === null ? '' : feature.default_limit, reset_period: feature.reset_period, visible_in_admin: feature.visible_in_admin, sort_order: feature.sort_order || 50, active: feature.active }) setEditingId(feature.id) setShowAddForm(false) } async function handleSave() { try { setError('') setSuccess('') // Validation if (!formData.name.trim()) { setError('Name erforderlich') return } const payload = { name: formData.name.trim(), category: formData.category, description: formData.description.trim(), unit: formData.unit, limit_type: formData.limit_type, default_limit: formData.default_limit === '' ? null : parseInt(formData.default_limit), reset_period: formData.reset_period, visible_in_admin: formData.visible_in_admin, sort_order: formData.sort_order, active: formData.active } if (editingId) { // Update existing await api.updateFeature(editingId, payload) setSuccess('Feature aktualisiert') } else { // Create new if (!formData.id.trim()) { setError('ID erforderlich') return } payload.id = formData.id.trim() await api.createFeature(payload) setSuccess('Feature erstellt') } await loadFeatures() resetForm() } catch (e) { setError(e.message) } } async function handleDelete(featureId) { if (!confirm('Feature wirklich löschen?')) return try { setError('') await api.deleteFeature(featureId) setSuccess('Feature gelöscht') await loadFeatures() } catch (e) { setError(e.message) } } if (loading) return (
) const categoryOptions = [ { value: 'data', label: 'Daten' }, { value: 'ai', label: 'KI' }, { value: 'export', label: 'Export' }, { value: 'integration', label: 'Integrationen' } ] const resetPeriodOptions = [ { value: 'never', label: 'Nie' }, { value: 'daily', label: 'Täglich' }, { value: 'monthly', label: 'Monatlich' } ] const limitTypeOptions = [ { value: 'count', label: 'Anzahl (Count)' }, { value: 'boolean', label: 'Ja/Nein (Boolean)' } ] return (
{/* Header */}
Feature-Registry
Verfügbare Features verwalten
{!showAddForm && !editingId && ( )}
{/* Messages */} {error && (
{error}
)} {success && (
{success}
)} {/* Add/Edit Form */} {(showAddForm || editingId) && (
{editingId ? 'Feature bearbeiten' : 'Neues Feature erstellen'}
{/* ID (nur bei Neuanlage) */} {!editingId && (
setFormData({ ...formData, id: e.target.value })} placeholder="z.B. weight_entries" />
)} {/* Name */}
setFormData({ ...formData, name: e.target.value })} placeholder="z.B. Gewichtseinträge" />
{/* Category + Limit Type */}
{/* Description */}
setFormData({ ...formData, description: e.target.value })} placeholder="Optionale Beschreibung" />
{/* Unit + Reset Period */}
setFormData({ ...formData, unit: e.target.value })} placeholder="z.B. count, calls" />
{/* Default Limit + Sort Order */}
setFormData({ ...formData, default_limit: e.target.value })} placeholder="Leer = unbegrenzt" />
setFormData({ ...formData, sort_order: parseInt(e.target.value) || 50 })} />
{/* Checkboxes */}
{/* Actions */}
)} {/* Features List */}
{features.length === 0 && ( )} {features.map((feature, idx) => ( ))}
Name ID Kategorie Typ Reset Std-Limit Aktiv Aktionen
Keine Features vorhanden
{feature.name} {feature.description && (
{feature.description}
)}
{feature.id} {feature.category} {feature.limit_type === 'boolean' ? '✓/✗' : '123'} {feature.reset_period} {feature.default_limit === null ? '∞' : feature.default_limit} {feature.active ? ( ✓ ) : ( ✗ )}
) }