proj/Frontend/components/dashboard/user-management.tsx
2026-01-22 11:49:48 +01:00

205 lines
9.8 KiB
TypeScript

"use client"
import { useState, useEffect } from "react"
import { useAuth } from "@/lib/auth-context"
import { type User } from "@/lib/types"
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { MoreHorizontal, Shield, ShieldAlert, Trash, KeyRound } from "lucide-react"
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog"
import { Label } from "@/components/ui/label"
import { useToast } from "@/components/ui/use-toast"
export function UserManagement() {
const { getAllUsers, updateUserRole, deleteUser, adminResetPassword, user: currentUser } = useAuth()
const { toast } = useToast()
const [users, setUsers] = useState<User[]>([])
const [loading, setLoading] = useState(true)
// State for reset password dialog
const [resetDialogOpen, setResetDialogOpen] = useState(false)
const [selectedUser, setSelectedUser] = useState<User | null>(null)
const [newPassword, setNewPassword] = useState("")
const loadUsers = async () => {
setLoading(true)
const data = await getAllUsers()
setUsers(data)
setLoading(false)
}
useEffect(() => {
loadUsers()
}, [])
const handleRoleChange = async (userId: number, newRole: string) => {
const success = await updateUserRole(userId, newRole)
if (success) {
toast({ title: "Rolle aktualisiert", description: `User ist jetzt ${newRole}` })
loadUsers()
} else {
toast({ title: "Fehler", description: "Rolle konnte nicht geändert werden", variant: "destructive" })
}
}
const handleDelete = async (userId: number) => {
if (confirm("Sind Sie sicher, dass Sie diesen Benutzer löschen möchten?")) {
const success = await deleteUser(userId)
if (success) {
toast({ title: "Benutzer gelöscht" })
loadUsers()
} else {
toast({ title: "Fehler", description: "Benutzer konnte nicht gelöscht werden", variant: "destructive" })
}
}
}
const handleResetPassword = async () => {
if (!selectedUser || !newPassword) return
const success = await adminResetPassword(selectedUser.id, newPassword)
if (success) {
toast({ title: "Passwort zurückgesetzt" })
setResetDialogOpen(false)
setNewPassword("")
setSelectedUser(null)
} else {
toast({ title: "Fehler", description: "Passwort konnte nicht zurückgesetzt werden", variant: "destructive" })
}
}
if (loading) return <div>Lade Benutzer...</div>
return (
<div className="space-y-4">
<div className="rounded-md border">
<Table>
<TableHeader>
<TableRow>
<TableHead>Name</TableHead>
<TableHead>Email</TableHead>
<TableHead>Rolle</TableHead>
<TableHead className="w-[70px]"></TableHead>
</TableRow>
</TableHeader>
<TableBody>
{users.map((user) => (
<TableRow key={user.id}>
<TableCell className="font-medium">{user.name}</TableCell>
<TableCell>{user.email}</TableCell>
<TableCell>
<div className="flex items-center gap-2">
{user.role === "ADMIN" && <ShieldAlert className="h-4 w-4 text-destructive" />}
{user.role === "LEHRKRAFT" && <span className="text-muted-foreground">Lehrkraft</span>}
{user.role === "RAUMBETREUER" && <span className="text-primary">Raumbetreuer</span>}
{user.role === "ADMIN" && <span className="font-bold text-destructive">Admin</span>}
</div>
</TableCell>
<TableCell>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="h-8 w-8 p-0">
<span className="sr-only">Open menu</span>
<MoreHorizontal className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuLabel>Aktionen</DropdownMenuLabel>
<DropdownMenuItem onClick={() => navigator.clipboard.writeText(user.email)}>
Email kopieren
</DropdownMenuItem>
<DropdownMenuSeparator />
{/* Safety: Cannot modify ID 1 and cannot modify self here ideally, but backend blocks ID 1 */}
{user.id !== 1 && (
<>
<DropdownMenuItem onClick={() => {
setSelectedUser(user)
setResetDialogOpen(true)
}}>
<KeyRound className="mr-2 h-4 w-4" /> Passwort zurücksetzen
</DropdownMenuItem>
<DropdownMenuSeparator />
{user.role !== "ADMIN" && (
<DropdownMenuItem onClick={() => handleRoleChange(user.id, "ADMIN")}>
<ShieldAlert className="mr-2 h-4 w-4" /> Zum Admin machen
</DropdownMenuItem>
)}
{user.role !== "LEHRKRAFT" && (
<DropdownMenuItem onClick={() => handleRoleChange(user.id, "LEHRKRAFT")}>
Zum Lehrer herabstufen
</DropdownMenuItem>
)}
{user.role !== "RAUMBETREUER" && (
<DropdownMenuItem onClick={() => handleRoleChange(user.id, "RAUMBETREUER")}>
<Shield className="mr-2 h-4 w-4" /> Zum Raumbetreuer machen
</DropdownMenuItem>
)}
<DropdownMenuSeparator />
<DropdownMenuItem onClick={() => handleDelete(user.id)} className="text-destructive">
<Trash className="mr-2 h-4 w-4" /> Löschen
</DropdownMenuItem>
</>
)}
</DropdownMenuContent>
</DropdownMenu>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
<Dialog open={resetDialogOpen} onOpenChange={setResetDialogOpen}>
<DialogContent>
<DialogHeader>
<DialogTitle>Passwort zurücksetzen für {selectedUser?.name}</DialogTitle>
<DialogDescription>
Setzen Sie ein neues Passwort für diesen Benutzer.
</DialogDescription>
</DialogHeader>
<div className="grid gap-4 py-4">
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="new-pass" className="text-right">
Neues Passwort
</Label>
<Input
id="new-pass"
type="password"
value={newPassword}
onChange={(e) => setNewPassword(e.target.value)}
className="col-span-3"
/>
</div>
</div>
<DialogFooter>
<Button variant="outline" onClick={() => setResetDialogOpen(false)}>Abbrechen</Button>
<Button onClick={handleResetPassword}>Speichern</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</div>
)
}