diff --git a/src/AppRouter.tsx b/src/AppRouter.tsx
index be93d3d..31846e4 100644
--- a/src/AppRouter.tsx
+++ b/src/AppRouter.tsx
@@ -24,6 +24,7 @@ import { Wallet } from "./pages/Wallet";
import { AccountMigration } from "./pages/AccountMigration";
import { SSODiscourse } from "./pages/SSODiscourse";
import { AcceptInvite } from "./pages/AcceptInvite";
+import { Metrics } from "./pages/Metrics";
// tslint:disable-next-line:no-any
const DefaultLayout = (props: any) => {
@@ -64,6 +65,7 @@ function AppRouter() {
+
diff --git a/src/pages/Metrics.tsx b/src/pages/Metrics.tsx
new file mode 100644
index 0000000..15ef143
--- /dev/null
+++ b/src/pages/Metrics.tsx
@@ -0,0 +1,73 @@
+import * as React from "react";
+import { connect, MapStateToProps } from "react-redux";
+import { Map } from "immutable";
+import { MemberId } from "@raha/api-shared/dist/models/identifiers";
+import { Operation } from "@raha/api-shared/dist/models/Operation";
+import { AppState } from "../store";
+import { Loading } from "../components/Loading";
+import { Member } from "../reducers/membersNew";
+
+interface OwnProps {}
+
+interface StateProps {
+ operations: Operation[];
+ members: Map;
+}
+
+type Props = OwnProps & StateProps;
+
+/**
+ * TODO this calculation should really be a cached (reselect?) connector.
+ * TODO date and duration parameters.
+ *
+ * Returns MAC, our "monthly active creators" metric which
+ * means the number of verified users who have created a
+ * public transaction within the last 30 days.
+ */
+function getMac(operations: Operation[], members: Map) {
+ const lastMonth = new Date();
+ lastMonth.setDate(lastMonth.getDate() - 30);
+ const memberIdSet = new Set();
+ for (let i = operations.length - 1; i >= 0; i--) {
+ const op = operations[i];
+ if (new Date(op.created_at) < lastMonth) {
+ break;
+ }
+ const member = members.get(op.creator_uid);
+ if (member && member.get("isVerified")) {
+ memberIdSet.add(op.creator_uid);
+ }
+ }
+ return memberIdSet.size;
+}
+
+// TODO improve styling, don't rely on h1/h2/h3, add graphs
+const MetricsView: React.StatelessComponent = props => {
+ const { members, operations } = props;
+ if (!operations || operations.length === 0) {
+ return ;
+ }
+ return (
+
+ MAC (Monthly Active Creators)
+
+ How many verified members have created at least one transaction in the
+ last 30 days?
+
+ {getMac(operations, members)}
+
+ );
+};
+
+const mapStateToProps: MapStateToProps<
+ StateProps,
+ OwnProps,
+ AppState
+> = state => {
+ return {
+ operations: state.operations,
+ members: state.membersNew.byMemberId
+ };
+};
+
+export const Metrics = connect(mapStateToProps)(MetricsView);