mirror of
https://github.com/formbricks/formbricks.git
synced 2026-05-01 19:32:57 -05:00
Co-authored-by: Johannes <johannes@formbricks.com> Co-authored-by: Matthias Nannt <mail@matthiasnannt.com>
This commit is contained in:
+3
-1
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { createId } from "@paralleldrive/cuid2";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import { PlusIcon } from "lucide-react";
|
||||
@@ -22,6 +23,7 @@ interface AddQuestionButtonProps {
|
||||
export const AddQuestionButton = ({ addQuestion, product, isCxMode }: AddQuestionButtonProps) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [hoveredQuestionId, setHoveredQuestionId] = useState<string | null>(null);
|
||||
const [parent] = useAutoAnimate();
|
||||
|
||||
const availableQuestionTypes = isCxMode ? CXQuestionTypes : questionTypes;
|
||||
|
||||
@@ -44,7 +46,7 @@ export const AddQuestionButton = ({ addQuestion, product, isCxMode }: AddQuestio
|
||||
</div>
|
||||
</div>
|
||||
</Collapsible.CollapsibleTrigger>
|
||||
<Collapsible.CollapsibleContent className="justify-left flex flex-col">
|
||||
<Collapsible.CollapsibleContent className="justify-left flex flex-col" ref={parent}>
|
||||
{/* <hr className="py-1 text-slate-600" /> */}
|
||||
{availableQuestionTypes.map((questionType) => (
|
||||
<button
|
||||
|
||||
+3
-1
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { PlusIcon } from "lucide-react";
|
||||
import { useEffect } from "react";
|
||||
import { createI18nString, extractLanguageCodes } from "@formbricks/lib/i18n/utils";
|
||||
@@ -91,6 +92,7 @@ export const AddressQuestionForm = ({
|
||||
question.country,
|
||||
]);
|
||||
|
||||
const [parent] = useAutoAnimate();
|
||||
return (
|
||||
<form>
|
||||
<QuestionFormInput
|
||||
@@ -106,7 +108,7 @@ export const AddressQuestionForm = ({
|
||||
attributeClasses={attributeClasses}
|
||||
/>
|
||||
|
||||
<div>
|
||||
<div ref={parent}>
|
||||
{question.subheader !== undefined && (
|
||||
<div className="inline-flex w-full items-center">
|
||||
<div className="w-full">
|
||||
|
||||
+4
-1
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import { CheckIcon } from "lucide-react";
|
||||
import { UseFormReturn } from "react-hook-form";
|
||||
@@ -32,6 +33,8 @@ export const BackgroundStylingCard = ({
|
||||
isUnsplashConfigured,
|
||||
form,
|
||||
}: BackgroundStylingCardProps) => {
|
||||
const [parent] = useAutoAnimate();
|
||||
|
||||
return (
|
||||
<Collapsible.Root
|
||||
open={open}
|
||||
@@ -72,7 +75,7 @@ export const BackgroundStylingCard = ({
|
||||
</div>
|
||||
</div>
|
||||
</Collapsible.CollapsibleTrigger>
|
||||
<Collapsible.CollapsibleContent>
|
||||
<Collapsible.CollapsibleContent className="flex flex-col" ref={parent}>
|
||||
<hr className="pt-1 text-slate-600" />
|
||||
<div className="flex flex-col gap-6 p-6 pt-2">
|
||||
<FormField
|
||||
|
||||
+3
-2
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { useState } from "react";
|
||||
import { LocalizedEditor } from "@formbricks/ee/multi-language/components/localized-editor";
|
||||
import { TAttributeClass } from "@formbricks/types/attribute-classes";
|
||||
@@ -41,9 +42,9 @@ export const CTAQuestionForm = ({
|
||||
attributeClasses,
|
||||
}: CTAQuestionFormProps): JSX.Element => {
|
||||
const [firstRender, setFirstRender] = useState(true);
|
||||
|
||||
const [parent] = useAutoAnimate();
|
||||
return (
|
||||
<form>
|
||||
<form ref={parent}>
|
||||
<QuestionFormInput
|
||||
id="headline"
|
||||
value={question.headline}
|
||||
|
||||
+3
-1
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import { CheckIcon } from "lucide-react";
|
||||
import React from "react";
|
||||
@@ -42,6 +43,7 @@ export const CardStylingSettings = ({
|
||||
const appCardArrangement = form.watch("cardArrangement.appSurveys") ?? "simple";
|
||||
const roundness = form.watch("roundness") ?? 8;
|
||||
|
||||
const [parent] = useAutoAnimate();
|
||||
return (
|
||||
<Collapsible.Root
|
||||
open={open}
|
||||
@@ -78,7 +80,7 @@ export const CardStylingSettings = ({
|
||||
</div>
|
||||
</Collapsible.CollapsibleTrigger>
|
||||
|
||||
<Collapsible.CollapsibleContent>
|
||||
<Collapsible.CollapsibleContent className="flex flex-col" ref={parent}>
|
||||
<hr className="py-1 text-slate-600" />
|
||||
|
||||
<div className="flex flex-col gap-6 p-6 pt-2">
|
||||
|
||||
+4
-2
@@ -3,6 +3,7 @@ import {
|
||||
getDefaultOperatorForQuestion,
|
||||
replaceEndingCardHeadlineRecall,
|
||||
} from "@/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/lib/utils";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { createId } from "@paralleldrive/cuid2";
|
||||
import {
|
||||
ArrowDownIcon,
|
||||
@@ -111,16 +112,17 @@ export function ConditionalLogic({
|
||||
logic: logicCopy,
|
||||
});
|
||||
};
|
||||
const [parent] = useAutoAnimate();
|
||||
|
||||
return (
|
||||
<div className="mt-4">
|
||||
<div className="mt-4" ref={parent}>
|
||||
<Label className="flex gap-2">
|
||||
Conditional Logic
|
||||
<SplitIcon className="h-4 w-4 rotate-90" />
|
||||
</Label>
|
||||
|
||||
{question.logic && question.logic.length > 0 && (
|
||||
<div className="mt-2 flex flex-col gap-4">
|
||||
<div className="mt-2 flex flex-col gap-4" ref={parent}>
|
||||
{question.logic.map((logicItem, logicItemIdx) => (
|
||||
<div
|
||||
key={logicItem.id}
|
||||
|
||||
+5
-1
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { PlusIcon } from "lucide-react";
|
||||
import { useEffect } from "react";
|
||||
import { createI18nString, extractLanguageCodes } from "@formbricks/lib/i18n/utils";
|
||||
@@ -78,6 +79,9 @@ export const ContactInfoQuestionForm = ({
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [question.firstName, question.lastName, question.email, question.phone, question.company]);
|
||||
|
||||
// Auto animate
|
||||
const [parent] = useAutoAnimate();
|
||||
|
||||
return (
|
||||
<form>
|
||||
<QuestionFormInput
|
||||
@@ -93,7 +97,7 @@ export const ContactInfoQuestionForm = ({
|
||||
attributeClasses={attributeClasses}
|
||||
/>
|
||||
|
||||
<div>
|
||||
<div ref={parent}>
|
||||
{question.subheader !== undefined && (
|
||||
<div className="inline-flex w-full items-center">
|
||||
<div className="w-full">
|
||||
|
||||
+3
-2
@@ -1,3 +1,4 @@
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { PlusIcon } from "lucide-react";
|
||||
import { createI18nString, extractLanguageCodes } from "@formbricks/lib/i18n/utils";
|
||||
import { TAttributeClass } from "@formbricks/types/attribute-classes";
|
||||
@@ -45,7 +46,7 @@ export const DateQuestionForm = ({
|
||||
attributeClasses,
|
||||
}: IDateQuestionFormProps): JSX.Element => {
|
||||
const surveyLanguageCodes = extractLanguageCodes(localSurvey.languages);
|
||||
|
||||
const [parent] = useAutoAnimate();
|
||||
return (
|
||||
<form>
|
||||
<QuestionFormInput
|
||||
@@ -60,7 +61,7 @@ export const DateQuestionForm = ({
|
||||
setSelectedLanguageCode={setSelectedLanguageCode}
|
||||
attributeClasses={attributeClasses}
|
||||
/>
|
||||
<div>
|
||||
<div ref={parent}>
|
||||
{question.subheader !== undefined && (
|
||||
<div className="mt-2 inline-flex w-full items-center">
|
||||
<div className="w-full">
|
||||
|
||||
+1
-1
@@ -203,7 +203,7 @@ export const EditEndingCard = ({
|
||||
</div>
|
||||
</div>
|
||||
</Collapsible.CollapsibleTrigger>
|
||||
<Collapsible.CollapsibleContent className="mt-3 px-4 pb-6">
|
||||
<Collapsible.CollapsibleContent className={`flex flex-col px-4 ${open && "mt-3 pb-6"}`}>
|
||||
<TooltipRenderer
|
||||
shouldRender={endingCard.type === "endScreen" && isRedirectToUrlDisabled}
|
||||
tooltipContent={"Redirect To Url is not available on free plan"}
|
||||
|
||||
+2
-2
@@ -72,7 +72,7 @@ export const EditWelcomeCard = ({
|
||||
<Collapsible.Root
|
||||
open={open}
|
||||
onOpenChange={setOpen}
|
||||
className="flex-1 rounded-r-lg border border-slate-200 transition-all duration-300 ease-in-out">
|
||||
className="flex-1 rounded-r-lg border border-slate-200 transition-all duration-200 ease-in-out">
|
||||
<Collapsible.CollapsibleTrigger
|
||||
asChild
|
||||
className="flex cursor-pointer justify-between rounded-r-lg p-4 hover:bg-slate-50">
|
||||
@@ -102,7 +102,7 @@ export const EditWelcomeCard = ({
|
||||
</div>
|
||||
</div>
|
||||
</Collapsible.CollapsibleTrigger>
|
||||
<Collapsible.CollapsibleContent className="px-4 pb-6">
|
||||
<Collapsible.CollapsibleContent className={`flex flex-col px-4 ${open && "pb-6"}`}>
|
||||
<form>
|
||||
<div className="mt-2">
|
||||
<Label htmlFor="companyLogo">Company Logo</Label>
|
||||
|
||||
+4
-1
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { PlusIcon, XCircleIcon } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { useMemo, useState } from "react";
|
||||
@@ -121,6 +122,8 @@ export const FileUploadQuestionForm = ({
|
||||
updateQuestion(questionIdx, { maxSizeInMB: checked ? defaultMaxSizeInMB : undefined });
|
||||
};
|
||||
|
||||
const [parent] = useAutoAnimate();
|
||||
|
||||
return (
|
||||
<form>
|
||||
<QuestionFormInput
|
||||
@@ -135,7 +138,7 @@ export const FileUploadQuestionForm = ({
|
||||
setSelectedLanguageCode={setSelectedLanguageCode}
|
||||
attributeClasses={attributeClasses}
|
||||
/>
|
||||
<div>
|
||||
<div ref={parent}>
|
||||
{question.subheader !== undefined && (
|
||||
<div className="inline-flex w-full items-center">
|
||||
<div className="w-full">
|
||||
|
||||
+6
-3
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import { CheckIcon, SparklesIcon } from "lucide-react";
|
||||
import React from "react";
|
||||
@@ -67,6 +68,8 @@ export const FormStylingSettings = ({
|
||||
}
|
||||
};
|
||||
|
||||
const [parent] = useAutoAnimate();
|
||||
|
||||
return (
|
||||
<Collapsible.Root
|
||||
open={open}
|
||||
@@ -103,10 +106,10 @@ export const FormStylingSettings = ({
|
||||
</div>
|
||||
</Collapsible.CollapsibleTrigger>
|
||||
|
||||
<Collapsible.CollapsibleContent>
|
||||
<hr className="py-1 text-slate-600" />
|
||||
<Collapsible.CollapsibleContent className="flex flex-col" ref={parent}>
|
||||
<hr className="py-1 text-slate-600" key={"hello"} />
|
||||
|
||||
<div className="flex flex-col gap-6 p-6 pt-2">
|
||||
<div className="flex flex-col gap-6 p-6 pt-2" key={"hjiii"}>
|
||||
<div className="flex flex-col gap-2">
|
||||
<FormField
|
||||
control={form.control}
|
||||
|
||||
+6
-2
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { findHiddenFieldUsedInLogic } from "@/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/lib/utils";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import { EyeOff } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
@@ -85,6 +86,9 @@ export const HiddenFieldsCard = ({
|
||||
);
|
||||
};
|
||||
|
||||
// Auto Animate
|
||||
const [parent] = useAutoAnimate();
|
||||
|
||||
return (
|
||||
<div className={cn(open ? "shadow-lg" : "shadow-md", "group z-10 flex flex-row rounded-lg bg-white")}>
|
||||
<div
|
||||
@@ -124,8 +128,8 @@ export const HiddenFieldsCard = ({
|
||||
</div>
|
||||
</div>
|
||||
</Collapsible.CollapsibleTrigger>
|
||||
<Collapsible.CollapsibleContent className="px-4 pb-6">
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<Collapsible.CollapsibleContent className={`flex flex-col px-4 ${open && "pb-6"}`} ref={parent}>
|
||||
<div className="flex flex-wrap gap-2" ref={parent}>
|
||||
{localSurvey.hiddenFields?.fieldIds && localSurvey.hiddenFields?.fieldIds?.length > 0 ? (
|
||||
localSurvey.hiddenFields?.fieldIds?.map((fieldId) => {
|
||||
return (
|
||||
|
||||
+4
-1
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import { AlertCircleIcon, CheckIcon, LinkIcon, MonitorIcon } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
@@ -89,6 +90,8 @@ export const HowToSendCard = ({ localSurvey, setLocalSurvey, environment }: HowT
|
||||
},
|
||||
];
|
||||
|
||||
const [parent] = useAutoAnimate();
|
||||
|
||||
return (
|
||||
<Collapsible.Root
|
||||
open={open}
|
||||
@@ -114,7 +117,7 @@ export const HowToSendCard = ({ localSurvey, setLocalSurvey, environment }: HowT
|
||||
</div>
|
||||
</div>
|
||||
</Collapsible.CollapsibleTrigger>
|
||||
<Collapsible.CollapsibleContent>
|
||||
<Collapsible.CollapsibleContent className="flex flex-col" ref={parent}>
|
||||
<hr className="py-1 text-slate-600" />
|
||||
<div className="p-3">
|
||||
<RadioGroup
|
||||
|
||||
+4
-1
@@ -4,6 +4,7 @@ import {
|
||||
getDefaultOperatorForQuestion,
|
||||
getMatchValueProps,
|
||||
} from "@/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/lib/utils";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { createId } from "@paralleldrive/cuid2";
|
||||
import { CopyIcon, EllipsisVerticalIcon, PlusIcon, TrashIcon, WorkflowIcon } from "lucide-react";
|
||||
import { cn } from "@formbricks/lib/cn";
|
||||
@@ -52,6 +53,8 @@ export function LogicEditorConditions({
|
||||
updateQuestion,
|
||||
depth = 0,
|
||||
}: LogicEditorConditionsProps) {
|
||||
const [parent] = useAutoAnimate();
|
||||
|
||||
const handleAddConditionBelow = (resourceId: string) => {
|
||||
const operator = getDefaultOperatorForQuestion(question);
|
||||
|
||||
@@ -334,7 +337,7 @@ export function LogicEditorConditions({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-y-2">
|
||||
<div ref={parent} className="flex flex-col gap-y-2">
|
||||
{conditions?.conditions.map((condition, index) => renderCondition(condition, index, conditions))}
|
||||
</div>
|
||||
);
|
||||
|
||||
+6
-4
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { PlusIcon, TrashIcon } from "lucide-react";
|
||||
import { createI18nString, extractLanguageCodes } from "@formbricks/lib/i18n/utils";
|
||||
import { TAttributeClass } from "@formbricks/types/attribute-classes";
|
||||
@@ -96,7 +97,8 @@ export const MatrixQuestionForm = ({
|
||||
show: true,
|
||||
},
|
||||
};
|
||||
|
||||
/// Auto animate
|
||||
const [parent] = useAutoAnimate();
|
||||
return (
|
||||
<form>
|
||||
<QuestionFormInput
|
||||
@@ -111,7 +113,7 @@ export const MatrixQuestionForm = ({
|
||||
setSelectedLanguageCode={setSelectedLanguageCode}
|
||||
attributeClasses={attributeClasses}
|
||||
/>
|
||||
<div>
|
||||
<div ref={parent}>
|
||||
{question.subheader !== undefined && (
|
||||
<div className="inline-flex w-full items-center">
|
||||
<div className="w-full">
|
||||
@@ -150,7 +152,7 @@ export const MatrixQuestionForm = ({
|
||||
<div>
|
||||
{/* Rows section */}
|
||||
<Label htmlFor="rows">Rows</Label>
|
||||
<div>
|
||||
<div ref={parent}>
|
||||
{question.rows.map((_, index) => (
|
||||
<div className="flex items-center" onKeyDown={(e) => handleKeyDown(e, "row")}>
|
||||
<QuestionFormInput
|
||||
@@ -192,7 +194,7 @@ export const MatrixQuestionForm = ({
|
||||
<div>
|
||||
{/* Columns section */}
|
||||
<Label htmlFor="columns">Columns</Label>
|
||||
<div>
|
||||
<div ref={parent}>
|
||||
{question.columns.map((_, index) => (
|
||||
<div className="flex items-center" onKeyDown={(e) => handleKeyDown(e, "column")}>
|
||||
<QuestionFormInput
|
||||
|
||||
+5
-2
@@ -3,6 +3,7 @@
|
||||
import { findOptionUsedInLogic } from "@/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/lib/utils";
|
||||
import { DndContext } from "@dnd-kit/core";
|
||||
import { SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { createId } from "@paralleldrive/cuid2";
|
||||
import { PlusIcon } from "lucide-react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
@@ -158,6 +159,8 @@ export const MultipleChoiceQuestionForm = ({
|
||||
}
|
||||
}, [isNew]);
|
||||
|
||||
// Auto animate
|
||||
const [parent] = useAutoAnimate();
|
||||
return (
|
||||
<form>
|
||||
<QuestionFormInput
|
||||
@@ -173,7 +176,7 @@ export const MultipleChoiceQuestionForm = ({
|
||||
attributeClasses={attributeClasses}
|
||||
/>
|
||||
|
||||
<div>
|
||||
<div ref={parent}>
|
||||
{question.subheader !== undefined && (
|
||||
<div className="inline-flex w-full items-center">
|
||||
<div className="w-full">
|
||||
@@ -236,7 +239,7 @@ export const MultipleChoiceQuestionForm = ({
|
||||
updateQuestion(questionIdx, { choices: newChoices });
|
||||
}}>
|
||||
<SortableContext items={question.choices} strategy={verticalListSortingStrategy}>
|
||||
<div className="flex flex-col">
|
||||
<div className="flex flex-col" ref={parent}>
|
||||
{question.choices &&
|
||||
question.choices.map((choice, choiceIdx) => (
|
||||
<QuestionOptionChoice
|
||||
|
||||
+5
-1
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { PlusIcon } from "lucide-react";
|
||||
import { createI18nString, extractLanguageCodes } from "@formbricks/lib/i18n/utils";
|
||||
import { TAttributeClass } from "@formbricks/types/attribute-classes";
|
||||
@@ -32,6 +33,9 @@ export const NPSQuestionForm = ({
|
||||
attributeClasses,
|
||||
}: NPSQuestionFormProps): JSX.Element => {
|
||||
const surveyLanguageCodes = extractLanguageCodes(localSurvey.languages);
|
||||
// Auto animate
|
||||
const [parent] = useAutoAnimate();
|
||||
|
||||
return (
|
||||
<form>
|
||||
<QuestionFormInput
|
||||
@@ -47,7 +51,7 @@ export const NPSQuestionForm = ({
|
||||
attributeClasses={attributeClasses}
|
||||
/>
|
||||
|
||||
<div>
|
||||
<div ref={parent}>
|
||||
{question.subheader !== undefined && (
|
||||
<div className="mt-2 inline-flex w-full items-center">
|
||||
<div className="w-full">
|
||||
|
||||
+4
-1
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { HashIcon, LinkIcon, MailIcon, MessageSquareTextIcon, PhoneIcon, PlusIcon } from "lucide-react";
|
||||
import { createI18nString, extractLanguageCodes } from "@formbricks/lib/i18n/utils";
|
||||
import { TAttributeClass } from "@formbricks/types/attribute-classes";
|
||||
@@ -54,6 +55,8 @@ export const OpenQuestionForm = ({
|
||||
updateQuestion(questionIdx, updatedAttributes);
|
||||
};
|
||||
|
||||
const [parent] = useAutoAnimate();
|
||||
|
||||
return (
|
||||
<form>
|
||||
<QuestionFormInput
|
||||
@@ -69,7 +72,7 @@ export const OpenQuestionForm = ({
|
||||
label={"Question*"}
|
||||
/>
|
||||
|
||||
<div>
|
||||
<div ref={parent}>
|
||||
{question.subheader !== undefined && (
|
||||
<div className="inline-flex w-full items-center">
|
||||
<div className="w-full">
|
||||
|
||||
+4
-2
@@ -1,3 +1,4 @@
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { createId } from "@paralleldrive/cuid2";
|
||||
import { PlusIcon } from "lucide-react";
|
||||
import { cn } from "@formbricks/lib/cn";
|
||||
@@ -64,7 +65,8 @@ export const PictureSelectionForm = ({
|
||||
choices: updatedChoices,
|
||||
});
|
||||
};
|
||||
|
||||
// Auto animate
|
||||
const [parent] = useAutoAnimate();
|
||||
return (
|
||||
<form>
|
||||
<QuestionFormInput
|
||||
@@ -79,7 +81,7 @@ export const PictureSelectionForm = ({
|
||||
setSelectedLanguageCode={setSelectedLanguageCode}
|
||||
attributeClasses={attributeClasses}
|
||||
/>
|
||||
<div>
|
||||
<div ref={parent}>
|
||||
{question.subheader !== undefined && (
|
||||
<div className="mt-2 inline-flex w-full items-center">
|
||||
<div className="w-full">
|
||||
|
||||
+4
-2
@@ -5,6 +5,7 @@ import { RankingQuestionForm } from "@/app/(app)/(survey-editor)/environments/[e
|
||||
import { formatTextWithSlashes } from "@/app/(app)/(survey-editor)/environments/[environmentId]/surveys/[surveyId]/edit/lib/utils";
|
||||
import { useSortable } from "@dnd-kit/sortable";
|
||||
import { CSS } from "@dnd-kit/utilities";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import { ChevronDownIcon, ChevronRightIcon, GripIcon } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
@@ -85,6 +86,7 @@ export const QuestionCard = ({
|
||||
|
||||
const open = activeQuestionId === question.id;
|
||||
const [openAdvanced, setOpenAdvanced] = useState(question.logic && question.logic.length > 0);
|
||||
const [parent] = useAutoAnimate();
|
||||
|
||||
const updateEmptyButtonLabels = (
|
||||
labelKey: "buttonLabel" | "backButtonLabel",
|
||||
@@ -229,7 +231,7 @@ export const QuestionCard = ({
|
||||
</div>
|
||||
</div>
|
||||
</Collapsible.CollapsibleTrigger>
|
||||
<Collapsible.CollapsibleContent className="px-4 pb-4">
|
||||
<Collapsible.CollapsibleContent className={`flex flex-col px-4 ${open && "pb-4"}`}>
|
||||
{question.type === TSurveyQuestionTypeEnum.OpenText ? (
|
||||
<OpenQuestionForm
|
||||
localSurvey={localSurvey}
|
||||
@@ -423,7 +425,7 @@ export const QuestionCard = ({
|
||||
{openAdvanced ? "Hide Advanced Settings" : "Show Advanced Settings"}
|
||||
</Collapsible.CollapsibleTrigger>
|
||||
|
||||
<Collapsible.CollapsibleContent className="space-y-4">
|
||||
<Collapsible.CollapsibleContent className="flex flex-col gap-4" ref={parent}>
|
||||
{question.type !== TSurveyQuestionTypeEnum.NPS &&
|
||||
question.type !== TSurveyQuestionTypeEnum.Rating &&
|
||||
question.type !== TSurveyQuestionTypeEnum.CTA ? (
|
||||
|
||||
+4
-1
@@ -1,4 +1,5 @@
|
||||
import { SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { TAttributeClass } from "@formbricks/types/attribute-classes";
|
||||
import { TProduct } from "@formbricks/types/product";
|
||||
import { TSurvey, TSurveyQuestionId } from "@formbricks/types/surveys/types";
|
||||
@@ -41,8 +42,10 @@ export const QuestionsDroppable = ({
|
||||
isFormbricksCloud,
|
||||
isCxMode,
|
||||
}: QuestionsDraggableProps) => {
|
||||
const [parent] = useAutoAnimate();
|
||||
|
||||
return (
|
||||
<div className="group mb-5 flex w-full flex-col gap-5">
|
||||
<div className="group mb-5 flex w-full flex-col gap-5" ref={parent}>
|
||||
<SortableContext items={localSurvey.questions} strategy={verticalListSortingStrategy}>
|
||||
{localSurvey.questions.map((question, questionIdx) => (
|
||||
<QuestionCard
|
||||
|
||||
+5
-1
@@ -12,6 +12,7 @@ import {
|
||||
useSensors,
|
||||
} from "@dnd-kit/core";
|
||||
import { SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { createId } from "@paralleldrive/cuid2";
|
||||
import React, { SetStateAction, useEffect, useMemo } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
@@ -410,6 +411,9 @@ export const QuestionsView = ({
|
||||
setLocalSurvey(updatedSurvey);
|
||||
};
|
||||
|
||||
// Auto animate
|
||||
const [parent] = useAutoAnimate();
|
||||
|
||||
return (
|
||||
<div className="mt-12 w-full px-5 py-4">
|
||||
{!isCxMode && (
|
||||
@@ -453,7 +457,7 @@ export const QuestionsView = ({
|
||||
</DndContext>
|
||||
|
||||
<AddQuestionButton addQuestion={addQuestion} product={product} isCxMode={isCxMode} />
|
||||
<div className="mt-5 flex flex-col gap-5">
|
||||
<div className="mt-5 flex flex-col gap-5" ref={parent}>
|
||||
<hr className="border-t border-dashed" />
|
||||
<DndContext
|
||||
id="endings"
|
||||
|
||||
+5
-2
@@ -2,6 +2,7 @@
|
||||
|
||||
import { DndContext } from "@dnd-kit/core";
|
||||
import { SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { createId } from "@paralleldrive/cuid2";
|
||||
import { PlusIcon } from "lucide-react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
@@ -107,6 +108,8 @@ export const RankingQuestionForm = ({
|
||||
}
|
||||
}, [question.choices?.length]);
|
||||
|
||||
const [parent] = useAutoAnimate();
|
||||
|
||||
return (
|
||||
<form>
|
||||
<QuestionFormInput
|
||||
@@ -122,7 +125,7 @@ export const RankingQuestionForm = ({
|
||||
attributeClasses={attributeClasses}
|
||||
/>
|
||||
|
||||
<div>
|
||||
<div ref={parent}>
|
||||
{question.subheader !== undefined && (
|
||||
<div className="inline-flex w-full items-center">
|
||||
<div className="w-full">
|
||||
@@ -181,7 +184,7 @@ export const RankingQuestionForm = ({
|
||||
updateQuestion(questionIdx, { choices: newChoices });
|
||||
}}>
|
||||
<SortableContext items={question.choices} strategy={verticalListSortingStrategy}>
|
||||
<div className="flex flex-col">
|
||||
<div className="flex flex-col" ref={parent}>
|
||||
{question.choices &&
|
||||
question.choices.map((choice, choiceIdx) => (
|
||||
<QuestionOptionChoice
|
||||
|
||||
+3
-2
@@ -1,3 +1,4 @@
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { HashIcon, PlusIcon, SmileIcon, StarIcon } from "lucide-react";
|
||||
import { createI18nString, extractLanguageCodes } from "@formbricks/lib/i18n/utils";
|
||||
import { TAttributeClass } from "@formbricks/types/attribute-classes";
|
||||
@@ -31,7 +32,7 @@ export const RatingQuestionForm = ({
|
||||
attributeClasses,
|
||||
}: RatingQuestionFormProps) => {
|
||||
const surveyLanguageCodes = extractLanguageCodes(localSurvey.languages);
|
||||
|
||||
const [parent] = useAutoAnimate();
|
||||
return (
|
||||
<form>
|
||||
<QuestionFormInput
|
||||
@@ -47,7 +48,7 @@ export const RatingQuestionForm = ({
|
||||
attributeClasses={attributeClasses}
|
||||
/>
|
||||
|
||||
<div>
|
||||
<div ref={parent}>
|
||||
{question.subheader !== undefined && (
|
||||
<div className="mt-2 inline-flex w-full items-center">
|
||||
<div className="w-full">
|
||||
|
||||
+5
-1
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import { CheckIcon } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
@@ -57,6 +58,9 @@ export const RecontactOptionsCard = ({
|
||||
);
|
||||
const [displayLimit, setDisplayLimit] = useState(localSurvey.displayLimit ?? 1);
|
||||
|
||||
// Auto animate
|
||||
const [parent] = useAutoAnimate();
|
||||
|
||||
const handleCheckMark = () => {
|
||||
if (ignoreWaiting) {
|
||||
const updatedSurvey = { ...localSurvey, recontactDays: null };
|
||||
@@ -119,7 +123,7 @@ export const RecontactOptionsCard = ({
|
||||
</div>
|
||||
</div>
|
||||
</Collapsible.CollapsibleTrigger>
|
||||
<Collapsible.CollapsibleContent className="pb-3">
|
||||
<Collapsible.CollapsibleContent className={`flex flex-col ${open && "pb-3"}`} ref={parent}>
|
||||
<hr className="py-1 text-slate-600" />
|
||||
<div className="p-3">
|
||||
<RadioGroup
|
||||
|
||||
+3
-1
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import { ArrowUpRight, CheckIcon } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
@@ -272,6 +273,7 @@ export const ResponseOptionsCard = ({
|
||||
return;
|
||||
}
|
||||
};
|
||||
const [parent] = useAutoAnimate();
|
||||
|
||||
return (
|
||||
<Collapsible.Root
|
||||
@@ -295,7 +297,7 @@ export const ResponseOptionsCard = ({
|
||||
</div>
|
||||
</div>
|
||||
</Collapsible.CollapsibleTrigger>
|
||||
<Collapsible.CollapsibleContent>
|
||||
<Collapsible.CollapsibleContent className="flex flex-col" ref={parent}>
|
||||
<hr className="py-1 text-slate-600" />
|
||||
<div className="p-3">
|
||||
{/* Close Survey on Limit */}
|
||||
|
||||
+4
-1
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import { CheckIcon } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
@@ -70,6 +71,8 @@ export const SurveyPlacementCard = ({
|
||||
}
|
||||
};
|
||||
|
||||
const [parent] = useAutoAnimate();
|
||||
|
||||
return (
|
||||
<Collapsible.Root
|
||||
open={open}
|
||||
@@ -95,7 +98,7 @@ export const SurveyPlacementCard = ({
|
||||
</div>
|
||||
</div>
|
||||
</Collapsible.CollapsibleTrigger>
|
||||
<Collapsible.CollapsibleContent className="pb-3">
|
||||
<Collapsible.CollapsibleContent className={`flex ${open && "pb-3"}`} ref={parent}>
|
||||
<hr className="py-1 text-slate-600" />
|
||||
<div className="p-6">
|
||||
<div className="flex flex-col gap-4">
|
||||
|
||||
+4
-2
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import { FileDigitIcon } from "lucide-react";
|
||||
import { cn } from "@formbricks/lib/cn";
|
||||
@@ -22,6 +23,7 @@ export const SurveyVariablesCard = ({
|
||||
setActiveQuestionId,
|
||||
}: SurveyVariablesCardProps) => {
|
||||
const open = activeQuestionId === variablesCardId;
|
||||
const [parent] = useAutoAnimate();
|
||||
|
||||
const setOpenState = (state: boolean) => {
|
||||
if (state) {
|
||||
@@ -57,8 +59,8 @@ export const SurveyVariablesCard = ({
|
||||
</div>
|
||||
</div>
|
||||
</Collapsible.CollapsibleTrigger>
|
||||
<Collapsible.CollapsibleContent className="px-4 pb-6">
|
||||
<div className="flex flex-col gap-2">
|
||||
<Collapsible.CollapsibleContent className={`flex flex-col px-4 ${open && "pb-6"}`} ref={parent}>
|
||||
<div className="flex flex-col gap-2" ref={parent}>
|
||||
{localSurvey.variables.length > 0 ? (
|
||||
localSurvey.variables.map((variable) => (
|
||||
<SurveyVariablesCardItem
|
||||
|
||||
+3
-1
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import { AlertCircle, CheckIcon, ChevronDownIcon, ChevronUpIcon, PencilIcon } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
@@ -154,6 +155,7 @@ export const TargetingCard = ({
|
||||
() => (localSurvey?.segment ? localSurvey.segment?.surveys?.length > 1 : false),
|
||||
[localSurvey.segment]
|
||||
);
|
||||
const [parent] = useAutoAnimate();
|
||||
|
||||
return (
|
||||
<Collapsible.Root
|
||||
@@ -176,7 +178,7 @@ export const TargetingCard = ({
|
||||
</div>
|
||||
</div>
|
||||
</Collapsible.CollapsibleTrigger>
|
||||
<Collapsible.CollapsibleContent className="min-w-full overflow-auto">
|
||||
<Collapsible.CollapsibleContent className="flex min-w-full flex-col overflow-auto" ref={parent}>
|
||||
<hr className="text-slate-600" />
|
||||
|
||||
<div className="flex flex-col gap-5 p-6">
|
||||
|
||||
+5
-1
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import {
|
||||
CheckIcon,
|
||||
@@ -126,6 +127,9 @@ export const WhenToSendCard = ({
|
||||
}
|
||||
}, [localSurvey.type]);
|
||||
|
||||
// Auto animate
|
||||
const [parent] = useAutoAnimate();
|
||||
|
||||
const containsEmptyTriggers = useMemo(() => {
|
||||
return !localSurvey.triggers || !localSurvey.triggers.length || !localSurvey.triggers[0];
|
||||
}, [localSurvey]);
|
||||
@@ -167,7 +171,7 @@ export const WhenToSendCard = ({
|
||||
</div>
|
||||
</Collapsible.CollapsibleTrigger>
|
||||
|
||||
<Collapsible.CollapsibleContent>
|
||||
<Collapsible.CollapsibleContent className="flex flex-col" ref={parent}>
|
||||
<hr className="py-1 text-slate-600" />
|
||||
|
||||
<div className="px-3 pb-3 pt-1">
|
||||
|
||||
+4
-1
@@ -11,6 +11,7 @@ import {
|
||||
} from "@dnd-kit/core";
|
||||
import { restrictToHorizontalAxis } from "@dnd-kit/modifiers";
|
||||
import { SortableContext, arrayMove, horizontalListSortingStrategy } from "@dnd-kit/sortable";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { VisibilityState, flexRender, getCoreRowModel, useReactTable } from "@tanstack/react-table";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
@@ -54,6 +55,8 @@ export const PersonTable = ({
|
||||
const [isExpanded, setIsExpanded] = useState<boolean | null>(null);
|
||||
const [rowSelection, setRowSelection] = useState({});
|
||||
const router = useRouter();
|
||||
|
||||
const [parent] = useAutoAnimate();
|
||||
// Generate columns
|
||||
const columns = useMemo(
|
||||
() => generatePersonTableColumns(isExpanded ?? false, searchValue),
|
||||
@@ -189,7 +192,7 @@ export const PersonTable = ({
|
||||
))}
|
||||
</TableHeader>
|
||||
|
||||
<TableBody>
|
||||
<TableBody ref={parent}>
|
||||
{table.getRowModel().rows.map((row) => (
|
||||
<TableRow
|
||||
key={row.id}
|
||||
|
||||
-1
@@ -43,7 +43,6 @@ export const BasicCreateSegmentModal = ({
|
||||
const [addFilterModalOpen, setAddFilterModalOpen] = useState(false);
|
||||
const [segment, setSegment] = useState<TSegment>(initialSegmentState);
|
||||
const [isCreatingSegment, setIsCreatingSegment] = useState(false);
|
||||
|
||||
const handleResetState = () => {
|
||||
setSegment(initialSegmentState);
|
||||
setOpen(false);
|
||||
|
||||
+3
-1
@@ -13,6 +13,7 @@ import {
|
||||
} from "@dnd-kit/core";
|
||||
import { restrictToHorizontalAxis } from "@dnd-kit/modifiers";
|
||||
import { SortableContext, arrayMove, horizontalListSortingStrategy } from "@dnd-kit/sortable";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { VisibilityState, getCoreRowModel, useReactTable } from "@tanstack/react-table";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { TEnvironment } from "@formbricks/types/environment";
|
||||
@@ -65,6 +66,7 @@ export const ResponseTable = ({
|
||||
const selectedResponse = responses?.find((response) => response.id === selectedResponseId) ?? null;
|
||||
const [isExpanded, setIsExpanded] = useState<boolean | null>(null);
|
||||
const [columnOrder, setColumnOrder] = useState<string[]>([]);
|
||||
const [parent] = useAutoAnimate();
|
||||
|
||||
// Generate columns
|
||||
const columns = generateResponseTableColumns(survey, isExpanded ?? false, isViewer);
|
||||
@@ -199,7 +201,7 @@ export const ResponseTable = ({
|
||||
))}
|
||||
</TableHeader>
|
||||
|
||||
<TableBody>
|
||||
<TableBody ref={parent}>
|
||||
{table.getRowModel().rows.map((row) => (
|
||||
<TableRow
|
||||
key={row.id}
|
||||
|
||||
+62
-57
@@ -8,10 +8,11 @@ import { getSurveyFilterDataAction } from "@/app/(app)/environments/[environment
|
||||
import { QuestionFilterComboBox } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/QuestionFilterComboBox";
|
||||
import { generateQuestionAndFilterOptions } from "@/app/lib/surveys/surveys";
|
||||
import { getSurveyFilterDataBySurveySharingKeyAction } from "@/app/share/[sharingKey]/actions";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import clsx from "clsx";
|
||||
import { ChevronDown, ChevronUp, Plus, TrashIcon } from "lucide-react";
|
||||
import { useParams } from "next/navigation";
|
||||
import { useEffect, useState } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { TSurvey, TSurveyQuestionTypeEnum } from "@formbricks/types/surveys/types";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { Checkbox } from "@formbricks/ui/components/Checkbox";
|
||||
@@ -31,6 +32,7 @@ interface ResponseFilterProps {
|
||||
|
||||
export const ResponseFilter = ({ survey }: ResponseFilterProps) => {
|
||||
const params = useParams();
|
||||
const [parent] = useAutoAnimate();
|
||||
const sharingKey = params.sharingKey as string;
|
||||
const isSharingPage = !!sharingKey;
|
||||
|
||||
@@ -224,63 +226,66 @@ export const ResponseFilter = ({ survey }: ResponseFilterProps) => {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{filterValue.filter?.map((s, i) => (
|
||||
<>
|
||||
<div className="flex w-full flex-wrap gap-3 md:flex-nowrap">
|
||||
<div
|
||||
className="grid w-full grid-cols-1 items-center gap-3 md:grid-cols-2"
|
||||
key={`${s.questionType.id}-${i}`}>
|
||||
<QuestionsComboBox
|
||||
key={`${s.questionType.label}-${i}`}
|
||||
options={questionComboBoxOptions}
|
||||
selected={s.questionType}
|
||||
onChangeValue={(value) => handleOnChangeQuestionComboBoxValue(value, i)}
|
||||
/>
|
||||
<QuestionFilterComboBox
|
||||
key={`${s.questionType.id}-${i}`}
|
||||
filterOptions={
|
||||
selectedOptions.questionFilterOptions.find(
|
||||
(q) =>
|
||||
(q.type === s.questionType.questionType || q.type === s.questionType.type) &&
|
||||
q.id === s.questionType.id
|
||||
)?.filterOptions
|
||||
}
|
||||
filterComboBoxOptions={
|
||||
selectedOptions.questionFilterOptions.find(
|
||||
(q) =>
|
||||
(q.type === s.questionType.questionType || q.type === s.questionType.type) &&
|
||||
q.id === s.questionType.id
|
||||
)?.filterComboBoxOptions
|
||||
}
|
||||
filterValue={filterValue.filter[i].filterType.filterValue}
|
||||
filterComboBoxValue={filterValue.filter[i].filterType.filterComboBoxValue}
|
||||
type={
|
||||
s?.questionType?.type === OptionsType.QUESTIONS
|
||||
? s?.questionType?.questionType
|
||||
: s?.questionType?.type
|
||||
}
|
||||
handleRemoveMultiSelect={(value) => handleRemoveMultiSelect(value, i)}
|
||||
onChangeFilterComboBoxValue={(value) => handleOnChangeFilterComboBoxValue(value, i)}
|
||||
onChangeFilterValue={(value) => handleOnChangeFilterValue(value, i)}
|
||||
disabled={!s?.questionType?.label}
|
||||
/>
|
||||
|
||||
<div ref={parent}>
|
||||
{filterValue.filter?.map((s, i) => (
|
||||
<React.Fragment key={i}>
|
||||
<div className="flex w-full flex-wrap gap-3 md:flex-nowrap">
|
||||
<div
|
||||
className="grid w-full grid-cols-1 items-center gap-3 md:grid-cols-2"
|
||||
key={`${s.questionType.id}-${i}`}>
|
||||
<QuestionsComboBox
|
||||
key={`${s.questionType.label}-${i}`}
|
||||
options={questionComboBoxOptions}
|
||||
selected={s.questionType}
|
||||
onChangeValue={(value) => handleOnChangeQuestionComboBoxValue(value, i)}
|
||||
/>
|
||||
<QuestionFilterComboBox
|
||||
key={`${s.questionType.id}-${i}`}
|
||||
filterOptions={
|
||||
selectedOptions.questionFilterOptions.find(
|
||||
(q) =>
|
||||
(q.type === s.questionType.questionType || q.type === s.questionType.type) &&
|
||||
q.id === s.questionType.id
|
||||
)?.filterOptions
|
||||
}
|
||||
filterComboBoxOptions={
|
||||
selectedOptions.questionFilterOptions.find(
|
||||
(q) =>
|
||||
(q.type === s.questionType.questionType || q.type === s.questionType.type) &&
|
||||
q.id === s.questionType.id
|
||||
)?.filterComboBoxOptions
|
||||
}
|
||||
filterValue={filterValue.filter[i].filterType.filterValue}
|
||||
filterComboBoxValue={filterValue.filter[i].filterType.filterComboBoxValue}
|
||||
type={
|
||||
s?.questionType?.type === OptionsType.QUESTIONS
|
||||
? s?.questionType?.questionType
|
||||
: s?.questionType?.type
|
||||
}
|
||||
handleRemoveMultiSelect={(value) => handleRemoveMultiSelect(value, i)}
|
||||
onChangeFilterComboBoxValue={(value) => handleOnChangeFilterComboBoxValue(value, i)}
|
||||
onChangeFilterValue={(value) => handleOnChangeFilterValue(value, i)}
|
||||
disabled={!s?.questionType?.label}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex w-full items-center justify-end gap-1 md:w-auto">
|
||||
<p className="block font-light text-slate-500 md:hidden">Delete</p>
|
||||
<TrashIcon
|
||||
className="w-4 cursor-pointer text-slate-500 md:text-black"
|
||||
onClick={() => handleDeleteFilter(i)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex w-full items-center justify-end gap-1 md:w-auto">
|
||||
<p className="block font-light text-slate-500 md:hidden">Delete</p>
|
||||
<TrashIcon
|
||||
className="w-4 cursor-pointer text-slate-500 md:text-black"
|
||||
onClick={() => handleDeleteFilter(i)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{i !== filterValue.filter.length - 1 && (
|
||||
<div className="my-6 flex items-center">
|
||||
<p className="mr-6 text-base text-slate-600">And</p>
|
||||
<hr className="w-full text-slate-600" />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
))}
|
||||
{i !== filterValue.filter.length - 1 && (
|
||||
<div className="my-6 flex items-center">
|
||||
<p className="mr-6 text-base text-slate-600">And</p>
|
||||
<hr className="w-full text-slate-600" />
|
||||
</div>
|
||||
)}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
<div className="mt-8 flex items-center justify-between">
|
||||
<Button size="sm" variant="secondary" onClick={handleAddNewFilter}>
|
||||
Add filter
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { getSurveysAction } from "@/app/(app)/environments/[environmentId]/surveys/actions";
|
||||
import { getFormattedFilters } from "@/app/(app)/environments/[environmentId]/surveys/lib/utils";
|
||||
import { TSurvey } from "@/app/(app)/environments/[environmentId]/surveys/types/surveys";
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { FORMBRICKS_SURVEYS_FILTERS_KEY_LS } from "@formbricks/lib/localStorage";
|
||||
import { TEnvironment } from "@formbricks/types/environment";
|
||||
@@ -49,6 +50,7 @@ export const SurveysList = ({
|
||||
const [isFilterInitialized, setIsFilterInitialized] = useState(false);
|
||||
|
||||
const filters = useMemo(() => getFormattedFilters(surveyFilters, userId), [surveyFilters, userId]);
|
||||
const [parent] = useAutoAnimate();
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window !== "undefined") {
|
||||
@@ -136,7 +138,7 @@ export const SurveysList = ({
|
||||
/>
|
||||
{surveys.length > 0 ? (
|
||||
<div>
|
||||
<div className="flex-col space-y-3">
|
||||
<div className="flex-col space-y-3" ref={parent}>
|
||||
<div className="mt-6 grid w-full grid-cols-8 place-items-center gap-3 px-6 pr-8 text-sm text-slate-800">
|
||||
<div className="col-span-2 place-self-start">Name</div>
|
||||
<div className="col-span-1">Status</div>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
import { ArrowUpRight, Languages } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
@@ -169,6 +170,8 @@ export const MultiLanguageCard: FC<MultiLanguageCardProps> = ({
|
||||
setLocalSurvey({ ...localSurvey, ...{ showLanguageSwitch: !localSurvey.showLanguageSwitch } });
|
||||
};
|
||||
|
||||
const [parent] = useAutoAnimate();
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
@@ -212,7 +215,7 @@ export const MultiLanguageCard: FC<MultiLanguageCardProps> = ({
|
||||
</div>
|
||||
</div>
|
||||
</Collapsible.CollapsibleTrigger>
|
||||
<Collapsible.CollapsibleContent className="px-4 pb-6">
|
||||
<Collapsible.CollapsibleContent className={`flex flex-col px-4 ${open && "pb-6"}`} ref={parent}>
|
||||
<div className="space-y-4">
|
||||
{!isMultiLanguageAllowed && !isFormbricksCloud && !isMultiLanguageActivated ? (
|
||||
<UpgradePlanNotice
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { structuredClone } from "@formbricks/lib/pollyfills/structuredClone";
|
||||
import { deleteResource, isResourceFilter, moveResource } from "@formbricks/lib/segment/utils";
|
||||
import { TAttributeClass } from "@formbricks/types/attribute-classes";
|
||||
@@ -21,6 +22,7 @@ export const BasicSegmentEditor = ({
|
||||
attributeClasses,
|
||||
viewOnly,
|
||||
}: BasicSegmentEditorProps) => {
|
||||
const [parent] = useAutoAnimate();
|
||||
const handleMoveResource = (resourceId: string, direction: "up" | "down") => {
|
||||
const localSegmentCopy = structuredClone(segment);
|
||||
if (localSegmentCopy.filters) {
|
||||
@@ -41,7 +43,7 @@ export const BasicSegmentEditor = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-4 rounded-lg">
|
||||
<div className="flex flex-col gap-4 rounded-lg" ref={parent}>
|
||||
{group?.map((groupItem) => {
|
||||
const { connector, resource, id: groupId } = groupItem;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { debounce } from "lodash";
|
||||
import { ImagePlusIcon, PencilIcon, TrashIcon } from "lucide-react";
|
||||
import { RefObject, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
@@ -504,6 +505,8 @@ export const QuestionFormInput = ({
|
||||
debouncedHandleUpdate(value);
|
||||
};
|
||||
|
||||
const [animationParent] = useAutoAnimate();
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<div className="w-full">
|
||||
@@ -511,7 +514,7 @@ export const QuestionFormInput = ({
|
||||
<Label htmlFor={id}>{label}</Label>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-4 bg-white">
|
||||
<div className="flex flex-col gap-4 bg-white" ref={animationParent}>
|
||||
{showImageUploader && id === "headline" && (
|
||||
<FileInput
|
||||
id="question-image"
|
||||
|
||||
Reference in New Issue
Block a user