Commit dc28dff6 authored by Max Alekseenko's avatar Max Alekseenko

add mixpanel events

parent 64e52b9e
......@@ -20,6 +20,7 @@ export enum EventTypes {
FILTERS = 'Filters',
BUTTON_CLICK = 'Button click',
PROMO_BANNER = 'Promo banner',
APP_FEEDBACK = 'App feedback',
}
/* eslint-disable @typescript-eslint/indent */
......@@ -135,5 +136,11 @@ Type extends EventTypes.PROMO_BANNER ? {
'Source': 'Marketplace';
'Link': string;
} :
Type extends EventTypes.APP_FEEDBACK ? {
'Action': 'Rating';
'Source': 'Discovery' | 'App modal' | 'App page';
'AppId': string;
'Score': number;
} :
undefined;
/* eslint-enable @typescript-eslint/indent */
......@@ -5,6 +5,7 @@ import React, { useCallback } from 'react';
import type { MarketplaceAppWithSecurityReport, ContractListTypes } from 'types/client/marketplace';
import useIsMobile from 'lib/hooks/useIsMobile';
import type { EventTypes, EventPayload } from 'lib/mixpanel/index';
import IconSvg from 'ui/shared/IconSvg';
import AppSecurityReport from './AppSecurityReport';
......@@ -21,7 +22,7 @@ interface Props extends MarketplaceAppWithSecurityReport {
className?: string;
showContractList: (id: string, type: ContractListTypes) => void;
userRating: number | undefined;
rateApp: (appId: string, recordId: string | undefined, rating: number) => void;
rateApp: (appId: string, recordId: string | undefined, rating: number, source: EventPayload<EventTypes.APP_FEEDBACK>['Source']) => void;
isSendingRating: boolean;
isRatingLoading: boolean;
canRate: boolean | undefined;
......@@ -180,6 +181,7 @@ const MarketplaceAppCard = ({
isSending={ isSendingRating }
isLoading={ isRatingLoading }
canRate={ canRate }
source="Discovery"
/>
<IconButton
aria-label="Mark as favorite"
......
......@@ -10,6 +10,7 @@ import { ContractListTypes } from 'types/client/marketplace';
import config from 'configs/app';
import useIsMobile from 'lib/hooks/useIsMobile';
import { nbsp } from 'lib/html-entities';
import type { EventTypes, EventPayload } from 'lib/mixpanel/index';
import * as mixpanel from 'lib/mixpanel/index';
import type { IconName } from 'ui/shared/IconSvg';
import IconSvg from 'ui/shared/IconSvg';
......@@ -28,7 +29,7 @@ type Props = {
data: MarketplaceAppWithSecurityReport;
showContractList: (id: string, type: ContractListTypes, hasPreviousStep: boolean) => void;
userRating: number | undefined;
rateApp: (appId: string, recordId: string | undefined, rating: number) => void;
rateApp: (appId: string, recordId: string | undefined, rating: number, source: EventPayload<EventTypes.APP_FEEDBACK>['Source']) => void;
isSendingRating: boolean;
isRatingLoading: boolean;
canRate: boolean | undefined;
......@@ -181,6 +182,7 @@ const MarketplaceAppModal = ({
isLoading={ isRatingLoading }
fullView
canRate={ canRate }
source="App modal"
/>
</Box>
) }
......
......@@ -96,6 +96,7 @@ const MarketplaceAppTopBar = ({ appId, data, isLoading, securityReport }: Props)
isSending={ isSendingRating }
isLoading={ isRatingLoading }
canRate={ canRate }
source="App page"
/>
{ !isMobile && (
<Flex flex="1" justifyContent="flex-end">
......
......@@ -4,6 +4,7 @@ import type { MouseEvent } from 'react';
import type { MarketplaceAppWithSecurityReport, ContractListTypes, UserRatings } from 'types/client/marketplace';
import type { EventTypes, EventPayload } from 'lib/mixpanel/index';
import * as mixpanel from 'lib/mixpanel/index';
import EmptySearchResult from './EmptySearchResult';
......@@ -19,7 +20,7 @@ type Props = {
onAppClick: (event: MouseEvent, id: string) => void;
showContractList: (id: string, type: ContractListTypes) => void;
userRatings: UserRatings;
rateApp: (appId: string, recordId: string, rating: number) => void;
rateApp: (appId: string, recordId: string, rating: number, source: EventPayload<EventTypes.APP_FEEDBACK>['Source']) => void;
isSendingRating: boolean;
isRatingLoading: boolean;
canRate: boolean | undefined;
......
......@@ -2,6 +2,7 @@ import { Text, Flex, Spinner, Button } from '@chakra-ui/react';
import React from 'react';
import { mdash } from 'lib/html-entities';
import type { EventTypes, EventPayload } from 'lib/mixpanel/index';
import IconSvg from 'ui/shared/IconSvg';
import Stars from './Stars';
......@@ -12,11 +13,12 @@ type Props = {
appId: string;
recordId?: string;
userRating: number | undefined;
rate: (appId: string, recordId: string | undefined, rating: number) => void;
rate: (appId: string, recordId: string | undefined, rating: number, source: EventPayload<EventTypes.APP_FEEDBACK>['Source']) => void;
isSending?: boolean;
source: EventPayload<EventTypes.APP_FEEDBACK>['Source'];
};
const PopoverContent = ({ appId, recordId, userRating, rate, isSending }: Props) => {
const PopoverContent = ({ appId, recordId, userRating, rate, isSending, source }: Props) => {
const [ hovered, setHovered ] = React.useState(-1);
const [ selected, setSelected ] = React.useState(-1);
......@@ -36,8 +38,8 @@ const PopoverContent = ({ appId, recordId, userRating, rate, isSending }: Props)
if (selected < 0) {
return;
}
rate(appId, recordId, selected + 1);
}, [ appId, recordId, selected, rate ]);
rate(appId, recordId, selected + 1, source);
}, [ appId, recordId, selected, rate, source ]);
if (userRating) {
return (
......
......@@ -2,6 +2,7 @@ import { Text, PopoverTrigger, PopoverBody, PopoverContent, useDisclosure, Skele
import React from 'react';
import config from 'configs/app';
import type { EventTypes, EventPayload } from 'lib/mixpanel/index';
import Popover from 'ui/shared/chakra/Popover';
import Content from './PopoverContent';
......@@ -16,16 +17,17 @@ type Props = {
rating?: number;
recordId?: string;
userRating: number | undefined;
rate: (appId: string, recordId: string | undefined, rating: number) => void;
rate: (appId: string, recordId: string | undefined, rating: number, source: EventPayload<EventTypes.APP_FEEDBACK>['Source']) => void;
isSending?: boolean;
isLoading?: boolean;
fullView?: boolean;
canRate: boolean | undefined;
source: EventPayload<EventTypes.APP_FEEDBACK>['Source'];
};
const Rating = ({
appId, rating, recordId, userRating, rate,
isSending, isLoading, fullView, canRate,
isSending, isLoading, fullView, canRate, source,
}: Props) => {
const { isOpen, onToggle, onClose } = useDisclosure();
// have to implement this solution because popover loses focus on button click inside it (issue: https://github.com/chakra-ui/chakra-ui/issues/7359)
......@@ -68,6 +70,7 @@ const Rating = ({
userRating={ userRating }
rate={ rate }
isSending={ isSending }
source={ source }
/>
</PopoverBody>
</PopoverContent>
......
......@@ -7,6 +7,8 @@ import type { UserRatings, AppRatings } from 'types/client/marketplace';
import config from 'configs/app';
import useApiQuery from 'lib/api/useApiQuery';
import useToast from 'lib/hooks/useToast';
import type { EventTypes, EventPayload } from 'lib/mixpanel/index';
import * as mixpanel from 'lib/mixpanel/index';
import { ADDRESS_COUNTERS } from 'stubs/address';
const feature = config.features.marketplace;
......@@ -89,7 +91,12 @@ export default function useRatings() {
setCanRate(canRate);
}, [ address, addressCountersQuery ]);
const rateApp = useCallback(async(appId: string, recordId: string | undefined, rating: number) => {
const rateApp = useCallback(async(
appId: string,
recordId: string | undefined,
rating: number,
source: EventPayload<EventTypes.APP_FEEDBACK>['Source'],
) => {
setIsSending(true);
try {
if (!address || !base) {
......@@ -119,6 +126,10 @@ export default function useRatings() {
description: 'Your rating improves the service',
});
fetchRatings();
mixpanel.logEvent(
mixpanel.EventTypes.APP_FEEDBACK,
{ Action: 'Rating', Source: source, AppId: appId, Score: rating },
);
} catch (error) {
toast({
status: 'error',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment