Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "Localize decimal separator" #10129

Merged
merged 1 commit into from
Jul 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/CONST.js
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,7 @@ const CONST = {
CARD_SECURITY_CODE: /^[0-9]{3,4}$/,
CARD_EXPIRATION_DATE: /^(0[1-9]|1[0-2])([^0-9])?([0-9]{4}|([0-9]{2}))$/,
PAYPAL_ME_USERNAME: /^[a-zA-Z0-9]+$/,
RATE_VALUE: /^\d{1,8}(\.\d*)?$/,

// Adapted from: https://gist.github.com/dperini/729294
// eslint-disable-next-line max-len
Expand Down
2 changes: 1 addition & 1 deletion src/components/BigNumberPad.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class BigNumberPad extends React.Component {
style={[styles.flex1, marginLeft]}
text={column === '<' ? column : this.props.toLocaleDigit(column)}
onLongPress={() => this.handleLongPress(column)}
onPress={() => this.props.numberPressed(column === '<' ? column : this.props.toLocaleDigit(column))}
onPress={() => this.props.numberPressed(column)}
onPressIn={ControlSelection.block}
onPressOut={() => {
clearInterval(this.state.timer);
Expand Down
57 changes: 48 additions & 9 deletions src/pages/iou/steps/IOUAmountPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
import PropTypes from 'prop-types';
import {withOnyx} from 'react-native-onyx';
import lodashGet from 'lodash/get';
import _ from 'underscore';
import ONYXKEYS from '../../../ONYXKEYS';
import styles from '../../../styles/styles';
import BigNumberPad from '../../../components/BigNumberPad';
Expand Down Expand Up @@ -52,11 +53,12 @@ class IOUAmountPage extends React.Component {

this.updateAmountNumberPad = this.updateAmountNumberPad.bind(this);
this.updateAmount = this.updateAmount.bind(this);
this.stripCommaFromAmount = this.stripCommaFromAmount.bind(this);
this.focusTextInput = this.focusTextInput.bind(this);
this.navigateToCurrencySelectionPage = this.navigateToCurrencySelectionPage.bind(this);

this.state = {
amount: props.selectedAmount.replace('.', this.props.fromLocaleDigit('.')),
amount: props.selectedAmount,
};
}

Expand Down Expand Up @@ -111,11 +113,20 @@ class IOUAmountPage extends React.Component {
* @returns {Boolean}
*/
validateAmount(amount) {
const decimalSeparator = this.props.fromLocaleDigit('.');
const decimalNumberRegex = RegExp(String.raw`^\d+([${decimalSeparator}]\d{0,2})?$`, 'i');
const decimalNumberRegex = new RegExp(/^\d+(,\d+)*(\.\d{0,2})?$/, 'i');
return amount === '' || (decimalNumberRegex.test(amount) && this.calculateAmountLength(amount) <= CONST.IOU.AMOUNT_MAX_LENGTH);
}

/**
* Strip comma from the amount
*
* @param {String} amount
* @returns {String}
*/
stripCommaFromAmount(amount) {
return amount.replace(/,/g, '');
}

/**
* Update amount with number or Backspace pressed for BigNumberPad.
* Validate new amount with decimal number regex up to 6 digits and 2 decimal digit to enable Next button
Expand All @@ -135,18 +146,44 @@ class IOUAmountPage extends React.Component {

this.setState((prevState) => {
const amount = `${prevState.amount}${key}`;
return this.validateAmount(amount) ? {amount} : prevState;
return this.validateAmount(amount) ? {amount: this.stripCommaFromAmount(amount)} : prevState;
});
}

/**
* Update amount on amount change
* Validate new amount with decimal number regex up to 6 digits and 2 decimal digit
*
* @param {String} amount - Changed amount from user input
* @param {String} text - Changed text from user input
*/
updateAmount(text) {
this.setState((prevState) => {
const amount = this.replaceAllDigits(text, this.props.fromLocaleDigit);
return this.validateAmount(amount)
? {amount: this.stripCommaFromAmount(amount)}
: prevState;
});
}

/**
* Replaces each character by calling `convertFn`. If `convertFn` throws an error, then
* the original character will be preserved.
*
* @param {String} text
* @param {Function} convertFn - `this.props.fromLocaleDigit` or `this.props.toLocaleDigit`
* @returns {String}
*/
updateAmount(amount) {
this.setState(prevState => (this.validateAmount(amount) ? {amount} : prevState));
replaceAllDigits(text, convertFn) {
return _.chain([...text])
.map((char) => {
try {
return convertFn(char);
} catch {
return char;
}
})
.join('')
.value();
}

navigateToCurrencySelectionPage() {
Expand All @@ -160,6 +197,8 @@ class IOUAmountPage extends React.Component {
}

render() {
const formattedAmount = this.replaceAllDigits(this.state.amount, this.props.toLocaleDigit);

return (
<>
<View style={[
Expand All @@ -171,7 +210,7 @@ class IOUAmountPage extends React.Component {
]}
>
<TextInputWithCurrencySymbol
formattedAmount={this.state.amount}
formattedAmount={formattedAmount}
onChangeAmount={this.updateAmount}
onCurrencyButtonPress={this.navigateToCurrencySelectionPage}
placeholder={this.props.numberFormat(0)}
Expand All @@ -191,7 +230,7 @@ class IOUAmountPage extends React.Component {
<Button
success
style={[styles.w100, styles.mt5]}
onPress={() => this.props.onStepComplete(this.state.amount.replace(this.props.fromLocaleDigit('.'), '.'))}
onPress={() => this.props.onStepComplete(this.state.amount)}
pressOnEnter
isDisabled={!this.state.amount.length || parseFloat(this.state.amount) < 0.01}
text={this.props.translate('common.next')}
Expand Down
17 changes: 12 additions & 5 deletions src/pages/workspace/reimburse/WorkspaceReimburseView.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,16 @@ class WorkspaceReimburseView extends React.Component {
}

getRateDisplayValue(value) {
return value.toString().replace('.', this.props.fromLocaleDigit('.'));
const numValue = parseFloat(value);
if (Number.isNaN(numValue)) {
return '';
}

return numValue.toFixed(3);
}

setRate(value) {
const decimalSeparator = this.props.fromLocaleDigit('.');
const rateValueRegex = RegExp(String.raw`^\d{1,8}([${decimalSeparator}]\d{0,3})?$`, 'i');
const isInvalidRateValue = value !== '' && !rateValueRegex.test(value);
const isInvalidRateValue = value !== '' && !CONST.REGEX.RATE_VALUE.test(value);

this.setState(prevState => ({
rateValue: !isInvalidRateValue ? value : prevState.rateValue,
Expand Down Expand Up @@ -112,12 +115,16 @@ class WorkspaceReimburseView extends React.Component {
}

updateRateValue(value) {
const numValue = parseFloat(value.replace(this.props.fromLocaleDigit('.'), '.'));
const numValue = parseFloat(value);

if (_.isNaN(numValue)) {
return;
}

this.setState({
rateValue: numValue.toFixed(3),
});

Policy.setCustomUnitRate(this.props.policyID, this.state.unitID, {
customUnitRateID: this.state.rateID,
name: this.state.rateName,
Expand Down