Chore: Hooks app/views/SetUsernameView (#4488)
* Chore: Hooks app/views/SetUsernameView * semantic change of loading state Co-authored-by: Gleidson Daniel <gleidson10daniel@hotmail.com>
This commit is contained in:
parent
e3a99a93e4
commit
eabb9f157c
|
@ -1,27 +1,28 @@
|
|||
import { RouteProp } from '@react-navigation/native';
|
||||
import { StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
|
||||
import React from 'react';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import { StackNavigationProp } from '@react-navigation/stack';
|
||||
import React, { useEffect, useLayoutEffect, useState } from 'react';
|
||||
import { ScrollView, StyleSheet, Text } from 'react-native';
|
||||
import Orientation from 'react-native-orientation-locker';
|
||||
import { connect } from 'react-redux';
|
||||
import { Dispatch } from 'redux';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import * as yup from 'yup';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
|
||||
import { loginRequest } from '../actions/login';
|
||||
import { themes } from '../lib/constants';
|
||||
import Button from '../containers/Button';
|
||||
import SafeAreaView from '../containers/SafeAreaView';
|
||||
import StatusBar from '../containers/StatusBar';
|
||||
import { FormTextInput } from '../containers/TextInput';
|
||||
import { IApplicationState } from '../definitions';
|
||||
import { ControlledFormTextInput } from '../containers/TextInput';
|
||||
import { SetUsernameStackParamList } from '../definitions/navigationTypes';
|
||||
import I18n from '../i18n';
|
||||
import KeyboardView from '../containers/KeyboardView';
|
||||
import { getUserSelector } from '../selectors/login';
|
||||
import { TSupportedThemes, withTheme } from '../theme';
|
||||
import { useTheme } from '../theme';
|
||||
import { isTablet, showErrorAlert } from '../lib/methods/helpers';
|
||||
import scrollPersistTaps from '../lib/methods/helpers/scrollPersistTaps';
|
||||
import sharedStyles from './Styles';
|
||||
import { Services } from '../lib/services';
|
||||
import { useAppSelector } from '../lib/hooks';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
loginTitle: {
|
||||
|
@ -30,122 +31,94 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
interface ISetUsernameViewState {
|
||||
interface ISubmit {
|
||||
username: string;
|
||||
saving: boolean;
|
||||
}
|
||||
|
||||
interface ISetUsernameViewProps {
|
||||
navigation: StackNavigationProp<SetUsernameStackParamList, 'SetUsernameView'>;
|
||||
route: RouteProp<SetUsernameStackParamList, 'SetUsernameView'>;
|
||||
server: string;
|
||||
userId: string;
|
||||
token: string;
|
||||
theme: TSupportedThemes;
|
||||
dispatch: Dispatch;
|
||||
}
|
||||
const schema = yup.object().shape({
|
||||
username: yup.string().required()
|
||||
});
|
||||
|
||||
class SetUsernameView extends React.Component<ISetUsernameViewProps, ISetUsernameViewState> {
|
||||
static navigationOptions = ({ route }: Pick<ISetUsernameViewProps, 'route'>): StackNavigationOptions => ({
|
||||
title: route.params?.title
|
||||
});
|
||||
const SetUsernameView = () => {
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
formState: { isValid },
|
||||
setValue
|
||||
} = useForm<ISubmit>({ mode: 'onChange', resolver: yupResolver(schema) });
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
constructor(props: ISetUsernameViewProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
username: '',
|
||||
saving: false
|
||||
};
|
||||
const { server } = this.props;
|
||||
props.navigation.setOptions({ title: server });
|
||||
const { colors } = useTheme();
|
||||
const dispatch = useDispatch();
|
||||
const { server, token } = useAppSelector(state => ({ server: state.server.server, token: getUserSelector(state).token }));
|
||||
|
||||
const navigation = useNavigation<StackNavigationProp<SetUsernameStackParamList, 'SetUsernameView'>>();
|
||||
|
||||
useLayoutEffect(() => {
|
||||
navigation.setOptions({ title: server });
|
||||
if (!isTablet) {
|
||||
Orientation.lockToPortrait();
|
||||
}
|
||||
}
|
||||
}, [navigation, server]);
|
||||
|
||||
async componentDidMount() {
|
||||
const suggestion = await Services.getUsernameSuggestion();
|
||||
if (suggestion.success) {
|
||||
this.setState({ username: suggestion.result });
|
||||
}
|
||||
}
|
||||
useEffect(() => {
|
||||
const init = async () => {
|
||||
const suggestion = await Services.getUsernameSuggestion();
|
||||
if (suggestion.success) {
|
||||
setValue('username', suggestion.result, { shouldValidate: true });
|
||||
}
|
||||
};
|
||||
init();
|
||||
}, []);
|
||||
|
||||
shouldComponentUpdate(nextProps: ISetUsernameViewProps, nextState: ISetUsernameViewState) {
|
||||
const { username, saving } = this.state;
|
||||
const { theme } = this.props;
|
||||
if (nextProps.theme !== theme) {
|
||||
return true;
|
||||
}
|
||||
if (nextState.username !== username) {
|
||||
return true;
|
||||
}
|
||||
if (nextState.saving !== saving) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
submit = async () => {
|
||||
const { username } = this.state;
|
||||
const { dispatch, token } = this.props;
|
||||
|
||||
if (!username.trim()) {
|
||||
const submit = async ({ username }: ISubmit) => {
|
||||
if (!isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({ saving: true });
|
||||
setLoading(true);
|
||||
try {
|
||||
await Services.saveUserProfile({ username });
|
||||
dispatch(loginRequest({ resume: token }));
|
||||
} catch (e: any) {
|
||||
showErrorAlert(e.message, I18n.t('Oops'));
|
||||
}
|
||||
this.setState({ saving: false });
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { username, saving } = this.state;
|
||||
const { theme } = this.props;
|
||||
return (
|
||||
<KeyboardView style={{ backgroundColor: themes[theme].auxiliaryBackground }} contentContainerStyle={sharedStyles.container}>
|
||||
<StatusBar />
|
||||
<ScrollView {...scrollPersistTaps} contentContainerStyle={sharedStyles.containerScrollView}>
|
||||
<SafeAreaView testID='set-username-view'>
|
||||
<Text style={[sharedStyles.loginTitle, sharedStyles.textBold, styles.loginTitle, { color: themes[theme].titleText }]}>
|
||||
{I18n.t('Username')}
|
||||
</Text>
|
||||
<Text style={[sharedStyles.loginSubtitle, sharedStyles.textRegular, { color: themes[theme].titleText }]}>
|
||||
{I18n.t('Set_username_subtitle')}
|
||||
</Text>
|
||||
<FormTextInput
|
||||
autoFocus
|
||||
placeholder={I18n.t('Username')}
|
||||
returnKeyType='send'
|
||||
onChangeText={value => this.setState({ username: value })}
|
||||
value={username}
|
||||
onSubmitEditing={this.submit}
|
||||
testID='set-username-view-input'
|
||||
clearButtonMode='while-editing'
|
||||
containerStyle={sharedStyles.inputLastChild}
|
||||
/>
|
||||
<Button
|
||||
title={I18n.t('Register')}
|
||||
type='primary'
|
||||
onPress={this.submit}
|
||||
testID='set-username-view-submit'
|
||||
disabled={!username}
|
||||
loading={saving}
|
||||
/>
|
||||
</SafeAreaView>
|
||||
</ScrollView>
|
||||
</KeyboardView>
|
||||
);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<KeyboardView style={{ backgroundColor: colors.auxiliaryBackground }} contentContainerStyle={sharedStyles.container}>
|
||||
<StatusBar />
|
||||
<ScrollView {...scrollPersistTaps} contentContainerStyle={sharedStyles.containerScrollView}>
|
||||
<SafeAreaView testID='set-username-view'>
|
||||
<Text style={[sharedStyles.loginTitle, sharedStyles.textBold, styles.loginTitle, { color: colors.titleText }]}>
|
||||
{I18n.t('Username')}
|
||||
</Text>
|
||||
<Text style={[sharedStyles.loginSubtitle, sharedStyles.textRegular, { color: colors.titleText }]}>
|
||||
{I18n.t('Set_username_subtitle')}
|
||||
</Text>
|
||||
<ControlledFormTextInput
|
||||
control={control}
|
||||
name='username'
|
||||
autoFocus
|
||||
placeholder={I18n.t('Username')}
|
||||
returnKeyType='send'
|
||||
onSubmitEditing={handleSubmit(submit)}
|
||||
testID='set-username-view-input'
|
||||
clearButtonMode='while-editing'
|
||||
containerStyle={sharedStyles.inputLastChild}
|
||||
/>
|
||||
<Button
|
||||
title={I18n.t('Register')}
|
||||
type='primary'
|
||||
onPress={handleSubmit(submit)}
|
||||
testID='set-username-view-submit'
|
||||
disabled={!isValid}
|
||||
loading={loading}
|
||||
/>
|
||||
</SafeAreaView>
|
||||
</ScrollView>
|
||||
</KeyboardView>
|
||||
);
|
||||
};
|
||||
|
||||
const mapStateToProps = (state: IApplicationState) => ({
|
||||
server: state.server.server,
|
||||
token: getUserSelector(state).token
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(withTheme(SetUsernameView));
|
||||
export default SetUsernameView;
|
||||
|
|
Loading…
Reference in New Issue