Files
donetick/src/views/Modals/Inputs/CreateChildUserModal.jsx
2026-07-29 10:38:20 -04:00

212 lines
6.1 KiB
JavaScript

import { FormControl, FormHelperText, Input, Typography } from '@mui/joy'
import { useEffect, useState } from 'react'
import ModalActions from '../../../components/common/ModalActions'
import { useResponsiveModal } from '../../../hooks/useResponsiveModal'
function CreateChildUserModal({ isOpen, onClose, onSuccess }) {
const { ResponsiveModal } = useResponsiveModal()
const [childName, setChildName] = useState('')
const [displayName, setDisplayName] = useState('')
const [password, setPassword] = useState('')
const [confirmPassword, setConfirmPassword] = useState('')
const [errors, setErrors] = useState({})
const [touched, setTouched] = useState({})
const [isSubmitting, setIsSubmitting] = useState(false)
useEffect(() => {
const newErrors = {}
if (touched.childName) {
if (!childName.trim()) {
newErrors.childName = 'Sub account name is required'
} else if (childName.length < 2) {
newErrors.childName = 'Sub account name must be at least 2 characters'
} else if (childName.length > 20) {
newErrors.childName = 'Sub account name must be less than 20 characters'
} else if (!/^[a-z.-]+$/.test(childName)) {
newErrors.childName =
'Sub account name can only contain lowercase letters, dot and dash'
}
}
if (touched.password) {
if (!password) {
newErrors.password = 'Password is required'
} else if (password.length < 8) {
newErrors.password = 'Password must be between 8 and 64 characters'
} else if (password.length > 64) {
newErrors.password = 'Password must be between 8 and 64 characters'
}
}
if (touched.confirmPassword) {
if (password !== confirmPassword) {
newErrors.confirmPassword = 'Passwords do not match'
}
}
if (touched.displayName && displayName.length > 50) {
newErrors.displayName = 'Display name must be less than 50 characters'
}
setErrors(newErrors)
}, [childName, displayName, password, confirmPassword, touched])
const handleSubmit = async () => {
setTouched({
childName: true,
password: true,
confirmPassword: true,
displayName: true,
})
if (Object.keys(errors).length > 0) {
return
}
setIsSubmitting(true)
try {
await onSuccess({
childName: childName.trim(),
displayName: displayName.trim() || childName.trim(),
password,
})
handleClose()
} catch (error) {
console.error('Failed to create child user:', error)
} finally {
setIsSubmitting(false)
}
}
const handleClose = () => {
setChildName('')
setDisplayName('')
setPassword('')
setConfirmPassword('')
setErrors({})
setTouched({})
setIsSubmitting(false)
onClose()
}
const isValid =
Object.keys(errors).length === 0 &&
childName.trim() &&
password &&
password === confirmPassword
return (
<ResponsiveModal
open={isOpen}
onClose={handleClose}
title='Create Sub Account'
description='Create a login that can complete tasks assigned to this account.'
size='md'
closeOnBackdrop={!isSubmitting}
closeOnEscape={!isSubmitting}
footer={
<ModalActions
secondary={{
label: 'Cancel',
onClick: handleClose,
disabled: isSubmitting,
}}
primary={{
label: 'Create Account',
onClick: handleSubmit,
disabled: !isValid || isSubmitting,
loading: isSubmitting,
}}
/>
}
>
<FormControl error={!!errors.childName} sx={{ mb: 2 }}>
<Typography level='body2' mb={1}>
Sub Account Name *
</Typography>
<Input
required
fullWidth
id='childName'
name='childName'
placeholder='Enter sub account name (e.g., sarah)'
value={childName}
onChange={e => {
setChildName(e.target.value)
setTouched(prev => ({ ...prev, childName: true }))
}}
/>
{errors.childName && (
<FormHelperText>{errors.childName}</FormHelperText>
)}
</FormControl>
<FormControl error={!!errors.displayName} sx={{ mb: 2 }}>
<Typography level='body2' mb={1}>
Display Name
</Typography>
<Input
fullWidth
id='displayName'
name='displayName'
placeholder='Display name (optional, defaults to sub account name)'
value={displayName}
onChange={e => {
setDisplayName(e.target.value)
setTouched(prev => ({ ...prev, displayName: true }))
}}
/>
{errors.displayName && (
<FormHelperText>{errors.displayName}</FormHelperText>
)}
</FormControl>
<FormControl error={!!errors.password} sx={{ mb: 2 }}>
<Typography level='body2' mb={1}>
Password *
</Typography>
<Input
required
fullWidth
name='password'
type='password'
id='password'
placeholder='Enter password (8-64 characters)'
value={password}
onChange={e => {
setPassword(e.target.value)
setTouched(prev => ({ ...prev, password: true }))
}}
/>
{errors.password && <FormHelperText>{errors.password}</FormHelperText>}
</FormControl>
<FormControl error={!!errors.confirmPassword} sx={{ mb: 3 }}>
<Typography level='body2' mb={1}>
Confirm Password *
</Typography>
<Input
required
fullWidth
name='confirmPassword'
type='password'
id='confirmPassword'
placeholder='Confirm password'
value={confirmPassword}
onChange={e => {
setConfirmPassword(e.target.value)
setTouched(prev => ({ ...prev, confirmPassword: true }))
}}
/>
{errors.confirmPassword && (
<FormHelperText>{errors.confirmPassword}</FormHelperText>
)}
</FormControl>
</ResponsiveModal>
)
}
export default CreateChildUserModal