feat: add company management and user-company assignment in admin panel
All checks were successful
Staging Build / build (push) Successful in 2m35s

This commit is contained in:
DanielS
2026-06-24 17:12:40 +02:00
parent 6b66cc5c41
commit 7a14aa0f75
8 changed files with 346 additions and 15 deletions

View File

@@ -11,9 +11,10 @@ import {
TableRow,
} from '@/components/ui/table'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Key, Trash2, Mail, Loader2 } from 'lucide-react'
import { Key, Trash2, Mail, Loader2, Building2 } 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'
@@ -30,7 +31,12 @@ const ROLE_BADGE_CLASSES: Record<Role, string> = {
gesperrt: 'bg-red-500/20 text-red-400 border border-red-500/30',
}
export function UserList({ initialUsers }: { initialUsers: any[] }) {
interface UserListProps {
initialUsers: any[]
companies: { id: string; name: string }[]
}
export function UserList({ initialUsers, companies }: UserListProps) {
const router = useRouter()
const [loadingId, setLoadingId] = useState<string | null>(null)
@@ -55,6 +61,18 @@ export function UserList({ initialUsers }: { initialUsers: any[] }) {
}
}
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)
@@ -69,7 +87,7 @@ export function UserList({ initialUsers }: { initialUsers: any[] }) {
<CardHeader>
<CardTitle>Benutzerverwaltung</CardTitle>
<CardDescription className="text-slate-400">
Verwalten Sie Rollen, Passwörter und Benutzerkonten.
Rollen, Firmenzuweisungen, Passwörter und Benutzerkonten verwalten.
</CardDescription>
</CardHeader>
<CardContent>
@@ -78,6 +96,7 @@ export function UserList({ initialUsers }: { initialUsers: any[] }) {
<TableRow className="border-white/10 hover:bg-white/5">
<TableHead className="text-slate-200">E-Mail</TableHead>
<TableHead className="text-slate-200">Rolle</TableHead>
<TableHead className="text-slate-200">Firma</TableHead>
<TableHead className="text-slate-200">Zuletzt angemeldet</TableHead>
<TableHead className="text-right text-slate-200">Aktionen</TableHead>
</TableRow>
@@ -86,6 +105,7 @@ export function UserList({ initialUsers }: { initialUsers: any[] }) {
{initialUsers.map((user) => {
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
return (
@@ -116,6 +136,25 @@ export function UserList({ initialUsers }: { initialUsers: any[] }) {
)}
</div>
</TableCell>
<TableCell>
<div className="flex items-center gap-2">
<Building2 className="w-4 h-4 text-slate-500 shrink-0" />
{isLoadingCompany ? (
<Loader2 className="h-4 w-4 animate-spin text-slate-400" />
) : (
<select
value={user.company_id || ''}
onChange={(e) => handleCompanyChange(user.id, e.target.value)}
className="text-xs bg-white/5 border border-white/10 rounded px-2 py-1 text-slate-300 hover:bg-white/10 cursor-pointer focus:outline-none focus:ring-1 focus:ring-primary/50 max-w-[150px]"
>
<option value="">Keine Firma</option>
{companies.map((c) => (
<option key={c.id} value={c.id}>{c.name}</option>
))}
</select>
)}
</div>
</TableCell>
<TableCell className="text-slate-400 text-sm">
{user.last_sign_in_at ? new Date(user.last_sign_in_at).toLocaleString('de-DE') : 'Noch nie'}
</TableCell>