mirror of
https://github.com/ecency/ecency-mobile.git
synced 2024-12-18 10:52:16 +03:00
improved beneficiary modal
1. manage validity state separate 2. 500 ms debounce for account check 3. tweak UI for better presentation
This commit is contained in:
parent
fa77aa48a2
commit
18016e604d
@ -1,21 +1,26 @@
|
||||
import React, { useState, useCallback, useEffect } from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { View, FlatList, Text } from 'react-native';
|
||||
import { useIntl } from 'react-intl';
|
||||
import AsyncStorage from '@react-native-community/async-storage';
|
||||
import { isArray, remove } from 'lodash';
|
||||
import { isArray, debounce } from 'lodash';
|
||||
|
||||
import { lookupAccounts } from '../../providers/hive/dhive';
|
||||
|
||||
import { FormInput, MainButton, Tag } from '..';
|
||||
import { FormInput, MainButton, Tag, TextButton } from '..';
|
||||
|
||||
import styles from './beneficiaryModalStyles';
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
const BeneficiaryModal = ({ username, handleOnSaveBeneficiaries, isDraft }) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const [beneficiaries, setBeneficiaries] = useState([
|
||||
{ account: username, weight: 10000, isValid: true },
|
||||
{ account: username, weight: 10000},
|
||||
]);
|
||||
const [validity, setValidity] = useState([{
|
||||
weightValid:true,
|
||||
usernameValid:true
|
||||
}])
|
||||
|
||||
useEffect(() => {
|
||||
if (!isDraft) {
|
||||
@ -37,7 +42,8 @@ const BeneficiaryModal = ({ username, handleOnSaveBeneficiaries, isDraft }) => {
|
||||
};
|
||||
|
||||
const _addAccount = () => {
|
||||
setBeneficiaries([...beneficiaries, { account: '', weight: 0, isValid: false }]);
|
||||
setBeneficiaries([...beneficiaries, { account: '', weight: 0}]);
|
||||
setValidity([...validity, {weightValid:false, usernameValid:false}])
|
||||
};
|
||||
|
||||
const _onWeightInputChange = (value, index) => {
|
||||
@ -47,60 +53,71 @@ const BeneficiaryModal = ({ username, handleOnSaveBeneficiaries, isDraft }) => {
|
||||
beneficiaries[0].weight = beneficiaries[0].weight - _diff;
|
||||
beneficiaries[index].weight = _value;
|
||||
|
||||
setBeneficiaries([...beneficiaries]);
|
||||
validity[index].weightValid = _value > 0 && _value <= 10000;
|
||||
|
||||
setBeneficiaries(beneficiaries);
|
||||
setValidity([...validity])
|
||||
};
|
||||
|
||||
const _onUsernameInputChange = (value, index) => {
|
||||
beneficiaries[index].account = value;
|
||||
|
||||
setBeneficiaries([...beneficiaries]);
|
||||
|
||||
lookupAccounts(value).then((res) => {
|
||||
const isValid =
|
||||
res.includes(value) &&
|
||||
beneficiaries[index].weight !== 0 &&
|
||||
beneficiaries[index].weight <= 10000;
|
||||
beneficiaries[index].isValid = isValid;
|
||||
setBeneficiaries([...beneficiaries]);
|
||||
const _lookupAccounts = debounce((username, index)=>{
|
||||
lookupAccounts(username).then((res) => {
|
||||
const isValid =
|
||||
res.includes(username)
|
||||
validity[index].usernameValid = isValid;
|
||||
setValidity([...validity]);
|
||||
});
|
||||
}, 500)
|
||||
|
||||
const _onUsernameInputChange = (value, index) => {
|
||||
_lookupAccounts(value, index);
|
||||
|
||||
beneficiaries[index].account = value;
|
||||
setBeneficiaries(beneficiaries);
|
||||
};
|
||||
|
||||
const _isValid = () => {
|
||||
return beneficiaries.every((item) => item.isValid);
|
||||
return validity.every((item) => (item.usernameValid && item.weightValid));
|
||||
};
|
||||
|
||||
const _onBlur = (item, index) => {
|
||||
const _onBlur = (item) => {
|
||||
if (item.weight === 0) {
|
||||
const newBeneficiaries = [...beneficiaries];
|
||||
remove(newBeneficiaries, (current) => {
|
||||
return current.account === item.account;
|
||||
});
|
||||
const newValidity = [...validity];
|
||||
|
||||
const index = newBeneficiaries.findIndex((current)=>current.account === item.account);
|
||||
if(index >= 0){
|
||||
newBeneficiaries.splice(index, 1);
|
||||
newValidity.splice(index, 1);
|
||||
}
|
||||
|
||||
setBeneficiaries(newBeneficiaries);
|
||||
setValidity(newValidity);
|
||||
}
|
||||
};
|
||||
|
||||
const renderInputs = ({ item, index }) => {
|
||||
|
||||
const renderInput = ({ item, index }) => {
|
||||
const _isCurrentUser = item.account === username;
|
||||
const {weightValid, usernameValid} = validity[index];
|
||||
|
||||
return (
|
||||
<View style={styles.inputWrapper}>
|
||||
<View style={styles.weightInput}>
|
||||
<FormInput
|
||||
isValid={_isCurrentUser || (item.weight !== 0 && item.weight <= 10000)}
|
||||
isValid={_isCurrentUser || weightValid}
|
||||
isEditable={!_isCurrentUser}
|
||||
value={`${item.weight / 100}`}
|
||||
inputStyle={styles.weightFormInput}
|
||||
wrapperStyle={styles.weightFormInputWrapper}
|
||||
onChange={(value) => _onWeightInputChange(value, index)}
|
||||
onBlur={() => _onBlur(item, index)}
|
||||
onBlur={() => _onBlur(item)}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.usernameInput}>
|
||||
<FormInput
|
||||
rightIconName="at"
|
||||
iconType="MaterialCommunityIcons"
|
||||
isValid={_isCurrentUser || item.isValid}
|
||||
isValid={_isCurrentUser || usernameValid}
|
||||
//isEditable={!_isCurrentUser}
|
||||
onChange={(value) => _onUsernameInputChange(value, index)}
|
||||
placeholder={intl.formatMessage({
|
||||
@ -117,12 +134,16 @@ const BeneficiaryModal = ({ username, handleOnSaveBeneficiaries, isDraft }) => {
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
const isAllValid = _isValid();
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View style={styles.bodyWrapper}>
|
||||
<FlatList
|
||||
data={beneficiaries}
|
||||
renderItem={renderInputs}
|
||||
renderItem={renderInput}
|
||||
extraData={validity}
|
||||
ListHeaderComponent={() => (
|
||||
<View style={styles.inputWrapper}>
|
||||
<View style={[styles.weightInput, { alignItems: 'center' }]}>
|
||||
@ -142,15 +163,17 @@ const BeneficiaryModal = ({ username, handleOnSaveBeneficiaries, isDraft }) => {
|
||||
</View>
|
||||
)}
|
||||
ListFooterComponent={() => (
|
||||
<View style={{ alignItems: 'flex-end', marginTop: 20 }}>
|
||||
<Tag
|
||||
value={intl.formatMessage({
|
||||
<View style={{marginTop: 20 }}>
|
||||
<TextButton
|
||||
text={intl.formatMessage({
|
||||
id: 'beneficiary_modal.addAccount',
|
||||
})}
|
||||
isFilter
|
||||
disabled={!_isValid()}
|
||||
isPin={_isValid()}
|
||||
disabled={!isAllValid}
|
||||
onPress={_addAccount}
|
||||
textStyle={{
|
||||
color:EStyleSheet.value(isAllValid?'$primaryBlue':"$iconColor"),
|
||||
fontWeight:'bold'
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
)}
|
@ -5,20 +5,21 @@ export default EStyleSheet.create({
|
||||
flex: 1,
|
||||
justifyContent: 'space-between',
|
||||
padding: 16,
|
||||
backgroundColor:'$modalBackground',
|
||||
},
|
||||
bodyWrapper: { flex: 3, paddingTop: 20 },
|
||||
inputWrapper: { flexDirection: 'row', alignItems: 'center' },
|
||||
text: { color: '$primaryBlack', marginBottom: 8 },
|
||||
weightInput: { flex: 1 },
|
||||
weightFormInput: { textAlign: 'center', color: '$primaryBlack' },
|
||||
weightFormInputWrapper: { marginTop: 0 },
|
||||
weightFormInputWrapper: { marginTop: 8, borderRadius:12 },
|
||||
usernameInput: { flex: 3, color: '$primaryBlack', marginLeft: 16 },
|
||||
usernameFormInputWrapper: { marginTop: 0, marginLeft: 10 },
|
||||
footerWrapper: { flex: 1 },
|
||||
usernameFormInputWrapper: { marginTop: 8, marginLeft: 10, borderRadius:12 },
|
||||
footerWrapper: { paddingTop:16, paddingBottom:16 },
|
||||
saveButton: {
|
||||
width: 100,
|
||||
width: 140,
|
||||
height: 44,
|
||||
alignSelf: 'center',
|
||||
alignSelf: 'flex-end',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
});
|
@ -3,9 +3,9 @@ import { Text, View, TouchableWithoutFeedback } from 'react-native';
|
||||
|
||||
import styles from './textButtonStyles';
|
||||
|
||||
const TextButtonView = ({ text, onPress, style, textStyle }) => (
|
||||
const TextButtonView = ({ text, onPress, style, textStyle, disabled }) => (
|
||||
<Fragment>
|
||||
<TouchableWithoutFeedback style={[styles.button]} onPress={() => onPress && onPress()}>
|
||||
<TouchableWithoutFeedback style={[styles.button]} disabled={disabled} onPress={() => onPress && onPress()}>
|
||||
<View style={style}>
|
||||
<Text style={[styles.buttonText, textStyle]}>{text}</Text>
|
||||
</View>
|
Loading…
Reference in New Issue
Block a user