Skip to content

Commit

Permalink
feat(start-campaign-button): warn before starting campaign without su…
Browse files Browse the repository at this point in the history
…rvey responses (#1616)

* feat(start-campaign-button): initial interaction step query
  • Loading branch information
henryk1229 authored Sep 11, 2023
1 parent 740e865 commit 9bf1c57
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 16 deletions.
14 changes: 13 additions & 1 deletion libs/spoke-codegen/src/graphql/campaign-builder.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,19 @@ query GetCampaignScriptPreview($campaignId: String!) {
}
}

mutation EditCampaignMessagingService($campaignId: String!, $payload: CampaignInput!) {
query GetCampaignInteractionSteps($campaignId: String!) {
campaign(id: $campaignId) {
id
interactionSteps {
id
}
}
}

mutation EditCampaignMessagingService(
$campaignId: String!
$payload: CampaignInput!
) {
editCampaign(id: $campaignId, campaign: $payload) {
id
messagingServiceSid
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import Button from "@material-ui/core/Button";
import Dialog from "@material-ui/core/Dialog";
import DialogActions from "@material-ui/core/DialogActions";
import DialogContent from "@material-ui/core/DialogContent";
import DialogTitle from "@material-ui/core/DialogTitle";
import React from "react";

interface CampaignSurveyResponseWarningDialogProps {
open: boolean;
campaignId: string;
onConfirm: () => void;
onClose: () => void;
}

const CampaignSurveyResponseWarningDialog = ({
open,
campaignId,
onConfirm,
onClose
}: CampaignSurveyResponseWarningDialogProps) => {
return (
<Dialog open={open}>
<DialogTitle>
{`Heads up! Campaign ${campaignId} currently has no survey responses. Do you want to start this campaign anyway?`}
</DialogTitle>
<DialogContent>
<p>
For the best experience for you and your texters, we recommend adding
survey responses before starting this campaign!
</p>
Without survey responses, texters can only use{" "}
<a
href="https://docs.spokerewired.com/article/67-tags"
target="_blank"
rel="noopener noreferrer"
>
Tags
</a>{" "}
to log data on this campaign.
<p>
Tags do not prepopulate scripts for texters and are not scoped to a
single campaign. Canned responses prepopulate scripts but log no data
at all. (
<a
href="https://docs.spokerewired.com/article/125-survey-responses-vs-canned-responses"
target="_blank"
rel="noopener noreferrer"
>
Read more
</a>
)
</p>
</DialogContent>
<DialogActions>
{[
<Button key="save" variant="contained" onClick={onConfirm}>
Start this campaign
</Button>,
<Button
key="close"
variant="contained"
color="primary"
onClick={onClose}
>
Cancel
</Button>
]}
</DialogActions>
</Dialog>
);
};

export default CampaignSurveyResponseWarningDialog;
66 changes: 51 additions & 15 deletions src/containers/AdminCampaignEdit/components/StartCampaignButton.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import Button from "@material-ui/core/Button";
import Tooltip from "@material-ui/core/Tooltip";
import {
useGetCampaignInteractionStepsQuery,
useGetCampaignStatusQuery,
useStartCampaignMutation
} from "@spoke/spoke-codegen";
import React, { useCallback } from "react";
import React, { useCallback, useState } from "react";

import { useSpokeContext } from "../../../client/spoke-context";
import { useAuthzContext } from "../../AuthzProvider";
import CampaignSurveyResponseWarningDialog from "./CampaignSurveyResponseWarningDialog";

export interface StartCampaignButtonProps {
campaignId: string;
Expand All @@ -23,8 +25,15 @@ export const StartCampaignButton: React.FC<StartCampaignButtonProps> = (
const { data, loading } = useGetCampaignStatusQuery({
variables: { campaignId }
});
const { data: campaignStepsData } = useGetCampaignInteractionStepsQuery({
variables: { campaignId }
});
const [startCampaign] = useStartCampaignMutation();

// manage warning confirmation and confirmation dialog state
const [warningConfirmed, setWarningConfirmed] = useState<boolean>(false);
const [confirmDialogOpen, setConfirmDialogOpen] = useState<boolean>(false);

const requiresApproval =
!authz.isSuperadmin &&
(orgSettings?.startCampaignRequiresApproval ?? true) &&
Expand All @@ -38,11 +47,30 @@ export const StartCampaignButton: React.FC<StartCampaignButtonProps> = (

const tooltipText = requiresApproval ? "Superadmin approval required" : "";

const campaignInteractionSteps =
campaignStepsData?.campaign?.interactionSteps ?? [];

const campaignHasSurveyResponses = campaignInteractionSteps.length > 1;

const handleConfirmWarningAndStartCampaign = useCallback(() => {
setWarningConfirmed(true);
setConfirmDialogOpen(false);
startCampaign({ variables: { campaignId } });
}, [startCampaign, campaignId]);

const handleCloseDialog = () => {
setConfirmDialogOpen(false);
};

const handleClick = useCallback(() => {
if (disabled) return;

if (!campaignHasSurveyResponses && !warningConfirmed) {
return setConfirmDialogOpen(true);
}

startCampaign({ variables: { campaignId } });
}, [startCampaign, campaignId]);
}, [startCampaign, campaignId, campaignHasSurveyResponses, warningConfirmed]);

const startText = data?.campaign?.isStarted
? "Already started"
Expand All @@ -53,19 +81,27 @@ export const StartCampaignButton: React.FC<StartCampaignButtonProps> = (
: "Start this campaign";

return (
<Tooltip title={tooltipText} placement="top">
<span>
<Button
variant="contained"
color="primary"
style={{ width: 210 }}
disabled={disabled}
onClick={handleClick}
>
{startText}
</Button>
</span>
</Tooltip>
<>
<Tooltip title={tooltipText} placement="top">
<span>
<Button
variant="contained"
color="primary"
style={{ width: 210 }}
disabled={disabled}
onClick={handleClick}
>
{startText}
</Button>
</span>
</Tooltip>
<CampaignSurveyResponseWarningDialog
open={confirmDialogOpen}
campaignId={campaignId}
onConfirm={handleConfirmWarningAndStartCampaign}
onClose={handleCloseDialog}
/>
</>
);
};

Expand Down

0 comments on commit 9bf1c57

Please sign in to comment.