'use client' import { useState } from 'react' import { onboardingService } from '../services/onboarding.service' import type { OnboardingRequest, DepartmentAssignment } from '../types/onboarding' interface FormData { resume_id: string keycloak_user_id: string keycloak_username: string hire_date: string storage_quota_gb: string email_quota_mb: string departments: DepartmentAssignment[] role_ids: string } interface FormErrors { resume_id?: string keycloak_user_id?: string keycloak_username?: string hire_date?: string storage_quota_gb?: string email_quota_mb?: string departments?: { [key: number]: { department_id?: string; position?: string } } } export default function OnboardingForm() { const [formData, setFormData] = useState({ resume_id: '', keycloak_user_id: '', keycloak_username: '', hire_date: '', storage_quota_gb: '20', email_quota_mb: '5120', departments: [], role_ids: '', }) const [errors, setErrors] = useState({}) const [isSubmitting, setIsSubmitting] = useState(false) const [successMessage, setSuccessMessage] = useState('') const [errorMessage, setErrorMessage] = useState('') const validateUUID = (uuid: string): boolean => { const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i return uuidRegex.test(uuid) } const validateForm = (): boolean => { const newErrors: FormErrors = {} // Required fields if (!formData.resume_id) { newErrors.resume_id = 'Resume ID is required' } if (!formData.keycloak_user_id) { newErrors.keycloak_user_id = 'Keycloak User ID is required' } else if (!validateUUID(formData.keycloak_user_id)) { newErrors.keycloak_user_id = 'Invalid UUID format' } if (!formData.keycloak_username) { newErrors.keycloak_username = 'Keycloak Username is required' } if (!formData.hire_date) { newErrors.hire_date = 'Hire Date is required' } // Validate storage quota const storageQuota = parseInt(formData.storage_quota_gb) if (formData.storage_quota_gb && storageQuota <= 0) { newErrors.storage_quota_gb = 'Storage quota must be positive' } // Validate departments const departmentErrors: { [key: number]: { department_id?: string; position?: string } } = {} formData.departments.forEach((dept, index) => { const deptErrors: { department_id?: string; position?: string } = {} if (!dept.department_id) { deptErrors.department_id = 'Department ID is required' } if (!dept.position) { deptErrors.position = 'Position is required' } if (Object.keys(deptErrors).length > 0) { departmentErrors[index] = deptErrors } }) if (Object.keys(departmentErrors).length > 0) { newErrors.departments = departmentErrors } setErrors(newErrors) return Object.keys(newErrors).length === 0 } const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() if (!validateForm()) { return } setIsSubmitting(true) setErrorMessage('') setSuccessMessage('') try { const request: OnboardingRequest = { resume_id: parseInt(formData.resume_id), keycloak_user_id: formData.keycloak_user_id, keycloak_username: formData.keycloak_username, hire_date: formData.hire_date, departments: formData.departments, role_ids: formData.role_ids ? formData.role_ids.split(',').map((id) => parseInt(id.trim())) : [], storage_quota_gb: formData.storage_quota_gb ? parseInt(formData.storage_quota_gb) : undefined, email_quota_mb: formData.email_quota_mb ? parseInt(formData.email_quota_mb) : undefined, } const response = await onboardingService.onboardEmployee(request) setSuccessMessage(response.message) // Reset form setFormData({ resume_id: '', keycloak_user_id: '', keycloak_username: '', hire_date: '', storage_quota_gb: '20', email_quota_mb: '5120', departments: [], role_ids: '', }) } catch (error: any) { const message = error.response?.data?.detail || 'An error occurred' setErrorMessage(message) } finally { setIsSubmitting(false) } } const handleInputChange = (field: keyof FormData, value: string) => { setFormData((prev) => ({ ...prev, [field]: value })) // Clear error for this field if (errors[field as keyof FormErrors]) { setErrors((prev) => { const newErrors = { ...prev } delete newErrors[field as keyof FormErrors] return newErrors }) } } const addDepartment = () => { setFormData((prev) => ({ ...prev, departments: [ ...prev.departments, { department_id: 0, position: '', membership_type: 'permanent', }, ], })) } const removeDepartment = (index: number) => { setFormData((prev) => ({ ...prev, departments: prev.departments.filter((_, i) => i !== index), })) } const updateDepartment = (index: number, field: keyof DepartmentAssignment, value: any) => { setFormData((prev) => ({ ...prev, departments: prev.departments.map((dept, i) => i === index ? { ...dept, [field]: value } : dept ), })) } return (

Employee Onboarding

{successMessage && (
{successMessage}
)} {errorMessage && (
{errorMessage}
)}
{/* Basic Information */}

Basic Information

{/* Resume ID */}
handleInputChange('resume_id', e.target.value)} className={`w-full px-3 py-2 border rounded ${ errors.resume_id ? 'border-red-500' : 'border-gray-300' }`} /> {errors.resume_id && (

{errors.resume_id}

)}
{/* Keycloak User ID */}
handleInputChange('keycloak_user_id', e.target.value)} placeholder="550e8400-e29b-41d4-a716-446655440000" className={`w-full px-3 py-2 border rounded ${ errors.keycloak_user_id ? 'border-red-500' : 'border-gray-300' }`} /> {errors.keycloak_user_id && (

{errors.keycloak_user_id}

)}
{/* Keycloak Username */}
handleInputChange('keycloak_username', e.target.value)} className={`w-full px-3 py-2 border rounded ${ errors.keycloak_username ? 'border-red-500' : 'border-gray-300' }`} /> {errors.keycloak_username && (

{errors.keycloak_username}

)}
{/* Hire Date */}
handleInputChange('hire_date', e.target.value)} className={`w-full px-3 py-2 border rounded ${ errors.hire_date ? 'border-red-500' : 'border-gray-300' }`} /> {errors.hire_date && (

{errors.hire_date}

)}
{/* Storage Quota */}
handleInputChange('storage_quota_gb', e.target.value)} className={`w-full px-3 py-2 border rounded ${ errors.storage_quota_gb ? 'border-red-500' : 'border-gray-300' }`} /> {errors.storage_quota_gb && (

{errors.storage_quota_gb}

)}
{/* Email Quota */}
handleInputChange('email_quota_mb', e.target.value)} className="w-full px-3 py-2 border border-gray-300 rounded" />
{/* Department Assignments */}

Department Assignments

{formData.departments.map((dept, index) => (
{/* Department ID */}
updateDepartment(index, 'department_id', parseInt(e.target.value) || 0) } className={`w-full px-3 py-2 border rounded ${ errors.departments?.[index]?.department_id ? 'border-red-500' : 'border-gray-300' }`} /> {errors.departments?.[index]?.department_id && (

{errors.departments[index].department_id}

)}
{/* Position */}
updateDepartment(index, 'position', e.target.value)} className={`w-full px-3 py-2 border rounded ${ errors.departments?.[index]?.position ? 'border-red-500' : 'border-gray-300' }`} /> {errors.departments?.[index]?.position && (

{errors.departments[index].position}

)}
{/* Membership Type */}
))}
{/* Role Assignments */}

Role Assignments

handleInputChange('role_ids', e.target.value)} placeholder="1, 2, 3" className="w-full px-3 py-2 border border-gray-300 rounded" />
{/* Submit Button */}
) }