961 lines
27 KiB
TypeScript
961 lines
27 KiB
TypeScript
import {RegisterProcess, ThemeMode} from '@caj/configs/appVar';
|
|
import {appVarActions} from '@caj/configs/appVarReducer';
|
|
import {defaultHeaderStyle} from '@caj/configs/colors';
|
|
import {SlideFromLeftView} from '@caj/helper/animations';
|
|
import {saveVarChanges} from '@caj/helper/appData';
|
|
import {apiBackendRequest, makeRequest} from '@caj/helper/request';
|
|
import {
|
|
accountNameOptions,
|
|
EMail,
|
|
emailOptions,
|
|
passwordOptions,
|
|
userNameOptions,
|
|
XToken,
|
|
} from '@caj/helper/types';
|
|
import {RootScreenNavigationProp} from '@caj/Navigation';
|
|
import {RootState, store} from '@caj/redux/store';
|
|
import {useNavigation} from '@react-navigation/native';
|
|
import {
|
|
createNativeStackNavigator,
|
|
NativeStackNavigationProp,
|
|
} from '@react-navigation/native-stack';
|
|
import {
|
|
Box,
|
|
Button,
|
|
Center,
|
|
Container,
|
|
FormControl,
|
|
Heading,
|
|
HStack,
|
|
Icon,
|
|
IconButton,
|
|
Input,
|
|
Pressable,
|
|
ScrollView,
|
|
Spinner,
|
|
Text,
|
|
useColorModeValue,
|
|
useTheme,
|
|
useToast,
|
|
VStack,
|
|
WarningOutlineIcon,
|
|
} from 'native-base';
|
|
|
|
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
|
|
|
|
import {baseFontSize} from 'native-base/lib/typescript/theme/tools';
|
|
import {useEffect, useRef, useState} from 'react';
|
|
import {useDispatch, useSelector} from 'react-redux';
|
|
import reactStringReplace from 'react-string-replace';
|
|
import ConfirmationCodeField from './ConfirmationCodeField';
|
|
import NameDisplay from './NameDisplay';
|
|
import showToast from './Toast';
|
|
import {NativeSyntheticEvent, TextInputFocusEventData} from 'react-native';
|
|
|
|
const validateEmail = (email: EMail) => {
|
|
return emailOptions.isAllowed(email);
|
|
};
|
|
|
|
export default function NotLoggedIn() {
|
|
const lang = useSelector((state: RootState) => state.appVariables.lang);
|
|
const theme = useSelector(
|
|
(state: RootState) => state.appVariables.preferences.theme,
|
|
);
|
|
|
|
const toast = useToast();
|
|
|
|
const navigation = useNavigation<RootScreenNavigationProp>();
|
|
|
|
return (
|
|
<Box alignItems="center" mt={5}>
|
|
<Text color="primary.400">{lang.appName}</Text>
|
|
<Text color="white.100">{lang.appNameDesc}</Text>
|
|
<VStack mt={5} space={4} alignItems="center">
|
|
<Button
|
|
w="72"
|
|
colorScheme="primary"
|
|
rounded="xl"
|
|
_text={{fontSize: 'xl'}}
|
|
onPress={() => {
|
|
navigation.navigate('Register', {screen: 'RegStepOne'});
|
|
}}>
|
|
Sign up
|
|
</Button>
|
|
<Button
|
|
w="72"
|
|
colorScheme="black"
|
|
variant={theme === ThemeMode.Darkest ? 'outline' : 'subtle'}
|
|
rounded="xl"
|
|
_text={{fontSize: 'xl', color: 'white.900'}}>
|
|
Log in
|
|
</Button>
|
|
</VStack>
|
|
</Box>
|
|
);
|
|
}
|
|
|
|
export function RegisterScreenAnim(props: any) {
|
|
return (
|
|
<SlideFromLeftView>
|
|
<RegisterScreen {...props} />
|
|
</SlideFromLeftView>
|
|
);
|
|
}
|
|
|
|
export type LoginStackNavigatorParamList = {
|
|
RegStepOne: undefined;
|
|
RegStepTwo: undefined;
|
|
RegStepFinal: undefined;
|
|
};
|
|
|
|
const LoginStack = createNativeStackNavigator<LoginStackNavigatorParamList>();
|
|
|
|
export type LoginScreenNavigationProp =
|
|
NativeStackNavigationProp<LoginStackNavigatorParamList>;
|
|
|
|
function RegisterScreen() {
|
|
const lang = useSelector((state: RootState) => state.appVariables.lang);
|
|
const theme = useSelector(
|
|
(state: RootState) => state.appVariables.preferences.theme,
|
|
);
|
|
|
|
return (
|
|
<LoginStack.Navigator>
|
|
<LoginStack.Screen
|
|
name="RegStepOne"
|
|
options={{
|
|
animation: 'slide_from_left',
|
|
title: lang.account.registration.registration,
|
|
headerShown: true,
|
|
...defaultHeaderStyle(theme, 'registration'),
|
|
}}
|
|
component={StepOne}
|
|
/>
|
|
<LoginStack.Screen
|
|
name="RegStepTwo"
|
|
options={{
|
|
animation: 'slide_from_right',
|
|
title: lang.account.registration.registration,
|
|
headerShown: true,
|
|
...defaultHeaderStyle(theme, 'registration'),
|
|
}}
|
|
component={StepTwo}
|
|
/>
|
|
<LoginStack.Screen
|
|
name="RegStepFinal"
|
|
options={{
|
|
animation: 'slide_from_right',
|
|
title: lang.account.registration.registration,
|
|
headerShown: true,
|
|
...defaultHeaderStyle(theme, 'registration'),
|
|
}}
|
|
component={StepFinal}
|
|
/>
|
|
</LoginStack.Navigator>
|
|
);
|
|
}
|
|
|
|
function Agreement() {
|
|
const toast = useToast();
|
|
const lang = useSelector((state: RootState) => state.appVariables.lang);
|
|
|
|
const textColor = useColorModeValue('blue.700', 'cyan.400');
|
|
|
|
let replacedText = reactStringReplace(
|
|
lang.account.registration.info,
|
|
'${TermsOfUse}',
|
|
(match, i) => (
|
|
<Text
|
|
key={match + i}
|
|
color={textColor}
|
|
bold
|
|
onPress={() => {
|
|
showToast(toast, {
|
|
title: lang.account.registration.termsOfUse,
|
|
variant: 'solid',
|
|
status: 'info',
|
|
description: undefined,
|
|
isClosable: true,
|
|
rest: {colorScheme: 'primary'},
|
|
});
|
|
}}>
|
|
{lang.account.registration.termsOfUse}
|
|
</Text>
|
|
),
|
|
);
|
|
|
|
replacedText = reactStringReplace(
|
|
replacedText,
|
|
'${privacyPolicy}',
|
|
(match, i) => (
|
|
<Text
|
|
key={match + i}
|
|
color={textColor}
|
|
bold
|
|
onPress={() => {
|
|
showToast(toast, {
|
|
title: lang.account.registration.privacyPolicy,
|
|
variant: 'solid',
|
|
status: 'info',
|
|
description: undefined,
|
|
isClosable: true,
|
|
rest: {colorScheme: 'primary'},
|
|
});
|
|
}}>
|
|
{lang.account.registration.privacyPolicy}
|
|
</Text>
|
|
),
|
|
);
|
|
|
|
return (
|
|
<Text textAlign={'justify'} color={'white.900'}>
|
|
{replacedText}
|
|
</Text>
|
|
);
|
|
}
|
|
|
|
function resendMail(email: EMail, toast: any): Promise<XToken> {
|
|
return new Promise<XToken>((resolve, reject) => {
|
|
makeRequest({
|
|
path: apiBackendRequest.REGISTER_RESEND_MAIL,
|
|
|
|
requestHeader: {},
|
|
request: {
|
|
Email: email,
|
|
},
|
|
//response: {
|
|
// XToken: undefined,
|
|
//},
|
|
})
|
|
.then(resp => {
|
|
console.log(1);
|
|
let token =
|
|
store.getState().appVariables.preferences.RegisterProcess.XToken;
|
|
if (token !== undefined /*resp.response.XToken !== undefined*/) {
|
|
showToast(toast, {
|
|
title: store.getState().appVariables.lang.info,
|
|
variant: 'solid',
|
|
status: 'info',
|
|
description:
|
|
store.getState().appVariables.lang.account.registration.stepTwo
|
|
.resend[2],
|
|
isClosable: true,
|
|
rest: {},
|
|
});
|
|
|
|
resolve(token);
|
|
} else {
|
|
reject(500);
|
|
showToast(toast, {
|
|
title: store.getState().appVariables.lang.error,
|
|
variant: 'solid',
|
|
status: 'error',
|
|
description: 'XToken is undefined',
|
|
isClosable: true,
|
|
rest: {},
|
|
});
|
|
}
|
|
})
|
|
.catch(resp => {
|
|
let text = 'unknown error ' + resp.status;
|
|
if (resp.status !== undefined) {
|
|
const _text =
|
|
store.getState().appVariables.lang.account.registration.stepTwo
|
|
.resendError[resp.status as number];
|
|
if (_text !== undefined) text = _text;
|
|
}
|
|
|
|
showToast(toast, {
|
|
title: store.getState().appVariables.lang.error,
|
|
variant: 'solid',
|
|
status: 'error',
|
|
description: text,
|
|
isClosable: true,
|
|
rest: {},
|
|
});
|
|
|
|
reject(resp.status);
|
|
});
|
|
});
|
|
}
|
|
|
|
function StepOne() {
|
|
const lang = useSelector((state: RootState) => state.appVariables.lang);
|
|
const regPro = useSelector(
|
|
(state: RootState) => state.appVariables.preferences.RegisterProcess,
|
|
);
|
|
|
|
const dispatch = useDispatch();
|
|
const toast = useToast();
|
|
|
|
const navigation = useNavigation<RootScreenNavigationProp>();
|
|
|
|
const initNoErrors = {
|
|
wrongFormat: false,
|
|
alreadyExists: false,
|
|
noEntered: false,
|
|
unknown: undefined,
|
|
};
|
|
|
|
const [errors, setErrors] = useState(initNoErrors);
|
|
|
|
const isError =
|
|
errors.wrongFormat ||
|
|
errors.alreadyExists ||
|
|
errors.noEntered ||
|
|
errors.unknown !== undefined;
|
|
|
|
const errorText = () => {
|
|
if (errors.wrongFormat) {
|
|
return lang.account.registration.stepOne.addressInvalid;
|
|
}
|
|
if (errors.alreadyExists) {
|
|
return lang.account.registration.stepOne.addressExists;
|
|
}
|
|
if (errors.noEntered) {
|
|
return lang.account.registration.stepOne.noMailEntered;
|
|
}
|
|
if (errors.unknown !== undefined) {
|
|
return errors.unknown;
|
|
}
|
|
};
|
|
|
|
const [isLoading, setLoading] = useState(false);
|
|
|
|
const [values, setValues] = useState({email: regPro.EMail});
|
|
|
|
useEffect(() => {
|
|
if (regPro.isRegistering === 'stepTwo') {
|
|
setLoading(true);
|
|
setErrors(initNoErrors);
|
|
|
|
setTimeout(nextStep, 500);
|
|
} else if (regPro.isRegistering === 'stepFinal') {
|
|
setLoading(true);
|
|
setErrors(initNoErrors);
|
|
|
|
setTimeout(nextStep, 500);
|
|
}
|
|
}, []);
|
|
|
|
const nextStep = () => {
|
|
setLoading(true);
|
|
setErrors(initNoErrors);
|
|
|
|
makeRequest({
|
|
path: apiBackendRequest.REGISTER_STEP_1,
|
|
requestHeader: {},
|
|
request: {
|
|
Email: values.email,
|
|
},
|
|
response: {
|
|
XToken: undefined,
|
|
},
|
|
})
|
|
.then(resp => {
|
|
let rp = {...regPro};
|
|
rp.isRegistering = 'stepTwo';
|
|
rp.EMail = values.email;
|
|
rp.XToken = resp.response.XToken;
|
|
|
|
dispatch(appVarActions.setRegisterProcess(rp));
|
|
saveVarChanges();
|
|
|
|
showToast(toast, {
|
|
title: lang.account.registration.stepOne.success,
|
|
variant: 'solid',
|
|
status: 'success',
|
|
description: undefined,
|
|
isClosable: true,
|
|
rest: {colorScheme: 'primary'},
|
|
});
|
|
|
|
navigation.navigate('Register', {screen: 'RegStepTwo'});
|
|
setLoading(false);
|
|
})
|
|
.catch(resp => {
|
|
if (resp.status === 401 || resp.status === 204) {
|
|
if (regPro.XToken !== undefined) {
|
|
let rp = {...regPro};
|
|
|
|
if (resp.status === 401) {
|
|
rp.isRegistering = 'stepTwo';
|
|
rp.EMail = values.email;
|
|
|
|
dispatch(appVarActions.setRegisterProcess(rp));
|
|
saveVarChanges();
|
|
|
|
navigation.navigate('Register', {screen: 'RegStepTwo'});
|
|
} else if (resp.status === 204) {
|
|
rp.isRegistering = 'stepFinal';
|
|
rp.EMail = values.email;
|
|
|
|
dispatch(appVarActions.setRegisterProcess(rp));
|
|
saveVarChanges();
|
|
|
|
navigation.navigate('Register', {screen: 'RegStepFinal'});
|
|
}
|
|
|
|
setLoading(false);
|
|
} else {
|
|
resendMail(values.email, toast)
|
|
.then(() => {
|
|
setLoading(false);
|
|
})
|
|
.catch(() => {
|
|
setLoading(false);
|
|
});
|
|
}
|
|
} else {
|
|
showToast(toast, {
|
|
title: 'Error',
|
|
variant: 'solid',
|
|
status: 'error',
|
|
description: resp.status,
|
|
isClosable: true,
|
|
rest: {colorScheme: 'primary'},
|
|
});
|
|
setLoading(false);
|
|
}
|
|
});
|
|
};
|
|
|
|
return (
|
|
<ScrollView keyboardShouldPersistTaps="handled">
|
|
<Box alignItems="center" mt={5}>
|
|
<FormControl
|
|
w="75%"
|
|
maxW="350px"
|
|
isRequired
|
|
isDisabled={isLoading}
|
|
isInvalid={isError}>
|
|
<FormControl.Label>
|
|
{lang.account.registration.stepOne.title}
|
|
</FormControl.Label>
|
|
<Input
|
|
autoFocus
|
|
placeholder={lang.account.registration.stepOne.title}
|
|
value={values.email}
|
|
autoCapitalize={'none'}
|
|
maxLength={emailOptions.maxLength}
|
|
keyboardType={'email-address'}
|
|
onChangeText={text => {
|
|
const mail = text.replaceAll(' ', '');
|
|
setValues({email: mail});
|
|
|
|
if (errors.noEntered && mail !== '') {
|
|
let err = errors;
|
|
err.noEntered = false;
|
|
setErrors({...err});
|
|
}
|
|
if (errors.wrongFormat && validateEmail(mail)) {
|
|
let err = errors;
|
|
err.wrongFormat = false;
|
|
setErrors({...err});
|
|
}
|
|
if (errors.alreadyExists) {
|
|
let err = errors;
|
|
err.alreadyExists = false;
|
|
setErrors({...err});
|
|
}
|
|
}}
|
|
/>
|
|
|
|
<FormControl.ErrorMessage leftIcon={<WarningOutlineIcon size="xs" />}>
|
|
{errorText()}
|
|
</FormControl.ErrorMessage>
|
|
</FormControl>
|
|
<Container marginY={5}>
|
|
<Agreement />
|
|
</Container>
|
|
<Button
|
|
w="75%"
|
|
maxW="350px"
|
|
colorScheme="primary"
|
|
rounded="xl"
|
|
_text={{fontSize: 'xl'}}
|
|
isLoading={isLoading}
|
|
onPress={() => {
|
|
if (values.email === '') {
|
|
let err = errors;
|
|
err.noEntered = true;
|
|
setErrors({...err});
|
|
} else if (validateEmail(values.email)) {
|
|
nextStep();
|
|
} else {
|
|
let err = errors;
|
|
err.wrongFormat = true;
|
|
setErrors({...err});
|
|
}
|
|
}}>
|
|
{lang.account.registration.stepOne.button}
|
|
</Button>
|
|
</Box>
|
|
</ScrollView>
|
|
);
|
|
}
|
|
|
|
function StepTwo() {
|
|
const lang = useSelector((state: RootState) => state.appVariables.lang);
|
|
const regPro = useSelector(
|
|
(state: RootState) => state.appVariables.preferences.RegisterProcess,
|
|
);
|
|
|
|
const dispatch = useDispatch();
|
|
|
|
const cellCount = 6;
|
|
const {colors} = useTheme();
|
|
|
|
const toast = useToast();
|
|
|
|
const navigation = useNavigation<RootScreenNavigationProp>();
|
|
|
|
const initNoErrors = {
|
|
noEntered: false,
|
|
};
|
|
|
|
const [errors, setErrors] = useState(initNoErrors);
|
|
|
|
const [isLoading, setLoading] = useState(false);
|
|
|
|
const [values, setValues] = useState({code: ''});
|
|
|
|
const headerText = () => {
|
|
return reactStringReplace(
|
|
lang.account.registration.stepTwo.title,
|
|
'${EMail}',
|
|
(match, i) => (
|
|
<Text key={match + i} color={'primary.400'}>
|
|
{regPro.EMail}
|
|
</Text>
|
|
),
|
|
);
|
|
};
|
|
|
|
const resendText = () => {
|
|
return reactStringReplace(
|
|
lang.account.registration.stepTwo.resend[0],
|
|
'${resend}',
|
|
(match, i) => (
|
|
<Text
|
|
key={match + i}
|
|
color={'primary.400'}
|
|
onPress={() => {
|
|
setLoading(true);
|
|
resendMail(
|
|
store.getState().appVariables.preferences.RegisterProcess.EMail,
|
|
toast,
|
|
)
|
|
.then(() => {
|
|
setLoading(false);
|
|
})
|
|
.catch(() => {
|
|
setLoading(false);
|
|
});
|
|
}}>
|
|
{lang.account.registration.stepTwo.resend[1]}
|
|
</Text>
|
|
),
|
|
);
|
|
};
|
|
|
|
const validate = (text: string) => {
|
|
setLoading(true);
|
|
setTimeout(() => {
|
|
makeRequest({
|
|
path: apiBackendRequest.REGISTER_STEP_2,
|
|
|
|
requestHeader: {},
|
|
requestGET: {':verifyId': text, ':xToken': regPro.XToken || ''},
|
|
})
|
|
.then(resp => {
|
|
let rp = {...regPro};
|
|
rp.isRegistering = 'stepFinal';
|
|
|
|
dispatch(appVarActions.setRegisterProcess(rp));
|
|
saveVarChanges();
|
|
|
|
showToast(toast, {
|
|
title: lang.account.registration.stepTwo.success,
|
|
variant: 'solid',
|
|
status: 'success',
|
|
description: undefined,
|
|
isClosable: true,
|
|
rest: {colorScheme: 'primary'},
|
|
});
|
|
|
|
navigation.navigate('Register', {screen: 'RegStepFinal'});
|
|
setLoading(false);
|
|
})
|
|
.catch(resp => {
|
|
let text = 'unknown error ' + resp.status;
|
|
if (resp.status !== undefined) {
|
|
const _text =
|
|
lang.account.registration.stepTwo.verificationError[
|
|
resp.status as number
|
|
];
|
|
if (_text !== undefined) text = _text;
|
|
}
|
|
|
|
showToast(toast, {
|
|
title: lang.error,
|
|
variant: 'solid',
|
|
status: 'error',
|
|
description: text,
|
|
isClosable: true,
|
|
rest: {},
|
|
});
|
|
|
|
setLoading(false);
|
|
if (resp.status === 422) {
|
|
let rp = {...regPro};
|
|
rp.isRegistering = false;
|
|
|
|
dispatch(appVarActions.setRegisterProcess(rp));
|
|
saveVarChanges();
|
|
navigation.navigate('Register', {screen: 'RegStepOne'});
|
|
}
|
|
});
|
|
}, 500);
|
|
};
|
|
|
|
return (
|
|
<ScrollView keyboardShouldPersistTaps="handled">
|
|
<Box alignItems="center" mt={5}>
|
|
<Center w="75%" maxW="1000px">
|
|
<Text>{headerText()}</Text>
|
|
<Box>
|
|
<FormControl isDisabled={isLoading} isInvalid={errors.noEntered}>
|
|
<ConfirmationCodeField
|
|
cellCount={cellCount}
|
|
charType="number"
|
|
disabled={isLoading}
|
|
rest={{mt: 5}}
|
|
onChange={(text: string) => {
|
|
setValues({code: text});
|
|
setErrors(initNoErrors);
|
|
}}
|
|
onFinish={(text: string) => validate(text)}
|
|
/>
|
|
|
|
<FormControl.ErrorMessage
|
|
leftIcon={<WarningOutlineIcon size="xs" />}>
|
|
{lang.account.registration.stepTwo.noCodeEntered}
|
|
</FormControl.ErrorMessage>
|
|
</FormControl>
|
|
</Box>
|
|
</Center>
|
|
<Container marginY={5}>
|
|
<Agreement />
|
|
</Container>
|
|
<Button
|
|
w="75%"
|
|
maxW="350px"
|
|
colorScheme="primary"
|
|
rounded="xl"
|
|
_text={{fontSize: 'xl'}}
|
|
isLoading={isLoading}
|
|
onPress={() => {
|
|
if (values.code.length === cellCount) {
|
|
validate(values.code);
|
|
} else {
|
|
let err = {...errors};
|
|
err.noEntered = true;
|
|
setErrors(err);
|
|
}
|
|
}}>
|
|
{lang.account.registration.stepTwo.button}
|
|
</Button>
|
|
<Container marginY={5}>
|
|
<Text textAlign={'justify'} color={'white.900'}>
|
|
{resendText()}
|
|
</Text>
|
|
</Container>
|
|
</Box>
|
|
</ScrollView>
|
|
);
|
|
}
|
|
function StepFinal() {
|
|
const lang = useSelector((state: RootState) => state.appVariables.lang);
|
|
const regPro = useSelector(
|
|
(state: RootState) => state.appVariables.preferences.RegisterProcess,
|
|
);
|
|
|
|
const dispatch = useDispatch();
|
|
|
|
const {colors} = useTheme();
|
|
|
|
const toast = useToast();
|
|
|
|
const navigation = useNavigation<RootScreenNavigationProp>();
|
|
|
|
const [isLoading, setLoading] = useState(false);
|
|
const [showPassword, setShowPassword] = useState(false);
|
|
|
|
interface inputElementType {
|
|
label: string;
|
|
input: string;
|
|
autoCapitalize: 'none' | 'words';
|
|
errorIndex: 'none' | string;
|
|
errorTextObject: any;
|
|
isPassword: boolean | 'passwordRepeat';
|
|
minLength: number;
|
|
maxLength: number;
|
|
onTextChange: any;
|
|
textChangeTimeout: number;
|
|
isAllowed: any;
|
|
}
|
|
|
|
const accountNameRef = useRef(setTimeout(() => {}));
|
|
const accountNameFetchRef = useRef(setTimeout(() => {}));
|
|
|
|
const accountName = {
|
|
label: lang.account.registration.stepFinal.accountName,
|
|
input: '',
|
|
errorIndex: 'none',
|
|
errorTextObject: lang.account.registration.stepFinal.accountNameError,
|
|
minLength: accountNameOptions.minLength,
|
|
maxLength: accountNameOptions.maxLength,
|
|
isAllowed: accountNameOptions.isAllowed,
|
|
isPassword: false,
|
|
onTextChange: (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
let text = e.nativeEvent.text;
|
|
let self = accountName;
|
|
|
|
clearTimeout(accountNameRef.current);
|
|
|
|
let obj = {...valuesAccountName};
|
|
accountNameRef.current = setTimeout(() => {
|
|
obj.input = text;
|
|
|
|
if (text.length < self.minLength) obj.errorIndex = 'tooShort';
|
|
else if (text.length > self.maxLength) obj.errorIndex = 'tooLong';
|
|
else if (self.isAllowed(text) === false) obj.errorIndex = 'invalid';
|
|
else obj.errorIndex = 'none';
|
|
|
|
setValuesAccountName(obj);
|
|
}, 50);
|
|
|
|
clearTimeout(accountNameFetchRef.current);
|
|
accountNameFetchRef.current = setTimeout(() => {
|
|
console.log(obj);
|
|
|
|
if (obj.errorIndex === 'none') {
|
|
makeRequest({
|
|
path: apiBackendRequest.REGISTER_STEP_FINAL_ACCOUNT_NAME_CHECK,
|
|
request: {AccountName: obj.input},
|
|
})
|
|
.then(resp => {
|
|
console.log('OK');
|
|
})
|
|
.catch(resp => {
|
|
if (resp.status !== undefined) {
|
|
obj.errorIndex = resp.status;
|
|
setValuesAccountName(obj);
|
|
}
|
|
});
|
|
}
|
|
}, 750);
|
|
},
|
|
} as inputElementType;
|
|
const [valuesAccountName, setValuesAccountName] = useState(accountName);
|
|
|
|
const userNameRef = useRef(setTimeout(() => {}));
|
|
|
|
const userName = {
|
|
label: lang.account.registration.stepFinal.userName,
|
|
input: '',
|
|
errorIndex: 'none',
|
|
errorTextObject: lang.account.registration.stepFinal.userNameError,
|
|
minLength: userNameOptions.minLength,
|
|
maxLength: userNameOptions.maxLength,
|
|
isAllowed: userNameOptions.isAllowed,
|
|
isPassword: false,
|
|
onTextChange: (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
let text = e.nativeEvent.text;
|
|
let self = userName;
|
|
|
|
clearTimeout(userNameRef.current);
|
|
|
|
userNameRef.current = setTimeout(() => {
|
|
let obj = {...valuesUserName};
|
|
obj.input = text;
|
|
|
|
if (text.length < self.minLength) obj.errorIndex = 'tooShort';
|
|
else if (text.length > self.maxLength) obj.errorIndex = 'tooLong';
|
|
else if (self.isAllowed(text) === false) obj.errorIndex = 'invalid';
|
|
else obj.errorIndex = 'none';
|
|
|
|
setValuesUserName(obj);
|
|
}, 50);
|
|
},
|
|
} as inputElementType;
|
|
const [valuesUserName, setValuesUserName] = useState(userName);
|
|
|
|
const passwordRef = useRef(setTimeout(() => {}));
|
|
|
|
const password = {
|
|
label: lang.account.registration.stepFinal.password,
|
|
input: '',
|
|
errorIndex: 'none',
|
|
errorTextObject: lang.account.registration.stepFinal.passwordError,
|
|
minLength: passwordOptions.minLength,
|
|
maxLength: passwordOptions.maxLength,
|
|
isAllowed: passwordOptions.isAllowed,
|
|
isPassword: true,
|
|
onTextChange: (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
let text = e.nativeEvent.text;
|
|
let self = password;
|
|
|
|
clearTimeout(passwordRef.current);
|
|
|
|
passwordRef.current = setTimeout(() => {
|
|
let obj = {...valuesPassword};
|
|
obj.input = text;
|
|
|
|
if (text.length < self.minLength) obj.errorIndex = 'tooShort';
|
|
else if (text.length > self.maxLength) obj.errorIndex = 'tooLong';
|
|
else if (self.isAllowed(text) === false) obj.errorIndex = 'invalid';
|
|
else obj.errorIndex = 'none';
|
|
|
|
setValuesPassword(obj);
|
|
|
|
let objRe = {...valuesPasswordRe};
|
|
if (text !== valuesPasswordRe.input) objRe.errorIndex = 'noMatch';
|
|
else objRe.errorIndex = 'none';
|
|
|
|
setValuesPasswordRe(objRe);
|
|
}, 50);
|
|
},
|
|
} as inputElementType;
|
|
const [valuesPassword, setValuesPassword] = useState(password);
|
|
|
|
const passwordReRef = useRef(setTimeout(() => {}));
|
|
|
|
const passwordRe = {
|
|
label: lang.account.registration.stepFinal.passwordRepeat,
|
|
input: '',
|
|
errorIndex: 'none',
|
|
errorTextObject: lang.account.registration.stepFinal.passwordError,
|
|
minLength: passwordOptions.minLength,
|
|
maxLength: passwordOptions.maxLength,
|
|
isAllowed: passwordOptions.isAllowed,
|
|
isPassword: 'passwordRepeat',
|
|
onTextChange: (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
let text = e.nativeEvent.text;
|
|
let self = passwordRe;
|
|
|
|
clearTimeout(passwordReRef.current);
|
|
|
|
passwordReRef.current = setTimeout(() => {
|
|
let obj = {...valuesPasswordRe};
|
|
obj.input = text;
|
|
console.log(text, valuesPassword.input);
|
|
|
|
if (text !== valuesPassword.input) obj.errorIndex = 'noMatch';
|
|
else obj.errorIndex = 'none';
|
|
|
|
setValuesPasswordRe(obj);
|
|
}, 50);
|
|
},
|
|
} as inputElementType;
|
|
const [valuesPasswordRe, setValuesPasswordRe] = useState(passwordRe);
|
|
|
|
const inputElement = (
|
|
val: inputElementType,
|
|
set: React.Dispatch<React.SetStateAction<inputElementType>>,
|
|
valConst: inputElementType,
|
|
autofocus?: boolean,
|
|
) => {
|
|
const isPassword =
|
|
val.isPassword === true || val.isPassword === 'passwordRepeat';
|
|
|
|
return (
|
|
<FormControl
|
|
w="75%"
|
|
maxW="350px"
|
|
isRequired
|
|
isDisabled={isLoading}
|
|
isInvalid={val.errorIndex !== 'none'}>
|
|
<FormControl.Label>{val.label}</FormControl.Label>
|
|
<Input
|
|
autoFocus={autofocus}
|
|
type={isPassword && showPassword === false ? 'password' : 'text'}
|
|
placeholder={''}
|
|
keyboardType={'default'}
|
|
onChange={valConst.onTextChange}
|
|
InputRightElement={
|
|
isPassword ? (
|
|
<IconButton
|
|
mr="2"
|
|
onPress={() => setShowPassword(!showPassword)}
|
|
icon={
|
|
<MaterialIcons
|
|
size={20}
|
|
name={showPassword ? 'visibility' : 'visibility-off'}
|
|
/>
|
|
}
|
|
borderRadius="full"
|
|
/>
|
|
) : undefined
|
|
}
|
|
/>
|
|
|
|
<FormControl.ErrorMessage leftIcon={<WarningOutlineIcon size="xs" />}>
|
|
{val.errorTextObject[val.errorIndex] !== undefined
|
|
? val.errorTextObject[val.errorIndex]
|
|
.replaceAll('$(minLength)', val.minLength)
|
|
.replaceAll('$(maxLength)', val.maxLength)
|
|
: val.errorTextObject[val.errorIndex] !== 'none'
|
|
? lang.error
|
|
: null}
|
|
</FormControl.ErrorMessage>
|
|
</FormControl>
|
|
);
|
|
};
|
|
|
|
return (
|
|
<ScrollView keyboardShouldPersistTaps="handled">
|
|
<VStack space={3} alignItems="center" mt={5}>
|
|
<Container maxWidth={'100%'} alignItems={'center'}>
|
|
<Center>
|
|
<Text>{lang.account.registration.stepFinal.displayName}</Text>
|
|
<NameDisplay
|
|
UserName={
|
|
valuesUserName.input !== ''
|
|
? valuesUserName.input
|
|
: lang.account.registration.stepFinal.userName
|
|
}
|
|
AccountName={
|
|
valuesAccountName.input !== ''
|
|
? valuesAccountName.input
|
|
: lang.account.registration.stepFinal.accountName
|
|
}
|
|
/>
|
|
</Center>
|
|
</Container>
|
|
{inputElement(valuesUserName, setValuesUserName, userName)}
|
|
{inputElement(valuesAccountName, setValuesAccountName, accountName)}
|
|
{inputElement(valuesPassword, setValuesPassword, password)}
|
|
{inputElement(valuesPasswordRe, setValuesPasswordRe, passwordRe)}
|
|
</VStack>
|
|
<Center>
|
|
<Container mt={5}>
|
|
<Agreement />
|
|
</Container>
|
|
<Button
|
|
marginY={5}
|
|
w="75%"
|
|
maxW="350px"
|
|
colorScheme="primary"
|
|
rounded="xl"
|
|
_text={{fontSize: 'xl'}}
|
|
isLoading={isLoading}
|
|
onPress={() => {}}>
|
|
{lang.account.registration.stepFinal.button}
|
|
</Button>
|
|
</Center>
|
|
</ScrollView>
|
|
);
|
|
}
|