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);