mirror of
https://github.com/ecency/ecency-mobile.git
synced 2024-12-30 00:52:42 +03:00
Merge pull request #2269 from ecency/sa/power-down-screen
[WIP] Redesign Power Down Screen
This commit is contained in:
commit
d0b1dedfe5
@ -0,0 +1,377 @@
|
|||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import { View, FlatList, Text, TouchableOpacity } from 'react-native';
|
||||||
|
import { useIntl } from 'react-intl';
|
||||||
|
import { isArray, debounce } from 'lodash';
|
||||||
|
|
||||||
|
import styles from './styles';
|
||||||
|
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||||
|
|
||||||
|
import { useAppDispatch, useAppSelector } from '../../hooks';
|
||||||
|
import { BeneficiaryModal, CheckBox, FormInput, IconButton, TextButton } from '../../components';
|
||||||
|
import { Beneficiary } from '../../redux/reducers/editorReducer';
|
||||||
|
import { lookupAccounts } from '../../providers/hive/dhive';
|
||||||
|
import { TEMP_BENEFICIARIES_ID } from '../../redux/constants/constants';
|
||||||
|
import {
|
||||||
|
removeBeneficiaries,
|
||||||
|
setBeneficiaries as setBeneficiariesAction,
|
||||||
|
} from '../../redux/actions/editorActions';
|
||||||
|
|
||||||
|
interface BeneficiarySelectionContentProps {
|
||||||
|
|
||||||
|
draftId: string;
|
||||||
|
setDisableDone: (value: boolean) => void;
|
||||||
|
powerDown?: boolean;
|
||||||
|
label?:string;
|
||||||
|
labelStyle?:string;
|
||||||
|
powerDownBeneficiaries?: Beneficiary[];
|
||||||
|
handleSaveBeneficiary?: (beneficiaries: Beneficiary[]) => void;
|
||||||
|
handleRemoveBeneficiary?: (beneficiary: Beneficiary) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BeneficiarySelectionContent = ({
|
||||||
|
label,
|
||||||
|
labelStyle,
|
||||||
|
draftId,
|
||||||
|
setDisableDone,
|
||||||
|
powerDown,
|
||||||
|
powerDownBeneficiaries,
|
||||||
|
handleSaveBeneficiary,
|
||||||
|
handleRemoveBeneficiary,
|
||||||
|
}: BeneficiarySelectionContentProps) => {
|
||||||
|
|
||||||
|
const intl = useIntl();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
|
const beneficiariesMap = useAppSelector((state) => state.editor.beneficiariesMap);
|
||||||
|
const username = useAppSelector((state) => state.account.currentAccount.name);
|
||||||
|
|
||||||
|
const [beneficiaries, setBeneficiaries] = useState<Beneficiary[]>([
|
||||||
|
{ account: username, weight: 10000, autoPowerUp: false },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const [newUsername, setNewUsername] = useState('');
|
||||||
|
const [newWeight, setNewWeight] = useState(0);
|
||||||
|
const [newAutoPowerUp, setNewAutoPowerUp] = useState(false);
|
||||||
|
const [isUsernameValid, setIsUsernameValid] = useState(false);
|
||||||
|
const [isWeightValid, setIsWeightValid] = useState(false);
|
||||||
|
const [newEditable, setNewEditable] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (powerDown) {
|
||||||
|
readPowerDownBeneficiaries();
|
||||||
|
}
|
||||||
|
}, [powerDownBeneficiaries]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (draftId) {
|
||||||
|
readTempBeneficiaries();
|
||||||
|
}
|
||||||
|
}, [draftId]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setDisableDone(newEditable);
|
||||||
|
}, [newEditable]);
|
||||||
|
|
||||||
|
const readPowerDownBeneficiaries = () => {
|
||||||
|
const tempBeneficiaries = [
|
||||||
|
{ account: username, weight: 10000, autoPowerUp: false },
|
||||||
|
...powerDownBeneficiaries,
|
||||||
|
];
|
||||||
|
|
||||||
|
if (isArray(tempBeneficiaries) && tempBeneficiaries.length > 0) {
|
||||||
|
//weight correction algorithm.
|
||||||
|
let othersWeight = 0;
|
||||||
|
tempBeneficiaries.forEach((item, index) => {
|
||||||
|
if (index > 0) {
|
||||||
|
othersWeight += item.weight;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
tempBeneficiaries[0].weight = 10000 - othersWeight;
|
||||||
|
|
||||||
|
setBeneficiaries([...tempBeneficiaries]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const readTempBeneficiaries = async () => {
|
||||||
|
if (beneficiariesMap) {
|
||||||
|
const tempBeneficiaries = beneficiariesMap[draftId || TEMP_BENEFICIARIES_ID];
|
||||||
|
|
||||||
|
if (isArray(tempBeneficiaries) && tempBeneficiaries.length > 0) {
|
||||||
|
//weight correction algorithm.
|
||||||
|
let othersWeight = 0;
|
||||||
|
tempBeneficiaries.forEach((item, index) => {
|
||||||
|
if (index > 0) {
|
||||||
|
othersWeight += item.weight;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
tempBeneficiaries[0].weight = 10000 - othersWeight;
|
||||||
|
|
||||||
|
setBeneficiaries(tempBeneficiaries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const _saveBeneficiaries = (value: Beneficiary[]) => {
|
||||||
|
if (handleSaveBeneficiary) {
|
||||||
|
handleSaveBeneficiary(value);
|
||||||
|
} else {
|
||||||
|
dispatch(setBeneficiariesAction(draftId || TEMP_BENEFICIARIES_ID, value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const _onSavePress = () => {
|
||||||
|
if (newEditable) {
|
||||||
|
beneficiaries.push({
|
||||||
|
account: newUsername,
|
||||||
|
weight: newWeight,
|
||||||
|
autoPowerUp: newAutoPowerUp,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_saveBeneficiaries(beneficiaries);
|
||||||
|
_resetInputs(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const _addAccount = () => {
|
||||||
|
if (isUsernameValid && isWeightValid) {
|
||||||
|
beneficiaries.push({
|
||||||
|
account: newUsername,
|
||||||
|
weight: newWeight,
|
||||||
|
});
|
||||||
|
setBeneficiaries([...beneficiaries]);
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsUsernameValid(false);
|
||||||
|
setIsWeightValid(false);
|
||||||
|
setNewWeight(0);
|
||||||
|
setNewUsername('');
|
||||||
|
setNewEditable(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const _onWeightInputChange = (value: string) => {
|
||||||
|
let _value = (parseInt(value, 10) || 0) * 100;
|
||||||
|
|
||||||
|
const _diff = _value - newWeight;
|
||||||
|
const newAuthorWeight = beneficiaries[0].weight - _diff;
|
||||||
|
beneficiaries[0].weight = newAuthorWeight;
|
||||||
|
|
||||||
|
setNewWeight(_value);
|
||||||
|
setIsWeightValid(_value >= 0 && newAuthorWeight >= 0);
|
||||||
|
setBeneficiaries([...beneficiaries]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const _lookupAccounts = debounce((username) => {
|
||||||
|
lookupAccounts(username).then((res) => {
|
||||||
|
const isValid = res.includes(username);
|
||||||
|
//check if username duplicates else lookup contacts, done here to avoid debounce and post call mismatch
|
||||||
|
const notExistAlready = !beneficiaries.find((item) => item.account === username);
|
||||||
|
setIsUsernameValid(isValid && notExistAlready);
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
const _onUsernameInputChange = (value) => {
|
||||||
|
setNewUsername(value);
|
||||||
|
_lookupAccounts(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const _resetInputs = (adjustWeight = true) => {
|
||||||
|
if (newWeight && adjustWeight) {
|
||||||
|
beneficiaries[0].weight = beneficiaries[0].weight + newWeight;
|
||||||
|
setBeneficiaries([...beneficiaries]);
|
||||||
|
}
|
||||||
|
|
||||||
|
setNewWeight(0);
|
||||||
|
setNewEditable(false);
|
||||||
|
setIsWeightValid(false);
|
||||||
|
setIsUsernameValid(false);
|
||||||
|
setNewUsername('');
|
||||||
|
};
|
||||||
|
|
||||||
|
const _renderHeader = () => (
|
||||||
|
<View style={styles.inputWrapper}>
|
||||||
|
{powerDown && (
|
||||||
|
<View style={{ ...styles.checkBoxHeader, marginTop: 4 }}>
|
||||||
|
<Text style={styles.contentLabel}>
|
||||||
|
{intl.formatMessage({ id: 'transfer.auto_vests' })}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<View style={{ ...styles.weightInput, marginTop: 4 }}>
|
||||||
|
<Text style={styles.contentLabel}>
|
||||||
|
{intl.formatMessage({
|
||||||
|
id: 'beneficiary_modal.percent',
|
||||||
|
})}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<View style={{ ...styles.usernameInput, marginTop: 4, marginLeft: 28 }}>
|
||||||
|
<Text style={styles.contentLabel}>
|
||||||
|
{intl.formatMessage({
|
||||||
|
id: 'beneficiary_modal.username',
|
||||||
|
})}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
|
||||||
|
const _handleCheckboxClick = (value, isCheck) => {
|
||||||
|
setNewAutoPowerUp(isCheck);
|
||||||
|
};
|
||||||
|
const _renderCheckBox = ({ locked, isChecked }: { locked: boolean; isChecked: boolean }) => (
|
||||||
|
<View style={styles.checkBoxContainer}>
|
||||||
|
<CheckBox
|
||||||
|
locked={locked}
|
||||||
|
isChecked={isChecked}
|
||||||
|
clicked={_handleCheckboxClick}
|
||||||
|
value={newAutoPowerUp}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
|
||||||
|
const _renderInput = () => {
|
||||||
|
return (
|
||||||
|
<View style={styles.inputWrapper}>
|
||||||
|
{powerDown && _renderCheckBox({ locked: false, isChecked: false })}
|
||||||
|
<View style={styles.weightInput}>
|
||||||
|
<FormInput
|
||||||
|
isValid={isWeightValid}
|
||||||
|
value={`${newWeight / 100}`}
|
||||||
|
inputStyle={styles.weightFormInput}
|
||||||
|
wrapperStyle={styles.weightFormInputWrapper}
|
||||||
|
onChange={(value) => _onWeightInputChange(value)}
|
||||||
|
selectTextOnFocus={true}
|
||||||
|
autoFocus={true}
|
||||||
|
returnKeyType={'next'}
|
||||||
|
keyboardType="numeric"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.usernameInput}>
|
||||||
|
<FormInput
|
||||||
|
rightIconName="at"
|
||||||
|
iconType="MaterialCommunityIcons"
|
||||||
|
isValid={isUsernameValid}
|
||||||
|
onChange={(value) => _onUsernameInputChange(value.trim())}
|
||||||
|
placeholder={intl.formatMessage({
|
||||||
|
id: 'beneficiary_modal.username',
|
||||||
|
})}
|
||||||
|
type="username"
|
||||||
|
isFirstImage
|
||||||
|
returnKeyType="done"
|
||||||
|
value={newUsername}
|
||||||
|
onSubmitEditing={isWeightValid && isUsernameValid && _onSavePress}
|
||||||
|
inputStyle={styles.usernameInput}
|
||||||
|
wrapperStyle={styles.usernameFormInputWrapper}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{isWeightValid && isUsernameValid ? (
|
||||||
|
<IconButton
|
||||||
|
name="check"
|
||||||
|
iconType="MaterialCommunityIcons"
|
||||||
|
color={EStyleSheet.value('$white')}
|
||||||
|
iconStyle={{ marginTop: 2 }}
|
||||||
|
size={24}
|
||||||
|
style={styles.doneButton}
|
||||||
|
onPress={_onSavePress}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<View style={{ width: 28 }} />
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const _renderFooter = () => (
|
||||||
|
<>
|
||||||
|
{newEditable && _renderInput()}
|
||||||
|
<View style={{ marginTop: 20, marginBottom: 32 }}>
|
||||||
|
<TextButton
|
||||||
|
text={
|
||||||
|
newEditable
|
||||||
|
? intl.formatMessage({
|
||||||
|
id: 'beneficiary_modal.cancel',
|
||||||
|
})
|
||||||
|
: intl.formatMessage({
|
||||||
|
id: 'beneficiary_modal.addAccount',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
onPress={newEditable ? _resetInputs : _addAccount}
|
||||||
|
textStyle={{
|
||||||
|
color: EStyleSheet.value('$primaryBlue'),
|
||||||
|
fontWeight: 'bold',
|
||||||
|
textAlign: 'left',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
const _renderItem = ({ item, index }) => {
|
||||||
|
const _isCurrentUser = item.account === username;
|
||||||
|
|
||||||
|
const _onRemovePress = () => {
|
||||||
|
beneficiaries[0].weight = beneficiaries[0].weight + item.weight;
|
||||||
|
const removedBeneficiary = beneficiaries.splice(index, 1);
|
||||||
|
setBeneficiaries([...beneficiaries]);
|
||||||
|
if(handleRemoveBeneficiary){
|
||||||
|
handleRemoveBeneficiary(removedBeneficiary[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_saveBeneficiaries(beneficiaries);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.inputWrapper}>
|
||||||
|
{powerDown && _renderCheckBox({ locked: true, isChecked: item.autoPowerUp })}
|
||||||
|
<View style={styles.weightInput}>
|
||||||
|
<FormInput
|
||||||
|
isValid={true}
|
||||||
|
isEditable={false}
|
||||||
|
value={`${item.weight / 100}`}
|
||||||
|
inputStyle={styles.weightFormInput}
|
||||||
|
wrapperStyle={styles.weightFormInputWrapper}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.usernameInput}>
|
||||||
|
<FormInput
|
||||||
|
isValid={true}
|
||||||
|
isEditable={false}
|
||||||
|
type="username"
|
||||||
|
isFirstImage
|
||||||
|
value={item.account}
|
||||||
|
inputStyle={styles.usernameInput}
|
||||||
|
wrapperStyle={styles.usernameFormInputWrapper}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
{!_isCurrentUser ? (
|
||||||
|
<IconButton
|
||||||
|
name="close"
|
||||||
|
iconType="MaterialCommunityIcons"
|
||||||
|
size={24}
|
||||||
|
color={EStyleSheet.value('$primaryBlack')}
|
||||||
|
iconStyle={{ paddingLeft: 8 }}
|
||||||
|
onPress={_onRemovePress}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<View style={{ width: 30 }} />
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<Text style={labelStyle || styles.settingLabel}>{label || intl.formatMessage({ id: 'editor.beneficiaries' })}</Text>
|
||||||
|
<FlatList
|
||||||
|
data={beneficiaries}
|
||||||
|
renderItem={_renderItem}
|
||||||
|
ListHeaderComponent={_renderHeader}
|
||||||
|
showsVerticalScrollIndicator={false}
|
||||||
|
/>
|
||||||
|
{_renderFooter()}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default BeneficiarySelectionContent;
|
65
src/components/beneficiarySelectionContent/styles.ts
Normal file
65
src/components/beneficiarySelectionContent/styles.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||||
|
import { getBottomSpace } from 'react-native-iphone-x-helper';
|
||||||
|
|
||||||
|
export default EStyleSheet.create({
|
||||||
|
|
||||||
|
sheetContent: {
|
||||||
|
backgroundColor: '$primaryBackgroundColor',
|
||||||
|
position:'absolute',
|
||||||
|
bottom:0,
|
||||||
|
left:0,
|
||||||
|
right:0,
|
||||||
|
zIndex:999
|
||||||
|
},
|
||||||
|
thumbStyle:{
|
||||||
|
width:72,
|
||||||
|
height:72,
|
||||||
|
marginVertical:8,
|
||||||
|
marginRight:8,
|
||||||
|
borderRadius:12,
|
||||||
|
backgroundColor:'$primaryLightGray'
|
||||||
|
},
|
||||||
|
selectedStyle:{
|
||||||
|
borderWidth:4,
|
||||||
|
borderColor:'$primaryBlack'
|
||||||
|
},
|
||||||
|
settingLabel:{
|
||||||
|
color: '$primaryDarkGray',
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
flexGrow: 1,
|
||||||
|
textAlign:'left',
|
||||||
|
},
|
||||||
|
listContainer:{
|
||||||
|
paddingBottom:getBottomSpace() + 16,
|
||||||
|
},
|
||||||
|
container:{
|
||||||
|
paddingVertical:16
|
||||||
|
},
|
||||||
|
bodyWrapper: { flex: 1, paddingTop: 20, paddingBottom:20},
|
||||||
|
inputWrapper: { flexDirection: 'row', alignItems: 'center'},
|
||||||
|
contentLabel: { color: '$iconColor', marginTop:4, textAlign:'left' },
|
||||||
|
weightInput: {width:80},
|
||||||
|
weightFormInput: { flex:1, color: '$primaryBlack', paddingLeft: 12 },
|
||||||
|
weightFormInputWrapper: { marginTop: 8 },
|
||||||
|
usernameInput: { flex:1, color: '$primaryBlack', marginLeft: 16, },
|
||||||
|
usernameFormInputWrapper: { marginTop: 8, marginRight: 12 },
|
||||||
|
footerWrapper: { paddingTop:16 },
|
||||||
|
saveButton: {
|
||||||
|
width: 140,
|
||||||
|
height: 44,
|
||||||
|
alignSelf: 'flex-end',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
doneButton:{borderRadius:16, backgroundColor:'$primaryBlue'},
|
||||||
|
thumbSelectContainer:{
|
||||||
|
marginTop:12,
|
||||||
|
},
|
||||||
|
checkBoxHeader: {
|
||||||
|
width: 50,
|
||||||
|
},
|
||||||
|
checkBoxContainer: {
|
||||||
|
width: 50,
|
||||||
|
marginTop:12,
|
||||||
|
}
|
||||||
|
});
|
@ -15,7 +15,7 @@ export default EStyleSheet.create({
|
|||||||
height: 24,
|
height: 24,
|
||||||
borderRadius: 12,
|
borderRadius: 12,
|
||||||
top: 15,
|
top: 15,
|
||||||
marginLeft: 12,
|
marginLeft: 8,
|
||||||
},
|
},
|
||||||
textInput: {
|
textInput: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
|
@ -101,7 +101,7 @@ const FormInputView = ({
|
|||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
{isFirstImage && value && value.length > 2 ? (
|
{isFirstImage && value && value.length > 2 ? (
|
||||||
<View style={{ flex: 0.15 }}>
|
<View style={{ flex: 0.2 }}>
|
||||||
<FastImage
|
<FastImage
|
||||||
style={styles.firstImage}
|
style={styles.firstImage}
|
||||||
source={{
|
source={{
|
||||||
|
@ -97,6 +97,7 @@ import Tooltip from './tooltip/tooltipView';
|
|||||||
import VideoPlayer from './videoPlayer/videoPlayerView';
|
import VideoPlayer from './videoPlayer/videoPlayerView';
|
||||||
import QRModal from './qrModal/qrModalView';
|
import QRModal from './qrModal/qrModalView';
|
||||||
import { SimpleChart } from './simpleChart';
|
import { SimpleChart } from './simpleChart';
|
||||||
|
import BeneficiarySelectionContent from './beneficiarySelectionContent/beneficiarySelectionContent';
|
||||||
|
|
||||||
// Basic UI Elements
|
// Basic UI Elements
|
||||||
import {
|
import {
|
||||||
@ -243,4 +244,5 @@ export {
|
|||||||
InsertLinkModal,
|
InsertLinkModal,
|
||||||
QRModal,
|
QRModal,
|
||||||
SimpleChart,
|
SimpleChart,
|
||||||
|
BeneficiarySelectionContent,
|
||||||
};
|
};
|
||||||
|
@ -576,11 +576,11 @@
|
|||||||
"stop_information": "Are you sure want to stop?",
|
"stop_information": "Are you sure want to stop?",
|
||||||
"percent": "Percent",
|
"percent": "Percent",
|
||||||
"auto_vests": "Auto Vests",
|
"auto_vests": "Auto Vests",
|
||||||
|
"vests": "Vests",
|
||||||
"save": "SAVE",
|
"save": "SAVE",
|
||||||
"percent_information": "Percent info",
|
"percent_information": "Percent info",
|
||||||
"next": "NEXT",
|
"next": "NEXT",
|
||||||
"delegate": "Delegate",
|
"delegate": "Delegate",
|
||||||
"power_down": "Power Down",
|
|
||||||
"withdraw_hive": "Withdraw HIVE",
|
"withdraw_hive": "Withdraw HIVE",
|
||||||
"withdraw_hbd": "Withdraw HIVE Dollar",
|
"withdraw_hbd": "Withdraw HIVE Dollar",
|
||||||
"incoming_funds": "Incoming Funds",
|
"incoming_funds": "Incoming Funds",
|
||||||
@ -599,7 +599,16 @@
|
|||||||
"confirm_summary": "Delegate {hp} HP ({vests} VESTS) To @{delegator} from @{delegatee} ",
|
"confirm_summary": "Delegate {hp} HP ({vests} VESTS) To @{delegator} from @{delegatee} ",
|
||||||
"confirm_summary_para": "This will overwrite your previous delegation of {prev} HP to this user.",
|
"confirm_summary_para": "This will overwrite your previous delegation of {prev} HP to this user.",
|
||||||
"username_alert": "Username Error!",
|
"username_alert": "Username Error!",
|
||||||
"username_alert_detail": "Please select different username"
|
"username_alert_detail": "Please select different username",
|
||||||
|
"power_down": "Power Down",
|
||||||
|
"power_down_amount_head": "Withdraw Amount",
|
||||||
|
"power_down_amount_subhead": "Enter amount for powering down hive power",
|
||||||
|
"withdraw_accounts":"Withdraw Accounts",
|
||||||
|
"amount_hp": "Amount (HP)",
|
||||||
|
"powering_down": "Powering Down",
|
||||||
|
"powering_down_subheading": "You are currently powering down.",
|
||||||
|
"powering_down_info": "Next power down is in {days} days, {hp} HIVE"
|
||||||
|
|
||||||
},
|
},
|
||||||
"boost": {
|
"boost": {
|
||||||
"title": "Get Points",
|
"title": "Get Points",
|
||||||
|
@ -4,6 +4,7 @@ export interface Beneficiary {
|
|||||||
account:string,
|
account:string,
|
||||||
weight:number,
|
weight:number,
|
||||||
isValid?:boolean,
|
isValid?:boolean,
|
||||||
|
autoPowerUp?: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
|
@ -18,7 +18,7 @@ interface BeneficiarySelectionContent {
|
|||||||
setDisableDone:(value:boolean)=>void;
|
setDisableDone:(value:boolean)=>void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BeneficiarySelectionContent = ({ draftId, setDisableDone }) => {
|
const BeneficiarySelectionContent = ({ draftId, setDisableDone}) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
@ -35,6 +35,7 @@ const BeneficiarySelectionContent = ({ draftId, setDisableDone }) => {
|
|||||||
const [isWeightValid, setIsWeightValid] = useState(false);
|
const [isWeightValid, setIsWeightValid] = useState(false);
|
||||||
const [newEditable, setNewEditable] = useState(false);
|
const [newEditable, setNewEditable] = useState(false);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
readTempBeneficiaries();
|
readTempBeneficiaries();
|
||||||
}, [draftId]);
|
}, [draftId]);
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
/* eslint-disable react/no-unused-state */
|
/* eslint-disable react/no-unused-state */
|
||||||
import React, { Fragment, Component } from 'react';
|
import React, { Fragment, Component } from 'react';
|
||||||
import { Text, View, ScrollView, Alert } from 'react-native';
|
import { Text, View, ScrollView, Alert, KeyboardAvoidingView, Platform } from 'react-native';
|
||||||
import { injectIntl } from 'react-intl';
|
import { injectIntl } from 'react-intl';
|
||||||
import Slider from '@esteemapp/react-native-slider';
|
import Slider from '@esteemapp/react-native-slider';
|
||||||
import get from 'lodash/get';
|
import get from 'lodash/get';
|
||||||
|
|
||||||
|
import { View as AnimatedView } from 'react-native-animatable';
|
||||||
import { getWithdrawRoutes } from '../../../providers/hive/dhive';
|
import { getWithdrawRoutes } from '../../../providers/hive/dhive';
|
||||||
import AUTH_TYPE from '../../../constants/authType';
|
import AUTH_TYPE from '../../../constants/authType';
|
||||||
|
|
||||||
@ -18,16 +19,20 @@ import {
|
|||||||
InformationBox,
|
InformationBox,
|
||||||
Icon,
|
Icon,
|
||||||
IconButton,
|
IconButton,
|
||||||
|
BeneficiarySelectionContent,
|
||||||
|
TextInput,
|
||||||
} from '../../../components';
|
} from '../../../components';
|
||||||
import WithdrawAccountModal from './withdrawAccountModal';
|
import WithdrawAccountModal from './withdrawAccountModal';
|
||||||
|
|
||||||
import parseToken from '../../../utils/parseToken';
|
import parseToken from '../../../utils/parseToken';
|
||||||
import parseDate from '../../../utils/parseDate';
|
import parseDate from '../../../utils/parseDate';
|
||||||
import { vestsToHp } from '../../../utils/conversions';
|
import { hpToVests, vestsToHp } from '../../../utils/conversions';
|
||||||
import { isEmptyDate } from '../../../utils/time';
|
import { isEmptyDate, daysTillDate } from '../../../utils/time';
|
||||||
|
|
||||||
import styles from './transferStyles';
|
import styles from './transferStyles';
|
||||||
import { OptionsModal } from '../../../components/atoms';
|
import { OptionsModal } from '../../../components/atoms';
|
||||||
|
import { Beneficiary } from '../../../redux/reducers/editorReducer';
|
||||||
|
|
||||||
/* Props
|
/* Props
|
||||||
* ------------------------------------------------
|
* ------------------------------------------------
|
||||||
* @prop { type } name - Description....
|
* @prop { type } name - Description....
|
||||||
@ -39,14 +44,18 @@ class PowerDownView extends Component {
|
|||||||
this.state = {
|
this.state = {
|
||||||
from: props.currentAccountName,
|
from: props.currentAccountName,
|
||||||
amount: 0,
|
amount: 0,
|
||||||
|
hp: 0.0,
|
||||||
steemConnectTransfer: false,
|
steemConnectTransfer: false,
|
||||||
isTransfering: false,
|
isTransfering: false,
|
||||||
isOpenWithdrawAccount: false,
|
isOpenWithdrawAccount: false,
|
||||||
destinationAccounts: [],
|
destinationAccounts: [],
|
||||||
|
disableDone: false,
|
||||||
|
isAmountValid: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.startActionSheet = React.createRef();
|
this.startActionSheet = React.createRef();
|
||||||
this.stopActionSheet = React.createRef();
|
this.stopActionSheet = React.createRef();
|
||||||
|
this.amountTextInput = React.createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Component Functions
|
// Component Functions
|
||||||
@ -86,6 +95,33 @@ class PowerDownView extends Component {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_handleAmountChange = ({ hpValue, availableVestingShares }) => {
|
||||||
|
const { hivePerMVests } = this.props;
|
||||||
|
const parsedValue = parseFloat(hpValue);
|
||||||
|
const vestsForHp = hpToVests(hpValue, hivePerMVests);
|
||||||
|
const totalHP = vestsToHp(availableVestingShares, hivePerMVests).toFixed(3);
|
||||||
|
|
||||||
|
if (Number.isNaN(parsedValue)) {
|
||||||
|
this.setState({ amount: 0, hp: 0.0, isAmountValid: false });
|
||||||
|
} else if (parsedValue >= totalHP) {
|
||||||
|
this.setState({
|
||||||
|
amount: availableVestingShares,
|
||||||
|
hp: totalHP,
|
||||||
|
isAmountValid: false,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.setState({ amount: vestsForHp, hp: parsedValue, isAmountValid: true });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_handleSliderAmountChange = ({ value, availableVestingShares }) => {
|
||||||
|
const { hivePerMVests } = this.props;
|
||||||
|
const hp = vestsToHp(value, hivePerMVests).toFixed(3);
|
||||||
|
const isAmountValid = value !== 0 && value <= availableVestingShares;
|
||||||
|
this.setState({ amount: value, hp, isAmountValid });
|
||||||
|
};
|
||||||
|
|
||||||
|
// renderers
|
||||||
_renderDropdown = (accounts, currentAccountName) => (
|
_renderDropdown = (accounts, currentAccountName) => (
|
||||||
<DropdownButton
|
<DropdownButton
|
||||||
dropdownButtonStyle={styles.dropdownButtonStyle}
|
dropdownButtonStyle={styles.dropdownButtonStyle}
|
||||||
@ -155,6 +191,80 @@ class PowerDownView extends Component {
|
|||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
_renderBeneficiarySelectionContent = () => {
|
||||||
|
const { intl } = this.props;
|
||||||
|
const { from, destinationAccounts, amount } = this.state;
|
||||||
|
|
||||||
|
const powerDownBeneficiaries = destinationAccounts?.map((item) => ({
|
||||||
|
account: item.username,
|
||||||
|
weight: item.percent * 100,
|
||||||
|
autoPowerUp: item.autoPowerUp,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const _handleSaveBeneficiary = (beneficiaries) => {
|
||||||
|
const destinationAccounts = beneficiaries.map((item) => ({
|
||||||
|
username: item.account,
|
||||||
|
percent: item.weight / 100,
|
||||||
|
autoPowerUp: item.autoPowerUp,
|
||||||
|
}));
|
||||||
|
let latestDestinationAccount = destinationAccounts[destinationAccounts.length - 1];
|
||||||
|
if (latestDestinationAccount.username && latestDestinationAccount.percent) {
|
||||||
|
this._handleOnSubmit(
|
||||||
|
latestDestinationAccount.username,
|
||||||
|
latestDestinationAccount.percent,
|
||||||
|
latestDestinationAccount.autoPowerUp,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const _handleRemoveBeneficiary = (beneficiary) => {
|
||||||
|
if (beneficiary) {
|
||||||
|
const beneficiaryAccount = {
|
||||||
|
username: beneficiary.account,
|
||||||
|
percent: beneficiary.weight / 100,
|
||||||
|
autoPowerUp: beneficiary.autoPowerUp,
|
||||||
|
};
|
||||||
|
this._removeDestinationAccount(beneficiaryAccount);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<View style={styles.beneficiaryContainer}>
|
||||||
|
<BeneficiarySelectionContent
|
||||||
|
label={intl.formatMessage({ id: 'transfer.withdraw_accounts' })}
|
||||||
|
labelStyle={{ ...styles.sectionHeading, paddingLeft: 0 }}
|
||||||
|
setDisableDone={this._handleSetDisableDone}
|
||||||
|
powerDown={true}
|
||||||
|
powerDownBeneficiaries={powerDownBeneficiaries}
|
||||||
|
handleSaveBeneficiary={_handleSaveBeneficiary}
|
||||||
|
handleRemoveBeneficiary={_handleRemoveBeneficiary}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
_renderAmountInput = (placeholder, availableVestingShares) => {
|
||||||
|
const { isAmountValid } = this.state;
|
||||||
|
return (
|
||||||
|
<TextInput
|
||||||
|
style={[styles.amountInput, !isAmountValid && styles.error]}
|
||||||
|
onChangeText={(hpValue) => {
|
||||||
|
this._handleAmountChange({ hpValue, availableVestingShares });
|
||||||
|
}}
|
||||||
|
value={this.state.hp}
|
||||||
|
placeholder={placeholder}
|
||||||
|
placeholderTextColor="#c1c5c7"
|
||||||
|
autoCapitalize="none"
|
||||||
|
multiline={false}
|
||||||
|
keyboardType="decimal-pad"
|
||||||
|
innerRef={this.amountTextInput}
|
||||||
|
blurOnSubmit={false}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
_handleSetDisableDone = (value) => {
|
||||||
|
this.setState({ disableDone: value });
|
||||||
|
};
|
||||||
_handleOnDropdownChange = (value) => {
|
_handleOnDropdownChange = (value) => {
|
||||||
const { fetchBalance } = this.props;
|
const { fetchBalance } = this.props;
|
||||||
|
|
||||||
@ -222,27 +332,12 @@ class PowerDownView extends Component {
|
|||||||
|
|
||||||
const spCalculated = vestsToHp(amount, hivePerMVests);
|
const spCalculated = vestsToHp(amount, hivePerMVests);
|
||||||
const fundPerWeek = Math.round((spCalculated / 13) * 1000) / 1000;
|
const fundPerWeek = Math.round((spCalculated / 13) * 1000) / 1000;
|
||||||
|
const totalHP = vestsToHp(availableVestingShares, hivePerMVests);
|
||||||
|
|
||||||
return (
|
const _renderSlider = () => (
|
||||||
<Fragment>
|
<View style={styles.sliderBox}>
|
||||||
<BasicHeader title={intl.formatMessage({ id: `transfer.${transferType}` })} />
|
<View style={styles.emptyBox} />
|
||||||
<View style={styles.container}>
|
<View style={styles.sliderContainer}>
|
||||||
<ScrollView>
|
|
||||||
<View style={styles.middleContent}>
|
|
||||||
<TransferFormItem
|
|
||||||
label={intl.formatMessage({ id: 'transfer.from' })}
|
|
||||||
rightComponent={() => this._renderDropdown(accounts, currentAccountName)}
|
|
||||||
/>
|
|
||||||
<TransferFormItem
|
|
||||||
label={intl.formatMessage({ id: 'transfer.destination_accounts' })}
|
|
||||||
rightComponent={this._renderDestinationAccountItems}
|
|
||||||
/>
|
|
||||||
{!poweringDown && (
|
|
||||||
<Fragment>
|
|
||||||
<TransferFormItem
|
|
||||||
label={intl.formatMessage({ id: 'transfer.amount' })}
|
|
||||||
rightComponent={() => this._renderInformationText(`${amount.toFixed(6)} VESTS`)}
|
|
||||||
/>
|
|
||||||
<Slider
|
<Slider
|
||||||
style={styles.slider}
|
style={styles.slider}
|
||||||
trackStyle={styles.track}
|
trackStyle={styles.track}
|
||||||
@ -251,65 +346,84 @@ class PowerDownView extends Component {
|
|||||||
thumbTintColor="#007ee5"
|
thumbTintColor="#007ee5"
|
||||||
maximumValue={availableVestingShares}
|
maximumValue={availableVestingShares}
|
||||||
value={amount}
|
value={amount}
|
||||||
onValueChange={(value) => {
|
onValueChange={(value) =>
|
||||||
this.setState({ amount: value });
|
this._handleSliderAmountChange({ value, availableVestingShares })
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Text style={styles.informationText}>
|
|
||||||
{intl.formatMessage({ id: 'transfer.amount_information' })}
|
|
||||||
</Text>
|
|
||||||
</Fragment>
|
|
||||||
)}
|
|
||||||
{poweringDown && (
|
|
||||||
<Fragment>
|
|
||||||
<TransferFormItem
|
|
||||||
label={intl.formatMessage({ id: 'transfer.incoming_funds' })}
|
|
||||||
rightComponent={() =>
|
|
||||||
this._renderIncomingFunds(
|
|
||||||
poweringDownFund,
|
|
||||||
poweringDownVests,
|
|
||||||
nextPowerDown.toLocaleString(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</Fragment>
|
<View style={styles.sliderAmountContainer}>
|
||||||
)}
|
<Text style={styles.amountText}>{`MAX ${totalHP.toFixed(3)} HP`}</Text>
|
||||||
</View>
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
|
||||||
|
const _renderMiddleContent = () => {
|
||||||
|
const { intl } = this.props;
|
||||||
|
return (
|
||||||
|
<AnimatedView animation="bounceInRight" delay={500} useNativeDriver>
|
||||||
|
<View style={styles.stepTwoContainer}>
|
||||||
|
<Text style={styles.sectionHeading}>
|
||||||
|
{intl.formatMessage({ id: 'transfer.power_down_amount_head' })}
|
||||||
|
</Text>
|
||||||
|
<View style={styles.alreadyDelegateRow}>
|
||||||
|
<Text style={styles.sectionSubheading}>
|
||||||
|
{intl.formatMessage({ id: 'transfer.power_down_amount_subhead' })}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<TransferFormItem
|
||||||
|
label={intl.formatMessage({ id: 'transfer.amount_hp' })}
|
||||||
|
rightComponent={() =>
|
||||||
|
this._renderAmountInput(
|
||||||
|
intl.formatMessage({ id: 'transfer.amount' }),
|
||||||
|
availableVestingShares,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
containerStyle={styles.paddBottom}
|
||||||
|
/>
|
||||||
|
{_renderSlider()}
|
||||||
|
<View style={styles.estimatedContainer}>
|
||||||
|
<Text style={styles.leftEstimated} />
|
||||||
|
<Text style={styles.rightEstimated}>
|
||||||
|
{intl.formatMessage({ id: 'transfer.estimated_weekly' })} :
|
||||||
|
{`+ ${fundPerWeek.toFixed(3)} HIVE`}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</AnimatedView>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const _renderPowerDownInfo = () => {
|
||||||
|
const days = daysTillDate(nextPowerDown);
|
||||||
|
return (
|
||||||
|
<View style={styles.powerDownInfoContainer}>
|
||||||
|
<Text style={styles.sectionHeading}>
|
||||||
|
{intl.formatMessage({ id: 'transfer.powering_down' })}
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.sectionSubheading}>
|
||||||
|
{intl.formatMessage({ id: 'transfer.powering_down_subheading' }) +
|
||||||
|
'\n\n' +
|
||||||
|
intl.formatMessage(
|
||||||
|
{ id: 'transfer.powering_down_info' },
|
||||||
|
{ days: days, hp: poweringDownFund },
|
||||||
|
)}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const _renderBottomContent = () => (
|
||||||
<View style={styles.bottomContent}>
|
<View style={styles.bottomContent}>
|
||||||
{!poweringDown && (
|
{!poweringDown && (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<View style={styles.informationView}>
|
|
||||||
<InformationBox
|
|
||||||
style={styles.spInformation}
|
|
||||||
text={`- ${spCalculated.toFixed(3)} HP`}
|
|
||||||
/>
|
|
||||||
<InformationBox
|
|
||||||
style={styles.vestsInformation}
|
|
||||||
text={`- ${amount.toFixed(0)} VESTS`}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
<Icon
|
|
||||||
style={styles.icon}
|
|
||||||
size={40}
|
|
||||||
iconType="MaterialIcons"
|
|
||||||
name="arrow-downward"
|
|
||||||
/>
|
|
||||||
<InformationBox
|
|
||||||
style={styles.steemInformation}
|
|
||||||
text={`+ ${fundPerWeek.toFixed(3)} HIVE`}
|
|
||||||
/>
|
|
||||||
<Text style={styles.informationText}>
|
|
||||||
{intl.formatMessage({ id: 'transfer.estimated_weekly' })}
|
|
||||||
</Text>
|
|
||||||
<MainButton
|
<MainButton
|
||||||
style={styles.button}
|
style={styles.button}
|
||||||
isDisable={amount <= 0}
|
isDisable={amount <= 0}
|
||||||
onPress={() => this.startActionSheet.current.show()}
|
onPress={() => this.startActionSheet.current.show()}
|
||||||
isLoading={isTransfering}
|
isLoading={isTransfering}
|
||||||
>
|
>
|
||||||
<Text style={styles.buttonText}>
|
<Text style={styles.buttonText}>{intl.formatMessage({ id: 'transfer.next' })}</Text>
|
||||||
{intl.formatMessage({ id: 'transfer.next' })}
|
|
||||||
</Text>
|
|
||||||
</MainButton>
|
</MainButton>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
@ -319,14 +433,26 @@ class PowerDownView extends Component {
|
|||||||
onPress={() => this.stopActionSheet.current.show()}
|
onPress={() => this.stopActionSheet.current.show()}
|
||||||
isLoading={isTransfering}
|
isLoading={isTransfering}
|
||||||
>
|
>
|
||||||
<Text style={styles.buttonText}>
|
<Text style={styles.buttonText}>{intl.formatMessage({ id: 'transfer.stop' })}</Text>
|
||||||
{intl.formatMessage({ id: 'transfer.stop' })}
|
|
||||||
</Text>
|
|
||||||
</MainButton>
|
</MainButton>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<BasicHeader title={intl.formatMessage({ id: `transfer.${transferType}` })} />
|
||||||
|
<KeyboardAvoidingView
|
||||||
|
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
||||||
|
style={styles.powerDownKeyboadrAvoidingContainer}
|
||||||
|
keyboardShouldPersistTaps
|
||||||
|
>
|
||||||
|
<ScrollView style={styles.scroll} contentContainerStyle={styles.scrollContentContainer}>
|
||||||
|
{!poweringDown && this._renderBeneficiarySelectionContent()}
|
||||||
|
{!poweringDown && _renderMiddleContent()}
|
||||||
|
{poweringDown && _renderPowerDownInfo()}
|
||||||
|
{_renderBottomContent()}
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</View>
|
</KeyboardAvoidingView>
|
||||||
<OptionsModal
|
<OptionsModal
|
||||||
ref={this.startActionSheet}
|
ref={this.startActionSheet}
|
||||||
options={[
|
options={[
|
||||||
|
@ -30,12 +30,11 @@ export default EStyleSheet.create({
|
|||||||
paddingVertical: 16,
|
paddingVertical: 16,
|
||||||
marginTop: 16,
|
marginTop: 16,
|
||||||
},
|
},
|
||||||
|
scroll: {},
|
||||||
middleContent: {
|
middleContent: {
|
||||||
flex: 3,
|
flex: 1,
|
||||||
justifyContent: 'center',
|
|
||||||
},
|
},
|
||||||
bottomContent: {
|
bottomContent: {
|
||||||
flex: 2,
|
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
},
|
},
|
||||||
@ -79,10 +78,12 @@ export default EStyleSheet.create({
|
|||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
|
marginVertical: 16,
|
||||||
},
|
},
|
||||||
stopButton: {
|
stopButton: {
|
||||||
width: '$deviceWidth / 3',
|
width: '$deviceWidth / 3',
|
||||||
marginTop: 30,
|
marginTop: 30,
|
||||||
|
marginBottom: 30,
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
backgroundColor: 'red',
|
backgroundColor: 'red',
|
||||||
@ -321,4 +322,41 @@ export default EStyleSheet.create({
|
|||||||
fullHeight: {
|
fullHeight: {
|
||||||
height: '100%',
|
height: '100%',
|
||||||
},
|
},
|
||||||
|
beneficiaryContainer: {
|
||||||
|
paddingHorizontal: 12,
|
||||||
|
zIndex: 2,
|
||||||
|
borderRadius: 12,
|
||||||
|
backgroundColor: '$primaryLightBackground',
|
||||||
|
},
|
||||||
|
scrollContentContainer: {
|
||||||
|
flexGrow: 1,
|
||||||
|
padding: 16,
|
||||||
|
},
|
||||||
|
estimatedContainer: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
marginTop: 12,
|
||||||
|
},
|
||||||
|
leftEstimated: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
rightEstimated: {
|
||||||
|
flex: 2,
|
||||||
|
fontSize: 12,
|
||||||
|
color: '$primaryBlack',
|
||||||
|
fontWeight: '600',
|
||||||
|
textAlign: 'right',
|
||||||
|
paddingRight: 16,
|
||||||
|
},
|
||||||
|
powerDownKeyboadrAvoidingContainer: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: '$primaryBackgroundColor',
|
||||||
|
},
|
||||||
|
powerDownInfoContainer: {
|
||||||
|
marginTop: 16,
|
||||||
|
paddingHorizontal: 12,
|
||||||
|
zIndex: 2,
|
||||||
|
paddingVertical: 16,
|
||||||
|
borderRadius: 12,
|
||||||
|
backgroundColor: '$primaryLightBackground',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
@ -134,3 +134,9 @@ export const isEmptyContentDate = (value) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const isEmptyDate = (s) => parseInt(s.split('-')[0], 10) < 1980;
|
export const isEmptyDate = (s) => parseInt(s.split('-')[0], 10) < 1980;
|
||||||
|
|
||||||
|
export const daysTillDate = (date) => {
|
||||||
|
var given = moment(new Date(date), 'YYYY-MM-DD');
|
||||||
|
var current = moment().startOf('day');
|
||||||
|
return Math.round(moment.duration(given.diff(current)).asDays());
|
||||||
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user