'use client' import { useState, useRef, useEffect, Fragment } from 'react' import { useRouter } from 'next/navigation' import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Key, Trash2, Mail, Loader2, Building2, Ban, Unlock, Search } from 'lucide-react' import { Button } from '@/components/ui/button' import { deleteUser, resetPassword, updateUserRole } from '@/lib/actions/users' import { assignCompanyToUser } from '@/lib/actions/companies' import { Badge } from '@/components/ui/badge' type Role = 'admin' | 'partner' | 'gesperrt' const ROLE_LABELS: Record = { admin: 'Admin', partner: 'Partner', gesperrt: 'Gesperrt', } const ROLE_BADGE_CLASSES: Record = { admin: 'bg-purple-500/20 text-purple-400 border border-purple-500/30', partner: 'bg-blue-500/20 text-blue-400 border border-blue-500/30', gesperrt: 'bg-red-500/20 text-red-400 border border-red-500/30', } interface UserListProps { initialUsers: any[] companies: { id: string; name: string }[] } export function UserList({ initialUsers, companies }: UserListProps) { const router = useRouter() const [loadingId, setLoadingId] = useState(null) const [companyDropdownOpen, setCompanyDropdownOpen] = useState(null) const [companySearch, setCompanySearch] = useState('') const [searchQuery, setSearchQuery] = useState('') const [groupByCompany, setGroupByCompany] = useState(false) const dropdownRef = useRef(null) useEffect(() => { function handleClickOutside(e: MouseEvent) { if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) { setCompanyDropdownOpen(null) setCompanySearch('') } } document.addEventListener('mousedown', handleClickOutside) return () => document.removeEventListener('mousedown', handleClickOutside) }, []) const handleDelete = async (id: string) => { if (confirm('Möchten Sie diesen Benutzer wirklich löschen?')) { setLoadingId(id) await deleteUser(id) setLoadingId(null) router.refresh() } } const handleRoleChange = async (id: string, newRole: Role) => { setLoadingId(id + '-role') try { await updateUserRole(id, newRole) router.refresh() } catch (e) { console.error('Fehler beim Ändern der Rolle:', e) } finally { setLoadingId(null) } } const handleToggleLock = async (id: string, currentRole: Role) => { const newRole = currentRole === 'gesperrt' ? 'partner' : 'gesperrt' setLoadingId(id + '-lock') try { await updateUserRole(id, newRole) router.refresh() } catch (e) { console.error('Fehler beim Sperren/Entsperren:', e) } finally { setLoadingId(null) } } const handleCompanyChange = async (userId: string, companyId: string) => { setLoadingId(userId + '-company') try { await assignCompanyToUser(userId, companyId === '' ? null : companyId) router.refresh() } catch (e) { console.error('Fehler beim Zuweisen der Firma:', e) } finally { setLoadingId(null) } } const handleResetPassword = async (email: string) => { try { await resetPassword(email) alert('Password-Reset Link generiert (siehe Mailpit/Supabase Log)') } catch (error) { alert('Fehler beim Passwort-Reset') } } const filteredUsers = initialUsers.filter((user) => { const emailMatch = user.email?.toLowerCase().includes(searchQuery.toLowerCase()) const companyMatch = user.company_name?.toLowerCase().includes(searchQuery.toLowerCase()) const roleMatch = user.role?.toLowerCase().includes(searchQuery.toLowerCase()) return emailMatch || companyMatch || roleMatch }) const displayUsers = groupByCompany ? [...filteredUsers].sort((a, b) => { const nameA = a.company_name || 'Keine Firma' const nameB = b.company_name || 'Keine Firma' if (!a.company_name && b.company_name) return 1 if (a.company_name && !b.company_name) return -1 return nameA.localeCompare(nameB) }) : filteredUsers let lastCompanyName: string | null = null return ( Benutzerverwaltung Rollen, Firmenzuweisungen, Passwörter und Benutzerkonten verwalten.
setSearchQuery(e.target.value)} className="w-full pl-9 pr-4 py-2 text-sm bg-white/5 border border-white/10 rounded-md text-slate-200 placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 focus:ring-offset-slate-950 transition-all" />
setGroupByCompany(e.target.checked)} className="h-4 w-4 rounded border-white/10 bg-slate-950 text-primary focus:ring-primary focus:ring-offset-slate-950 accent-primary cursor-pointer" />
E-Mail Rolle Firma Zuletzt angemeldet Aktionen {displayUsers.map((user: any) => { const role: Role = (['admin', 'partner', 'gesperrt'].includes(user.role) ? user.role : 'partner') as Role const isLoadingRole = loadingId === user.id + '-role' const isLoadingCompany = loadingId === user.id + '-company' const isLoadingDelete = loadingId === user.id const currentCompanyName = user.company_name || 'Keine Firma' const showGroupHeader = groupByCompany && currentCompanyName !== lastCompanyName lastCompanyName = currentCompanyName return ( {showGroupHeader && ( Firma: {currentCompanyName} )}
{user.email}
{isLoadingRole ? ( ) : ( )}
{isLoadingCompany ? ( ) : ( )}
{companyDropdownOpen === user.id && (
setCompanySearch(e.target.value)} className="w-full text-xs bg-white/5 border border-white/10 rounded px-2 py-1.5 text-slate-200 placeholder-slate-500 focus:outline-none focus:ring-1 focus:ring-primary/50" autoFocus />
{companies .filter((c) => c.name.toLowerCase().includes(companySearch.toLowerCase())) .map((c) => ( ))}
)}
{user.last_sign_in_at ? new Date(user.last_sign_in_at).toLocaleString('de-DE') : 'Noch nie'}
) })}
) }