| import React, { useState, useRef, useEffect, useMemo } from "react"; | 
| import { | 
|     useTranslate, | 
|     useNotify, | 
|     useRefresh, | 
| } from 'react-admin'; | 
| import { | 
|     Dialog, | 
|     DialogActions, | 
|     DialogContent, | 
|     DialogTitle, | 
|     Stack, | 
|     Grid, | 
|     Box, | 
|     Stepper, | 
|     Step, | 
|     StepLabel, | 
|     StepContent, | 
|     Button, | 
|     TextField, | 
|     InputAdornment, | 
|     IconButton, | 
| } from '@mui/material'; | 
| import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form"; | 
| import { matchPath, useLocation } from 'react-router'; | 
| import DialogCloseButton from "@/page/components/DialogCloseButton"; | 
| import Visibility from '@mui/icons-material/Visibility'; | 
| import VisibilityOff from '@mui/icons-material/VisibilityOff'; | 
| import request from '@/utils/request'; | 
|   | 
| const TenantCreate = (props) => { | 
|     const { open, setOpen } = props; | 
|     const translate = useTranslate(); | 
|     const notify = useNotify(); | 
|     const refresh = useRefresh(); | 
|     const { | 
|         control, | 
|         handleSubmit, | 
|         watch, | 
|         setValue, | 
|         getValues, | 
|         reset, | 
|         formState: { | 
|             errors, | 
|             isDirty, | 
|         }, | 
|         trigger | 
|     } = useForm(); | 
|   | 
|     const passwordVal = watch('password'); | 
|   | 
|     const [activeStep, setActiveStep] = useState(0); | 
|     const [showPassword, setShowPassword] = useState(false); | 
|   | 
|     const validateCurrentStep = async () => { | 
|         let fieldsToValidate = []; | 
|         if (activeStep === 0) { | 
|             fieldsToValidate = ['name', 'flag']; | 
|         } else if (activeStep === 1) { | 
|             fieldsToValidate = ['username', 'email', 'password', 'confirmPassword']; | 
|         } else if (activeStep === 2) { | 
|             fieldsToValidate = ['memo']; | 
|         } | 
|         return await trigger(fieldsToValidate); | 
|     }; | 
|   | 
|     const handleNext = async () => { | 
|         const isValid = await validateCurrentStep(); | 
|         if (!isValid) { | 
|             return; | 
|         } | 
|         setActiveStep(prev => prev + 1); | 
|     }; | 
|   | 
|     const handleBack = () => { | 
|         setActiveStep(prev => prev - 1); | 
|     }; | 
|   | 
|     const handleClose = (event, reason) => { | 
|         if (reason !== "backdropClick") { | 
|             setActiveStep(0); | 
|             setOpen(false); | 
|             reset(); | 
|         } | 
|     }; | 
|   | 
|     const onSubmit = (data) => { | 
|         request.post('/tenant/init', data).then(res => { | 
|             const { code, msg, data } = res.data; | 
|             if (code === 200) { | 
|                 notify(msg, { type: 'success', messageArgs: { _: msg } }); | 
|                 setOpen(false); | 
|                 reset(); | 
|                 refresh(); | 
|             } else { | 
|                 notify(msg, { type: 'error', messageArgs: { _: msg } }); | 
|             } | 
|         }).catch((error) => { | 
|             notify(error.message, { type: 'error', messageArgs: { _: error.message } }); | 
|             console.error(error); | 
|         }) | 
|     } | 
|   | 
|     return ( | 
|         <> | 
|             <Dialog | 
|                 open={open} | 
|                 onClose={handleClose} | 
|                 aria-labelledby="form-dialog-title" | 
|                 fullWidth | 
|                 disableRestoreFocus | 
|                 maxWidth="md"   // 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 
|             > | 
|                 <DialogTitle id="form-dialog-title" sx={{ | 
|                     position: 'sticky', | 
|                     top: 0, | 
|                     backgroundColor: 'background.paper', | 
|                     zIndex: 1000 | 
|                 }}> | 
|                     {translate('create.title')} | 
|                     <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}> | 
|                         <DialogCloseButton onClose={handleClose} /> | 
|                     </Box> | 
|                 </DialogTitle> | 
|                 <DialogContent sx={{ mt: 2 }}> | 
|                     {open && ( | 
|                         <form noValidate onSubmit={handleSubmit(onSubmit)} > | 
|                             <Stepper activeStep={activeStep} orientation="vertical"> | 
|                                 <Step> | 
|                                     <StepLabel>{translate('page.tenant.create.title.basic')}</StepLabel> | 
|                                     <StepContent> | 
|                                         <Stack spacing={3} mt={2} direction='column' width={'50%'}> | 
|                                             <Controller | 
|                                                 name="name" | 
|                                                 control={control} | 
|                                                 defaultValue="" | 
|                                                 rules={{ required: true }} | 
|                                                 parse={v => v} | 
|                                                 render={({ field, fieldState: { error } }) => ( | 
|                                                     <TextField | 
|                                                         {...field} | 
|                                                         label={translate('table.field.tenant.name')} | 
|                                                         variant="outlined" | 
|                                                         autoComplete="off" | 
|                                                         error={!!error} | 
|                                                         helperText={error ? translate('ra.validation.required') : ""} | 
|                                                     /> | 
|                                                 )} | 
|                                             /> | 
|                                             <Controller | 
|                                                 name="flag" | 
|                                                 control={control} | 
|                                                 defaultValue="" | 
|                                                 rules={{ | 
|                                                     required: { | 
|                                                         value: true, | 
|                                                         message: translate('ra.validation.required') | 
|                                                     }, | 
|                                                     pattern: { | 
|                                                         value: /^[A-Za-z]{3,20}$/, | 
|                                                         message: translate('page.tenant.create.tip.onlyEn'), | 
|                                                     } | 
|                                                 }} | 
|                                                 parse={v => v} | 
|                                                 render={({ field, fieldState: { error } }) => ( | 
|                                                     <TextField | 
|                                                         {...field} | 
|                                                         label={translate('table.field.tenant.flag')} | 
|                                                         variant="outlined" | 
|                                                         autoComplete="off" | 
|                                                         error={!!error} | 
|                                                         helperText={error ? error.message : ""} | 
|                                                     /> | 
|                                                 )} | 
|                                             /> | 
|                                         </Stack> | 
|                                         <Box sx={{ mt: 3 }}> | 
|                                             <Button onClick={handleNext} variant="contained"> | 
|                                                 {translate('page.tenant.create.btn.next')} | 
|                                             </Button> | 
|                                             <Button disabled={activeStep === 0} onClick={handleBack}> | 
|                                                 {translate('page.tenant.create.btn.back')} | 
|                                             </Button> | 
|                                         </Box> | 
|                                     </StepContent> | 
|                                 </Step> | 
|   | 
|                                 <Step> | 
|                                     <StepLabel>{translate('page.tenant.create.title.root')}</StepLabel> | 
|                                     <StepContent> | 
|                                         <Stack spacing={3} mt={2} direction='column' width={'50%'}> | 
|                                             <Controller | 
|                                                 name="username" | 
|                                                 control={control} | 
|                                                 defaultValue="" | 
|                                                 rules={{ | 
|                                                     required: { | 
|                                                         value: true, | 
|                                                         message: translate('ra.validation.required') | 
|                                                     }, | 
|                                                     pattern: { | 
|                                                         value: /^[A-Za-z0-9]{3,20}$/, | 
|                                                         message: translate('page.settings.resetPwd.tip.usernameLimit'), | 
|                                                     }, | 
|                                                 }} | 
|                                                 parse={v => v} | 
|                                                 render={({ field, fieldState: { error } }) => ( | 
|                                                     <TextField | 
|                                                         {...field} | 
|                                                         label={translate('table.field.user.username')} | 
|                                                         variant="outlined" | 
|                                                         autoComplete="off" | 
|                                                         error={!!error} | 
|                                                         helperText={error ? error.message : ""} | 
|                                                     /> | 
|                                                 )} | 
|                                             /> | 
|                                             <Controller | 
|                                                 name="email" | 
|                                                 control={control} | 
|                                                 defaultValue="" | 
|                                                 rules={{ | 
|                                                     required: false, | 
|                                                     pattern: { | 
|                                                         value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, | 
|                                                         message: translate("ra.validation.email"), | 
|                                                     }, | 
|                                                 }} | 
|                                                 render={({ field, fieldState: { error } }) => ( | 
|                                                     <TextField | 
|                                                         {...field} | 
|                                                         label={translate('table.field.user.email')} | 
|                                                         variant="outlined" | 
|                                                         autoComplete="off" | 
|                                                         error={!!error} | 
|                                                         helperText={error ? error.message : ""} | 
|                                                     /> | 
|                                                 )} | 
|                                             /> | 
|                                             <Controller | 
|                                                 name="password" | 
|                                                 control={control} | 
|                                                 defaultValue="" | 
|                                                 rules={{ | 
|                                                     required: { | 
|                                                         value: true, | 
|                                                         message: translate('ra.validation.required'), | 
|                                                     }, | 
|                                                     pattern: { | 
|                                                         value: /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d\.]{6,13}$/, | 
|                                                         message: translate('page.settings.resetPwd.tip.pwdInputLimit'), | 
|                                                     }, | 
|                                                 }} | 
|                                                 render={({ field, fieldState: { error } }) => ( | 
|                                                     <TextField | 
|                                                         {...field} | 
|                                                         label={translate('page.settings.resetPwd.newPwd')} | 
|                                                         type={showPassword ? 'text' : 'password'} | 
|                                                         variant="outlined" | 
|                                                         autoComplete="off" | 
|                                                         error={!!error} | 
|                                                         helperText={error ? error.message : ""} | 
|                                                         InputProps={{ | 
|                                                             endAdornment: ( | 
|                                                                 <InputAdornment position="end"> | 
|                                                                     <IconButton | 
|                                                                         aria-label="toggle password visibility" | 
|                                                                         onClick={() => setShowPassword((show) => !show)} | 
|                                                                         onMouseDown={(event) => { event.preventDefault() }} | 
|                                                                         edge="end" | 
|                                                                     > | 
|                                                                         {showPassword ? <VisibilityOff /> : <Visibility />} | 
|                                                                     </IconButton> | 
|                                                                 </InputAdornment> | 
|                                                             ), | 
|                                                         }} | 
|                                                     /> | 
|                                                 )} | 
|                                             /> | 
|                                             <Controller | 
|                                                 name="confirmPassword" | 
|                                                 control={control} | 
|                                                 defaultValue="" | 
|                                                 rules={{ | 
|                                                     required: translate('ra.validation.required'), | 
|                                                     validate: value => | 
|                                                         value === passwordVal || translate('page.settings.resetPwd.tip.pwdNotMatch'), | 
|                                                 }} | 
|                                                 render={({ field, fieldState: { error } }) => ( | 
|                                                     <TextField | 
|                                                         {...field} | 
|                                                         label={translate('page.settings.resetPwd.confirmNewPwd')} | 
|                                                         type={showPassword ? 'text' : 'password'} | 
|                                                         variant="outlined" | 
|                                                         autoComplete="off" | 
|                                                         error={!!error} | 
|                                                         helperText={error?.message || ""} | 
|                                                         InputProps={{ | 
|                                                             endAdornment: ( | 
|                                                                 <InputAdornment position="end"> | 
|                                                                     <IconButton | 
|                                                                         aria-label="toggle password visibility" | 
|                                                                         onClick={() => setShowPassword((show) => !show)} | 
|                                                                         onMouseDown={(event) => { event.preventDefault() }} | 
|                                                                         edge="end" | 
|                                                                     > | 
|                                                                         {showPassword ? <VisibilityOff /> : <Visibility />} | 
|                                                                     </IconButton> | 
|                                                                 </InputAdornment> | 
|                                                             ), | 
|                                                         }} | 
|                                                     /> | 
|                                                 )} | 
|                                             /> | 
|                                         </Stack> | 
|                                         <Box sx={{ mt: 3 }}> | 
|                                             <Button onClick={handleNext} variant="contained"> | 
|                                                 {translate('page.tenant.create.btn.next')} | 
|                                             </Button> | 
|                                             <Button onClick={handleBack}> | 
|                                                 {translate('page.tenant.create.btn.back')} | 
|                                             </Button> | 
|                                         </Box> | 
|                                     </StepContent> | 
|                                 </Step> | 
|   | 
|                                 <Step> | 
|                                     <StepLabel>{translate('page.tenant.create.title.confirm')}</StepLabel> | 
|                                     <StepContent> | 
|                                         <Stack spacing={3} mt={2} direction='column' width={'50%'}> | 
|                                             <Controller | 
|                                                 name="memo" | 
|                                                 control={control} | 
|                                                 defaultValue="" | 
|                                                 rules={{ required: false }} | 
|                                                 parse={v => v} | 
|                                                 render={({ field, fieldState: { error } }) => ( | 
|                                                     <TextField | 
|                                                         {...field} | 
|                                                         label={translate('common.field.memo')} | 
|                                                         variant="outlined" | 
|                                                         autoComplete="off" | 
|                                                         fullWidth | 
|                                                         multiline | 
|                                                         minRows={2} | 
|                                                         error={!!error} | 
|                                                         helperText={error ? translate('ra.validation.required') : ""} | 
|                                                     /> | 
|                                                 )} | 
|                                             /> | 
|                                         </Stack> | 
|                                         <Box sx={{ mt: 3 }}> | 
|                                             <Button type="submit" variant="contained"> | 
|                                                 {translate('ra.action.save')} | 
|                                             </Button> | 
|                                             <Button onClick={handleBack}> | 
|                                                 {translate('page.tenant.create.btn.back')} | 
|                                             </Button> | 
|                                         </Box> | 
|                                     </StepContent> | 
|                                 </Step> | 
|                             </Stepper> | 
|                         </form> | 
|                     )} | 
|                 </DialogContent> | 
|                 <DialogActions sx={{ height: 10, position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}> | 
|                 </DialogActions> | 
|             </Dialog> | 
|         </> | 
|     ) | 
| } | 
|   | 
| export default TenantCreate; |