From bb45d484db8daa9b6633c892e110a8dc8844d6e8 Mon Sep 17 00:00:00 2001
From: vincentlu <t1341870251@gmail.com>
Date: 星期一, 10 二月 2025 15:16:35 +0800
Subject: [PATCH] #

---
 rsf-admin/src/page/tenant/TenantCreate.jsx |  400 ++++++++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 327 insertions(+), 73 deletions(-)

diff --git a/rsf-admin/src/page/tenant/TenantCreate.jsx b/rsf-admin/src/page/tenant/TenantCreate.jsx
index 37e3d05..4e0dea7 100644
--- a/rsf-admin/src/page/tenant/TenantCreate.jsx
+++ b/rsf-admin/src/page/tenant/TenantCreate.jsx
@@ -23,100 +23,354 @@
     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 "../components/DialogCloseButton";
 import StatusSelectInput from "../components/StatusSelectInput";
 import MemoInput from "../components/MemoInput";
+import Visibility from '@mui/icons-material/Visibility';
+import VisibilityOff from '@mui/icons-material/VisibilityOff';
 
 const TenantCreate = (props) => {
     const { open, setOpen } = props;
-
     const translate = useTranslate();
     const notify = useNotify();
+    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 handleSuccess = async (data) => {
-        setOpen(false);
-        notify('common.response.success');
-    };
+    const onSubmit = (data) => {
+        console.log(data);
+        return;
 
-    const handleError = async (error) => {
-        notify(error.message || 'common.response.fail', { type: 'error', messageArgs: { _: error.message } });
-    };
+        // setOpen(false);
+        reset();
+        // notify('common.response.success');
+
+        // notify(error.message || 'common.response.fail', { type: 'error', messageArgs: { _: error.message } });
+    }
 
     return (
         <>
-            <CreateBase
-                record={{}}
-                transform={(data) => {
-                    return data;
-                }}
-                mutationOptions={{ onSuccess: handleSuccess, onError: handleError }}
+            <Dialog
+                open={open}
+                onClose={handleClose}
+                aria-labelledby="form-dialog-title"
+                fullWidth
+                disableRestoreFocus
+                maxWidth="md"   // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
             >
-                <Dialog
-                    open={open}
-                    onClose={handleClose}
-                    aria-labelledby="form-dialog-title"
-                    fullWidth
-                    disableRestoreFocus
-                    maxWidth="md"   // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
-                >
-                    <Form>
-                        <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>
-                            <Grid container rowSpacing={2} columnSpacing={2}>
-                                <Grid item xs={6} display="flex" gap={1}>
-                                    <TextInput
-                                        label="table.field.tenant.name"
-                                        source="name"
-                                        parse={v => v}
-                                        autoFocus
-                                        validate={required()}
-                                    />
-                                </Grid>
-                                <Grid item xs={6} display="flex" gap={1}>
-                                    <TextInput
-                                        label="table.field.tenant.flag"
-                                        source="flag"
-                                        parse={v => v}
-                                        autoFocus
-                                        validate={required()}
-                                    />
-                                </Grid>
-                                <Grid item xs={6} display="flex" gap={1}>
-                                    <StatusSelectInput />
-                                </Grid>
-                                <Grid item xs={12} display="flex" gap={1}>
-                                    <Stack direction="column" spacing={1} width={'100%'}>
-                                        <MemoInput />
-                                    </Stack>
-                                </Grid>
-                            </Grid>
-                        </DialogContent>
-                        <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
-                            <Toolbar sx={{ width: '100%', justifyContent: 'space-between' }}  >
-                                <SaveButton />
-                            </Toolbar>
-                        </DialogActions>
-                    </Form>
-                </Dialog>
-            </CreateBase>
+                <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>
         </>
     )
 }

--
Gitblit v1.9.1