import React, { useState, useRef, useEffect, useMemo } from "react"; 
 | 
import { useLocation } from 'react-router-dom'; 
 | 
import { 
 | 
    Box, 
 | 
    CircularProgress, 
 | 
    Typography, 
 | 
    Button, 
 | 
    TextField, 
 | 
    Stack, 
 | 
    Autocomplete, 
 | 
    InputAdornment, 
 | 
    IconButton, 
 | 
} from '@mui/material'; 
 | 
import { 
 | 
    useTranslate, 
 | 
    useLogin, 
 | 
    useNotify, 
 | 
    email as validEmail, 
 | 
} from 'react-admin'; 
 | 
import { useForm, Controller } from 'react-hook-form'; 
 | 
import ProviderChoices from "./ProviderChoices"; 
 | 
import Visibility from '@mui/icons-material/Visibility'; 
 | 
import VisibilityOff from '@mui/icons-material/VisibilityOff'; 
 | 
import { sendEmailCode, register } from '@/api/auth'; 
 | 
  
 | 
const Register = (props) => { 
 | 
    const translate = useTranslate(); 
 | 
    const notify = useNotify(); 
 | 
    const login = useLogin(); 
 | 
    const location = useLocation(); 
 | 
    const { systemInfo } = props; 
 | 
  
 | 
    const { control, watch, handleSubmit, setValue, setError, clearErrors } = useForm(); 
 | 
  
 | 
    const email = watch('email'); 
 | 
    const username = watch('username'); 
 | 
    const password = watch('password'); 
 | 
    const confirmPassword = watch('confirmPassword'); 
 | 
    const code = watch('code'); 
 | 
  
 | 
    const [loading, setLoading] = useState(false); 
 | 
    const [codeLoading, setCodeLoading] = useState(false); 
 | 
    const [showPassword, setShowPassword] = useState(true); 
 | 
    const [isCounting, setIsCounting] = useState(false); 
 | 
    const [countdown, setCountdown] = useState(60); 
 | 
  
 | 
    // send code 
 | 
    const handleSendCode = async () => { 
 | 
        if (!email) { 
 | 
            setError("email", { 
 | 
                message: translate('ra.validation.required') 
 | 
            }) 
 | 
            return; 
 | 
        } 
 | 
        const emailError = validEmail()(email); 
 | 
        if (emailError) { 
 | 
            setError("email", { 
 | 
                message: translate("ra.validation.email") 
 | 
            }) 
 | 
            return; 
 | 
        } 
 | 
        clearErrors("email"); 
 | 
        setCodeLoading(true); 
 | 
        sendEmailCode({ email }).then(res => { 
 | 
            setCodeLoading(false); 
 | 
            const { code, msg, data } = res; 
 | 
            if (code === 200) { 
 | 
                notify(msg, { type: 'success', messageArgs: { _: msg } }); 
 | 
  
 | 
                const timestamp = Math.floor(Date.now() / 1000); 
 | 
                const expirationTime = timestamp + 60; 
 | 
                localStorage.setItem('codeExpirationTime', expirationTime); 
 | 
  
 | 
                setIsCounting(true); 
 | 
                setCountdown(60); 
 | 
            } else if (code === 10005 || code === 10006) { 
 | 
                setError('email', { 
 | 
                    message: msg 
 | 
                }) 
 | 
            } else { 
 | 
                notify(msg, { type: 'error', messageArgs: { _: msg } }); 
 | 
            } 
 | 
        }).catch((error) => { 
 | 
            setCodeLoading(false); 
 | 
            notify(error.message, { type: 'error', messageArgs: { _: error.message } }); 
 | 
            console.error(error); 
 | 
        }) 
 | 
    }; 
 | 
  
 | 
    // countdown 
 | 
    useEffect(() => { 
 | 
        const codeExpirationTime = localStorage.getItem('codeExpirationTime'); 
 | 
        if (codeExpirationTime) { 
 | 
            const currentTimestamp = Math.floor(Date.now() / 1000); 
 | 
            const remainingTime = codeExpirationTime - currentTimestamp; 
 | 
            if (remainingTime > 0) { 
 | 
                setCountdown(remainingTime); 
 | 
                setIsCounting(true); 
 | 
            } 
 | 
        } 
 | 
  
 | 
        const interval = setInterval(() => { 
 | 
            if (isCounting && countdown > 0) { 
 | 
                setCountdown(prev => prev - 1); 
 | 
            } else if (countdown <= 0) { 
 | 
                clearInterval(interval); 
 | 
                setIsCounting(false); 
 | 
                localStorage.removeItem('codeExpirationTime'); 
 | 
            } 
 | 
        }, 1000); 
 | 
  
 | 
        return () => clearInterval(interval); 
 | 
    }, [countdown, isCounting]); 
 | 
  
 | 
    // register 
 | 
    const onSubmit = (params) => { 
 | 
        setLoading(true); 
 | 
        register(params).then(res => { 
 | 
            setLoading(false); 
 | 
            const { code, msg, data } = res; 
 | 
            if (code === 200) { 
 | 
                notify(msg, { type: 'success', messageArgs: { _: msg } }); 
 | 
                // to login 
 | 
                login( 
 | 
                    params, 
 | 
                    location.state ? (location.state).nextPathname : '/' 
 | 
                ).catch(({ code, msg }) => { 
 | 
                    setLoading(false); 
 | 
                    notify(msg, { type: 'error', messageArgs: { _: msg } }); 
 | 
                }); 
 | 
            } else if (code === 10002) { 
 | 
                setError("username", { 
 | 
                    message: msg 
 | 
                }) 
 | 
            } else { 
 | 
                notify(msg, { type: 'error', messageArgs: { _: msg } }); 
 | 
            } 
 | 
        }).catch((error) => { 
 | 
            setLoading(false); 
 | 
            notify(error.message, { type: 'error', messageArgs: { _: error.message } }); 
 | 
            console.error(error); 
 | 
        }) 
 | 
    }; 
 | 
  
 | 
    return ( 
 | 
        <> 
 | 
            <Box 
 | 
                p={2} 
 | 
                display="flex" 
 | 
                flexDirection='column' 
 | 
                component="form" onSubmit={handleSubmit(onSubmit)} noValidate 
 | 
            > 
 | 
                <Stack spacing={2}> 
 | 
                    <Controller 
 | 
                        name="username" 
 | 
                        control={control} 
 | 
                        defaultValue="" 
 | 
                        rules={{ required: true }} 
 | 
                        render={({ field, fieldState: { error } }) => ( 
 | 
                            <TextField 
 | 
                                {...field} 
 | 
                                label={translate("page.login.username")} 
 | 
                                variant="standard" 
 | 
                                disabled={loading} 
 | 
                                autoFocus 
 | 
                                autoComplete="off" 
 | 
                                error={!!error} 
 | 
                                helperText={error?.message || ""} 
 | 
                            /> 
 | 
                        )} 
 | 
                    /> 
 | 
  
 | 
                    <Controller 
 | 
                        name="password" 
 | 
                        control={control} 
 | 
                        defaultValue="" 
 | 
                        rules={{ 
 | 
                            required: 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.login.password")} 
 | 
                                type={showPassword ? 'text' : 'password'} 
 | 
                                variant="standard" 
 | 
                                disabled={loading} 
 | 
                                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> 
 | 
                                    ), 
 | 
                                }} 
 | 
                            /> 
 | 
                        )} 
 | 
                    /> 
 | 
  
 | 
                    <Controller 
 | 
                        name="confirmPassword" 
 | 
                        control={control} 
 | 
                        defaultValue="" 
 | 
                        rules={{ 
 | 
                            required: translate('ra.validation.required'), 
 | 
                            validate: value => 
 | 
                                value === password || translate('page.settings.resetPwd.tip.pwdNotMatch'), 
 | 
                        }} 
 | 
                        render={({ field, fieldState: { error } }) => ( 
 | 
                            <TextField 
 | 
                                {...field} 
 | 
                                label={translate('page.login.confirmPwd')} 
 | 
                                type={showPassword ? 'text' : 'password'} 
 | 
                                variant="standard" 
 | 
                                disabled={loading} 
 | 
                                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> 
 | 
                                    ), 
 | 
                                }} 
 | 
                            /> 
 | 
                        )} 
 | 
                    /> 
 | 
  
 | 
                    <Controller 
 | 
                        name="email" 
 | 
                        control={control} 
 | 
                        defaultValue="" 
 | 
                        rules={{ 
 | 
                            required: translate('ra.validation.required'), 
 | 
                            pattern: { 
 | 
                                value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, 
 | 
                                message: translate("ra.validation.email"), 
 | 
                            }, 
 | 
                        }} 
 | 
                        render={({ field, fieldState: { error } }) => ( 
 | 
                            <TextField 
 | 
                                {...field} 
 | 
                                label={translate('page.login.email')} 
 | 
                                variant="standard" 
 | 
                                disabled={loading} 
 | 
                                // autoComplete="off" 
 | 
                                error={!!error} 
 | 
                                helperText={error ? error.message : ""} 
 | 
                            /> 
 | 
                        )} 
 | 
                    /> 
 | 
  
 | 
                    <Box display="flex" alignItems="center" justifyContent='center' width="100%"> 
 | 
                        <Controller 
 | 
                            name="code" 
 | 
                            control={control} 
 | 
                            defaultValue="" 
 | 
                            rules={{ 
 | 
                                required: translate('ra.validation.required'), 
 | 
                            }} 
 | 
                            render={({ field, fieldState: { error } }) => ( 
 | 
                                <TextField 
 | 
                                    {...field} 
 | 
                                    label={translate('page.login.code')} 
 | 
                                    variant="standard" 
 | 
                                    disabled={loading} 
 | 
                                    autoComplete="off" 
 | 
                                    error={!!error} 
 | 
                                    helperText={error ? error.message : ""} 
 | 
                                    sx={{ 
 | 
                                        width: '65%', 
 | 
                                        mr: 2, 
 | 
                                    }} 
 | 
                                /> 
 | 
                            )} 
 | 
                        /> 
 | 
  
 | 
                        <Button 
 | 
                            variant="outlined" 
 | 
                            onClick={handleSendCode} 
 | 
                            disabled={codeLoading || isCounting} 
 | 
                            sx={{ 
 | 
                                width: '35%', 
 | 
                                mt: 1, 
 | 
                                whiteSpace: 'nowrap', 
 | 
                            }} 
 | 
                        > 
 | 
                            {codeLoading ? ( 
 | 
                                <CircularProgress size={20} color="primary" sx={{ marginRight: 1 }} /> 
 | 
                            ) : 
 | 
                                isCounting ? ( 
 | 
                                    `${countdown}s` 
 | 
                                ) : ( 
 | 
                                    translate('page.login.button.code') 
 | 
                                ) 
 | 
                            } 
 | 
                        </Button> 
 | 
                    </Box> 
 | 
  
 | 
                    <Box /> 
 | 
  
 | 
                    <Button 
 | 
                        type="submit" 
 | 
                        variant="contained" 
 | 
                        disabled={loading || !(email && username && password && confirmPassword && code)} 
 | 
                        sx={{ 
 | 
                            backgroundColor: "#3D4BA7" 
 | 
                        }} 
 | 
                    > 
 | 
                        {loading && <CircularProgress size={25} thickness={2} />} 
 | 
                        {translate('page.login.button.register')} 
 | 
                    </Button> 
 | 
  
 | 
                </Stack> 
 | 
                <Box mt={1} mb={1} sx={{ textAlign: 'center' }}>or</Box> 
 | 
  
 | 
                <ProviderChoices type="REGISTER" /> 
 | 
            </Box > 
 | 
        </> 
 | 
    ) 
 | 
} 
 | 
  
 | 
export default Register; 
 |