diff --git a/apps/formbricks-com/components/dummyUI/templates.ts b/apps/formbricks-com/components/dummyUI/templates.ts
index 8c9521db4c..702a4e49a0 100644
--- a/apps/formbricks-com/components/dummyUI/templates.ts
+++ b/apps/formbricks-com/components/dummyUI/templates.ts
@@ -22,9 +22,9 @@ import {
VideoTabletAdjustIcon,
} from "@formbricks/ui/icons";
-import { createId } from "@paralleldrive/cuid2";
-import { TTemplate } from "@formbricks/types/templates";
import { TSurveyQuestionType } from "@formbricks/types/surveys";
+import { TTemplate } from "@formbricks/types/templates";
+import { createId } from "@paralleldrive/cuid2";
const thankYouCardDefault = {
enabled: true,
@@ -32,6 +32,12 @@ const thankYouCardDefault = {
subheader: "We appreciate your feedback.",
};
+const welcomeCardDefault = {
+ enabled: true,
+ timeToFinish: false,
+ showResponseCount: false,
+};
+
export const customSurvey: TTemplate = {
name: "Start from scratch",
description: "Create a survey without template.",
@@ -51,10 +57,7 @@ export const customSurvey: TTemplate = {
},
],
thankYouCard: thankYouCardDefault,
- welcomeCard: {
- enabled: false,
- timeToFinish: false,
- },
+ welcomeCard: welcomeCardDefault,
hiddenFields: {
enabled: false,
},
@@ -150,10 +153,7 @@ export const templates: TTemplate[] = [
},
],
thankYouCard: thankYouCardDefault,
- welcomeCard: {
- enabled: false,
- timeToFinish: false,
- },
+ welcomeCard: welcomeCardDefault,
hiddenFields: {
enabled: false,
},
@@ -260,10 +260,7 @@ export const templates: TTemplate[] = [
},
],
thankYouCard: thankYouCardDefault,
- welcomeCard: {
- enabled: false,
- timeToFinish: false,
- },
+ welcomeCard: welcomeCardDefault,
hiddenFields: {
enabled: false,
},
@@ -340,10 +337,7 @@ export const templates: TTemplate[] = [
},
],
thankYouCard: thankYouCardDefault,
- welcomeCard: {
- enabled: false,
- timeToFinish: false,
- },
+ welcomeCard: welcomeCardDefault,
hiddenFields: {
enabled: false,
},
@@ -389,10 +383,7 @@ export const templates: TTemplate[] = [
},
],
thankYouCard: thankYouCardDefault,
- welcomeCard: {
- enabled: false,
- timeToFinish: false,
- },
+ welcomeCard: welcomeCardDefault,
hiddenFields: {
enabled: false,
},
@@ -447,10 +438,7 @@ export const templates: TTemplate[] = [
},
],
thankYouCard: thankYouCardDefault,
- welcomeCard: {
- enabled: false,
- timeToFinish: false,
- },
+ welcomeCard: welcomeCardDefault,
hiddenFields: {
enabled: false,
},
@@ -513,10 +501,7 @@ export const templates: TTemplate[] = [
},
],
thankYouCard: thankYouCardDefault,
- welcomeCard: {
- enabled: false,
- timeToFinish: false,
- },
+ welcomeCard: welcomeCardDefault,
hiddenFields: {
enabled: false,
},
@@ -582,10 +567,7 @@ export const templates: TTemplate[] = [
},
],
thankYouCard: thankYouCardDefault,
- welcomeCard: {
- enabled: false,
- timeToFinish: false,
- },
+ welcomeCard: welcomeCardDefault,
hiddenFields: {
enabled: false,
},
@@ -640,10 +622,7 @@ export const templates: TTemplate[] = [
},
],
thankYouCard: thankYouCardDefault,
- welcomeCard: {
- enabled: false,
- timeToFinish: false,
- },
+ welcomeCard: welcomeCardDefault,
hiddenFields: {
enabled: false,
},
@@ -685,10 +664,7 @@ export const templates: TTemplate[] = [
},
],
thankYouCard: thankYouCardDefault,
- welcomeCard: {
- enabled: false,
- timeToFinish: false,
- },
+ welcomeCard: welcomeCardDefault,
hiddenFields: {
enabled: false,
},
@@ -723,10 +699,7 @@ export const templates: TTemplate[] = [
},
],
thankYouCard: thankYouCardDefault,
- welcomeCard: {
- enabled: false,
- timeToFinish: false,
- },
+ welcomeCard: welcomeCardDefault,
hiddenFields: {
enabled: false,
},
@@ -752,10 +725,7 @@ export const templates: TTemplate[] = [
},
],
thankYouCard: thankYouCardDefault,
- welcomeCard: {
- enabled: false,
- timeToFinish: false,
- },
+ welcomeCard: welcomeCardDefault,
hiddenFields: {
enabled: false,
},
@@ -803,10 +773,7 @@ export const templates: TTemplate[] = [
},
],
thankYouCard: thankYouCardDefault,
- welcomeCard: {
- enabled: false,
- timeToFinish: false,
- },
+ welcomeCard: welcomeCardDefault,
hiddenFields: {
enabled: false,
},
@@ -848,10 +815,7 @@ export const templates: TTemplate[] = [
},
],
thankYouCard: thankYouCardDefault,
- welcomeCard: {
- enabled: false,
- timeToFinish: false,
- },
+ welcomeCard: welcomeCardDefault,
hiddenFields: {
enabled: false,
},
@@ -905,10 +869,7 @@ export const templates: TTemplate[] = [
},
],
thankYouCard: thankYouCardDefault,
- welcomeCard: {
- enabled: false,
- timeToFinish: false,
- },
+ welcomeCard: welcomeCardDefault,
hiddenFields: {
enabled: false,
},
@@ -961,10 +922,7 @@ export const templates: TTemplate[] = [
},
],
thankYouCard: thankYouCardDefault,
- welcomeCard: {
- enabled: false,
- timeToFinish: false,
- },
+ welcomeCard: welcomeCardDefault,
hiddenFields: {
enabled: false,
},
@@ -1013,10 +971,7 @@ export const templates: TTemplate[] = [
},
],
thankYouCard: thankYouCardDefault,
- welcomeCard: {
- enabled: false,
- timeToFinish: false,
- },
+ welcomeCard: welcomeCardDefault,
hiddenFields: {
enabled: false,
},
@@ -1043,10 +998,7 @@ export const templates: TTemplate[] = [
},
],
thankYouCard: thankYouCardDefault,
- welcomeCard: {
- enabled: false,
- timeToFinish: false,
- },
+ welcomeCard: welcomeCardDefault,
hiddenFields: {
enabled: false,
},
@@ -1071,10 +1023,7 @@ export const templates: TTemplate[] = [
},
],
thankYouCard: thankYouCardDefault,
- welcomeCard: {
- enabled: false,
- timeToFinish: false,
- },
+ welcomeCard: welcomeCardDefault,
hiddenFields: {
enabled: false,
},
@@ -1098,10 +1047,7 @@ export const templates: TTemplate[] = [
},
],
thankYouCard: thankYouCardDefault,
- welcomeCard: {
- enabled: false,
- timeToFinish: false,
- },
+ welcomeCard: welcomeCardDefault,
hiddenFields: {
enabled: false,
},
@@ -1142,10 +1088,7 @@ export const templates: TTemplate[] = [
},
],
thankYouCard: thankYouCardDefault,
- welcomeCard: {
- enabled: false,
- timeToFinish: false,
- },
+ welcomeCard: welcomeCardDefault,
hiddenFields: {
enabled: false,
},
@@ -1179,10 +1122,7 @@ export const templates: TTemplate[] = [
},
],
thankYouCard: thankYouCardDefault,
- welcomeCard: {
- enabled: false,
- timeToFinish: false,
- },
+ welcomeCard: welcomeCardDefault,
hiddenFields: {
enabled: false,
},
@@ -1216,10 +1156,7 @@ export const templates: TTemplate[] = [
},
],
thankYouCard: thankYouCardDefault,
- welcomeCard: {
- enabled: false,
- timeToFinish: false,
- },
+ welcomeCard: welcomeCardDefault,
hiddenFields: {
enabled: false,
},
@@ -1281,10 +1218,7 @@ export const templates: TTemplate[] = [
},
],
thankYouCard: thankYouCardDefault,
- welcomeCard: {
- enabled: false,
- timeToFinish: false,
- },
+ welcomeCard: welcomeCardDefault,
hiddenFields: {
enabled: false,
},
diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryMetadata.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryMetadata.tsx
index a384e18431..8c7be758c7 100644
--- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryMetadata.tsx
+++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryMetadata.tsx
@@ -73,8 +73,6 @@ export default function SummaryMetadata({
return ttc;
}, [responses]);
- console.log(ttc);
-
const totalResponses = responses.length;
return (
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 f2e7083161..709db8f861 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
@@ -177,6 +177,28 @@ export default function EditWelcomeCard({
+ {localSurvey?.type === "link" && (
+
+
+
+ updateSurvey({ showResponseCount: !localSurvey.welcomeCard.showResponseCount })
+ }
+ />
+
+
+
+
+ Display number of responses for survey
+
+
+
+ )}
diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/components/PreviewSurvey.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/components/PreviewSurvey.tsx
index fcb5b3c5ea..c22dfb45ea 100644
--- a/apps/web/app/(app)/environments/[environmentId]/surveys/components/PreviewSurvey.tsx
+++ b/apps/web/app/(app)/environments/[environmentId]/surveys/components/PreviewSurvey.tsx
@@ -3,11 +3,12 @@
import Modal from "@/app/(app)/environments/[environmentId]/surveys/components/Modal";
import TabOption from "@/app/(app)/environments/[environmentId]/surveys/components/TabOption";
-import { SurveyInline } from "@formbricks/ui/Survey";
import type { TEnvironment } from "@formbricks/types/environment";
import type { TProduct } from "@formbricks/types/product";
+import { TUploadFileConfig } from "@formbricks/types/storage";
import { TSurvey } from "@formbricks/types/surveys";
import { Button } from "@formbricks/ui/Button";
+import { SurveyInline } from "@formbricks/ui/Survey";
import { ArrowPathRoundedSquareIcon } from "@heroicons/react/24/outline";
import {
ArrowsPointingInIcon,
@@ -17,7 +18,6 @@ import {
} from "@heroicons/react/24/solid";
import { Variants, motion } from "framer-motion";
import { useEffect, useRef, useState } from "react";
-import { TUploadFileConfig } from "@formbricks/types/storage";
type TPreviewType = "modal" | "fullwidth" | "email";
@@ -226,6 +226,7 @@ export default function PreviewSurvey({
isBrandingEnabled={product.linkSurveyBranding}
onActiveQuestionChange={setActiveQuestionId}
onFileUpload={onFileUpload}
+ responseCount={42}
/>
@@ -297,6 +298,7 @@ export default function PreviewSurvey({
onActiveQuestionChange={setActiveQuestionId}
isRedirectDisabled={true}
onFileUpload={onFileUpload}
+ responseCount={42}
/>
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 589e65b9d9..272826db12 100644
--- a/apps/web/app/(app)/environments/[environmentId]/surveys/templates/templates.ts
+++ b/apps/web/app/(app)/environments/[environmentId]/surveys/templates/templates.ts
@@ -23,6 +23,7 @@ const welcomeCardDefault: TSurveyWelcomeCard = {
headline: "Welcome!",
html: "Thanks for providing your feedback - let's go!",
timeToFinish: true,
+ showResponseCount: false,
};
export const testTemplate: TTemplate = {
@@ -320,6 +321,7 @@ export const testTemplate: TTemplate = {
welcomeCard: {
enabled: false,
timeToFinish: false,
+ showResponseCount: false,
},
hiddenFields: {
enabled: false,
diff --git a/apps/web/app/api/v1/client/[environmentId]/in-app/sync/route.ts b/apps/web/app/api/v1/client/[environmentId]/in-app/sync/route.ts
index 4c8df57090..6df73b4e18 100644
--- a/apps/web/app/api/v1/client/[environmentId]/in-app/sync/route.ts
+++ b/apps/web/app/api/v1/client/[environmentId]/in-app/sync/route.ts
@@ -46,7 +46,6 @@ export async function GET(
getActionClasses(environmentId),
getProductByEnvironmentId(environmentId),
]);
-
if (!product) {
throw new Error("Product not found");
}
diff --git a/apps/web/app/s/[surveyId]/components/LinkSurvey.tsx b/apps/web/app/s/[surveyId]/components/LinkSurvey.tsx
index 3afb3c97fa..2a2288e973 100644
--- a/apps/web/app/s/[surveyId]/components/LinkSurvey.tsx
+++ b/apps/web/app/s/[surveyId]/components/LinkSurvey.tsx
@@ -25,6 +25,7 @@ interface LinkSurveyProps {
singleUseId?: string;
singleUseResponse?: TResponse;
webAppUrl: string;
+ responseCount?: number;
}
export default function LinkSurvey({
@@ -36,6 +37,7 @@ export default function LinkSurvey({
singleUseId,
singleUseResponse,
webAppUrl,
+ responseCount,
}: LinkSurveyProps) {
const responseId = singleUseResponse?.id;
const searchParams = useSearchParams();
@@ -187,6 +189,7 @@ export default function LinkSurvey({
activeQuestionId={activeQuestionId}
autoFocus={autoFocus}
prefillResponseData={prefillResponseData}
+ responseCount={responseCount}
/>
>
diff --git a/apps/web/app/s/[surveyId]/page.tsx b/apps/web/app/s/[surveyId]/page.tsx
index 10fa4cca4c..6c9fb08e3e 100644
--- a/apps/web/app/s/[surveyId]/page.tsx
+++ b/apps/web/app/s/[surveyId]/page.tsx
@@ -15,6 +15,7 @@ import type { Metadata } from "next";
import { notFound } from "next/navigation";
import { getEmailVerificationStatus } from "./lib/helpers";
import { ZId } from "@formbricks/types/environment";
+import { getResponseCountBySurveyId } from "@formbricks/lib/response/service";
interface LinkSurveyPageProps {
params: {
@@ -166,7 +167,7 @@ export default async function LinkSurveyPage({ params, searchParams }: LinkSurve
}
const isSurveyPinProtected = Boolean(!!survey && survey.pin);
-
+ const responseCount = await getResponseCountBySurveyId(survey.id);
if (isSurveyPinProtected) {
return (
);
}
diff --git a/packages/surveys/src/components/general/Survey.tsx b/packages/surveys/src/components/general/Survey.tsx
index 6a64afbcc8..0fcf576ca6 100644
--- a/packages/surveys/src/components/general/Survey.tsx
+++ b/packages/surveys/src/components/general/Survey.tsx
@@ -1,4 +1,5 @@
import FormbricksBranding from "@/components/general/FormbricksBranding";
+import ProgressBar from "@/components/general/ProgressBar";
import { AutoCloseWrapper } from "@/components/wrappers/AutoCloseWrapper";
import { evaluateCondition } from "@/lib/logicEvaluator";
import { cn } from "@/lib/utils";
@@ -8,7 +9,6 @@ import { useEffect, useRef, useState } from "preact/hooks";
import QuestionConditional from "./QuestionConditional";
import ThankYouCard from "./ThankYouCard";
import WelcomeCard from "./WelcomeCard";
-import ProgressBar from "@/components/general/ProgressBar";
export function Survey({
survey,
@@ -22,6 +22,7 @@ export function Survey({
isRedirectDisabled = false,
prefillResponseData,
onFileUpload,
+ responseCount,
}: SurveyBaseProps) {
const [questionId, setQuestionId] = useState(
activeQuestionId || (survey.welcomeCard.enabled ? "start" : survey?.questions[0]?.id)
@@ -33,7 +34,6 @@ export function Survey({
const currentQuestion = survey.questions[currentQuestionIndex];
const contentRef = useRef(null);
const [ttc, setTtc] = useState({});
-
useEffect(() => {
if (activeQuestionId === "hidden") return;
if (activeQuestionId === "start" && !survey.welcomeCard.enabled) {
@@ -131,9 +131,9 @@ export function Survey({
html={survey.welcomeCard.html}
fileUrl={survey.welcomeCard.fileUrl}
buttonLabel={survey.welcomeCard.buttonLabel}
- timeToFinish={survey.welcomeCard.timeToFinish}
onSubmit={onSubmit}
survey={survey}
+ responseCount={responseCount}
/>
);
} else if (questionId === "end" && survey.thankYouCard.enabled) {
diff --git a/packages/surveys/src/components/general/SurveyInline.tsx b/packages/surveys/src/components/general/SurveyInline.tsx
index e142c909e1..7d2f897c56 100644
--- a/packages/surveys/src/components/general/SurveyInline.tsx
+++ b/packages/surveys/src/components/general/SurveyInline.tsx
@@ -12,6 +12,7 @@ export function SurveyInline({
prefillResponseData,
isRedirectDisabled = false,
onFileUpload,
+ responseCount,
}: SurveyBaseProps) {
return (
@@ -26,6 +27,7 @@ export function SurveyInline({
prefillResponseData={prefillResponseData}
isRedirectDisabled={isRedirectDisabled}
onFileUpload={onFileUpload}
+ responseCount={responseCount}
/>
);
diff --git a/packages/surveys/src/components/general/SurveyModal.tsx b/packages/surveys/src/components/general/SurveyModal.tsx
index 93eddefa34..1f760e37e6 100644
--- a/packages/surveys/src/components/general/SurveyModal.tsx
+++ b/packages/surveys/src/components/general/SurveyModal.tsx
@@ -18,6 +18,7 @@ export function SurveyModal({
onFinished = () => {},
onFileUpload,
isRedirectDisabled = false,
+ responseCount,
}: SurveyModalProps) {
const [isOpen, setIsOpen] = useState(true);
@@ -55,6 +56,7 @@ export function SurveyModal({
}}
onFileUpload={onFileUpload}
isRedirectDisabled={isRedirectDisabled}
+ responseCount={responseCount}
/>
diff --git a/packages/surveys/src/components/general/WelcomeCard.tsx b/packages/surveys/src/components/general/WelcomeCard.tsx
index 8eb6f26383..1095ee4dda 100644
--- a/packages/surveys/src/components/general/WelcomeCard.tsx
+++ b/packages/surveys/src/components/general/WelcomeCard.tsx
@@ -10,9 +10,9 @@ interface WelcomeCardProps {
html?: string;
fileUrl?: string;
buttonLabel?: string;
- timeToFinish?: boolean;
onSubmit: (data: TResponseData, ttc: TResponseTtc) => void;
survey: TSurvey;
+ responseCount?: number;
}
const TimerIcon = () => {
@@ -32,14 +32,34 @@ const TimerIcon = () => {
);
};
+const UsersIcon = () => {
+ return (
+
+ );
+};
+
export default function WelcomeCard({
headline,
html,
fileUrl,
buttonLabel,
- timeToFinish,
onSubmit,
survey,
+ responseCount,
}: WelcomeCardProps) {
const calculateTimeToComplete = () => {
let idx = calculateElementIdx(survey, 0);
@@ -69,6 +89,9 @@ export default function WelcomeCard({
return `${minutes} minutes`;
};
+ const timeToFinish = survey.welcomeCard.timeToFinish;
+ const showResponseCount = survey.welcomeCard.showResponseCount;
+
return (
{fileUrl && (
@@ -93,12 +116,30 @@ export default function WelcomeCard({
Press Enter ↵
- {timeToFinish && (
+
+ {timeToFinish && !showResponseCount ? (
-
Takes {calculateTimeToComplete()}
+
+ Takes {calculateTimeToComplete()}
+
- )}
+ ) : showResponseCount && !timeToFinish && responseCount && responseCount > 3 ? (
+
+
+
+ {`${responseCount} people responded`}
+
+
+ ) : timeToFinish && showResponseCount ? (
+
+
+
+ Takes {calculateTimeToComplete()}
+ {responseCount && responseCount > 3 ? `⋅ ${responseCount} people responded` : ""}
+
+
+ ) : null}
);
}
diff --git a/packages/surveys/src/types/props.ts b/packages/surveys/src/types/props.ts
index e58c9439bf..d196025acf 100644
--- a/packages/surveys/src/types/props.ts
+++ b/packages/surveys/src/types/props.ts
@@ -15,6 +15,7 @@ export interface SurveyBaseProps {
isRedirectDisabled?: boolean;
prefillResponseData?: TResponseData;
onFileUpload: (file: File, config?: TUploadFileConfig) => Promise;
+ responseCount?: number;
}
export interface SurveyInlineProps extends SurveyBaseProps {
diff --git a/packages/types/js.ts b/packages/types/js.ts
index 847a6f0fba..4049f94be4 100644
--- a/packages/types/js.ts
+++ b/packages/types/js.ts
@@ -1,8 +1,8 @@
import z from "zod";
-import { ZPerson, ZPersonAttributes, ZPersonClient } from "./people";
-import { ZSurvey } from "./surveys";
import { ZActionClass } from "./actionClasses";
+import { ZPerson, ZPersonAttributes, ZPersonClient } from "./people";
import { ZProduct } from "./product";
+import { ZSurvey } from "./surveys";
const ZSurveyWithTriggers = ZSurvey.extend({
triggers: z.array(ZActionClass).or(z.array(z.string())),
diff --git a/packages/types/surveys.ts b/packages/types/surveys.ts
index 796c196438..c0af2e707c 100644
--- a/packages/types/surveys.ts
+++ b/packages/types/surveys.ts
@@ -27,6 +27,7 @@ export const ZSurveyWelcomeCard = z.object({
fileUrl: z.string().optional(),
buttonLabel: z.string().optional(),
timeToFinish: z.boolean().default(true),
+ showResponseCount: z.boolean().default(false),
});
export const ZSurveyHiddenFields = z.object({
diff --git a/packages/ui/Survey/index.tsx b/packages/ui/Survey/index.tsx
index 69c29fadeb..f1db9f6d1c 100644
--- a/packages/ui/Survey/index.tsx
+++ b/packages/ui/Survey/index.tsx
@@ -20,6 +20,7 @@ interface SurveyProps {
autoFocus?: boolean;
prefillResponseData?: TResponseData;
isRedirectDisabled?: boolean;
+ responseCount?: number;
}
interface SurveyModalProps extends SurveyProps {
@@ -42,6 +43,7 @@ export const SurveyInline = ({
prefillResponseData,
isRedirectDisabled,
onFileUpload,
+ responseCount,
}: SurveyProps) => {
const containerId = useMemo(() => createContainerId(), []);
useEffect(() => {
@@ -59,6 +61,7 @@ export const SurveyInline = ({
prefillResponseData,
isRedirectDisabled,
onFileUpload,
+ responseCount,
});
}, [
activeQuestionId,
@@ -74,6 +77,7 @@ export const SurveyInline = ({
prefillResponseData,
isRedirectDisabled,
onFileUpload,
+ responseCount,
]);
return ;
};
@@ -94,6 +98,7 @@ export const SurveyModal = ({
autoFocus,
isRedirectDisabled,
onFileUpload,
+ responseCount,
}: SurveyModalProps) => {
useEffect(() => {
renderSurveyModal({
@@ -112,6 +117,7 @@ export const SurveyModal = ({
autoFocus,
isRedirectDisabled,
onFileUpload,
+ responseCount,
});
}, [
activeQuestionId,
@@ -129,6 +135,7 @@ export const SurveyModal = ({
autoFocus,
isRedirectDisabled,
onFileUpload,
+ responseCount,
]);
return ;
};