@@ -2,6 +2,7 @@ import { useEffect, useState } from 'react';
22
33import { Loader2 } from 'lucide-react' ;
44import { useTranslation } from 'react-i18next' ;
5+ import { z } from 'zod' ;
56
67import { Button } from '@/components/ui/button' ;
78import { FormInput } from '@/components/ui/FormInput' ;
@@ -52,12 +53,6 @@ export const UserModal: React.FC<UserModalProps> = ({
5253 status : 'invited' ,
5354 } ) ;
5455
55- const [ errors , setErrors ] = useState ( {
56- username : false ,
57- email : false ,
58- role : false ,
59- } ) ;
60-
6156 // Reset form when modal opens or user changes
6257 useEffect ( ( ) => {
6358 if ( isOpen ) {
@@ -80,33 +75,29 @@ export const UserModal: React.FC<UserModalProps> = ({
8075 status : 'invited' ,
8176 } ) ;
8277 }
83- setErrors ( { username : false , email : false , role : false } ) ;
8478 }
8579 } , [ isOpen , user , mode ] ) ;
8680
81+ const emailSchema = z . string ( ) . email ( ) ;
82+
83+ const isEmailValid = ( email : string ) : boolean => {
84+ try {
85+ emailSchema . parse ( email ) ;
86+ return true ;
87+ } catch {
88+ return false ;
89+ }
90+ } ;
91+
8792 const isFormValid = ( ) : boolean => {
8893 const hasUsername = Boolean ( formData . username . trim ( ) ) ;
89- const hasEmail = Boolean ( formData . email . trim ( ) ) ;
94+ const hasValidEmail = Boolean ( formData . email . trim ( ) ) && isEmailValid ( formData . email . trim ( ) ) ;
9095 const hasValidRole = Boolean ( formData . role && formData . role !== 0 ) ;
91- return hasUsername && hasEmail && hasValidRole ;
92- } ;
93-
94- const validateForm = ( ) : boolean => {
95- const newErrors = {
96- username : ! formData . username . trim ( ) ,
97- email : ! formData . email . trim ( ) ,
98- role : ! formData . role || formData . role === 0 ,
99- } ;
10096
101- setErrors ( newErrors ) ;
102- return ! Object . values ( newErrors ) . some ( Boolean ) ;
97+ return hasUsername && hasValidEmail && hasValidRole ;
10398 } ;
10499
105100 const handleSubmit = async ( ) : Promise < void > => {
106- if ( ! validateForm ( ) ) {
107- return ;
108- }
109-
110101 try {
111102 if ( mode === 'edit' && user ) {
112103 await onSave ( { ...user , ...formData } ) ;
@@ -126,7 +117,7 @@ export const UserModal: React.FC<UserModalProps> = ({
126117
127118 const modalTitle = mode === 'create' ? t ( 'addUser' ) : t ( 'editProfile' ) ;
128119 const submitText = mode === 'create' ? t ( 'addUser' ) : t ( 'saveUser' ) ;
129- const isButtonDisabled = isLoading || ( mode === 'edit' && ! isFormValid ( ) ) ;
120+ const isButtonDisabled = isLoading || ! isFormValid ( ) ;
130121
131122 return (
132123 < div className = 'text-gray-800' >
@@ -135,8 +126,6 @@ export const UserModal: React.FC<UserModalProps> = ({
135126 < FormInput
136127 required
137128 disabled = { mode === 'edit' }
138- error = { errors . email }
139- errorMessage = 'Email is required.'
140129 label = {
141130 < >
142131 < span style = { { color : 'red' } } > *</ span > { t ( 'email' ) }
@@ -149,8 +138,6 @@ export const UserModal: React.FC<UserModalProps> = ({
149138
150139 < FormInput
151140 required
152- error = { errors . username }
153- errorMessage = 'Username is required.'
154141 helperText = 'Visible to all Scribe users'
155142 label = {
156143 < >
@@ -175,8 +162,6 @@ export const UserModal: React.FC<UserModalProps> = ({
175162
176163 < FormSelect
177164 disabled = { disableRoleSelection }
178- error = { errors . role }
179- errorMessage = 'Role is required.'
180165 label = {
181166 < >
182167 < span style = { { color : 'red' } } > *</ span > { t ( 'role' ) }
0 commit comments