| | |
| | | import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form"; |
| | | import { |
| | | Stack, |
| | | Grid, |
| | | Box, |
| | | Typography, |
| | | TextField, |
| | | Button, |
| | | FormControl, |
| | | InputLabel, |
| | | Select, |
| | | MenuItem, |
| | | FormHelperText, |
| | | CircularProgress, |
| | | InputAdornment, |
| | | IconButton, |
| | | } from '@mui/material'; |
| | | import { updateUserInfo } from '@/api/auth'; |
| | | import avatar from '/avatar.jpg' |
| | | import { requestResetPassword } from '@/api/auth'; |
| | | import Visibility from '@mui/icons-material/Visibility'; |
| | | import VisibilityOff from '@mui/icons-material/VisibilityOff'; |
| | | |
| | | const SecuritySettings = (props) => { |
| | | const translate = useTranslate(); |
| | | const notify = useNotify(); |
| | | const { children, userInfo } = props; |
| | | const { userInfo } = props; |
| | | |
| | | const { control, handleSubmit, watch, setValue, getValues, formState: { isDirty } } = useForm(); |
| | | const { control, handleSubmit, watch, setValue, getValues, reset, formState: { errors }, setError } = useForm(); |
| | | |
| | | const oldPasswordVal = watch('oldPassword'); |
| | | const newPasswordVal = watch('newPassword'); |
| | | const confirmPasswordVal = watch('confirmPassword'); |
| | | |
| | | const [loading, setLoading] = useState(false); |
| | | const [showOldPassword, setShowOldPassword] = useState(false); |
| | | const [showNewPassword, setShowNewPassword] = useState(false); |
| | | |
| | | useEffect(() => { |
| | | if (userInfo) { |
| | | setValue("username", userInfo.username || "", { shouldDirty: false }); |
| | | setValue("nickname", userInfo.nickname || "", { shouldDirty: false }); |
| | | setValue("sex", userInfo.sex ?? "", { shouldDirty: false }); |
| | | setValue("code", userInfo.code || "", { shouldDirty: false }); |
| | | setValue("phone", userInfo.phone || "", { shouldDirty: false }); |
| | | setValue("email", userInfo.email || "", { shouldDirty: false }); |
| | | setValue("realName", userInfo.realName || "", { shouldDirty: false }); |
| | | setValue("idCard", userInfo.idCard || "", { shouldDirty: false }); |
| | | } |
| | | }, [userInfo, setValue]) |
| | | |
| | | const onSubmit = (data) => { |
| | | const onSubmit = (params) => { |
| | | setLoading(true); |
| | | updateUserInfo({ id: userInfo.id, ...data }).then(res => { |
| | | requestResetPassword(params).then(res => { |
| | | setLoading(false); |
| | | const { code, msg, data } = res; |
| | | if (code === 200) { |
| | | notify(msg, { type: 'success', messageArgs: { _: msg } }); |
| | | const userToPersist = { |
| | | avatar: avatar, |
| | | fullName: data.nickname, |
| | | id: data.id, |
| | | username: data.username |
| | | } |
| | | localStorage.setItem("user", JSON.stringify(userToPersist)); |
| | | reset(); |
| | | } else if (code === 10001) { |
| | | setError('oldPassword', { |
| | | message: msg, |
| | | }); |
| | | } else { |
| | | notify(msg, { type: 'error', messageArgs: { _: msg } }); |
| | | } |
| | |
| | | }} |
| | | > |
| | | <Controller |
| | | name="username" |
| | | name="oldPassword" |
| | | control={control} |
| | | defaultValue="" |
| | | rules={{ required: true }} |
| | | rules={{ required: translate('ra.validation.required') }} |
| | | render={({ field, fieldState: { error } }) => ( |
| | | <TextField |
| | | {...field} |
| | | label={translate('table.field.user.username')} |
| | | label={translate('page.settings.resetPwd.currPwd')} |
| | | type={showOldPassword ? 'text' : 'password'} |
| | | variant="outlined" |
| | | autoComplete="off" |
| | | helperText={error ? translate('ra.validation.required') : ""} |
| | | disabled |
| | | error={Boolean(errors.oldPassword)} |
| | | helperText={errors.oldPassword?.message || ""} |
| | | InputProps={{ |
| | | endAdornment: ( |
| | | <InputAdornment position="end"> |
| | | <IconButton |
| | | aria-label="toggle password visibility" |
| | | onClick={() => setShowOldPassword((show) => !show)} |
| | | onMouseDown={(event) => { event.preventDefault() }} |
| | | edge="end" |
| | | > |
| | | {showOldPassword ? <VisibilityOff /> : <Visibility />} |
| | | </IconButton> |
| | | </InputAdornment> |
| | | ), |
| | | }} |
| | | /> |
| | | )} |
| | | /> |
| | | <Controller |
| | | name="nickname" |
| | | control={control} |
| | | defaultValue="" |
| | | rules={{ required: true }} |
| | | render={({ field, fieldState: { error } }) => ( |
| | | <TextField |
| | | {...field} |
| | | label={translate('table.field.user.nickname')} |
| | | variant="outlined" |
| | | autoComplete="off" |
| | | error={!!error} |
| | | helperText={error ? translate('ra.validation.required') : ""} |
| | | /> |
| | | )} |
| | | /> |
| | | <Controller |
| | | name="sex" |
| | | control={control} |
| | | defaultValue="" |
| | | rules={{ required: true }} |
| | | render={({ field, fieldState: { error } }) => ( |
| | | <FormControl fullWidth variant="outlined" error={!!error}> |
| | | <InputLabel>{translate('table.field.user.sex')}</InputLabel> |
| | | <Select |
| | | {...field} |
| | | label={translate('table.field.user.sex')} |
| | | > |
| | | <MenuItem value={0}> |
| | | <em>{translate('table.field.user.sexes.unknown')}</em> |
| | | </MenuItem> |
| | | <MenuItem value={1}>{translate('table.field.user.sexes.male')}</MenuItem> |
| | | <MenuItem value={2}>{translate('table.field.user.sexes.female')}</MenuItem> |
| | | </Select> |
| | | {error && <FormHelperText>{translate('ra.validation.required')}</FormHelperText>} |
| | | </FormControl> |
| | | )} |
| | | /> |
| | | <Controller |
| | | name="code" |
| | | control={control} |
| | | defaultValue="" |
| | | rules={{ required: false }} |
| | | render={({ field, fieldState: { error } }) => ( |
| | | <TextField |
| | | {...field} |
| | | label={translate('table.field.user.code')} |
| | | variant="outlined" |
| | | autoComplete="off" |
| | | error={!!error} |
| | | helperText={error ? translate('ra.validation.required') : ""} |
| | | /> |
| | | )} |
| | | /> |
| | | <Controller |
| | | name="phone" |
| | | control={control} |
| | | defaultValue="" |
| | | rules={{ required: false }} |
| | | render={({ field, fieldState: { error } }) => ( |
| | | <TextField |
| | | {...field} |
| | | label={translate('table.field.user.phone')} |
| | | variant="outlined" |
| | | autoComplete="off" |
| | | error={!!error} |
| | | helperText={error ? translate('ra.validation.required') : ""} |
| | | /> |
| | | )} |
| | | /> |
| | | <Controller |
| | | name="email" |
| | | name="newPassword" |
| | | control={control} |
| | | defaultValue="" |
| | | rules={{ |
| | | required: false, |
| | | required: translate('ra.validation.required'), |
| | | pattern: { |
| | | value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, |
| | | message: translate("ra.validation.email"), |
| | | value: /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d\.]{6,13}$/, |
| | | message: translate('page.settings.resetPwd.tip.pwdInputLimit'), |
| | | }, |
| | | validate: (value) => { |
| | | if (value === oldPasswordVal) { |
| | | return translate('page.settings.resetPwd.tip.pwdNotSameAsOld'); |
| | | } |
| | | return true; |
| | | } |
| | | }} |
| | | render={({ field, fieldState: { error } }) => ( |
| | | <TextField |
| | | {...field} |
| | | label={translate('table.field.user.email')} |
| | | label={translate('page.settings.resetPwd.newPwd')} |
| | | type={showNewPassword ? 'text' : 'password'} |
| | | variant="outlined" |
| | | autoComplete="off" |
| | | error={!!error} |
| | | helperText={error ? error.message : ""} |
| | | error={Boolean(errors.newPassword)} |
| | | helperText={errors.newPassword?.message || ""} |
| | | InputProps={{ |
| | | endAdornment: ( |
| | | <InputAdornment position="end"> |
| | | <IconButton |
| | | aria-label="toggle password visibility" |
| | | onClick={() => setShowNewPassword((show) => !show)} |
| | | onMouseDown={(event) => { event.preventDefault() }} |
| | | edge="end" |
| | | > |
| | | {showNewPassword ? <VisibilityOff /> : <Visibility />} |
| | | </IconButton> |
| | | </InputAdornment> |
| | | ), |
| | | }} |
| | | /> |
| | | )} |
| | | /> |
| | | <Controller |
| | | name="realName" |
| | | name="confirmPassword" |
| | | control={control} |
| | | defaultValue="" |
| | | rules={{ required: false }} |
| | | rules={{ |
| | | required: translate('ra.validation.required'), |
| | | validate: value => |
| | | value === newPasswordVal || translate('page.settings.resetPwd.tip.pwdNotMatch'), |
| | | }} |
| | | render={({ field, fieldState: { error } }) => ( |
| | | <TextField |
| | | {...field} |
| | | label={translate('table.field.user.realName')} |
| | | label={translate('page.settings.resetPwd.confirmNewPwd')} |
| | | type={showNewPassword ? 'text' : 'password'} |
| | | variant="outlined" |
| | | autoComplete="off" |
| | | error={!!error} |
| | | helperText={error ? translate('ra.validation.required') : ""} |
| | | /> |
| | | )} |
| | | /> |
| | | <Controller |
| | | name="idCard" |
| | | control={control} |
| | | defaultValue="" |
| | | rules={{ required: false }} |
| | | render={({ field, fieldState: { error } }) => ( |
| | | <TextField |
| | | {...field} |
| | | label={translate('table.field.user.idCard')} |
| | | variant="outlined" |
| | | autoComplete="off" |
| | | error={!!error} |
| | | helperText={error ? translate('ra.validation.required') : ""} |
| | | error={Boolean(errors.confirmPassword)} |
| | | helperText={errors.confirmPassword?.message || ""} |
| | | InputProps={{ |
| | | endAdornment: ( |
| | | <InputAdornment position="end"> |
| | | <IconButton |
| | | aria-label="toggle password visibility" |
| | | onClick={() => setShowNewPassword((show) => !show)} |
| | | onMouseDown={(event) => { event.preventDefault() }} |
| | | edge="end" |
| | | > |
| | | {showNewPassword ? <VisibilityOff /> : <Visibility />} |
| | | </IconButton> |
| | | </InputAdornment> |
| | | ), |
| | | }} |
| | | /> |
| | | )} |
| | | /> |
| | | <Button |
| | | type="submit" |
| | | variant="contained" |
| | | disabled={loading || !isDirty} |
| | | disabled={loading || !(oldPasswordVal && newPasswordVal && confirmPasswordVal)} |
| | | sx={{ |
| | | alignSelf: 'flex-start', |
| | | width: '120px' |
| | | }} |
| | | > |
| | | {loading && <CircularProgress size={25} thickness={2} />} |
| | | {translate('ra.action.save')} |
| | | {translate('page.settings.resetPwd.resetBtn')} |
| | | </Button> |
| | | </Stack> |
| | | </form> |