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({