Files
remark42/frontend/app/components/user-info/user-info.tsx
T

105 lines
2.9 KiB
TypeScript

import { h, JSX, Component, FunctionComponent } from 'preact';
import b from 'bem-react-helper';
import { useSelector } from 'react-redux';
import { useIntl, defineMessages, FormattedMessage, IntlShape } from 'react-intl';
import { StoreState } from 'store';
import { Comment } from 'common/types';
import { fetchInfo } from 'store/user-info/actions';
import { userInfo } from 'common/user-info-settings';
import postMessage from 'utils/postMessage';
import { bindActions } from 'utils/actionBinder';
import { useActions } from 'hooks/useAction';
import { AvatarIcon } from '../avatar-icon';
import LastCommentsList from './last-comments-list';
const boundActions = bindActions({ fetchInfo });
const messages = defineMessages({
unexpectedError: {
id: 'user-info.unexpected-error',
defaultMessage: 'Something went wrong',
},
});
type Props = {
comments: Comment[] | null;
} & typeof boundActions & { intl: IntlShape };
interface State {
isLoading: boolean;
error: string | null;
}
class UserInfo extends Component<Props, State> {
state = { isLoading: true, error: null };
componentWillMount(): void {
if (!this.props.comments && this.state.isLoading) {
this.props
.fetchInfo()
.then(() => {
this.setState({ isLoading: false });
})
.catch(() => {
this.setState({ isLoading: false, error: this.props.intl.formatMessage(messages.unexpectedError) });
});
}
document.addEventListener('keydown', UserInfo.onKeyDown);
}
componentWillUnmount(): void {
document.removeEventListener('keydown', UserInfo.onKeyDown);
}
render(): JSX.Element | null {
const user = userInfo;
const { comments = [] } = this.props;
const { isLoading } = this.state;
// TODO: handle
if (!user) {
return null;
}
return (
<div className={b('root user-info', {})}>
<AvatarIcon mix="user-info__avatar" picture={user.picture} />
<p className="user-info__title">
<FormattedMessage
id="user-info.last-comments"
defaultMessage="Last comments by {userName}"
values={{ userName: user.name }}
/>
</p>
<p className="user-info__id">{user.id}</p>
{!!comments && <LastCommentsList isLoading={isLoading} comments={comments} />}
</div>
);
}
/**
* Global on `keydown` handler which is set on component mount.
* Listens for user's `esc` key press
*/
static onKeyDown(e: KeyboardEvent): void {
// ESCAPE key pressed
if (e.keyCode === 27) {
postMessage({ isUserInfoShown: false });
}
}
}
const commentsSelector = (state: StoreState) => state.userComments[userInfo.id];
export const ConnectedUserInfo: FunctionComponent = () => {
const comments = useSelector(commentsSelector);
const actions = useActions(boundActions);
const intl = useIntl();
return <UserInfo comments={comments} {...actions} intl={intl} />;
};