Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Allow "Take Now" to start when respondent is not explicitly assigned (M2-7796) #536

Merged
merged 5 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions src/features/PassSurvey/hooks/useStartSurvey.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ActivityStatus, EntityType } from '~/abstract/lib/GroupBuilder';
import { EntityType } from '~/abstract/lib/GroupBuilder';
import { appletModel } from '~/entities/applet';
import { AppletBaseDTO } from '~/shared/api';
import ROUTES from '~/shared/constants/routes';
Expand All @@ -23,21 +23,19 @@ type OnActivityCardClickProps = {
eventId: string;
targetSubjectId: string | null;
flowId: string | null;
status: ActivityStatus;
shouldRestart: boolean;
};

type Props = {
applet: AppletBaseDTO;
applet?: AppletBaseDTO;
isPublic: boolean;
publicAppletKey: string | null;
};

export const useStartSurvey = (props: Props) => {
const navigator = useCustomNavigation();

const appletId = props.applet.id;
const flows = props.applet.activityFlows;
const appletId = props.applet?.id;
const flows = props.applet?.activityFlows;

const { removeGroupProgress } = appletModel.hooks.useGroupProgressStateManager();

Expand All @@ -47,6 +45,10 @@ export const useStartSurvey = (props: Props) => {
appletModel.hooks.useMultiInformantState();

function navigateToEntity(params: NavigateToEntityProps) {
if (!appletId) {
return;
}

const { activityId, flowId, eventId, targetSubjectId, entityType } = params;

if (props.isPublic && props.publicAppletKey) {
Expand Down Expand Up @@ -82,7 +84,7 @@ export const useStartSurvey = (props: Props) => {
shouldRestart,
}: OnActivityCardClickProps) {
const analyticsPayload: MixpanelPayload = {
[MixpanelProps.AppletId]: props.applet.id,
[MixpanelProps.AppletId]: appletId,
[MixpanelProps.ActivityId]: activityId,
};

Expand All @@ -102,7 +104,7 @@ export const useStartSurvey = (props: Props) => {
Mixpanel.track(MixpanelEvents.AssessmentStarted, analyticsPayload);

if (flowId) {
const flow = flows.find((x) => x.id === flowId);
const flow = flows?.find((x) => x.id === flowId);
const firstActivityId: string | null = flow?.activityIds[0] ?? null;

if (!firstActivityId) {
Expand Down
80 changes: 80 additions & 0 deletions src/widgets/ActivityGroups/model/hooks/useTakeNowRedirect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { useMemo } from 'react';

import { openStoreLink } from '~/abstract/lib';
import { isSupportedActivity } from '~/entities/activity';
import { useStartSurvey } from '~/features/PassSurvey';
import { AppletBaseDTO, AppletEventsResponse, HydratedAssignmentDTO } from '~/shared/api';

export function useTakeNowRedirect({
activityOrFlowId,
applet,
assignments = [],
events = [],
isPublic = false,
publicAppletKey = null,
}: {
activityOrFlowId?: string | null;
applet?: AppletBaseDTO;
assignments?: HydratedAssignmentDTO[] | null;
events?: AppletEventsResponse['events'];
isPublic?: boolean;
publicAppletKey?: string | null;
}) {
const { startSurvey } = useStartSurvey({ applet, isPublic, publicAppletKey });

const handleTakeNowRedirect = useMemo(
() =>
({
activityId,
eventId,
flowId = null,
isSupported = true,
}: {
activityId: string;
eventId: string;
flowId?: string | null;
isSupported?: boolean;
}) => {
if (!isSupported) {
openStoreLink();
return;
}

startSurvey({ activityId, eventId, flowId, shouldRestart: true, targetSubjectId: null });
},
[startSurvey],
);

if (assignments && applet && events && activityOrFlowId) {
const activity = applet.activities.find(({ id }) => id === activityOrFlowId);
const flow = applet.activityFlows.find(({ id }) => id === activityOrFlowId);
const event = events.find(({ entityId }) => entityId === (activity?.id || flow?.id));

if (!event) {
return;
}

if (activity) {
return handleTakeNowRedirect({
activityId: activity.id,
isSupported: isSupportedActivity(activity.containsResponseTypes),
eventId: event.id,
});
}

if (flow) {
const flowActivities = flow.activityIds.map((activityId) =>
applet.activities.find(({ id }) => activityId === id),
);

return handleTakeNowRedirect({
activityId: flow.activityIds[0],
isSupported: flowActivities.every(
(activity) => !!activity && isSupportedActivity(activity.containsResponseTypes),
),
eventId: event.id,
flowId: flow.id,
});
}
}
}
20 changes: 0 additions & 20 deletions src/widgets/ActivityGroups/ui/ActivityCard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import {
useAppSelector,
useCustomMediaQuery,
MixpanelPayload,
useOnceLayoutEffect,
} from '~/shared/utils';
import { TargetSubjectLabel } from '~/widgets/TargetSubjectLabel';

Expand Down Expand Up @@ -107,7 +106,6 @@ export const ActivityCard = ({ activityListItem }: Props) => {
activityId: activityListItem.activityId,
eventId: activityListItem.eventId,
targetSubjectId: activityListItem.targetSubject?.id ?? null,
status: activityListItem.status,
flowId: activityListItem.flowId,
shouldRestart,
});
Expand Down Expand Up @@ -143,24 +141,6 @@ export const ActivityCard = ({ activityListItem }: Props) => {
Mixpanel.track(MixpanelEvents.ActivityResumed, analyticsPayload);
};

// Start activity on mount if doing Take Now on this activity.
useOnceLayoutEffect(() => {
if (
context.startActivityOrFlow &&
// TODO: This `!activityListItem.targetSubject` check is added to ensure that Take Now is
// only triggered once, on the singular self-report instance of ActivityCard. However, this
// causes Take Now to fail when there is no self-report card, which is a possible scenario
// with the introduction of MI assignments. Remove this check when Take Now is refactored in
// https://mindlogger.atlassian.net/browse/M2-7796
!activityListItem.targetSubject &&
((!isFlow && context.startActivityOrFlow === activityListItem.activityId) ||
(isFlow && context.startActivityOrFlow === activityListItem.flowId))
) {
// Pass `true` to ensure activity doesn't resume from a previous progress state.
onStartActivity(true);
}
});

return (
<ActivityCardBase isDisabled={isDisabled} isFlow={isFlow}>
<Box
Expand Down
21 changes: 17 additions & 4 deletions src/widgets/ActivityGroups/ui/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useLocation, useNavigate } from 'react-router-dom';

import { ActivityGroupList } from './ActivityGroupList';
import { AppletDetailsContext } from '../lib';
import { useTakeNowRedirect } from '../model/hooks/useTakeNowRedirect';

import { appletModel, useAppletBaseInfoByIdQuery } from '~/entities/applet';
import { useMyAssignmentsQuery } from '~/entities/assignment';
Expand All @@ -20,17 +21,20 @@ type PublicAppletDetails = {
isPublic: true;
startActivityOrFlow?: string | null;
publicAppletKey: string;
appletId?: undefined;
};

type PrivateAppletDetails = {
isPublic: false;
startActivityOrFlow?: string | null;
appletId: string;
publicAppletKey?: undefined;
};

type Props = PublicAppletDetails | PrivateAppletDetails;

export const ActivityGroups = (props: Props) => {
const { appletId, isPublic, publicAppletKey, startActivityOrFlow } = props;
const { t } = useCustomTranslation();
const navigate = useNavigate();
const location = useLocation();
Expand All @@ -39,8 +43,7 @@ export const ActivityGroups = (props: Props) => {
isOpen: false,
});
const { featureFlag } = useFeatureFlags();
const isAssignmentsEnabled =
featureFlag(FeatureFlag.EnableActivityAssign, false) && !props.isPublic;
const isAssignmentsEnabled = featureFlag(FeatureFlag.EnableActivityAssign, false) && !isPublic;

const {
isError: isAppletError,
Expand All @@ -60,7 +63,7 @@ export const ActivityGroups = (props: Props) => {
isError: isAssignmentsError,
isLoading: isAssignmentsLoading,
data: assignments = null,
} = useMyAssignmentsQuery(isAssignmentsEnabled ? props.appletId : undefined, {
} = useMyAssignmentsQuery(isAssignmentsEnabled ? appletId : undefined, {
select: (data) => data.data.result.assignments,
enabled: isAssignmentsEnabled,
});
Expand All @@ -74,7 +77,8 @@ export const ActivityGroups = (props: Props) => {

useOnceEffect(() => {
ensureMultiInformantStateExists();
if (isInMultiInformantFlow() && !props.startActivityOrFlow) {

if (isInMultiInformantFlow() && !startActivityOrFlow) {
resetMultiInformantState();
}

Expand All @@ -92,6 +96,15 @@ export const ActivityGroups = (props: Props) => {
}
});

useTakeNowRedirect({
activityOrFlowId: startActivityOrFlow,
applet,
assignments,
events: events?.events,
isPublic,
publicAppletKey,
});

if (isAppletLoading || isEventsLoading || (isAssignmentsEnabled && isAssignmentsLoading)) {
return <Loader />;
}
Expand Down
Loading