mirror of
https://github.com/formbricks/formbricks.git
synced 2026-01-08 08:50:25 -06:00
feat: Show the number of Responses to Respondents (#1720)
Co-authored-by: Johannes <johannes@formbricks.com>
This commit is contained in:
@@ -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,
|
||||
},
|
||||
|
||||
@@ -73,8 +73,6 @@ export default function SummaryMetadata({
|
||||
return ttc;
|
||||
}, [responses]);
|
||||
|
||||
console.log(ttc);
|
||||
|
||||
const totalResponses = responses.length;
|
||||
|
||||
return (
|
||||
|
||||
@@ -177,6 +177,28 @@ export default function EditWelcomeCard({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{localSurvey?.type === "link" && (
|
||||
<div className="mt-6 flex items-center">
|
||||
<div className="mr-2">
|
||||
<Switch
|
||||
id="showResponseCount"
|
||||
name="showResponseCount"
|
||||
checked={localSurvey?.welcomeCard?.showResponseCount}
|
||||
onCheckedChange={() =>
|
||||
updateSurvey({ showResponseCount: !localSurvey.welcomeCard.showResponseCount })
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-column">
|
||||
<Label htmlFor="showResponseCount" className="">
|
||||
Show Response Count
|
||||
</Label>
|
||||
<div className="text-sm text-gray-500 dark:text-gray-400">
|
||||
Display number of responses for survey
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</form>
|
||||
</Collapsible.CollapsibleContent>
|
||||
</Collapsible.Root>
|
||||
|
||||
@@ -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}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -297,6 +298,7 @@ export default function PreviewSurvey({
|
||||
onActiveQuestionChange={setActiveQuestionId}
|
||||
isRedirectDisabled={true}
|
||||
onFileUpload={onFileUpload}
|
||||
responseCount={42}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -46,7 +46,6 @@ export async function GET(
|
||||
getActionClasses(environmentId),
|
||||
getProductByEnvironmentId(environmentId),
|
||||
]);
|
||||
|
||||
if (!product) {
|
||||
throw new Error("Product not found");
|
||||
}
|
||||
|
||||
@@ -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}
|
||||
/>
|
||||
</ContentWrapper>
|
||||
</>
|
||||
|
||||
@@ -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 (
|
||||
<PinScreen
|
||||
@@ -192,6 +193,7 @@ export default async function LinkSurveyPage({ params, searchParams }: LinkSurve
|
||||
singleUseId={isSingleUseSurvey ? singleUseId : undefined}
|
||||
singleUseResponse={singleUseResponse ? singleUseResponse : undefined}
|
||||
webAppUrl={WEBAPP_URL}
|
||||
responseCount={survey.welcomeCard.showResponseCount ? responseCount : undefined}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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<HTMLDivElement | null>(null);
|
||||
const [ttc, setTtc] = useState<TResponseTtc>({});
|
||||
|
||||
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) {
|
||||
|
||||
@@ -12,6 +12,7 @@ export function SurveyInline({
|
||||
prefillResponseData,
|
||||
isRedirectDisabled = false,
|
||||
onFileUpload,
|
||||
responseCount,
|
||||
}: SurveyBaseProps) {
|
||||
return (
|
||||
<div id="fbjs" className="formbricks-form h-full w-full">
|
||||
@@ -26,6 +27,7 @@ export function SurveyInline({
|
||||
prefillResponseData={prefillResponseData}
|
||||
isRedirectDisabled={isRedirectDisabled}
|
||||
onFileUpload={onFileUpload}
|
||||
responseCount={responseCount}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -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}
|
||||
/>
|
||||
</Modal>
|
||||
</div>
|
||||
|
||||
@@ -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 (
|
||||
<div className="mr-1">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
class="h-4 w-4">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M15 19.128a9.38 9.38 0 002.625.372 9.337 9.337 0 004.121-.952 4.125 4.125 0 00-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 018.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0111.964-3.07M12 6.375a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zm8.25 2.25a2.625 2.625 0 11-5.25 0 2.625 2.625 0 015.25 0z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
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 (
|
||||
<div>
|
||||
{fileUrl && (
|
||||
@@ -93,12 +116,30 @@ export default function WelcomeCard({
|
||||
<div className="text-subheading flex items-center text-xs">Press Enter ↵</div>
|
||||
</div>
|
||||
</div>
|
||||
{timeToFinish && (
|
||||
|
||||
{timeToFinish && !showResponseCount ? (
|
||||
<div className="item-center mt-4 flex text-slate-500">
|
||||
<TimerIcon />
|
||||
<p className="text-xs">Takes {calculateTimeToComplete()}</p>
|
||||
<p className="pt-1 text-xs">
|
||||
<span> Takes {calculateTimeToComplete()} </span>
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
) : showResponseCount && !timeToFinish && responseCount && responseCount > 3 ? (
|
||||
<div className="item-center mt-4 flex text-slate-500">
|
||||
<UsersIcon />
|
||||
<p className="pt-1 text-xs">
|
||||
<span>{`${responseCount} people responded`}</span>
|
||||
</p>
|
||||
</div>
|
||||
) : timeToFinish && showResponseCount ? (
|
||||
<div className="item-center mt-4 flex text-slate-500">
|
||||
<TimerIcon />
|
||||
<p className="pt-1 text-xs">
|
||||
<span> Takes {calculateTimeToComplete()} </span>
|
||||
<span>{responseCount && responseCount > 3 ? `⋅ ${responseCount} people responded` : ""}</span>
|
||||
</p>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ export interface SurveyBaseProps {
|
||||
isRedirectDisabled?: boolean;
|
||||
prefillResponseData?: TResponseData;
|
||||
onFileUpload: (file: File, config?: TUploadFileConfig) => Promise<string>;
|
||||
responseCount?: number;
|
||||
}
|
||||
|
||||
export interface SurveyInlineProps extends SurveyBaseProps {
|
||||
|
||||
@@ -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())),
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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 <div id={containerId} className="h-full w-full" />;
|
||||
};
|
||||
@@ -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 <div id="formbricks-survey"></div>;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user