From a2f51f0d81b0cade48c8e70a244c4ec17abb6571 Mon Sep 17 00:00:00 2001 From: Dicken Date: Tue, 26 May 2026 13:53:13 +0200 Subject: [PATCH] Dateien nach "frontend/src" hochladen --- frontend/src/App.jsx | 148 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 142 insertions(+), 6 deletions(-) diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 9e1306c..14839e0 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -701,6 +701,137 @@ const Sec = ({title, children}) => ( ); +// ── Benutzerverwaltung ──────────────────────────────────────────────────────── +function UserManagement({ toast }) { + const [users, setUsers] = useState([]); + const [loading, setLoading] = useState(true); + const [form, setForm] = useState({ username:'', password:'', role:'user' }); + const [resetId, setResetId] = useState(null); + const [resetPw, setResetPw] = useState(''); + const [delId, setDelId] = useState(null); + const { confirm, ConfirmDialog } = useConfirm(); + + const load = () => { + setLoading(true); + api('/admin/users').then(setUsers).catch(e=>toast(e.message,'error')).finally(()=>setLoading(false)); + }; + useEffect(()=>{ load(); },[]); + + const create = async () => { + if (!form.username.trim()||!form.password) { toast('Alle Felder ausfüllen','error'); return; } + try { + await api('/admin/users',{body:form}); + toast(`Benutzer "${form.username}" angelegt`); + setForm({username:'',password:'',role:'user'}); load(); + } catch(e) { toast(e.message,'error'); } + }; + + const del = async id => { + if (!await confirm('Benutzer und alle seine Daten wirklich löschen?')) return; + try { await api(`/admin/users/${id}`,{method:'DELETE'}); toast('Gelöscht'); load(); } + catch(e) { toast(e.message,'error'); } + }; + + const resetPassword = async () => { + if (!resetPw||resetPw.length<8) { toast('Mind. 8 Zeichen','error'); return; } + try { + await api(`/admin/users/${resetId}/reset-password`,{method:'PUT',body:{newPassword:resetPw}}); + toast('Passwort zurückgesetzt'); setResetId(null); setResetPw(''); + } catch(e) { toast(e.message,'error'); } + }; + + return ( +
+ + + {/* Neuen Benutzer anlegen */} + + setForm(f=>({...f,username:e.target.value}))} autoCapitalize="none"/> + setForm(f=>({...f,password:e.target.value}))}/> +
+ + +
+ +
+ + {/* Passwort-Reset Modal */} + {resetId && ( +
+
+
+ Passwort zurücksetzen +
+ setResetPw(e.target.value)}/> +
+ + +
+
+
+ )} + + {/* Benutzerliste */} + + {loading &&
Lädt…
} + {users.map(u => ( +
+
+
+ {u.username} + {u.role} +
+
+ + {u.role !== 'admin' && ( + + )} +
+
+ {/* Statistik */} +
+ {[ + ['◈ Archiv', u.archiv], + ['📦 Bestellungen', u.bestellung], + ['✓ Todos', u.todos], + ['🔗 Links', u.links], + [`✎ ${u.noteLen} Zeichen`, null], + ].map(([label, val]) => ( + + {label}{val !== null ? `: ${val}` : ''} + + ))} +
+
+ ))} +
+
+ ); +} + // Field außerhalb definiert → Tastatur bleibt beim Tippen erhalten const Field = ({ label, type='text', value, onChange, placeholder='', autoCapitalize='off' }) => (
@@ -711,7 +842,7 @@ const Field = ({ label, type='text', value, onChange, placeholder='', autoCapita
); -function AdminPanel({ toast, mobile }) { +function AdminPanel({ toast, mobile, user }) { const [section, setSection] = useState('profil'); const [pw, setPw] = useState({ current:'', newPw:'', confirm:'' }); const [avatar, setAvatar] = useState(localStorage.getItem('dd_avatar') || null); @@ -765,8 +896,9 @@ function AdminPanel({ toast, mobile }) {

Einstellungen

-
- {[['profil','Profil'],['backup','Backup']].map(([k,l]) => ( +
+ {[['profil','Profil'], ...(user?.role==='admin'?[['benutzer','Benutzer'],['backup','Backup']]:[])] + .map(([k,l]) => ( } - + {user?.role==='admin' && setUn(p=>({...p,newUsername:e.target.value}))} /> setUn(p=>({...p,unPw:e.target.value}))} /> - + } setPw(p=>({...p,current:e.target.value}))} /> setPw(p=>({...p,newPw:e.target.value}))} /> @@ -830,6 +962,10 @@ function AdminPanel({ toast, mobile }) {
)} + {section === 'benutzer' && user?.role==='admin' && ( +
+ )} + {section === 'backup' && (
@@ -917,7 +1053,7 @@ export default function App() { )}
{active==='dashboard' && } - {active==='admin' && user?.role==='admin' && } + {active==='admin' && user?.role==='admin' && } {activeTool && }