import { useState, useEffect } from 'react' import { Save, Edit2, X, Info } 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 [formData, setFormData] = useState({ name: '', category: 'data', description: '', 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({ name: '', category: 'data', description: '', limit_type: 'count', default_limit: '', reset_period: 'never', visible_in_admin: true, sort_order: 50, active: true }) setEditingId(null) } function startEdit(feature) { setFormData({ name: feature.name, category: feature.category, description: feature.description || '', 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) } async function handleSave() { try { setError('') setSuccess('') if (!formData.name.trim()) { setError('Name erforderlich') return } const payload = { name: formData.name.trim(), category: formData.category, description: formData.description.trim(), 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 } await api.updateFeature(editingId, payload) setSuccess('Feature aktualisiert') await loadFeatures() resetForm() } 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 (akkumuliert)' }, { 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-Konfiguration
Limitierungs-Einstellungen für registrierte Features
{/* Info Box */}
Hinweis: Features werden automatisch via Code registriert. Hier können nur Basis-Einstellungen (Limit-Typ, Reset-Periode, Standards) angepasst werden. Neue Features hinzuzufügen erfordert Code-Änderungen im Backend.
{/* Messages */} {error && (
{error}
)} {success && (
{success}
)} {/* Edit Form */} {editingId && (
Feature konfigurieren
{/* Feature ID (read-only) */}
{/* Name */}
setFormData({ ...formData, name: e.target.value })} placeholder="z.B. Gewichtseinträge" />
{/* Description */}
setFormData({ ...formData, description: e.target.value })} placeholder="Kurze Erklärung was dieses Feature limitiert" />
{/* Category + Limit Type */}
{/* Count-specific fields (only for limit_type='count') */} {formData.limit_type === 'count' && ( <> {/* Reset Period */}
Wann wird der Nutzungszähler zurückgesetzt?
{/* Default Limit */}
setFormData({ ...formData, default_limit: e.target.value })} placeholder="Leer = unbegrenzt" />
Fallback-Wert wenn kein Tier-spezifisches Limit gesetzt ist
)} {/* Boolean info */} {formData.limit_type === 'boolean' && (
Boolean-Feature: Ist entweder verfügbar (AN) oder nicht verfügbar (AUS). Keine Zähler oder Reset-Perioden notwendig.
)} {/* Sort Order */}
setFormData({ ...formData, sort_order: parseInt(e.target.value) || 50 })} />
Niedrigere Werte erscheinen weiter oben in Listen (Standard: 50)
{/* Checkboxes */}
{/* Actions */}
)} {/* Features List */}
{features.length === 0 && ( )} {features.map((feature, idx) => ( ))}
Feature Kategorie Limit-Typ Reset Standard Status Aktion
Keine Features registriert
{feature.name}
{feature.id}
{feature.description && (
{feature.description}
)}
{feature.category} {feature.limit_type === 'boolean' ? '✓/✗' : '123'} {feature.reset_period === 'never' ? '∞' : feature.reset_period === 'daily' ? '1d' : '1m'} {feature.default_limit === null ? '∞' : feature.default_limit} {feature.active ? ( ✓ Aktiv ) : ( ✗ Inaktiv )}
{/* Legend */}
Limit-Typ:
Boolean (✓/✗): Feature ist entweder verfügbar oder nicht (z.B. "KI aktiviert")
Count (123): Feature hat ein Nutzungs-Limit (z.B. "max. 50 Einträge")
Reset-Periode: ∞ = nie, 1d = täglich, 1m = monatlich
) }