diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryDropOffs.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryDropOffs.tsx index f19f406ef9..e5740ebcbe 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryDropOffs.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryDropOffs.tsx @@ -2,7 +2,8 @@ import { TimerIcon } from "lucide-react"; import { useTranslation } from "react-i18next"; -import { TSurvey, TSurveyQuestionType, TSurveySummary } from "@formbricks/types/surveys/types"; +import { TSurveyElementTypeEnum } from "@formbricks/types/surveys/elements"; +import { TSurvey, TSurveySummary } from "@formbricks/types/surveys/types"; import { recallToHeadline } from "@/lib/utils/recall"; import { formatTextWithSlashes } from "@/modules/survey/editor/lib/utils"; import { getQuestionIcon } from "@/modules/survey/lib/questions"; @@ -15,7 +16,7 @@ interface SummaryDropOffsProps { export const SummaryDropOffs = ({ dropOff, survey }: SummaryDropOffsProps) => { const { t } = useTranslation(); - const getIcon = (questionType: TSurveyQuestionType) => { + const getIcon = (questionType: TSurveyElementTypeEnum) => { const Icon = getQuestionIcon(questionType, t); return ; }; diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryList.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryList.tsx index 8739089caf..fa0f7d4fcd 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryList.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryList.tsx @@ -4,7 +4,8 @@ import { toast } from "react-hot-toast"; import { useTranslation } from "react-i18next"; import { TEnvironment } from "@formbricks/types/environment"; import { TI18nString } from "@formbricks/types/i18n"; -import { TSurveyQuestionId, TSurveyQuestionTypeEnum, TSurveySummary } from "@formbricks/types/surveys/types"; +import { TSurveyElementTypeEnum } from "@formbricks/types/surveys/elements"; +import { TSurveySummary } from "@formbricks/types/surveys/types"; import { TSurvey } from "@formbricks/types/surveys/types"; import { TUserLocale } from "@formbricks/types/user"; import { @@ -45,9 +46,9 @@ export const SummaryList = ({ summary, environment, responseCount, survey, local const { setSelectedFilter, selectedFilter } = useResponseFilter(); const { t } = useTranslation(); const setFilter = ( - questionId: TSurveyQuestionId, + questionId: string, label: TI18nString, - questionType: TSurveyQuestionTypeEnum, + questionType: TSurveyElementTypeEnum, filterValue: string, filterComboBoxValue?: string | string[] ) => { @@ -111,7 +112,7 @@ export const SummaryList = ({ summary, environment, responseCount, survey, local /> ) : ( summary.map((questionSummary) => { - if (questionSummary.type === TSurveyQuestionTypeEnum.OpenText) { + if (questionSummary.type === TSurveyElementTypeEnum.OpenText) { return ( ); } - if (questionSummary.type === TSurveyQuestionTypeEnum.NPS) { + if (questionSummary.type === TSurveyElementTypeEnum.NPS) { return ( ); } - if (questionSummary.type === TSurveyQuestionTypeEnum.CTA) { + if (questionSummary.type === TSurveyElementTypeEnum.CTA) { return ( ); } - if (questionSummary.type === TSurveyQuestionTypeEnum.Rating) { + if (questionSummary.type === TSurveyElementTypeEnum.Rating) { return ( ); } - if (questionSummary.type === TSurveyQuestionTypeEnum.Consent) { + if (questionSummary.type === TSurveyElementTypeEnum.Consent) { return ( ); } - if (questionSummary.type === TSurveyQuestionTypeEnum.PictureSelection) { + if (questionSummary.type === TSurveyElementTypeEnum.PictureSelection) { return ( ); } - if (questionSummary.type === TSurveyQuestionTypeEnum.Date) { + if (questionSummary.type === TSurveyElementTypeEnum.Date) { return ( ); } - if (questionSummary.type === TSurveyQuestionTypeEnum.FileUpload) { + if (questionSummary.type === TSurveyElementTypeEnum.FileUpload) { return ( ); } - if (questionSummary.type === TSurveyQuestionTypeEnum.Cal) { + if (questionSummary.type === TSurveyElementTypeEnum.Cal) { return ( ); } - if (questionSummary.type === TSurveyQuestionTypeEnum.Matrix) { + if (questionSummary.type === TSurveyElementTypeEnum.Matrix) { return ( ); } - if (questionSummary.type === TSurveyQuestionTypeEnum.Address) { + if (questionSummary.type === TSurveyElementTypeEnum.Address) { return ( ); } - if (questionSummary.type === TSurveyQuestionTypeEnum.Ranking) { + if (questionSummary.type === TSurveyElementTypeEnum.Ranking) { return ( ); } - if (questionSummary.type === TSurveyQuestionTypeEnum.ContactInfo) { + if (questionSummary.type === TSurveyElementTypeEnum.ContactInfo) { return ( [ { - id: QuestionId.OpenText, + id: TSurveyElementTypeEnum.OpenText, label: t("templates.free_text"), description: t("templates.free_text_description"), icon: MessageSquareTextIcon, @@ -62,10 +79,10 @@ export const getQuestionTypes = (t: TFunction): TQuestion[] => [ inputType: "text", buttonLabel: createI18nString(t("templates.next"), []), backButtonLabel: createI18nString(t("templates.back"), []), - } as Partial, + } as Partial, }, { - id: QuestionId.MultipleChoiceSingle, + id: TSurveyElementTypeEnum.MultipleChoiceSingle, label: t("templates.single_select"), description: t("templates.single_select_description"), icon: Rows3Icon, @@ -84,10 +101,10 @@ export const getQuestionTypes = (t: TFunction): TQuestion[] => [ shuffleOption: "none", buttonLabel: createI18nString(t("templates.next"), []), backButtonLabel: createI18nString(t("templates.back"), []), - } as Partial, + } as Partial, }, { - id: QuestionId.MultipleChoiceMulti, + id: TSurveyElementTypeEnum.MultipleChoiceMulti, label: t("templates.multi_select"), description: t("templates.multi_select_description"), icon: ListIcon, @@ -110,10 +127,10 @@ export const getQuestionTypes = (t: TFunction): TQuestion[] => [ shuffleOption: "none", buttonLabel: createI18nString(t("templates.next"), []), backButtonLabel: createI18nString(t("templates.back"), []), - } as Partial, + } as Partial, }, { - id: QuestionId.PictureSelection, + id: TSurveyElementTypeEnum.PictureSelection, label: t("templates.picture_selection"), description: t("templates.picture_selection_description"), icon: ImageIcon, @@ -123,10 +140,10 @@ export const getQuestionTypes = (t: TFunction): TQuestion[] => [ choices: [], buttonLabel: createI18nString(t("templates.next"), []), backButtonLabel: createI18nString(t("templates.back"), []), - } as Partial, + } as Partial, }, { - id: QuestionId.Rating, + id: TSurveyElementTypeEnum.Rating, label: t("templates.rating"), description: t("templates.rating_description"), icon: StarIcon, @@ -138,10 +155,10 @@ export const getQuestionTypes = (t: TFunction): TQuestion[] => [ upperLabel: createI18nString(t("templates.rating_upper_label"), []), buttonLabel: createI18nString(t("templates.next"), []), backButtonLabel: createI18nString(t("templates.back"), []), - } as Partial, + } as Partial, }, { - id: QuestionId.NPS, + id: TSurveyElementTypeEnum.NPS, label: t("templates.nps"), description: t("templates.nps_description"), icon: PresentationIcon, @@ -151,10 +168,10 @@ export const getQuestionTypes = (t: TFunction): TQuestion[] => [ upperLabel: createI18nString(t("templates.nps_upper_label"), []), buttonLabel: createI18nString(t("templates.next"), []), backButtonLabel: createI18nString(t("templates.back"), []), - } as Partial, + } as Partial, }, { - id: QuestionId.Ranking, + id: TSurveyElementTypeEnum.Ranking, label: t("templates.ranking"), description: t("templates.ranking_description"), icon: ListOrderedIcon, @@ -172,10 +189,10 @@ export const getQuestionTypes = (t: TFunction): TQuestion[] => [ ], buttonLabel: createI18nString(t("templates.next"), []), backButtonLabel: createI18nString(t("templates.back"), []), - } as Partial, + } as Partial, }, { - id: QuestionId.Matrix, + id: TSurveyElementTypeEnum.Matrix, label: t("templates.matrix"), description: t("templates.matrix_description"), icon: Grid3X3Icon, @@ -192,10 +209,10 @@ export const getQuestionTypes = (t: TFunction): TQuestion[] => [ buttonLabel: createI18nString(t("templates.next"), []), backButtonLabel: createI18nString(t("templates.back"), []), shuffleOption: "none", - } as Partial, + } as Partial, }, { - id: QuestionId.CTA, + id: TSurveyElementTypeEnum.CTA, label: t("templates.statement_call_to_action"), description: t("templates.cta_description"), icon: MousePointerClickIcon, @@ -206,10 +223,10 @@ export const getQuestionTypes = (t: TFunction): TQuestion[] => [ buttonExternal: false, dismissButtonLabel: createI18nString(t("templates.skip"), []), backButtonLabel: createI18nString(t("templates.back"), []), - } as Partial, + } as Partial, }, { - id: QuestionId.Consent, + id: TSurveyElementTypeEnum.Consent, label: t("templates.consent"), description: t("templates.consent_description"), icon: CheckIcon, @@ -219,10 +236,10 @@ export const getQuestionTypes = (t: TFunction): TQuestion[] => [ label: createI18nString("", []), buttonLabel: createI18nString(t("templates.next"), []), backButtonLabel: createI18nString(t("templates.back"), []), - } as Partial, + } as Partial, }, { - id: QuestionId.FileUpload, + id: TSurveyElementTypeEnum.FileUpload, label: t("templates.file_upload"), description: t("templates.file_upload_description"), icon: ArrowUpFromLineIcon, @@ -231,10 +248,10 @@ export const getQuestionTypes = (t: TFunction): TQuestion[] => [ allowMultipleFiles: false, buttonLabel: createI18nString(t("templates.next"), []), backButtonLabel: createI18nString(t("templates.back"), []), - } as Partial, + } as Partial, }, { - id: QuestionId.Date, + id: TSurveyElementTypeEnum.Date, label: t("templates.date"), description: t("templates.date_description"), icon: CalendarDaysIcon, @@ -243,10 +260,10 @@ export const getQuestionTypes = (t: TFunction): TQuestion[] => [ format: "M-d-y", buttonLabel: createI18nString(t("templates.next"), []), backButtonLabel: createI18nString(t("templates.back"), []), - } as Partial, + } as Partial, }, { - id: QuestionId.Cal, + id: TSurveyElementTypeEnum.Cal, label: t("templates.schedule_a_meeting"), description: t("templates.schedule_a_meeting_description"), icon: PhoneIcon, @@ -255,10 +272,10 @@ export const getQuestionTypes = (t: TFunction): TQuestion[] => [ calUserName: "rick/get-rick-rolled", buttonLabel: createI18nString(t("templates.next"), []), backButtonLabel: createI18nString(t("templates.back"), []), - } as Partial, + } as Partial, }, { - id: QuestionId.Address, + id: TSurveyElementTypeEnum.Address, label: t("templates.address"), description: t("templates.address_description"), icon: HomeIcon, @@ -272,10 +289,10 @@ export const getQuestionTypes = (t: TFunction): TQuestion[] => [ country: { show: true, required: true, placeholder: { default: "Country" } }, buttonLabel: createI18nString(t("templates.next"), []), backButtonLabel: createI18nString(t("templates.back"), []), - } as Partial, + } as Partial, }, { - id: QuestionId.ContactInfo, + id: TSurveyElementTypeEnum.ContactInfo, label: t("templates.contact_info"), description: t("templates.contact_info_description"), icon: ContactIcon, @@ -288,30 +305,30 @@ export const getQuestionTypes = (t: TFunction): TQuestion[] => [ company: { show: true, required: true, placeholder: { default: "Company" } }, buttonLabel: createI18nString(t("templates.next"), []), backButtonLabel: createI18nString(t("templates.back"), []), - } as Partial, + } as Partial, }, ]; export const getCXQuestionTypes = (t: TFunction) => getQuestionTypes(t).filter((questionType) => { return [ - TSurveyQuestionTypeEnum.OpenText, - TSurveyQuestionTypeEnum.MultipleChoiceSingle, - TSurveyQuestionTypeEnum.MultipleChoiceMulti, - TSurveyQuestionTypeEnum.Rating, - TSurveyQuestionTypeEnum.NPS, - TSurveyQuestionTypeEnum.Consent, - TSurveyQuestionTypeEnum.CTA, - ].includes(questionType.id as TSurveyQuestionTypeEnum); + TSurveyElementTypeEnum.OpenText, + TSurveyElementTypeEnum.MultipleChoiceSingle, + TSurveyElementTypeEnum.MultipleChoiceMulti, + TSurveyElementTypeEnum.Rating, + TSurveyElementTypeEnum.NPS, + TSurveyElementTypeEnum.Consent, + TSurveyElementTypeEnum.CTA, + ].includes(questionType.id as TSurveyElementTypeEnum); }); -export const getQuestionIconMap = (t: TFunction): Record => +export const getQuestionIconMap = (t: TFunction): Record => getQuestionTypes(t).reduce( (prev, curr) => ({ ...prev, [curr.id]: , }), - {} as Record + {} as Record ); export const getQuestionNameMap = (t: TFunction) => @@ -321,9 +338,9 @@ export const getQuestionNameMap = (t: TFunction) => [curr.id]: curr.label, }), {} - ) as Record; + ) as Record; -export const getQuestionIcon = (type: TSurveyQuestionTypeEnum, t: TFunction) => { +export const getQuestionIcon = (type: TSurveyElementTypeEnum, t: TFunction) => { return getQuestionTypes(t).find((questionType) => questionType.id === type)?.icon; }; @@ -339,7 +356,7 @@ export const getCXQuestionNameMap = (t: TFunction) => [curr.id]: curr.label, }), {} - ) as Record; + ) as Record; export const universalQuestionPresets = { required: false, diff --git a/packages/surveys/src/lib/utils.test.ts b/packages/surveys/src/lib/utils.test.ts index 6847ae0ff1..95143efea2 100644 --- a/packages/surveys/src/lib/utils.test.ts +++ b/packages/surveys/src/lib/utils.test.ts @@ -232,15 +232,6 @@ describe("getQuestionsFromSurvey", () => { expect(questions[2].id).toBe("q3"); }); - test("should return empty array when blocks is undefined", () => { - const surveyWithoutBlocks = { - ...baseMockSurvey, - }; - delete (surveyWithoutBlocks as Partial).blocks; - - expect(getQuestionsFromSurvey(surveyWithoutBlocks as TJsEnvironmentStateSurvey)).toEqual([]); - }); - test("should return empty array when blocks is empty", () => { const survey = { ...baseMockSurvey,