2022-05-27 10:13:44 -07:00
|
|
|
import React, { useMemo } from 'react';
|
|
|
|
import { defineMessages, useIntl } from 'react-intl';
|
2022-01-19 14:59:10 -08:00
|
|
|
|
2022-11-15 06:11:30 -08:00
|
|
|
import IconButton from 'soapbox/components/icon-button';
|
2022-11-16 05:32:32 -08:00
|
|
|
import BundleContainer from 'soapbox/features/ui/containers/bundle-container';
|
2022-03-09 13:57:37 -08:00
|
|
|
import { DatePicker } from 'soapbox/features/ui/util/async-components';
|
2022-11-26 08:38:16 -08:00
|
|
|
import { useInstance, useFeatures } from 'soapbox/hooks';
|
2022-01-19 14:59:10 -08:00
|
|
|
|
|
|
|
const messages = defineMessages({
|
2022-01-25 15:08:20 -08:00
|
|
|
birthdayPlaceholder: { id: 'edit_profile.fields.birthday_placeholder', defaultMessage: 'Your birthday' },
|
2022-01-26 09:43:00 -08:00
|
|
|
previousMonth: { id: 'datepicker.previous_month', defaultMessage: 'Previous month' },
|
|
|
|
nextMonth: { id: 'datepicker.next_month', defaultMessage: 'Next month' },
|
|
|
|
previousYear: { id: 'datepicker.previous_year', defaultMessage: 'Previous year' },
|
|
|
|
nextYear: { id: 'datepicker.next_year', defaultMessage: 'Next year' },
|
2022-01-19 14:59:10 -08:00
|
|
|
});
|
|
|
|
|
2022-05-27 10:13:44 -07:00
|
|
|
interface IBirthdayInput {
|
2023-02-15 13:26:27 -08:00
|
|
|
value?: string
|
|
|
|
onChange: (value: string) => void
|
|
|
|
required?: boolean
|
2022-05-27 10:13:44 -07:00
|
|
|
}
|
2022-01-19 14:59:10 -08:00
|
|
|
|
2022-05-27 10:13:44 -07:00
|
|
|
const BirthdayInput: React.FC<IBirthdayInput> = ({ value, onChange, required }) => {
|
|
|
|
const intl = useIntl();
|
|
|
|
const features = useFeatures();
|
2022-11-26 08:38:16 -08:00
|
|
|
const instance = useInstance();
|
2022-01-19 14:59:10 -08:00
|
|
|
|
2022-05-27 10:13:44 -07:00
|
|
|
const supportsBirthdays = features.birthdays;
|
2022-11-26 08:38:16 -08:00
|
|
|
const minAge = instance.pleroma.getIn(['metadata', 'birthday_min_age']) as number;
|
2022-01-19 14:59:10 -08:00
|
|
|
|
2022-05-27 10:13:44 -07:00
|
|
|
const maxDate = useMemo(() => {
|
|
|
|
if (!supportsBirthdays) return null;
|
|
|
|
|
|
|
|
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;
|
2022-01-19 14:59:10 -08:00
|
|
|
|
2022-05-27 10:13:44 -07:00
|
|
|
const date = new Date(value);
|
|
|
|
return new Date(date.getTime() + (date.getTimezoneOffset() * 60000));
|
|
|
|
}, [value]);
|
|
|
|
|
|
|
|
if (!supportsBirthdays) return null;
|
|
|
|
|
|
|
|
const renderCustomHeader = ({
|
2022-01-26 09:43:00 -08:00
|
|
|
decreaseMonth,
|
|
|
|
increaseMonth,
|
|
|
|
prevMonthButtonDisabled,
|
|
|
|
nextMonthButtonDisabled,
|
|
|
|
decreaseYear,
|
|
|
|
increaseYear,
|
|
|
|
prevYearButtonDisabled,
|
|
|
|
nextYearButtonDisabled,
|
|
|
|
date,
|
2022-05-27 10:13:44 -07:00
|
|
|
}: {
|
2023-02-15 13:26:27 -08:00
|
|
|
decreaseMonth(): void
|
|
|
|
increaseMonth(): void
|
|
|
|
prevMonthButtonDisabled: boolean
|
|
|
|
nextMonthButtonDisabled: boolean
|
|
|
|
decreaseYear(): void
|
|
|
|
increaseYear(): void
|
|
|
|
prevYearButtonDisabled: boolean
|
|
|
|
nextYearButtonDisabled: boolean
|
|
|
|
date: Date
|
2022-01-26 09:43:00 -08:00
|
|
|
}) => {
|
|
|
|
return (
|
2022-05-27 10:13:44 -07:00
|
|
|
<div className='flex flex-col gap-2'>
|
|
|
|
<div className='flex items-center justify-between'>
|
2022-01-26 09:43:00 -08:00
|
|
|
<IconButton
|
2022-12-04 17:40:09 -08:00
|
|
|
className='datepicker__button rtl:rotate-180'
|
2022-07-09 09:20:02 -07:00
|
|
|
src={require('@tabler/icons/chevron-left.svg')}
|
2022-01-26 09:43:00 -08:00
|
|
|
onClick={decreaseMonth}
|
|
|
|
disabled={prevMonthButtonDisabled}
|
|
|
|
aria-label={intl.formatMessage(messages.previousMonth)}
|
|
|
|
title={intl.formatMessage(messages.previousMonth)}
|
|
|
|
/>
|
|
|
|
{intl.formatDate(date, { month: 'long' })}
|
|
|
|
<IconButton
|
2022-12-04 17:40:09 -08:00
|
|
|
className='datepicker__button rtl:rotate-180'
|
2022-07-09 09:20:02 -07:00
|
|
|
src={require('@tabler/icons/chevron-right.svg')}
|
2022-01-26 09:43:00 -08:00
|
|
|
onClick={increaseMonth}
|
|
|
|
disabled={nextMonthButtonDisabled}
|
|
|
|
aria-label={intl.formatMessage(messages.nextMonth)}
|
|
|
|
title={intl.formatMessage(messages.nextMonth)}
|
|
|
|
/>
|
|
|
|
</div>
|
2022-05-27 10:13:44 -07:00
|
|
|
<div className='flex items-center justify-between'>
|
2022-01-26 09:43:00 -08:00
|
|
|
<IconButton
|
2022-12-04 17:40:09 -08:00
|
|
|
className='datepicker__button rtl:rotate-180'
|
2022-07-09 09:20:02 -07:00
|
|
|
src={require('@tabler/icons/chevron-left.svg')}
|
2022-01-26 09:43:00 -08:00
|
|
|
onClick={decreaseYear}
|
|
|
|
disabled={prevYearButtonDisabled}
|
|
|
|
aria-label={intl.formatMessage(messages.previousYear)}
|
|
|
|
title={intl.formatMessage(messages.previousYear)}
|
|
|
|
/>
|
|
|
|
{intl.formatDate(date, { year: 'numeric' })}
|
|
|
|
<IconButton
|
2022-12-04 17:40:09 -08:00
|
|
|
className='datepicker__button rtl:rotate-180'
|
2022-07-09 09:20:02 -07:00
|
|
|
src={require('@tabler/icons/chevron-right.svg')}
|
2022-01-26 09:43:00 -08:00
|
|
|
onClick={increaseYear}
|
|
|
|
disabled={nextYearButtonDisabled}
|
|
|
|
aria-label={intl.formatMessage(messages.nextYear)}
|
|
|
|
title={intl.formatMessage(messages.nextYear)}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
2022-05-27 10:13:44 -07:00
|
|
|
};
|
2022-01-19 14:59:10 -08:00
|
|
|
|
2022-07-18 15:11:12 -07:00
|
|
|
const handleChange = (date: Date) => onChange(date ? new Date(date.getTime() - (date.getTimezoneOffset() * 60000)).toISOString().slice(0, 10) : '');
|
2022-01-25 07:51:15 -08:00
|
|
|
|
2022-05-27 10:13:44 -07:00
|
|
|
return (
|
2023-02-01 14:13:42 -08:00
|
|
|
<div className='relative mt-1 rounded-md shadow-sm'>
|
2022-05-27 10:13:44 -07:00
|
|
|
<BundleContainer fetchComponent={DatePicker}>
|
|
|
|
{Component => (<Component
|
|
|
|
selected={selected}
|
|
|
|
wrapperClassName='react-datepicker-wrapper'
|
|
|
|
onChange={handleChange}
|
|
|
|
placeholderText={intl.formatMessage(messages.birthdayPlaceholder)}
|
|
|
|
minDate={new Date('1900-01-01')}
|
|
|
|
maxDate={maxDate}
|
|
|
|
required={required}
|
|
|
|
renderCustomHeader={renderCustomHeader}
|
2022-07-18 15:11:12 -07:00
|
|
|
isClearable={!required}
|
2022-05-27 10:13:44 -07:00
|
|
|
/>)}
|
|
|
|
</BundleContainer>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|
2022-01-19 14:59:10 -08:00
|
|
|
|
2022-05-27 10:13:44 -07:00
|
|
|
export default BirthdayInput;
|