import { useState, useEffect } from 'react' import { Save, Plus, Edit2, Trash2, X } from 'lucide-react' import { api } from '../utils/api' export default function AdminTiersPage() { const [loading, setLoading] = useState(true) const [error, setError] = useState('') const [success, setSuccess] = useState('') const [tiers, setTiers] = useState([]) const [editingId, setEditingId] = useState(null) const [showAddForm, setShowAddForm] = useState(false) const [formData, setFormData] = useState({ id: '', name: '', description: '', price_monthly_cents: '', price_yearly_cents: '', sort_order: 50, active: true }) useEffect(() => { loadTiers() }, []) async function loadTiers() { try { setLoading(true) const data = await api.listTiers() setTiers(data) setError('') } catch (e) { setError(e.message) } finally { setLoading(false) } } function resetForm() { setFormData({ id: '', name: '', description: '', price_monthly_cents: '', price_yearly_cents: '', sort_order: 50, active: true }) setEditingId(null) setShowAddForm(false) } function startEdit(tier) { setFormData({ id: tier.id, name: tier.name, description: tier.description || '', price_monthly_cents: tier.price_monthly_cents === null ? '' : tier.price_monthly_cents, price_yearly_cents: tier.price_yearly_cents === null ? '' : tier.price_yearly_cents, sort_order: tier.sort_order || 50, active: tier.active }) setEditingId(tier.id) setShowAddForm(false) } async function handleSave() { try { setError('') setSuccess('') // Validation if (!formData.name.trim()) { setError('Name erforderlich') return } const payload = { name: formData.name.trim(), description: formData.description.trim(), price_monthly_cents: formData.price_monthly_cents === '' ? null : parseInt(formData.price_monthly_cents), price_yearly_cents: formData.price_yearly_cents === '' ? null : parseInt(formData.price_yearly_cents), sort_order: formData.sort_order, active: formData.active } if (editingId) { // Update existing await api.updateTier(editingId, payload) setSuccess('Tier aktualisiert') } else { // Create new if (!formData.id.trim()) { setError('ID erforderlich') return } payload.id = formData.id.trim() await api.createTier(payload) setSuccess('Tier erstellt') } await loadTiers() resetForm() } catch (e) { setError(e.message) } } async function handleDelete(tierId) { if (!confirm('Tier wirklich deaktivieren?')) return try { setError('') await api.deleteTier(tierId) setSuccess('Tier deaktiviert') await loadTiers() } catch (e) { setError(e.message) } } function formatPrice(cents) { if (cents === null || cents === undefined) return 'Kostenlos' return `${(cents / 100).toFixed(2)} €` } if (loading) return (
) return (
{/* Header */}
Tier-Verwaltung
Subscription-Tiers konfigurieren
{!showAddForm && !editingId && ( )}
{/* Messages */} {error && (
{error}
)} {success && (
{success}
)} {/* Add/Edit Form */} {(showAddForm || editingId) && (
{editingId ? 'Tier bearbeiten' : 'Neuen Tier erstellen'}
{/* ID (nur bei Neuanlage) */} {!editingId && (
setFormData({ ...formData, id: e.target.value })} placeholder="z.B. enterprise" /> Kleinbuchstaben, keine Leerzeichen
)} {/* Name */}
setFormData({ ...formData, name: e.target.value })} placeholder="z.B. Enterprise" />
{/* Description */}
setFormData({ ...formData, description: e.target.value })} placeholder="z.B. Für Teams und Unternehmen" />
{/* Pricing */}
setFormData({ ...formData, price_monthly_cents: e.target.value })} placeholder="Leer = kostenlos" /> {formData.price_monthly_cents ? formatPrice(parseInt(formData.price_monthly_cents)) : '-'}
setFormData({ ...formData, price_yearly_cents: e.target.value })} placeholder="Leer = kostenlos" /> {formData.price_yearly_cents ? formatPrice(parseInt(formData.price_yearly_cents)) : '-'}
{/* Sort Order + Active */}
setFormData({ ...formData, sort_order: parseInt(e.target.value) || 50 })} />
{/* Actions */}
)} {/* Tiers List */}
{tiers.length === 0 && (
Keine Tiers vorhanden
)} {tiers.map(tier => (
{tier.name}
{tier.id} {!tier.active && ( INAKTIV )}
{tier.description && (
{tier.description}
)}
Monatlich: {formatPrice(tier.price_monthly_cents)}
Jährlich: {formatPrice(tier.price_yearly_cents)}
Sortierung: {tier.sort_order}
))}
{/* Info */}
Hinweis: Limits für jeden Tier können in der{' '} Tier Limits Matrix {' '} konfiguriert werden.
) }