mirror of
https://github.com/formbricks/formbricks.git
synced 2025-12-30 10:19:51 -06:00
fix: Check for complete submission before displaying CTA on Thank You… (#1979)
Co-authored-by: Matthias Nannt <mail@matthiasnannt.com>
This commit is contained in:
committed by
GitHub
parent
21787f2af5
commit
8064e1ecf6
@@ -18,6 +18,7 @@ import ContentWrapper from "@formbricks/ui/ContentWrapper";
|
||||
import { SurveyInline } from "@formbricks/ui/Survey";
|
||||
|
||||
let setIsError = (_: boolean) => {};
|
||||
let setIsResponseSendingFinished = (_: boolean) => {};
|
||||
|
||||
interface LinkSurveyProps {
|
||||
survey: TSurvey;
|
||||
@@ -72,6 +73,10 @@ export default function LinkSurvey({
|
||||
onResponseSendingFailed: () => {
|
||||
setIsError(true);
|
||||
},
|
||||
onResponseSendingFinished: () => {
|
||||
// when response of current question is processed successfully
|
||||
setIsResponseSendingFinished(true);
|
||||
},
|
||||
setSurveyState: setSurveyState,
|
||||
},
|
||||
surveyState
|
||||
@@ -157,6 +162,9 @@ export default function LinkSurvey({
|
||||
getSetIsError={(f: (value: boolean) => void) => {
|
||||
setIsError = f;
|
||||
}}
|
||||
getSetIsResponseSendingFinished={(f: (value: boolean) => void) => {
|
||||
setIsResponseSendingFinished = f;
|
||||
}}
|
||||
onRetry={() => {
|
||||
setIsError(false);
|
||||
responseQueue.processQueue();
|
||||
|
||||
@@ -16,6 +16,7 @@ const logger = Logger.getInstance();
|
||||
const errorHandler = ErrorHandler.getInstance();
|
||||
let surveyRunning = false;
|
||||
let setIsError = (_: boolean) => {};
|
||||
let setIsResponseSendingFinished = (_: boolean) => {};
|
||||
|
||||
export const renderWidget = async (survey: TSurvey) => {
|
||||
if (surveyRunning) {
|
||||
@@ -40,6 +41,9 @@ export const renderWidget = async (survey: TSurvey) => {
|
||||
onResponseSendingFailed: () => {
|
||||
setIsError(true);
|
||||
},
|
||||
onResponseSendingFinished: () => {
|
||||
setIsResponseSendingFinished(true);
|
||||
},
|
||||
},
|
||||
surveyState
|
||||
);
|
||||
@@ -51,7 +55,6 @@ export const renderWidget = async (survey: TSurvey) => {
|
||||
const darkOverlay = productOverwrites.darkOverlay ?? product.darkOverlay;
|
||||
const placement = productOverwrites.placement ?? product.placement;
|
||||
const isBrandingEnabled = product.inAppSurveyBranding;
|
||||
|
||||
const formbricksSurveys = await loadFormbricksSurveysExternally();
|
||||
|
||||
setTimeout(() => {
|
||||
@@ -66,6 +69,9 @@ export const renderWidget = async (survey: TSurvey) => {
|
||||
getSetIsError: (f: (value: boolean) => void) => {
|
||||
setIsError = f;
|
||||
},
|
||||
getSetIsResponseSendingFinished: (f: (value: boolean) => void) => {
|
||||
setIsResponseSendingFinished = f;
|
||||
},
|
||||
onDisplay: async () => {
|
||||
const { userId } = config.get();
|
||||
// if config does not have a person, we store the displays in local storage
|
||||
|
||||
@@ -9,6 +9,7 @@ interface QueueConfig {
|
||||
environmentId: string;
|
||||
retryAttempts: number;
|
||||
onResponseSendingFailed?: (responseUpdate: TResponseUpdate) => void;
|
||||
onResponseSendingFinished?: () => void;
|
||||
setSurveyState?: (state: SurveyState) => void;
|
||||
}
|
||||
|
||||
@@ -68,6 +69,9 @@ export class ResponseQueue {
|
||||
}
|
||||
this.isRequestInProgress = false;
|
||||
} else {
|
||||
if (responseUpdate.finished && this.config.onResponseSendingFinished) {
|
||||
this.config.onResponseSendingFinished();
|
||||
}
|
||||
this.isRequestInProgress = false;
|
||||
this.processQueue(); // process the next item in the queue if any
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ export function Survey({
|
||||
isRedirectDisabled = false,
|
||||
prefillResponseData,
|
||||
getSetIsError,
|
||||
getSetIsResponseSendingFinished,
|
||||
onFileUpload,
|
||||
responseCount,
|
||||
}: SurveyBaseProps) {
|
||||
@@ -36,6 +37,9 @@ export function Survey({
|
||||
activeQuestionId || (survey.welcomeCard.enabled ? "start" : survey?.questions[0]?.id)
|
||||
);
|
||||
const [showError, setShowError] = useState(false);
|
||||
// flag state to store whether response processing has been completed or not
|
||||
const [isResponseSendingFinished, setIsResponseSendingFinished] = useState(false);
|
||||
|
||||
const [loadingElement, setLoadingElement] = useState(false);
|
||||
const [history, setHistory] = useState<string[]>([]);
|
||||
const [responseData, setResponseData] = useState<TResponseData>({});
|
||||
@@ -85,7 +89,15 @@ export function Survey({
|
||||
setShowError(value);
|
||||
});
|
||||
}
|
||||
});
|
||||
}, [getSetIsError]);
|
||||
|
||||
useEffect(() => {
|
||||
if (getSetIsResponseSendingFinished) {
|
||||
getSetIsResponseSendingFinished((value: boolean) => {
|
||||
setIsResponseSendingFinished(value);
|
||||
});
|
||||
}
|
||||
}, [getSetIsResponseSendingFinished]);
|
||||
|
||||
let currIdxTemp = currentQuestionIndex;
|
||||
let currQuesTemp = currentQuestion;
|
||||
@@ -216,6 +228,7 @@ export function Survey({
|
||||
} else if (questionId === "end" && survey.thankYouCard.enabled) {
|
||||
return (
|
||||
<ThankYouCard
|
||||
isResponseSendingFinished={isResponseSendingFinished}
|
||||
headline={
|
||||
typeof survey.thankYouCard.headline === "string"
|
||||
? replaceRecallInfo(survey.thankYouCard.headline)
|
||||
|
||||
@@ -15,6 +15,7 @@ export function SurveyModal({
|
||||
darkOverlay,
|
||||
highlightBorderColor,
|
||||
onDisplay,
|
||||
getSetIsResponseSendingFinished,
|
||||
onActiveQuestionChange,
|
||||
onResponse,
|
||||
onClose,
|
||||
@@ -49,6 +50,7 @@ export function SurveyModal({
|
||||
isBrandingEnabled={isBrandingEnabled}
|
||||
activeQuestionId={activeQuestionId}
|
||||
onDisplay={onDisplay}
|
||||
getSetIsResponseSendingFinished={getSetIsResponseSendingFinished}
|
||||
onActiveQuestionChange={onActiveQuestionChange}
|
||||
onResponse={onResponse}
|
||||
onClose={close}
|
||||
|
||||
@@ -13,6 +13,7 @@ interface ThankYouCardProps {
|
||||
buttonLabel?: string;
|
||||
buttonLink?: string;
|
||||
imageUrl?: string;
|
||||
isResponseSendingFinished: boolean;
|
||||
}
|
||||
|
||||
export default function ThankYouCard({
|
||||
@@ -23,9 +24,10 @@ export default function ThankYouCard({
|
||||
buttonLabel,
|
||||
buttonLink,
|
||||
imageUrl,
|
||||
isResponseSendingFinished,
|
||||
}: ThankYouCardProps) {
|
||||
useEffect(() => {
|
||||
if (!buttonLink) return;
|
||||
if (!buttonLink || !isResponseSendingFinished) return;
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
if (event.key === "Enter") {
|
||||
window.top?.location.replace(buttonLink);
|
||||
@@ -35,7 +37,7 @@ export default function ThankYouCard({
|
||||
return () => {
|
||||
window.removeEventListener("keydown", handleKeyDown);
|
||||
};
|
||||
}, [buttonLink]);
|
||||
}, [buttonLink, isResponseSendingFinished]);
|
||||
|
||||
return (
|
||||
<div className="text-center">
|
||||
@@ -66,7 +68,7 @@ export default function ThankYouCard({
|
||||
<Headline alignTextCenter={true} headline={headline} questionId="thankYouCard" />
|
||||
<Subheader subheader={subheader} questionId="thankYouCard" />
|
||||
<RedirectCountDown redirectUrl={redirectUrl} isRedirectDisabled={isRedirectDisabled} />
|
||||
{buttonLabel && (
|
||||
{buttonLabel && isResponseSendingFinished && (
|
||||
<div className="mt-6 flex w-full flex-col items-center justify-center space-y-4">
|
||||
<Button
|
||||
buttonLabel={buttonLabel}
|
||||
|
||||
@@ -7,6 +7,7 @@ export interface SurveyBaseProps {
|
||||
isBrandingEnabled: boolean;
|
||||
activeQuestionId?: string;
|
||||
getSetIsError?: (getSetError: (value: boolean) => void) => void;
|
||||
getSetIsResponseSendingFinished?: (getSetIsResponseSendingFinished: (value: boolean) => void) => void;
|
||||
onDisplay?: () => void;
|
||||
onResponse?: (response: TResponseUpdate) => void;
|
||||
onFinished?: () => void;
|
||||
|
||||
@@ -1,40 +1,11 @@
|
||||
import { useEffect, useMemo } from "react";
|
||||
|
||||
import { renderSurveyInline, renderSurveyModal } from "@formbricks/surveys";
|
||||
import { TResponseData, TResponseUpdate } from "@formbricks/types/responses";
|
||||
import { TUploadFileConfig } from "@formbricks/types/storage";
|
||||
import { TSurvey } from "@formbricks/types/surveys";
|
||||
import { SurveyInlineProps, SurveyModalProps } from "@formbricks/types/formbricksSurveys";
|
||||
|
||||
const createContainerId = () => `formbricks-survey-container`;
|
||||
|
||||
interface SurveyProps {
|
||||
survey: TSurvey;
|
||||
brandColor: string;
|
||||
isBrandingEnabled: boolean;
|
||||
activeQuestionId?: string;
|
||||
getSetIsError?: (getSetError: (value: boolean) => void) => void;
|
||||
onRetry?: () => void;
|
||||
onDisplay?: () => void;
|
||||
onResponse?: (response: TResponseUpdate) => void;
|
||||
onFinished?: () => void;
|
||||
onActiveQuestionChange?: (questionId: string) => void;
|
||||
onClose?: () => void;
|
||||
onFileUpload: (file: File, config?: TUploadFileConfig) => Promise<string>;
|
||||
autoFocus?: boolean;
|
||||
prefillResponseData?: TResponseData;
|
||||
isRedirectDisabled?: boolean;
|
||||
responseCount?: number;
|
||||
supportEmail?: string | null;
|
||||
}
|
||||
|
||||
interface SurveyModalProps extends SurveyProps {
|
||||
placement: "topRight" | "bottomRight" | "bottomLeft" | "topLeft" | "center";
|
||||
clickOutside: boolean;
|
||||
darkOverlay: boolean;
|
||||
highlightBorderColor: string | null;
|
||||
}
|
||||
|
||||
export const SurveyInline = (props: SurveyProps) => {
|
||||
export const SurveyInline = (props: Omit<SurveyInlineProps & { brandColor: string }, "containerId">) => {
|
||||
const containerId = useMemo(() => createContainerId(), []);
|
||||
useEffect(() => {
|
||||
renderSurveyInline({
|
||||
@@ -45,7 +16,7 @@ export const SurveyInline = (props: SurveyProps) => {
|
||||
return <div id={containerId} className="h-full w-full" />;
|
||||
};
|
||||
|
||||
export const SurveyModal = (props: SurveyModalProps) => {
|
||||
export const SurveyModal = (props: SurveyModalProps & { brandColor: string }) => {
|
||||
useEffect(() => {
|
||||
renderSurveyModal(props);
|
||||
}, [props]);
|
||||
|
||||
Reference in New Issue
Block a user