import { useEffect } from 'react'; import type { ReactElement } from 'react'; import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; import { Modal, FormField, FormSelect, PrimaryButton, SecondaryButton } from '@/components/shared'; import type { CreateRoleRequest } from '@/types/role'; // Validation schema const newRoleSchema = z.object({ name: z.string().min(1, 'Role name is required'), code: z.enum(['super_admin', 'tenant_admin', 'quality_manager', 'developer', 'viewer'], { message: 'Role code is required', }), description: z.string().min(1, 'Description is required'), scope: z.enum(['platform', 'tenant', 'module'], { message: 'Scope is required', }), }); type NewRoleFormData = z.infer; interface NewRoleModalProps { isOpen: boolean; onClose: () => void; onSubmit: (data: CreateRoleRequest) => Promise; isLoading?: boolean; } const scopeOptions = [ { value: 'platform', label: 'Platform' }, { value: 'tenant', label: 'Tenant' }, { value: 'module', label: 'Module' }, ]; const roleCodeOptions = [ { value: 'super_admin', label: 'Super Admin' }, { value: 'tenant_admin', label: 'Tenant Admin' }, { value: 'quality_manager', label: 'Quality Manager' }, { value: 'developer', label: 'Developer' }, { value: 'viewer', label: 'Viewer' }, ]; export const NewRoleModal = ({ isOpen, onClose, onSubmit, isLoading = false, }: NewRoleModalProps): ReactElement | null => { const { register, handleSubmit, setValue, watch, reset, setError, clearErrors, formState: { errors }, } = useForm({ resolver: zodResolver(newRoleSchema), defaultValues: { scope: 'platform', code: undefined, }, }); const scopeValue = watch('scope'); const codeValue = watch('code'); // Reset form when modal closes useEffect(() => { if (!isOpen) { reset({ name: '', code: undefined, description: '', scope: 'platform', }); clearErrors(); } }, [isOpen, reset, clearErrors]); const handleFormSubmit = async (data: NewRoleFormData): Promise => { clearErrors(); try { await onSubmit(data); } catch (error: any) { // Handle validation errors from API if (error?.response?.data?.details && Array.isArray(error.response.data.details)) { const validationErrors = error.response.data.details; validationErrors.forEach((detail: { path: string; message: string }) => { if (detail.path === 'name' || detail.path === 'code' || detail.path === 'description' || detail.path === 'scope') { setError(detail.path as keyof NewRoleFormData, { type: 'server', message: detail.message, }); } }); } else { // Handle general errors // Check for nested error object with message property const errorObj = error?.response?.data?.error; const errorMessage = (typeof errorObj === 'object' && errorObj !== null && 'message' in errorObj ? errorObj.message : null) || (typeof errorObj === 'string' ? errorObj : null) || error?.response?.data?.message || error?.message || 'Failed to create role. Please try again.'; setError('root', { type: 'server', message: typeof errorMessage === 'string' ? errorMessage : 'Failed to create role. Please try again.', }); } } }; return ( Cancel {isLoading ? 'Creating...' : 'Create Role'} } >
{/* General Error Display */} {errors.root && (

{errors.root.message}

)} {/* Role Name and Role Code Row */}
setValue('code', value as 'super_admin' | 'tenant_admin' | 'quality_manager' | 'developer' | 'viewer')} error={errors.code?.message} />
{/* Description */} {/* Scope */} setValue('scope', value as 'platform' | 'tenant' | 'module')} error={errors.scope?.message} />
); };