From ac8cf987d39a5c07cb7bb2e71d1aa36fbed69af1 Mon Sep 17 00:00:00 2001
From: Dhruwang Jariwala <67850763+Dhruwang@users.noreply.github.com>
Date: Fri, 10 Nov 2023 22:44:33 +0530
Subject: [PATCH] feat: Ttc on welcome card (#1461)
Co-authored-by: Johannes <72809645+jobenjada@users.noreply.github.com>
---
.../edit/components/EditWelcomeCard.tsx | 4 +-
.../surveys/templates/templates.ts | 2 +-
.../surveys/src/components/ProgressBar.tsx | 26 ++-------
packages/surveys/src/components/Survey.tsx | 1 +
.../surveys/src/components/WelcomeCard.tsx | 56 ++++++++++++++++++-
packages/surveys/src/lib/logicEvaluator.ts | 1 -
packages/surveys/src/lib/utils.ts | 24 ++++++++
packages/types/surveys.ts | 2 +-
8 files changed, 89 insertions(+), 27 deletions(-)
diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/components/EditWelcomeCard.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/components/EditWelcomeCard.tsx
index 36c6f064e1..f2e7083161 100644
--- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/components/EditWelcomeCard.tsx
+++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/components/EditWelcomeCard.tsx
@@ -157,7 +157,7 @@ export default function EditWelcomeCard({
- {/*
diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/templates/templates.ts b/apps/web/app/(app)/environments/[environmentId]/surveys/templates/templates.ts
index e1a155982a..5a25830bb3 100644
--- a/apps/web/app/(app)/environments/[environmentId]/surveys/templates/templates.ts
+++ b/apps/web/app/(app)/environments/[environmentId]/surveys/templates/templates.ts
@@ -18,7 +18,7 @@ const welcomeCardDefault: TSurveyWelcomeCard = {
enabled: false,
headline: "Welcome!",
html: "Thanks for providing your feedback - let's go!",
- timeToFinish: false,
+ timeToFinish: true,
};
export const templates: TTemplate[] = [
diff --git a/packages/surveys/src/components/ProgressBar.tsx b/packages/surveys/src/components/ProgressBar.tsx
index 25e1d05d77..64c64bcf0e 100644
--- a/packages/surveys/src/components/ProgressBar.tsx
+++ b/packages/surveys/src/components/ProgressBar.tsx
@@ -1,6 +1,7 @@
import { TSurveyWithTriggers } from "@formbricks/types/js";
import { useEffect, useState } from "preact/hooks";
import Progress from "./Progress";
+import { calculateElementIdx } from "../lib/utils";
interface ProgressBarProps {
survey: TSurveyWithTriggers;
@@ -13,6 +14,7 @@ const PROGRESS_INCREMENT = 0.1;
export default function ProgressBar({ survey, questionId, brandColor }: ProgressBarProps) {
const [progress, setProgress] = useState(0); // [0, 1]
const [prevQuestionIdx, setPrevQuestionIdx] = useState(0); // [0, survey.questions.length
+ const [prevQuestionId, setPrevQuestionId] = useState(""); // [0, survey.questions.length
useEffect(() => {
// calculate progress
@@ -20,28 +22,10 @@ export default function ProgressBar({ survey, questionId, brandColor }: Progress
function calculateProgress(questionId: string, survey: TSurveyWithTriggers, progress: number) {
if (survey.questions.length === 0) return 0;
if (questionId === "end") return 1;
-
let currentQustionIdx = survey.questions.findIndex((e) => e.id === questionId);
- if (progress > 0 && currentQustionIdx === prevQuestionIdx) return progress;
+ if (progress > 0 && questionId === prevQuestionId) return progress;
if (currentQustionIdx === -1) currentQustionIdx = 0;
- const currentQuestion = survey.questions[currentQustionIdx];
- const surveyLength = survey.questions.length;
- const middleIdx = Math.floor(surveyLength / 2);
- const possibleNextQuestions = currentQuestion.logic?.map((l) => l.destination) || [];
-
- const getLastQuestionIndex = () => {
- const lastQuestion = survey.questions
- .filter((q) => possibleNextQuestions.includes(q.id))
- .sort((a, b) => survey.questions.indexOf(a) - survey.questions.indexOf(b))
- .pop();
- return survey.questions.findIndex((e) => e.id === lastQuestion?.id);
- };
-
- let elementIdx = currentQustionIdx || 0.5;
- const lastprevQuestionIdx = getLastQuestionIndex();
-
- if (lastprevQuestionIdx > 0) elementIdx = Math.min(middleIdx, lastprevQuestionIdx - 1);
- if (possibleNextQuestions.includes("end")) elementIdx = middleIdx;
+ const elementIdx = calculateElementIdx(survey, currentQustionIdx);
const newProgress = elementIdx / survey.questions.length;
@@ -57,7 +41,7 @@ export default function ProgressBar({ survey, questionId, brandColor }: Progress
} else if (newProgress <= progress && progress + PROGRESS_INCREMENT <= 1) {
updatedProgress = progress + PROGRESS_INCREMENT;
}
-
+ setPrevQuestionId(questionId);
setPrevQuestionIdx(currentQustionIdx);
return updatedProgress;
}
diff --git a/packages/surveys/src/components/Survey.tsx b/packages/surveys/src/components/Survey.tsx
index f83ed04fbd..f3ef345c19 100644
--- a/packages/surveys/src/components/Survey.tsx
+++ b/packages/surveys/src/components/Survey.tsx
@@ -131,6 +131,7 @@ export function Survey({
timeToFinish={survey.welcomeCard.timeToFinish}
brandColor={brandColor}
onSubmit={onSubmit}
+ survey={survey}
/>
);
} else if (questionId === "end" && survey.thankYouCard.enabled) {
diff --git a/packages/surveys/src/components/WelcomeCard.tsx b/packages/surveys/src/components/WelcomeCard.tsx
index 83ac7e5c82..321347d57c 100644
--- a/packages/surveys/src/components/WelcomeCard.tsx
+++ b/packages/surveys/src/components/WelcomeCard.tsx
@@ -1,6 +1,8 @@
import Headline from "./Headline";
import HtmlBody from "./HtmlBody";
import SubmitButton from "./SubmitButton";
+import { calculateElementIdx } from "../lib/utils";
+import { TSurveyWithTriggers } from "@formbricks/types/js";
interface WelcomeCardProps {
headline?: string;
@@ -10,8 +12,26 @@ interface WelcomeCardProps {
timeToFinish?: boolean;
brandColor: string;
onSubmit: (data: { [x: string]: any }) => void;
+ survey: TSurveyWithTriggers;
}
+const TimerIcon = () => {
+ return (
+
+ );
+};
+
export default function WelcomeCard({
headline,
html,
@@ -20,7 +40,36 @@ export default function WelcomeCard({
timeToFinish,
brandColor,
onSubmit,
+ survey,
}: WelcomeCardProps) {
+ const calculateTimeToComplete = () => {
+ let idx = calculateElementIdx(survey, 0);
+ if (idx === 0.5) {
+ idx = 1;
+ }
+ const timeInSeconds = (survey.questions.length / idx) * 15; //15 seconds per question.
+ if (timeInSeconds > 360) {
+ // If it's more than 6 minutes
+ return "6+ minutes";
+ }
+ // Calculate minutes, if there are any seconds left, add a minute
+ const minutes = Math.floor(timeInSeconds / 60);
+ const remainingSeconds = timeInSeconds % 60;
+
+ if (remainingSeconds > 0) {
+ // If there are any seconds left, we'll need to round up to the next minute
+ if (minutes === 0) {
+ // If less than 1 minute, return 'less than 1 minute'
+ return "less than 1 minute";
+ } else {
+ // If more than 1 minute, return 'less than X minutes', where X is minutes + 1
+ return `less than ${minutes + 1} minutes`;
+ }
+ }
+ // If there are no remaining seconds, just return the number of minutes
+ return `${minutes} minutes`;
+ };
+
return (
{fileUrl && (
@@ -46,7 +95,12 @@ export default function WelcomeCard({
Press Enter ↵
- {timeToFinish && <>>}
+ {timeToFinish && (
+
+
+
Takes {calculateTimeToComplete()}
+
+ )}
);
}
diff --git a/packages/surveys/src/lib/logicEvaluator.ts b/packages/surveys/src/lib/logicEvaluator.ts
index 85c4c90af8..f6cd083924 100644
--- a/packages/surveys/src/lib/logicEvaluator.ts
+++ b/packages/surveys/src/lib/logicEvaluator.ts
@@ -47,7 +47,6 @@ export function evaluateCondition(logic: TSurveyLogic, responseValue: any): bool
(Array.isArray(responseValue) && responseValue.length === 0) ||
responseValue === "" ||
responseValue === null ||
- responseValue === undefined ||
responseValue === "dismissed"
);
default:
diff --git a/packages/surveys/src/lib/utils.ts b/packages/surveys/src/lib/utils.ts
index 9f606ad95d..d513134b4f 100644
--- a/packages/surveys/src/lib/utils.ts
+++ b/packages/surveys/src/lib/utils.ts
@@ -1,3 +1,5 @@
+import { TSurveyWithTriggers } from "@formbricks/types/js";
+
export const cn = (...classes: string[]) => {
return classes.filter(Boolean).join(" ");
};
@@ -45,3 +47,25 @@ export const shuffleQuestions = (array: any[], shuffleOption: string) => {
return arrayCopy;
};
+
+export const calculateElementIdx = (survey: TSurveyWithTriggers, currentQustionIdx: number): number => {
+ const currentQuestion = survey.questions[currentQustionIdx];
+ const surveyLength = survey.questions.length;
+ const middleIdx = Math.floor(surveyLength / 2);
+ const possibleNextQuestions = currentQuestion?.logic?.map((l) => l.destination) || [];
+
+ const getLastQuestionIndex = () => {
+ const lastQuestion = survey.questions
+ .filter((q) => possibleNextQuestions.includes(q.id))
+ .sort((a, b) => survey.questions.indexOf(a) - survey.questions.indexOf(b))
+ .pop();
+ return survey.questions.findIndex((e) => e.id === lastQuestion?.id);
+ };
+
+ let elementIdx = currentQustionIdx || 0.5;
+ const lastprevQuestionIdx = getLastQuestionIndex();
+
+ if (lastprevQuestionIdx > 0) elementIdx = Math.min(middleIdx, lastprevQuestionIdx - 1);
+ if (possibleNextQuestions.includes("end")) elementIdx = middleIdx;
+ return elementIdx;
+};
diff --git a/packages/types/surveys.ts b/packages/types/surveys.ts
index 1b5420dd51..2447d146b4 100644
--- a/packages/types/surveys.ts
+++ b/packages/types/surveys.ts
@@ -25,7 +25,7 @@ export const ZSurveyWelcomeCard = z.object({
html: z.string().optional(),
fileUrl: z.string().optional(),
buttonLabel: z.string().optional(),
- timeToFinish: z.boolean().default(false),
+ timeToFinish: z.boolean().default(true),
});
export const ZSurveyHiddenFields = z.object({