Skip to content

Commit

Permalink
Merge pull request #24255 from Skalakid/16297-migrate-TimezoneSelectPage
Browse files Browse the repository at this point in the history
16297 - Migrate TimezoneSelectPage.js to function component
  • Loading branch information
marcaaron authored Aug 9, 2023
2 parents 39e4ca2 + 1bbb12d commit 1e22b21
Showing 1 changed file with 54 additions and 100 deletions.
154 changes: 54 additions & 100 deletions src/pages/settings/Profile/TimezoneSelectPage.js
Original file line number Diff line number Diff line change
@@ -1,135 +1,89 @@
import lodashGet from 'lodash/get';
import React, {Component} from 'react';
import React, {useState, useRef} from 'react';
import _ from 'underscore';
import moment from 'moment-timezone';
import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsPropTypes, withCurrentUserPersonalDetailsDefaultProps} from '../../../components/withCurrentUserPersonalDetails';
import ScreenWrapper from '../../../components/ScreenWrapper';
import HeaderWithBackButton from '../../../components/HeaderWithBackButton';
import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize';
import CONST from '../../../CONST';
import * as PersonalDetails from '../../../libs/actions/PersonalDetails';
import compose from '../../../libs/compose';
import Navigation from '../../../libs/Navigation/Navigation';
import ROUTES from '../../../ROUTES';
import SelectionListRadio from '../../../components/SelectionListRadio';
import useLocalize from '../../../hooks/useLocalize';

const propTypes = {
...withLocalizePropTypes,
...withCurrentUserPersonalDetailsPropTypes,
};

const defaultProps = {
...withCurrentUserPersonalDetailsDefaultProps,
};

class TimezoneSelectPage extends Component {
constructor(props) {
super(props);

this.saveSelectedTimezone = this.saveSelectedTimezone.bind(this);
this.filterShownTimezones = this.filterShownTimezones.bind(this);
this.getTimezoneOption = this.getTimezoneOption.bind(this);

this.timezone = this.getUserTimezone(props.currentUserPersonalDetails);
this.allTimezones = _.chain(moment.tz.names())
.filter((timezone) => !timezone.startsWith('Etc/GMT'))
.map(this.getTimezoneOption)
.value();

this.state = {
timezoneInputText: this.timezone.selected,
timezoneOptions: this.allTimezones,
};
}

componentDidUpdate() {
// componentDidUpdate is added in order to update the timezone options when automatic is toggled on/off as
// navigating back doesn't unmount the page, thus it won't update the timezone options & stay disabled without this.
const newTimezone = this.getUserTimezone(this.props.currentUserPersonalDetails);
if (_.isEqual(this.timezone, newTimezone)) {
return;
}
this.timezone = newTimezone;
this.allTimezones = _.map(this.allTimezones, (timezone) => {
const text = timezone.text.split('-')[0];
return this.getTimezoneOption(text);
});

this.setState({
timezoneInputText: this.timezone.selected,
timezoneOptions: this.allTimezones,
});
}

/**
* We add the current time to the key to fix a bug where the list options don't update unless the key is updated.
* @param {String} text
* @return {string} key for list item
*/
getKey(text) {
return `${text}-${new Date().getTime()}`;
}

/**
* Get timezone option object for the list.
* @param {String} text
* @return {Object} Timezone list option
*/
getTimezoneOption(text) {
return {
text,
keyForList: this.getKey(text),
isSelected: text === this.timezone.selected,
};
}

/**
* @param {Object} currentUserPersonalDetails
* @return {Object} user's timezone data
*/
getUserTimezone(currentUserPersonalDetails) {
return lodashGet(currentUserPersonalDetails, 'timezone', CONST.DEFAULT_TIME_ZONE);
}
/**
* We add the current time to the key to fix a bug where the list options don't update unless the key is updated.
* @param {String} text
* @return {string} key for list item
*/
const getKey = (text) => `${text}-${new Date().getTime()}`;

/**
* @param {Object} currentUserPersonalDetails
* @return {Object} user's timezone data
*/
const getUserTimezone = (currentUserPersonalDetails) => lodashGet(currentUserPersonalDetails, 'timezone', CONST.DEFAULT_TIME_ZONE);

function TimezoneSelectPage(props) {
const {translate} = useLocalize();
const timezone = useRef(getUserTimezone(props.currentUserPersonalDetails));
const allTimezones = useRef(
_.chain(moment.tz.names())
.filter((tz) => !tz.startsWith('Etc/GMT'))
.map((text) => ({
text,
keyForList: getKey(text),
isSelected: text === timezone.current.selected,
}))
.value(),
);
const [timezoneInputText, setTimezoneInputText] = useState(timezone.current.selected);
const [timezoneOptions, setTimezoneOptions] = useState(allTimezones.current);

/**
* @param {Object} timezone
* @param {String} timezone.text
*/
saveSelectedTimezone({text}) {
const saveSelectedTimezone = ({text}) => {
PersonalDetails.updateSelectedTimezone(text);
}
};

/**
* @param {String} searchText
*/
filterShownTimezones(searchText) {
this.setState({
timezoneInputText: searchText,
timezoneOptions: _.filter(this.allTimezones, (tz) => tz.text.toLowerCase().includes(searchText.trim().toLowerCase())),
});
}

render() {
return (
<ScreenWrapper includeSafeAreaPaddingBottom={false}>
<HeaderWithBackButton
title={this.props.translate('timezonePage.timezone')}
onBackButtonPress={() => Navigation.goBack(ROUTES.SETTINGS_TIMEZONE)}
/>
<SelectionListRadio
textInputLabel={this.props.translate('timezonePage.timezone')}
textInputValue={this.state.timezoneInputText}
onChangeText={this.filterShownTimezones}
onSelectRow={this.saveSelectedTimezone}
sections={[{data: this.state.timezoneOptions, indexOffset: 0, isDisabled: this.timezone.automatic}]}
initiallyFocusedOptionKey={_.get(_.filter(this.state.timezoneOptions, (tz) => tz.text === this.timezone.selected)[0], 'keyForList')}
/>
</ScreenWrapper>
);
}
const filterShownTimezones = (searchText) => {
setTimezoneInputText(searchText);
setTimezoneOptions(_.filter(allTimezones.current, (tz) => tz.text.toLowerCase().includes(searchText.trim().toLowerCase())));
};

return (
<ScreenWrapper includeSafeAreaPaddingBottom={false}>
<HeaderWithBackButton
title={translate('timezonePage.timezone')}
onBackButtonPress={() => Navigation.goBack(ROUTES.SETTINGS_TIMEZONE)}
/>
<SelectionListRadio
textInputLabel={translate('timezonePage.timezone')}
textInputValue={timezoneInputText}
onChangeText={filterShownTimezones}
onSelectRow={saveSelectedTimezone}
sections={[{data: timezoneOptions, indexOffset: 0, isDisabled: timezone.current.automatic}]}
initiallyFocusedOptionKey={_.get(_.filter(timezoneOptions, (tz) => tz.text === timezone.current.selected)[0], 'keyForList')}
/>
</ScreenWrapper>
);
}

TimezoneSelectPage.propTypes = propTypes;
TimezoneSelectPage.defaultProps = defaultProps;

export default compose(withLocalize, withCurrentUserPersonalDetails)(TimezoneSelectPage);
export default withCurrentUserPersonalDetails(TimezoneSelectPage);

0 comments on commit 1e22b21

Please sign in to comment.