107 lines
4.2 KiB
JavaScript
107 lines
4.2 KiB
JavaScript
import { useEffect, useState } from 'react'
|
|
import api from '../api/client'
|
|
import { Plus, Trash2 } from 'lucide-react'
|
|
|
|
export default function SettingsPage() {
|
|
const [users, setUsers] = useState([])
|
|
const [showAdd, setShowAdd] = useState(false)
|
|
const [form, setForm] = useState({ username: '', password: '', display_name: '' })
|
|
|
|
const reload = () => api.getUsers().then((u) => setUsers(u || []))
|
|
useEffect(() => { reload() }, [])
|
|
|
|
const handleAdd = async () => {
|
|
if (!form.username || !form.password) return
|
|
await api.createUser(form)
|
|
setForm({ username: '', password: '', display_name: '' })
|
|
setShowAdd(false)
|
|
reload()
|
|
}
|
|
|
|
const handleDelete = async (id) => {
|
|
if (!confirm('Benutzer wirklich loeschen?')) return
|
|
await api.deleteUser(id)
|
|
reload()
|
|
}
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<h1 className="text-xl font-bold text-white">Einstellungen</h1>
|
|
|
|
{/* Users */}
|
|
<div className="bg-gray-900 rounded-lg border border-gray-800 overflow-hidden">
|
|
<div className="px-4 py-3 border-b border-gray-800 flex items-center justify-between">
|
|
<span className="text-sm font-medium text-gray-300">Benutzer</span>
|
|
<button
|
|
onClick={() => setShowAdd(true)}
|
|
className="flex items-center gap-1 text-sm text-orange-400 hover:text-orange-300"
|
|
>
|
|
<Plus className="w-4 h-4" />
|
|
Hinzufuegen
|
|
</button>
|
|
</div>
|
|
|
|
{showAdd && (
|
|
<div className="px-4 py-3 border-b border-gray-800 flex gap-2 items-end">
|
|
<div>
|
|
<label className="text-xs text-gray-500">Benutzer</label>
|
|
<input
|
|
type="text"
|
|
value={form.username}
|
|
onChange={(e) => setForm({ ...form, username: e.target.value })}
|
|
className="w-full bg-gray-800 border border-gray-700 rounded px-2 py-1 text-white text-sm focus:outline-none focus:border-orange-500"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label className="text-xs text-gray-500">Passwort</label>
|
|
<input
|
|
type="password"
|
|
value={form.password}
|
|
onChange={(e) => setForm({ ...form, password: e.target.value })}
|
|
className="w-full bg-gray-800 border border-gray-700 rounded px-2 py-1 text-white text-sm focus:outline-none focus:border-orange-500"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label className="text-xs text-gray-500">Anzeigename</label>
|
|
<input
|
|
type="text"
|
|
value={form.display_name}
|
|
onChange={(e) => setForm({ ...form, display_name: e.target.value })}
|
|
className="w-full bg-gray-800 border border-gray-700 rounded px-2 py-1 text-white text-sm focus:outline-none focus:border-orange-500"
|
|
/>
|
|
</div>
|
|
<button onClick={handleAdd} className="px-3 py-1 bg-orange-600 hover:bg-orange-700 rounded text-sm text-white">
|
|
Anlegen
|
|
</button>
|
|
<button onClick={() => setShowAdd(false)} className="px-3 py-1 bg-gray-800 rounded text-sm text-gray-400">
|
|
Abbrechen
|
|
</button>
|
|
</div>
|
|
)}
|
|
|
|
<div className="divide-y divide-gray-800">
|
|
{users.map((u) => (
|
|
<div key={u.id} className="px-4 py-2.5 flex items-center justify-between">
|
|
<div>
|
|
<span className="text-sm text-white">{u.username}</span>
|
|
{u.display_name && (
|
|
<span className="text-sm text-gray-500 ml-2">({u.display_name})</span>
|
|
)}
|
|
<span className="ml-2 text-xs text-gray-600">{u.role}</span>
|
|
</div>
|
|
<div className="flex items-center gap-3">
|
|
<span className="text-xs text-gray-600">
|
|
{u.last_login ? `Letzter Login: ${new Date(u.last_login).toLocaleString('de-DE')}` : 'Nie eingeloggt'}
|
|
</span>
|
|
<button onClick={() => handleDelete(u.id)} className="text-gray-500 hover:text-red-400">
|
|
<Trash2 className="w-4 h-4" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|