phone editing widget works

This commit is contained in:
or-else
2023-01-25 17:08:07 -08:00
parent 34f17f45b1
commit e2f3201ddb
32 changed files with 246 additions and 106 deletions
+7 -3
View File
@@ -15,9 +15,13 @@ export default class Alert extends React.PureComponent {
:
null
}
<button className="primary" onClick={this.props.onConfirm}>
{this.props.confirm || <FormattedMessage id="button_ok" defaultMessage="OK" description="Button [OK]" />}
</button>
{this.props.onConfirm ?
<button className="primary" onClick={this.props.onConfirm}>
{this.props.confirm || <FormattedMessage id="button_ok" defaultMessage="OK" description="Button [OK]" />}
</button>
:
null
}
</div>
</div>
</div>);
+27 -17
View File
@@ -1,39 +1,47 @@
// Selector for country dialing code.
import React from 'react';
import { FormattedDisplayName } from 'react-intl';
import { injectIntl } from 'react-intl';
import * as dcodes from '../dcodes.json';
import { flagEmoji } from '../lib/strformat';
export default class PhoneCountrySelector extends React.PureComponent {
class PhoneCountrySelector extends React.PureComponent {
constructor(props) {
super(props);
this.codeMap = {};
dcodes.default.forEach(dc => { this.codeMap[dc.code] = dc.dial; });
this.countries = [];
const { formatDisplayName } = props.intl;
dcodes.default.forEach(dc => {
const parts = dc.dial.split(',');
parts.forEach(part => {
this.countries.push({
dial: part.trim(),
code: dc.code,
flag: flagEmoji(dc.code),
name: formatDisplayName(dc.code, {type: 'region'})
});
});
});
this.handleClick = this.handleClick.bind(this);
}
handleClick(e) {
e.preventDefault();
this.props.onSubmit(e.target.dataset.code, e.target.dataset.dial);
this.countries.sort((a, b) => a.name.localeCompare(b.name));
}
render() {
const countries = [];
const selected = this.props.selected || 'US';
dcodes.default.forEach((dc, idx) => {
const style = (dc.code == selected ? 'selected ' : '');
countries.push(<li className={style} key={idx} data-code={dc.code} data-dial={dc.dial} onClick={this.handleClick}>
<span className="country-flag">{flagEmoji(dc.code)}</span>&nbsp;
<FormattedDisplayName type="region" value={dc.code} />
&nbsp;<span className="dial-code">+{dc.dial}</span>
this.countries.forEach((c, idx) => {
const style = (c.code == selected ? 'selected ' : '');
countries.push(<li className={style} key={idx} onClick={_ => this.props.onSubmit(c.code, c.dial)}>
<span className="country-flag">{c.flag}</span>
<span className="country">&nbsp;{c.name}</span>
<span className="dial-code">&nbsp;+{c.dial}</span>
</li>);
});
return (
<div className="scrollable-panel">
<div className="scrollable-panel" style={{height: '30rem'}}>
<ul className="phone-country-selector">
{countries}
</ul>
@@ -41,3 +49,5 @@ export default class PhoneCountrySelector extends React.PureComponent {
);
}
}
export default injectIntl(PhoneCountrySelector);
+38 -8
View File
@@ -2,6 +2,9 @@
import React from 'react';
import { injectIntl } from 'react-intl';
import { getExampleNumber, parsePhoneNumber } from 'libphonenumber-js/mobile';
import examples from 'libphonenumber-js/mobile/examples'
import * as dcodes from '../dcodes.json';
import { flagEmoji } from '../lib/strformat';
@@ -12,10 +15,14 @@ class PhoneEdit extends React.PureComponent {
this.codeMap = {};
dcodes.default.forEach(dc => { this.codeMap[dc.code] = dc.dial; });
const code = props.countryCode || 'US';
const dial = this.codeMap[code];
this.state = {
countryCode: props.countryCode || 'US',
dialCode: this.codeMap[props.countryCode || 'US'],
localNumber: ''
countryCode: code,
dialCode: dial,
localNumber: '',
placeholderNumber: this.placeholderNumber(code, dial)
};
this.handleChange = this.handleChange.bind(this);
@@ -29,10 +36,18 @@ class PhoneEdit extends React.PureComponent {
}
handleFinished(e) {
// this.setCustomValidity("Mobile phone number required");
e.preventDefault();
const number = `${this.state.dialCode}${this.state.localNumber.trim()}`.replace(/[^\d]/g, '')
this.props.onSubmit(`+${number}`);
const raw = `${this.state.dialCode}${this.state.localNumber.trim()}`.replace(/[^\d]/g, '')
let number = null;
try {
number = parsePhoneNumber(raw);
} catch (err) {}
if (!number || !number.isValid()) {
this.inputField.setCustomValidity("Mobile phone number required");
return;
}
this.props.onSubmit(number.format('E.164'));
}
@@ -43,7 +58,15 @@ class PhoneEdit extends React.PureComponent {
}
showCountrySelector() {
this.props.onShowCountrySelector(this.state.countryCode, this.state.dialCode);
this.props.onShowCountrySelector(this.state.countryCode, this.state.dialCode,
(code, dial) => {
console.log('Callback', code, dial);
this.setState({
countryCode: code,
dialCode: dial,
placeholderNumber: this.placeholderNumber(code, dial)
})
});
}
// Filter out characters not permitted in a phone number.
@@ -56,13 +79,20 @@ class PhoneEdit extends React.PureComponent {
return number.replace(/[^-\s().\d]/g, '');
}
placeholderNumber(code, dial) {
console.log('In nplaceholder', code, dial);
const number = getExampleNumber(code, examples).formatInternational();
return number.substring(dial.length + 1).trim();
}
render() {
console.log('placeholder:', this.state.placeholderNumber);
return (
<>
<span className="dial-code" onClick={this.showCountrySelector}>
<span className="country-flag">{flagEmoji(this.state.countryCode)}&nbsp;</span>
+{this.state.dialCode}&nbsp;</span>
<input type="tel" placeholder={this.state.placeholder}
<input type="tel" ref={ref => {this.inputField = ref}} placeholder={this.state.placeholderNumber}
value={this.state.localNumber} onChange={this.handleChange}
maxLength={17} onKeyDown={this.handleKeyDown} onBlur={this.handleFinished}
required autoFocus={this.props.autoFocus} />