diff --git a/app/soapbox/components/birthday_input.js b/app/soapbox/components/birthday_input.tsx similarity index 56% rename from app/soapbox/components/birthday_input.js rename to app/soapbox/components/birthday_input.tsx index 912ba82fb..2b4e4833f 100644 --- a/app/soapbox/components/birthday_input.js +++ b/app/soapbox/components/birthday_input.tsx @@ -1,13 +1,10 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import { defineMessages, injectIntl } from 'react-intl'; -import { connect } from 'react-redux'; +import React, { useMemo } from 'react'; +import { defineMessages, useIntl } from 'react-intl'; import IconButton from 'soapbox/components/icon_button'; import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; import { DatePicker } from 'soapbox/features/ui/util/async-components'; -import { getFeatures } from 'soapbox/utils/features'; +import { useAppSelector, useFeatures } from 'soapbox/hooks'; const messages = defineMessages({ birthdayPlaceholder: { id: 'edit_profile.fields.birthday_placeholder', defaultMessage: 'Your birthday' }, @@ -17,29 +14,37 @@ const messages = defineMessages({ nextYear: { id: 'datepicker.next_year', defaultMessage: 'Next year' }, }); -const mapStateToProps = state => { - const features = getFeatures(state.get('instance')); +interface IBirthdayInput { + value?: string, + onChange: (value: string) => void, + required?: boolean, +} - return { - supportsBirthdays: features.birthdays, - minAge: state.getIn(['instance', 'pleroma', 'metadata', 'birthday_min_age']), - }; -}; +const BirthdayInput: React.FC = ({ value, onChange, required }) => { + const intl = useIntl(); + const features = useFeatures(); -export default @connect(mapStateToProps) -@injectIntl -class BirthdayInput extends ImmutablePureComponent { + const supportsBirthdays = features.birthdays; + const minAge = useAppSelector((state) => state.instance.getIn(['pleroma', 'metadata', 'birthday_min_age'])) as number; - static propTypes = { - hint: PropTypes.node, - required: PropTypes.bool, - supportsBirthdays: PropTypes.bool, - minAge: PropTypes.number, - onChange: PropTypes.func.isRequired, - value: PropTypes.instanceOf(Date), - }; + const maxDate = useMemo(() => { + if (!supportsBirthdays) return null; - renderHeader = ({ + let maxDate = new Date(); + maxDate = new Date(maxDate.getTime() - minAge * 1000 * 60 * 60 * 24 + maxDate.getTimezoneOffset() * 1000 * 60); + return maxDate; + }, [minAge]); + + const selected = useMemo(() => { + if (!supportsBirthdays || !value) return null; + + const date = new Date(value); + return new Date(date.getTime() + (date.getTimezoneOffset() * 60000)); + }, [value]); + + if (!supportsBirthdays) return null; + + const renderCustomHeader = ({ decreaseMonth, increaseMonth, prevMonthButtonDisabled, @@ -49,12 +54,20 @@ class BirthdayInput extends ImmutablePureComponent { prevYearButtonDisabled, nextYearButtonDisabled, date, + }: { + decreaseMonth(): void, + increaseMonth(): void, + prevMonthButtonDisabled: boolean, + nextMonthButtonDisabled: boolean, + decreaseYear(): void, + increaseYear(): void, + prevYearButtonDisabled: boolean, + nextYearButtonDisabled: boolean, + date: Date, }) => { - const { intl } = this.props; - return ( -
-
+
+
-
+
); - } + }; - render() { - const { intl, value, onChange, supportsBirthdays, hint, required, minAge } = this.props; + const handleChange = (date: Date) => onChange(new Date(date.getTime() - (date.getTimezoneOffset() * 60000)).toISOString().slice(0, 10)); - if (!supportsBirthdays) return null; + return ( +
+ + {Component => ()} + +
+ ); +}; - let maxDate = new Date(); - maxDate = new Date(maxDate.getTime() - minAge * 1000 * 60 * 60 * 24 + maxDate.getTimezoneOffset() * 1000 * 60); - - return ( -
- {hint && ( -
- {hint} -
- )} -
- - {Component => ()} - -
-
- ); - } - -} +export default BirthdayInput; diff --git a/app/soapbox/features/auth_login/components/registration_form.tsx b/app/soapbox/features/auth_login/components/registration_form.tsx index 22a7bbca9..0c3e048ce 100644 --- a/app/soapbox/features/auth_login/components/registration_form.tsx +++ b/app/soapbox/features/auth_login/components/registration_form.tsx @@ -58,7 +58,6 @@ const RegistrationForm: React.FC = ({ inviteToken }) => { const [usernameUnavailable, setUsernameUnavailable] = useState(false); const [passwordConfirmation, setPasswordConfirmation] = useState(''); const [passwordMismatch, setPasswordMismatch] = useState(false); - const [birthday, setBirthday] = useState(undefined); const source = useRef(axios.CancelToken.source()); @@ -111,8 +110,8 @@ const RegistrationForm: React.FC = ({ inviteToken }) => { setPasswordMismatch(!passwordsMatch()); }; - const onBirthdayChange = (newBirthday: Date) => { - setBirthday(newBirthday); + const onBirthdayChange = (birthday: string) => { + updateParams({ birthday }); }; const launchModal = () => { @@ -187,10 +186,6 @@ const RegistrationForm: React.FC = ({ inviteToken }) => { if (inviteToken) { params.set('token', inviteToken); } - - if (birthday) { - params.set('birthday', new Date(birthday.getTime() - (birthday.getTimezoneOffset() * 60000)).toISOString().slice(0, 10)); - } }); setSubmissionLoading(true); @@ -291,7 +286,7 @@ const RegistrationForm: React.FC = ({ inviteToken }) => { {birthdayRequired && ( diff --git a/app/soapbox/features/edit_profile/index.tsx b/app/soapbox/features/edit_profile/index.tsx index d7f60b572..788031852 100644 --- a/app/soapbox/features/edit_profile/index.tsx +++ b/app/soapbox/features/edit_profile/index.tsx @@ -4,6 +4,7 @@ import { defineMessages, useIntl, FormattedMessage } from 'react-intl'; import { updateNotificationSettings } from 'soapbox/actions/accounts'; import { patchMe } from 'soapbox/actions/me'; import snackbar from 'soapbox/actions/snackbar'; +import BirthdayInput from 'soapbox/components/birthday_input'; import List, { ListItem } from 'soapbox/components/list'; import { useAppSelector, useAppDispatch, useOwnAccount, useFeatures } from 'soapbox/hooks'; import { normalizeAccount } from 'soapbox/normalizers'; @@ -242,6 +243,10 @@ const EditProfile: React.FC = () => { }; }; + const handleBirthdayChange = (date: string) => { + updateData('birthday', date); + }; + const handleHideNetworkChange: React.ChangeEventHandler = e => { const hide = e.target.checked; @@ -325,10 +330,9 @@ const EditProfile: React.FC = () => { } > - )}