import React, { useEffect } from 'react'; import Widget from 'App/mstore/types/widget'; import Funnel from 'App/mstore/types/funnel'; import cn from 'classnames'; import { observer } from 'mobx-react-lite'; import { NoContent, Icon } from 'UI'; import { Tag, Tooltip } from 'antd'; import { useModal } from 'App/components/Modal'; import { useStore } from '@/mstore'; import Filter from '@/mstore/types/filter'; import stl from './FunnelWidget.module.css'; import Funnelbar, { UxTFunnelBar } from './FunnelBar'; import { useTranslation } from 'react-i18next'; interface Props { metric?: Widget; isWidget?: boolean; data: { funnel: Funnel }; compData: { funnel: Funnel }; } function FunnelWidget(props: Props) { const { t } = useTranslation(); const { dashboardStore, searchStore } = useStore(); const [focusedFilter, setFocusedFilter] = React.useState(null); const { isWidget = false, data, metric, compData } = props; const funnel = data.funnel || { stages: [] }; const totalSteps = funnel.stages.length; const stages = isWidget ? [...funnel.stages.slice(0, 1), funnel.stages[funnel.stages.length - 1]] : funnel.stages; const hasMoreSteps = funnel.stages.length > 2; const lastStage = funnel.stages[funnel.stages.length - 1]; const remainingSteps = totalSteps - 2; const { hideModal } = useModal(); const metricLabel = metric?.metricFormat == 'userCount' ? t('Users') : t('Sessions'); const { drillDownFilter } = dashboardStore; const { drillDownPeriod } = dashboardStore; const comparisonPeriod = metric ? dashboardStore.comparisonPeriods[metric.metricId] : undefined; const metricFilters = metric?.series[0]?.filter.filters || []; const applyDrillDown = (index: number, isComp?: boolean) => { const filter = new Filter().fromData({ filters: metricFilters.slice(0, index + 1), }); const periodTimestamps = isComp && index > -1 ? comparisonPeriod.toTimestamps() : drillDownPeriod.toTimestamps(); drillDownFilter.merge({ filters: filter.toJson().filters, startTimestamp: periodTimestamps.startTimestamp, endTimestamp: periodTimestamps.endTimestamp, }); }; useEffect( () => () => { if (isWidget) return; hideModal(); }, [], ); const focusStage = (index: number, isComp?: boolean) => { funnel.stages.forEach((s, i) => { // turning on all filters if one was focused already if (focusedFilter === index) { s.updateKey('isActive', true); setFocusedFilter(null); } else { setFocusedFilter(index); if (i === index) { s.updateKey('isActive', true); } else { s.updateKey('isActive', false); } } }); applyDrillDown(focusedFilter === index ? -1 : index, isComp); }; const shownStages = React.useMemo(() => { const stages: { data: Funnel['stages'][0]; compData?: Funnel['stages'][0]; }[] = []; for (let i = 0; i < funnel.stages.length; i++) { const stage: any = { data: funnel.stages[i], compData: undefined }; const compStage = compData?.funnel.stages[i]; if (compStage) { stage.compData = compStage; } stages.push(stage); } return stages; }, [data, compData]); const viewType = metric?.viewType; const isHorizontal = viewType === 'columnChart'; const noEvents = metric.series[0].filter.filters.length === 0; const isUsers = metric?.metricFormat === 'userCount'; return ( {noEvents ? t('Select an event to start seeing the funnel') : t('No data available for the selected period.')} } show={!stages || stages.length === 0} >
{!isWidget && shownStages.map((stage: any, index: any) => ( ))} {isWidget && ( <> {hasMoreSteps && } {funnel.stages.length > 1 && ( )} )}
{t('Total conversion')} {funnel.totalConversions}
{t('Lost conversion')} {funnel.lostConversions}
{funnel.totalDropDueToIssues > 0 && (
{' '} {funnel.totalDropDueToIssues}  {t('sessions dropped due to issues.')}
)}
); } export const EmptyStage = observer(({ total }: any) => (
{`+${total} ${total > 1 ? 'steps' : 'step'}`}
)); export const Stage = observer( ({ metricLabel, stage, index, uxt, focusStage, focusedFilter, compData, isHorizontal, }: any) => stage ? (
{!uxt ? ( ) : ( )}
) : null, ); export const IndexNumber = observer(({ index }: any) => (
{index === 0 ? : index}
)); export default observer(FunnelWidget);