diff --git a/app/soapbox/components/birthday_reminders.js b/app/soapbox/components/birthday_reminders.js
index a00a1ba33..8c1896bf7 100644
--- a/app/soapbox/components/birthday_reminders.js
+++ b/app/soapbox/components/birthday_reminders.js
@@ -1,6 +1,7 @@
import PropTypes from 'prop-types';
import React from 'react';
+import { HotKeys } from 'react-hotkeys';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { injectIntl, FormattedMessage } from 'react-intl';
@@ -51,6 +52,12 @@ class BirthdayReminders extends ImmutablePureComponent {
dispatch(fetchBirthdayReminders(day, month));
}
+ getHandlers() {
+ return {
+ open: this.handleOpenBirthdaysModal,
+ };
+ }
+
handleOpenBirthdaysModal = () => {
const { dispatch } = this.props;
@@ -101,17 +108,19 @@ class BirthdayReminders extends ImmutablePureComponent {
if (!birthdays || birthdays.size === 0) return null;
return (
-
-
-
-
-
+
+
+
+
+
+
-
- {this.renderMessage()}
-
+
+ {this.renderMessage()}
+
+
-
+
);
}
diff --git a/app/soapbox/features/birthdays/account.js b/app/soapbox/features/birthdays/account.js
new file mode 100644
index 000000000..141fd7b8e
--- /dev/null
+++ b/app/soapbox/features/birthdays/account.js
@@ -0,0 +1,88 @@
+import PropTypes from 'prop-types';
+import React from 'react';
+import ImmutablePropTypes from 'react-immutable-proptypes';
+import ImmutablePureComponent from 'react-immutable-pure-component';
+import { defineMessages, injectIntl } from 'react-intl';
+import { connect } from 'react-redux';
+
+import Avatar from 'soapbox/components/avatar';
+import DisplayName from 'soapbox/components/display_name';
+import Icon from 'soapbox/components/icon';
+import Permalink from 'soapbox/components/permalink';
+import { makeGetAccount } from 'soapbox/selectors';
+
+const messages = defineMessages({
+ birthDate: { id: 'account.birth_date', defaultMessage: 'Birth date: {date}' },
+});
+
+const makeMapStateToProps = () => {
+ const getAccount = makeGetAccount();
+
+ const mapStateToProps = (state, { accountId }) => {
+ const account = getAccount(state, accountId);
+
+ return {
+ account,
+ };
+ };
+
+ return mapStateToProps;
+};
+
+export default @connect(makeMapStateToProps)
+@injectIntl
+class Account extends ImmutablePureComponent {
+
+ static propTypes = {
+ accountId: PropTypes.string.isRequired,
+ intl: PropTypes.object.isRequired,
+ account: ImmutablePropTypes.map,
+ };
+
+ static defaultProps = {
+ added: false,
+ };
+
+ componentDidMount() {
+ const { account, accountId } = this.props;
+
+ if (accountId && !account) {
+ this.props.fetchAccount(accountId);
+ }
+ }
+
+ render() {
+ const { account, intl } = this.props;
+
+ if (!account) return null;
+
+ const birthDate = account.getIn(['pleroma', 'birth_date']);
+ if (!birthDate) return null;
+
+ const formattedBirthDate = intl.formatDate(birthDate, { day: 'numeric', month: 'short', year: 'numeric' });
+
+ return (
+
+
+
+
+
+
+
+ {formattedBirthDate}
+
+
+
+ );
+ }
+
+}
diff --git a/app/soapbox/features/ui/components/birthdays_modal.js b/app/soapbox/features/ui/components/birthdays_modal.js
index 995ad5cc5..9a0744ba7 100644
--- a/app/soapbox/features/ui/components/birthdays_modal.js
+++ b/app/soapbox/features/ui/components/birthdays_modal.js
@@ -7,7 +7,7 @@ import { connect } from 'react-redux';
import IconButton from 'soapbox/components/icon_button';
import LoadingIndicator from 'soapbox/components/loading_indicator';
import ScrollableList from 'soapbox/components/scrollable_list';
-import AccountContainer from 'soapbox/containers/account_container';
+import Account from 'soapbox/features/birthdays/account';
const messages = defineMessages({
close: { id: 'lightbox.close', defaultMessage: 'Close' },
@@ -69,7 +69,7 @@ class BirthdaysModal extends React.PureComponent {
emptyMessage={emptyMessage}
>
{accountIds.map(id =>
-
,
+
,
)}
);
diff --git a/app/soapbox/features/ui/components/profile_info_panel.js b/app/soapbox/features/ui/components/profile_info_panel.js
index f2af515f5..98abf8d86 100644
--- a/app/soapbox/features/ui/components/profile_info_panel.js
+++ b/app/soapbox/features/ui/components/profile_info_panel.js
@@ -80,6 +80,41 @@ class ProfileInfoPanel extends ImmutablePureComponent {
return badges;
}
+ getBirthDate = () => {
+ const { account, intl } = this.props;
+
+ const birthDate = account.getIn(['pleroma', 'birth_date']);
+ if (!birthDate) return null;
+
+ const formattedBirthDate = intl.formatDate(birthDate, { day: 'numeric', month: 'long', year: 'numeric' });
+
+ const date = new Date(birthDate);
+ const today = new Date();
+
+ const hasBirthday = date.getDate() === today.getDate() && date.getMonth() === today.getMonth();
+
+ if (hasBirthday) {
+ return (
+
+
+
+
+ );
+ }
+ return (
+
+
+
+
+ );
+ }
+
render() {
const { account, displayFqn, intl, identity_proofs, username } = this.props;
@@ -103,7 +138,6 @@ class ProfileInfoPanel extends ImmutablePureComponent {
const deactivated = !account.getIn(['pleroma', 'is_active'], true);
const displayNameHtml = deactivated ? { __html: intl.formatMessage(messages.deactivated) } : { __html: account.get('display_name_html') };
const memberSinceDate = intl.formatDate(account.get('created_at'), { month: 'long', year: 'numeric' });
- const birthDate = account.getIn(['pleroma', 'birth_date']) && intl.formatDate(account.getIn(['pleroma', 'birth_date']), { day: 'numeric', month: 'long', year: 'numeric' });
const verified = isVerified(account);
const badges = this.getBadges();
@@ -151,14 +185,7 @@ class ProfileInfoPanel extends ImmutablePureComponent {
/>
}
- {birthDate &&