// File: frontend/app/(protected)/admin/users/_components/user-form-dialog.jsx 'use client'; import { useState, useEffect } from 'react'; import api from '@/lib/api'; import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from '@/components/ui/dialog'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Switch } from '@/components/ui/switch'; import { Checkbox } from "@/components/ui/checkbox"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Trash2 } from 'lucide-react'; import { ScrollArea } from '@/components/ui/scroll-area'; export function UserFormDialog({ user, isOpen, setIsOpen, onSuccess }) { const [formData, setFormData] = useState({}); const [allRoles, setAllRoles] = useState([]); const [selectedSystemRoles, setSelectedSystemRoles] = useState(new Set()); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(''); const [allProjects, setAllProjects] = useState([]); const [projectRoles, setProjectRoles] = useState([]); const [selectedProjectId, setSelectedProjectId] = useState(''); const [selectedRoleId, setSelectedRoleId] = useState(''); const isEditMode = !!user; useEffect(() => { const fetchPrerequisites = async () => { try { const [rolesRes, projectsRes] = await Promise.all([ api.get('/rbac/roles'), api.get('/projects'), ]); setAllRoles(rolesRes.data); setAllProjects(projectsRes.data); } catch (err) { console.error('Failed to fetch prerequisites', err); } }; if (isOpen) { fetchPrerequisites(); } }, [isOpen]); useEffect(() => { const fetchUserData = async () => { if (isEditMode) { setFormData({ username: user.username, email: user.email, first_name: user.first_name || '', last_name: user.last_name || '', is_active: user.is_active, }); setSelectedSystemRoles(new Set(user.Roles?.map(role => role.id) || [])); try { const res = await api.get(`/rbac/user-project-roles?userId=${user.id}`); setProjectRoles(res.data); } catch (err) { console.error("Failed to fetch user's project roles", err); setProjectRoles([]); } } else { setFormData({ username: '', email: '', password: '', first_name: '', last_name: '', is_active: true }); setSelectedSystemRoles(new Set()); setProjectRoles([]); } setError(''); setSelectedProjectId(''); setSelectedRoleId(''); }; if (isOpen) { fetchUserData(); } }, [user, isOpen]); const handleInputChange = (e) => { const { id, value } = e.target; setFormData((prev) => ({ ...prev, [id]: value })); }; const handleSystemRoleChange = (roleId) => { setSelectedSystemRoles(prev => { const newSet = new Set(prev); if (newSet.has(roleId)) newSet.delete(roleId); else newSet.add(roleId); return newSet; }); }; const handleAddProjectRole = async () => { if (!selectedProjectId || !selectedRoleId) { setError("Please select both a project and a role."); return; } setIsLoading(true); setError(''); try { await api.post('/rbac/user-project-roles', { userId: user.id, projectId: selectedProjectId, roleId: selectedRoleId }); const res = await api.get(`/rbac/user-project-roles?userId=${user.id}`); setProjectRoles(res.data); setSelectedProjectId(''); setSelectedRoleId(''); } catch(err) { setError(err.response?.data?.message || 'Failed to add project role.'); } finally { setIsLoading(false); } }; const handleRemoveProjectRole = async (assignment) => { setIsLoading(true); setError(''); try { await api.delete('/rbac/user-project-roles', { data: { userId: user.id, projectId: assignment.project_id, roleId: assignment.role_id } }); setProjectRoles(prev => prev.filter(p => p.id !== assignment.id)); } catch(err) { setError(err.response?.data?.message || 'Failed to remove project role.'); } finally { setIsLoading(false); } }; const handleSaveUserDetails = async () => { setIsLoading(true); setError(''); const payload = { ...formData, roles: Array.from(selectedSystemRoles) }; try { if (isEditMode) { await api.put(`/users/${user.id}`, payload); } else { await api.post('/users', payload); } onSuccess(); setIsOpen(false); } catch (err) { setError(err.response?.data?.message || 'An unexpected error occurred.'); } finally { setIsLoading(false); } }; return ( {isEditMode ? `Edit User: ${user.username}` : 'Create New User'}
{/* Section 1: User Details & System Roles */}

User Details & System Roles

{!isEditMode && (
)}
{allRoles.map(role => (
handleSystemRoleChange(role.id)} />
))}
setFormData(prev => ({...prev, is_active: checked}))} />
{/* Section 2: Project Role Assignments */}

Project Role Assignments

{isEditMode ? ( <>

Assign New Project Role

Current Assignments

{projectRoles.length > 0 ? projectRoles.map(pr => (
{pr.Project.name} as {pr.Role.name}
)) :

No project assignments.

}
) :

Save the user first to assign project roles.

}
{error &&

{error}

}
); }