diff --git a/app/soapbox/features/admin/components/report.js b/app/soapbox/features/admin/components/report.js
deleted file mode 100644
index 08fe61f22..000000000
--- a/app/soapbox/features/admin/components/report.js
+++ /dev/null
@@ -1,126 +0,0 @@
-import React from 'react';
-import ImmutablePropTypes from 'react-immutable-proptypes';
-import ImmutablePureComponent from 'react-immutable-pure-component';
-import { injectIntl, FormattedMessage, defineMessages } from 'react-intl';
-import { connect } from 'react-redux';
-import { Link } from 'react-router-dom';
-
-import { closeReports } from 'soapbox/actions/admin';
-import { deactivateUserModal, deleteUserModal } from 'soapbox/actions/moderation';
-import snackbar from 'soapbox/actions/snackbar';
-import Avatar from 'soapbox/components/avatar';
-import { Button } from 'soapbox/components/ui';
-import DropdownMenu from 'soapbox/containers/dropdown_menu_container';
-import Accordion from 'soapbox/features/ui/components/accordion';
-
-import ReportStatus from './report_status';
-
-const messages = defineMessages({
- reportClosed: { id: 'admin.reports.report_closed_message', defaultMessage: 'Report on @{name} was closed' },
- deactivateUser: { id: 'admin.users.actions.deactivate_user', defaultMessage: 'Deactivate @{name}' },
- deleteUser: { id: 'admin.users.actions.delete_user', defaultMessage: 'Delete @{name}' },
-});
-
-export default @connect()
-@injectIntl
-class Report extends ImmutablePureComponent {
-
- static propTypes = {
- report: ImmutablePropTypes.map.isRequired,
- };
-
- state = {
- accordionExpanded: false,
- };
-
- makeMenu = () => {
- const { intl, report } = this.props;
-
- return [{
- text: intl.formatMessage(messages.deactivateUser, { name: report.getIn(['account', 'username']) }),
- action: this.handleDeactivateUser,
- icon: require('@tabler/icons/icons/user-off.svg'),
- }, {
- text: intl.formatMessage(messages.deleteUser, { name: report.getIn(['account', 'username']) }),
- action: this.handleDeleteUser,
- icon: require('@tabler/icons/icons/user-minus.svg'),
- }];
- }
-
- handleCloseReport = () => {
- const { intl, dispatch, report } = this.props;
- dispatch(closeReports([report.get('id')])).then(() => {
- const message = intl.formatMessage(messages.reportClosed, { name: report.getIn(['account', 'username']) });
- dispatch(snackbar.success(message));
- }).catch(() => {});
- }
-
- handleDeactivateUser = () => {
- const { intl, dispatch, report } = this.props;
- const accountId = report.getIn(['account', 'id']);
- dispatch(deactivateUserModal(intl, accountId, () => this.handleCloseReport()));
- }
-
- handleDeleteUser = () => {
- const { intl, dispatch, report } = this.props;
- const accountId = report.getIn(['account', 'id']);
- dispatch(deleteUserModal(intl, accountId, () => this.handleCloseReport()));
- }
-
- handleAccordionToggle = setting => {
- this.setState({ accordionExpanded: setting });
- }
-
- render() {
- const { report } = this.props;
- const { accordionExpanded } = this.state;
- const menu = this.makeMenu();
- const statuses = report.get('statuses');
- const statusCount = statuses.count();
- const acct = report.getIn(['account', 'acct']);
- const reporterAcct = report.getIn(['actor', 'acct']);
-
- return (
-
-
-
-
- @{acct} }}
- />
-
-
- {statusCount > 0 && (
-
- {statuses.map(status => )}
-
- )}
-
-
- {report.get('content', '').length > 0 &&
-
- }
-
— @{reporterAcct}
-
-
-
-
-
-
-
- );
- }
-
-}
diff --git a/app/soapbox/features/admin/components/report.tsx b/app/soapbox/features/admin/components/report.tsx
new file mode 100644
index 000000000..16e99bb7c
--- /dev/null
+++ b/app/soapbox/features/admin/components/report.tsx
@@ -0,0 +1,118 @@
+import React, { useState } from 'react';
+import { useIntl, FormattedMessage, defineMessages } from 'react-intl';
+import { Link } from 'react-router-dom';
+
+import { closeReports } from 'soapbox/actions/admin';
+import { deactivateUserModal, deleteUserModal } from 'soapbox/actions/moderation';
+import snackbar from 'soapbox/actions/snackbar';
+import Avatar from 'soapbox/components/avatar';
+import { Button } from 'soapbox/components/ui';
+import DropdownMenu from 'soapbox/containers/dropdown_menu_container';
+import Accordion from 'soapbox/features/ui/components/accordion';
+import { useAppDispatch } from 'soapbox/hooks';
+
+import ReportStatus from './report_status';
+
+import type { Map as ImmutableMap, List as ImmutableList } from 'immutable';
+import type { Status } from 'soapbox/types/entities';
+
+const messages = defineMessages({
+ reportClosed: { id: 'admin.reports.report_closed_message', defaultMessage: 'Report on @{name} was closed' },
+ deactivateUser: { id: 'admin.users.actions.deactivate_user', defaultMessage: 'Deactivate @{name}' },
+ deleteUser: { id: 'admin.users.actions.delete_user', defaultMessage: 'Delete @{name}' },
+});
+
+interface IReport {
+ report: ImmutableMap;
+}
+
+const Report: React.FC = ({ report }) => {
+ const intl = useIntl();
+ const dispatch = useAppDispatch();
+
+ const [accordionExpanded, setAccordionExpanded] = useState(false);
+
+ const makeMenu = () => {
+ return [{
+ text: intl.formatMessage(messages.deactivateUser, { name: report.getIn(['account', 'username']) as string }),
+ action: handleDeactivateUser,
+ icon: require('@tabler/icons/icons/user-off.svg'),
+ }, {
+ text: intl.formatMessage(messages.deleteUser, { name: report.getIn(['account', 'username']) as string }),
+ action: handleDeleteUser,
+ icon: require('@tabler/icons/icons/user-minus.svg'),
+ }];
+ };
+
+ const handleCloseReport = () => {
+ dispatch(closeReports([report.get('id')])).then(() => {
+ const message = intl.formatMessage(messages.reportClosed, { name: report.getIn(['account', 'username']) as string });
+ dispatch(snackbar.success(message));
+ }).catch(() => {});
+ };
+
+ const handleDeactivateUser = () => {
+ const accountId = report.getIn(['account', 'id']);
+ dispatch(deactivateUserModal(intl, accountId, () => handleCloseReport()));
+ };
+
+ const handleDeleteUser = () => {
+ const accountId = report.getIn(['account', 'id']) as string;
+ dispatch(deleteUserModal(intl, accountId, () => handleCloseReport()));
+ };
+
+ const handleAccordionToggle = (setting: boolean) => {
+ setAccordionExpanded(setting);
+ };
+
+ const menu = makeMenu();
+ const statuses = report.get('statuses') as ImmutableList;
+ const statusCount = statuses.count();
+ const acct = report.getIn(['account', 'acct']) as string;
+ const reporterAcct = report.getIn(['actor', 'acct']) as string;
+
+ return (
+
+
+
+
+ @{acct} }}
+ />
+
+
+ {statusCount > 0 && (
+
+ {statuses.map(status => )}
+
+ )}
+
+
+ {report.get('content', '').length > 0 &&
+
+ }
+
— @{reporterAcct}
+
+
+
+
+
+
+
+
+ );
+};
+
+export default Report;