Skip to content

Commit

Permalink
Merge pull request #23880 from shubham1206agra/datepicker-functional
Browse files Browse the repository at this point in the history
Convert Date Picker to Functional Component
  • Loading branch information
srikarparsi authored Aug 2, 2023
2 parents 1efc85f + f60a4db commit b570e34
Showing 1 changed file with 49 additions and 62 deletions.
111 changes: 49 additions & 62 deletions src/components/DatePicker/index.js
Original file line number Diff line number Diff line change
@@ -1,99 +1,86 @@
import React from 'react';
import React, {useEffect, useRef} from 'react';
import moment from 'moment';
import _ from 'underscore';
import TextInput from '../TextInput';
import CONST from '../../CONST';
import * as Browser from '../../libs/Browser';
import {propTypes, defaultProps} from './datepickerPropTypes';
import withWindowDimensions, {windowDimensionsPropTypes} from '../withWindowDimensions';
import './styles.css';

const datePickerPropTypes = {
...propTypes,
...windowDimensionsPropTypes,
};
function DatePicker({maxDate, minDate, onInputChange, innerRef, label, value, placeholder, errorText, containerStyles, disabled, onBlur}) {
const inputRef = useRef(null);

class DatePicker extends React.Component {
constructor(props) {
super(props);

this.setDate = this.setDate.bind(this);
this.showDatepicker = this.showDatepicker.bind(this);
}

componentDidMount() {
useEffect(() => {
// Adds nice native datepicker on web/desktop. Not possible to set this through props
this.inputRef.setAttribute('type', 'date');
this.inputRef.setAttribute('max', moment(this.props.maxDate).format(CONST.DATE.MOMENT_FORMAT_STRING));
this.inputRef.setAttribute('min', moment(this.props.minDate).format(CONST.DATE.MOMENT_FORMAT_STRING));
this.inputRef.classList.add('expensify-datepicker');
}
inputRef.current.setAttribute('type', 'date');
inputRef.current.setAttribute('max', moment(maxDate).format(CONST.DATE.MOMENT_FORMAT_STRING));
inputRef.current.setAttribute('min', moment(minDate).format(CONST.DATE.MOMENT_FORMAT_STRING));
inputRef.current.classList.add('expensify-datepicker');
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

/**
* Trigger the `onChange` handler when the user input has a complete date or is cleared
* @param {String} text
*/
setDate(text) {
const setDate = (text) => {
if (!text) {
this.props.onInputChange('');
onInputChange('');
return;
}

const asMoment = moment(text, true);
if (asMoment.isValid()) {
this.props.onInputChange(asMoment.format(CONST.DATE.MOMENT_FORMAT_STRING));
onInputChange(asMoment.format(CONST.DATE.MOMENT_FORMAT_STRING));
}
}
};

/**
* Pops the datepicker up when we focus this field. This only works on mWeb chrome
* On mWeb chrome the user needs to tap on the field again in order to bring the datepicker. But our current styles
* don't make this very obvious. To avoid confusion we open the datepicker when the user focuses the field
*/
showDatepicker() {
if (!this.inputRef || !Browser.isMobileChrome()) {
const showDatepicker = () => {
if (!inputRef.current || !Browser.isMobileChrome()) {
return;
}

this.inputRef.click();
}
inputRef.current.click();
};

render() {
return (
<TextInput
forceActiveLabel
ref={(el) => {
this.inputRef = el;
return (
<TextInput
forceActiveLabel
ref={(el) => {
inputRef.current = el;

if (_.isFunction(this.props.innerRef)) {
this.props.innerRef(el);
}
}}
onFocus={this.showDatepicker}
label={this.props.label}
accessibilityLabel={this.props.label}
accessibilityRole={CONST.ACCESSIBILITY_ROLE.TEXT}
onInputChange={this.setDate}
value={this.props.value}
placeholder={this.props.placeholder}
errorText={this.props.errorText}
containerStyles={this.props.containerStyles}
disabled={this.props.disabled}
onBlur={this.props.onBlur}
/>
);
}
if (_.isFunction(innerRef)) {
innerRef(el);
}
}}
onFocus={showDatepicker}
label={label}
accessibilityLabel={label}
accessibilityRole={CONST.ACCESSIBILITY_ROLE.TEXT}
onInputChange={setDate}
value={value}
placeholder={placeholder}
errorText={errorText}
containerStyles={containerStyles}
disabled={disabled}
onBlur={onBlur}
/>
);
}

DatePicker.propTypes = datePickerPropTypes;
DatePicker.displayName = 'DatePicker';
DatePicker.propTypes = propTypes;
DatePicker.defaultProps = defaultProps;

export default withWindowDimensions(
React.forwardRef((props, ref) => (
<DatePicker
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
innerRef={ref}
/>
)),
);
export default React.forwardRef((props, ref) => (
<DatePicker
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
innerRef={ref}
/>
));

0 comments on commit b570e34

Please sign in to comment.