mirror of
https://github.com/formbricks/formbricks.git
synced 2026-04-23 05:17:49 -05:00
Fix Preview on Delete in Survey Builder & Fix Button Text on light brand color (#284)
* Fix Preview on Delete in Survey Builder * Fix Button Text on light brand color --------- Co-authored-by: Matthias Nannt <mail@matthiasnannt.com>
This commit is contained in:
@@ -42,8 +42,10 @@ export default function PreviewSurvey({
|
||||
setProgress(calculateProgress(questions, lastActiveQuestionId));
|
||||
}
|
||||
|
||||
function calculateProgress(questions, id) {
|
||||
const elementIdx = questions.findIndex((e) => e.id === id);
|
||||
function calculateProgress(questions, activeQuestionId) {
|
||||
if (activeQuestionId === "thank-you-card") return 1;
|
||||
|
||||
const elementIdx = questions.findIndex((e) => e.id === activeQuestionId);
|
||||
return elementIdx / questions.length;
|
||||
}
|
||||
}, [activeQuestionId, lastActiveQuestionId, questions]);
|
||||
|
||||
+14
-3
@@ -22,18 +22,29 @@ export default function QuestionDropdown({
|
||||
<EllipsisHorizontalIcon className="h-5 w-5 text-slate-600 focus:outline-none active:outline-none" />
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
<DropdownMenuItem className="justify-between" onClick={() => deleteQuestion(questionIdx)}>
|
||||
<DropdownMenuItem
|
||||
className="justify-between"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
deleteQuestion(questionIdx);
|
||||
}}>
|
||||
Delete <TrashIcon className="ml-3 h-4" />
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
className="justify-between"
|
||||
onClick={() => moveQuestion(questionIdx, true)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
moveQuestion(questionIdx, true);
|
||||
}}
|
||||
disabled={questionIdx == 0}>
|
||||
Move up <ArrowUpIcon className="ml-3 h-4" />
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
className="justify-between"
|
||||
onClick={() => moveQuestion(questionIdx, false)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
moveQuestion(questionIdx, false);
|
||||
}}
|
||||
disabled={lastQuestion}>
|
||||
Move down
|
||||
<ArrowDownIcon className="h-4" />
|
||||
|
||||
+13
-1
@@ -48,10 +48,22 @@ export default function QuestionsView({
|
||||
};
|
||||
|
||||
const deleteQuestion = (questionIdx: number) => {
|
||||
const questionId = localSurvey.questions[questionIdx].id;
|
||||
|
||||
const updatedSurvey = JSON.parse(JSON.stringify(localSurvey));
|
||||
updatedSurvey.questions.splice(questionIdx, 1);
|
||||
setLocalSurvey(updatedSurvey);
|
||||
delete internalQuestionIdMap[localSurvey.questions[questionIdx].id];
|
||||
delete internalQuestionIdMap[questionId];
|
||||
|
||||
if (questionId === activeQuestionId) {
|
||||
if (questionIdx < localSurvey.questions.length - 1) {
|
||||
setActiveQuestionId(localSurvey.questions[questionIdx + 1].id);
|
||||
} else if (localSurvey.thankYouCard.enabled) {
|
||||
setActiveQuestionId("thank-you-card");
|
||||
} else {
|
||||
setActiveQuestionId(localSurvey.questions[questionIdx - 1].id);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const addQuestion = (question: any) => {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import type { CTAQuestion } from "@formbricks/types/questions";
|
||||
import Headline from "./Headline";
|
||||
import HtmlBody from "./HtmlBody";
|
||||
import { cn } from "@/../../packages/lib/cn";
|
||||
import { isLight } from "@/lib/utils";
|
||||
|
||||
interface CTAQuestionProps {
|
||||
question: CTAQuestion;
|
||||
@@ -35,7 +37,10 @@ export default function CTAQuestion({ question, onSubmit, lastQuestion, brandCol
|
||||
}
|
||||
onSubmit({ [question.id]: "clicked" });
|
||||
}}
|
||||
className="flex items-center rounded-md border border-transparent px-3 py-3 text-base font-medium leading-4 text-white shadow-sm hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-slate-500 focus:ring-offset-2"
|
||||
className={cn(
|
||||
"flex items-center rounded-md border border-transparent px-3 py-3 text-base font-medium leading-4 shadow-sm hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-slate-500 focus:ring-offset-2",
|
||||
isLight(brandColor) ? "text-black" : "text-white"
|
||||
)}
|
||||
style={{ backgroundColor: brandColor }}>
|
||||
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
|
||||
</button>
|
||||
|
||||
@@ -3,6 +3,7 @@ import { cn } from "@formbricks/lib/cn";
|
||||
import type { MultipleChoiceMultiQuestion } from "@formbricks/types/questions";
|
||||
import Headline from "./Headline";
|
||||
import Subheader from "./Subheader";
|
||||
import SubmitButton from "@/components/preview/SubmitButton";
|
||||
|
||||
interface MultipleChoiceMultiProps {
|
||||
question: MultipleChoiceMultiQuestion;
|
||||
@@ -93,12 +94,7 @@ export default function MultipleChoiceMultiQuestion({
|
||||
/>
|
||||
<div className="mt-4 flex w-full justify-between">
|
||||
<div></div>
|
||||
<button
|
||||
type="submit"
|
||||
className="flex items-center rounded-md border border-transparent px-3 py-3 text-base font-medium leading-4 text-white shadow-sm hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-slate-500 focus:ring-offset-2"
|
||||
style={{ backgroundColor: brandColor }}>
|
||||
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
|
||||
</button>
|
||||
<SubmitButton {...{ question, lastQuestion, brandColor }} />
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { MultipleChoiceSingleQuestion } from "@formbricks/types/questions";
|
||||
import { useState } from "react";
|
||||
import Headline from "./Headline";
|
||||
import Subheader from "./Subheader";
|
||||
import SubmitButton from "@/components/preview/SubmitButton";
|
||||
|
||||
interface MultipleChoiceSingleProps {
|
||||
question: MultipleChoiceSingleQuestion;
|
||||
@@ -69,12 +70,7 @@ export default function MultipleChoiceSingleQuestion({
|
||||
</div>
|
||||
<div className="mt-4 flex w-full justify-between">
|
||||
<div></div>
|
||||
<button
|
||||
type="submit"
|
||||
className="flex items-center rounded-md border border-transparent px-3 py-3 text-base font-medium leading-4 text-white shadow-sm hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-slate-500 focus:ring-offset-2"
|
||||
style={{ backgroundColor: brandColor }}>
|
||||
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
|
||||
</button>
|
||||
<SubmitButton {...{ question, lastQuestion, brandColor }} />
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
|
||||
@@ -3,6 +3,7 @@ import { cn } from "@formbricks/lib/cn";
|
||||
import type { NPSQuestion } from "@formbricks/types/questions";
|
||||
import Headline from "./Headline";
|
||||
import Subheader from "./Subheader";
|
||||
import SubmitButton from "@/components/preview/SubmitButton";
|
||||
|
||||
interface NPSQuestionProps {
|
||||
question: NPSQuestion;
|
||||
@@ -69,12 +70,7 @@ export default function NPSQuestion({ question, onSubmit, lastQuestion, brandCol
|
||||
{!question.required && (
|
||||
<div className="mt-4 flex w-full justify-between">
|
||||
<div></div>
|
||||
<button
|
||||
type="submit"
|
||||
className="flex items-center rounded-md border border-transparent px-3 py-3 text-base font-medium leading-4 text-white shadow-sm hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-slate-500 focus:ring-offset-2"
|
||||
style={{ backgroundColor: brandColor }}>
|
||||
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
|
||||
</button>
|
||||
<SubmitButton {...{ question, lastQuestion, brandColor }} />
|
||||
</div>
|
||||
)}
|
||||
</form>
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { OpenTextQuestion } from "@formbricks/types/questions";
|
||||
import { useState } from "react";
|
||||
import Headline from "./Headline";
|
||||
import Subheader from "./Subheader";
|
||||
import SubmitButton from "@/components/preview/SubmitButton";
|
||||
|
||||
interface OpenTextQuestionProps {
|
||||
question: OpenTextQuestion;
|
||||
@@ -44,12 +45,7 @@ export default function OpenTextQuestion({
|
||||
</div>
|
||||
<div className="mt-4 flex w-full justify-between">
|
||||
<div></div>
|
||||
<button
|
||||
type="submit"
|
||||
className="flex items-center rounded-md border border-transparent px-3 py-3 text-base font-medium leading-4 text-white shadow-sm hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-slate-500 focus:ring-offset-2"
|
||||
style={{ backgroundColor: brandColor }}>
|
||||
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
|
||||
</button>
|
||||
<SubmitButton {...{ question, lastQuestion, brandColor }} />
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
TiredFace,
|
||||
WearyFace,
|
||||
} from "../Smileys";
|
||||
import SubmitButton from "@/components/preview/SubmitButton";
|
||||
|
||||
interface RatingQuestionProps {
|
||||
question: RatingQuestion;
|
||||
@@ -130,12 +131,7 @@ export default function RatingQuestion({
|
||||
{!question.required && (
|
||||
<div className="mt-4 flex w-full justify-between">
|
||||
<div></div>
|
||||
<button
|
||||
type="submit"
|
||||
className="flex items-center rounded-md border border-transparent px-3 py-3 text-base font-medium leading-4 text-white shadow-sm hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-slate-500 focus:ring-offset-2"
|
||||
style={{ backgroundColor: brandColor }}>
|
||||
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
|
||||
</button>
|
||||
<SubmitButton {...{ question, lastQuestion, brandColor }} />
|
||||
</div>
|
||||
)}
|
||||
</form>
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import { cn } from "@/../../packages/lib/cn";
|
||||
import { isLight } from "@/lib/utils";
|
||||
|
||||
function SubmitButton({ question, lastQuestion, brandColor }) {
|
||||
return (
|
||||
<button
|
||||
type="submit"
|
||||
className={cn(
|
||||
"flex items-center rounded-md border border-transparent px-3 py-3 text-base font-medium leading-4 text-white shadow-sm hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-slate-500 focus:ring-offset-2",
|
||||
isLight(brandColor) ? "text-black" : "text-white"
|
||||
)}
|
||||
style={{ backgroundColor: brandColor }}>
|
||||
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
export default SubmitButton;
|
||||
@@ -39,3 +39,17 @@ export const scrollToTop = () => {
|
||||
behavior: "smooth",
|
||||
});
|
||||
};
|
||||
|
||||
export function isLight(color) {
|
||||
let r, g, b;
|
||||
if (color.length === 4) {
|
||||
r = parseInt(color[1] + color[1], 16);
|
||||
g = parseInt(color[2] + color[2], 16);
|
||||
b = parseInt(color[3] + color[3], 16);
|
||||
} else if (color.length === 7) {
|
||||
r = parseInt(color[1] + color[2], 16);
|
||||
g = parseInt(color[3] + color[4], 16);
|
||||
b = parseInt(color[5] + color[6], 16);
|
||||
}
|
||||
return r * 0.299 + g * 0.587 + b * 0.114 > 128;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { CTAQuestion } from "../../../types/questions";
|
||||
import { h } from "preact";
|
||||
import Headline from "./Headline";
|
||||
import HtmlBody from "./HtmlBody";
|
||||
import SubmitButton from "./SubmitButton";
|
||||
|
||||
interface CTAQuestionProps {
|
||||
question: CTAQuestion;
|
||||
@@ -28,7 +29,7 @@ export default function CTAQuestion({ question, onSubmit, lastQuestion, brandCol
|
||||
{question.dismissButtonLabel || "Skip"}
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
{/* <button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
if (question.buttonExternal && question.buttonUrl) {
|
||||
@@ -39,7 +40,19 @@ export default function CTAQuestion({ question, onSubmit, lastQuestion, brandCol
|
||||
className="fb-flex fb-items-center fb-rounded-md fb-border fb-border-transparent fb-px-3 fb-py-3 fb-text-base fb-font-medium fb-leading-4 fb-text-white fb-shadow-sm fb-hover:opacity-90 fb-focus:outline-none fb-focus:ring-2 fb-focus:ring-slate-500 fb-focus:ring-offset-2"
|
||||
style={{ backgroundColor: brandColor }}>
|
||||
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
|
||||
</button>
|
||||
</button> */}
|
||||
<SubmitButton
|
||||
question={question}
|
||||
lastQuestion={lastQuestion}
|
||||
brandColor={brandColor}
|
||||
onClick={() => {
|
||||
if (question.buttonExternal && question.buttonUrl) {
|
||||
window?.open(question.buttonUrl, "_blank")?.focus();
|
||||
}
|
||||
onSubmit({ [question.id]: "clicked" });
|
||||
}}
|
||||
type="button"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useState } from "preact/hooks";
|
||||
import { cn } from "../lib/utils";
|
||||
import Headline from "./Headline";
|
||||
import Subheader from "./Subheader";
|
||||
import SubmitButton from "./SubmitButton";
|
||||
|
||||
interface MultipleChoiceMultiProps {
|
||||
question: MultipleChoiceMultiQuestion;
|
||||
@@ -90,12 +91,12 @@ export default function MultipleChoiceMultiQuestion({
|
||||
/>
|
||||
<div className="fb-mt-4 fb-flex fb-w-full fb-justify-between">
|
||||
<div></div>
|
||||
<button
|
||||
type="submit"
|
||||
className="fb-flex fb-items-center fb-rounded-md fb-border fb-border-transparent fb-px-3 fb-py-3 fb-text-base fb-font-medium fb-leading-4 fb-text-white fb-shadow-sm hover:fb-opacity-90 focus:fb-outline-none focus:fb-ring-2 focus:fb-ring-offset-2 focus:fb-ring-slate-500"
|
||||
style={{ backgroundColor: brandColor }}>
|
||||
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
|
||||
</button>
|
||||
<SubmitButton
|
||||
question={question}
|
||||
lastQuestion={lastQuestion}
|
||||
brandColor={brandColor}
|
||||
onClick={() => {}}
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
|
||||
@@ -4,6 +4,7 @@ import { cn } from "../lib/utils";
|
||||
import type { MultipleChoiceSingleQuestion } from "../../../types/questions";
|
||||
import Headline from "./Headline";
|
||||
import Subheader from "./Subheader";
|
||||
import SubmitButton from "./SubmitButton";
|
||||
|
||||
interface MultipleChoiceSingleProps {
|
||||
question: MultipleChoiceSingleQuestion;
|
||||
@@ -71,12 +72,12 @@ export default function MultipleChoiceSingleQuestion({
|
||||
</div>
|
||||
<div className="fb-mt-4 fb-flex fb-w-full fb-justify-between">
|
||||
<div></div>
|
||||
<button
|
||||
type="submit"
|
||||
className="fb-flex fb-items-center fb-rounded-md fb-border fb-border-transparent fb-px-3 fb-py-3 fb-text-base fb-font-medium fb-leading-4 fb-text-white fb-shadow-sm hover:fb-opacity-90 focus:fb-outline-none focus:fb-ring-2 focus:fb-ring-offset-2 focus:ring-slate-500"
|
||||
style={{ backgroundColor: brandColor }}>
|
||||
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
|
||||
</button>
|
||||
<SubmitButton
|
||||
question={question}
|
||||
lastQuestion={lastQuestion}
|
||||
brandColor={brandColor}
|
||||
onClick={() => {}}
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
|
||||
@@ -4,6 +4,7 @@ import { cn } from "../lib/utils";
|
||||
import type { NPSQuestion } from "../../../types/questions";
|
||||
import Headline from "./Headline";
|
||||
import Subheader from "./Subheader";
|
||||
import SubmitButton from "./SubmitButton";
|
||||
|
||||
interface NPSQuestionProps {
|
||||
question: NPSQuestion;
|
||||
@@ -70,12 +71,12 @@ export default function NPSQuestion({ question, onSubmit, lastQuestion, brandCol
|
||||
{!question.required && (
|
||||
<div className="fb-mt-4 fb-flex fb-w-full fb-justify-between">
|
||||
<div></div>
|
||||
<button
|
||||
type="submit"
|
||||
className="fb-flex fb-items-center fb-rounded-md fb-border fb-border-transparent fb-px-3 fb-py-3 fb-text-base fb-font-medium fb-leading-4 fb-text-white fb-shadow-sm hover:fb-opacity-90 focus:fb-outline-none focus:fb-ring-2 focus:fb-ring-offset-2 focus:fb-ring-slate-500"
|
||||
style={{ backgroundColor: brandColor }}>
|
||||
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
|
||||
</button>
|
||||
<SubmitButton
|
||||
question={question}
|
||||
lastQuestion={lastQuestion}
|
||||
brandColor={brandColor}
|
||||
onClick={() => {}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</form>
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { OpenTextQuestion } from "../../../types/questions";
|
||||
import { h } from "preact";
|
||||
import Headline from "./Headline";
|
||||
import Subheader from "./Subheader";
|
||||
import SubmitButton from "./SubmitButton";
|
||||
|
||||
interface OpenTextQuestionProps {
|
||||
question: OpenTextQuestion;
|
||||
@@ -40,12 +41,12 @@ export default function OpenTextQuestion({
|
||||
</div>
|
||||
<div className="fb-mt-4 fb-flex fb-w-full fb-justify-between">
|
||||
<div></div>
|
||||
<button
|
||||
type="submit"
|
||||
className="fb-flex fb-items-center fb-rounded-md fb-border fb-border-transparent fb-px-3 fb-py-3 fb-text-base fb-font-medium fb-leading-4 fb-text-white fb-shadow-sm hover:fb-opacity-90 focus:fb-outline-none focus:fb-ring-2 focus:fb-ring-offset-2 focus:fb-ring-slate-500"
|
||||
style={{ backgroundColor: brandColor }}>
|
||||
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
|
||||
</button>
|
||||
<SubmitButton
|
||||
question={question}
|
||||
lastQuestion={lastQuestion}
|
||||
brandColor={brandColor}
|
||||
onClick={() => {}}
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
TiredFace,
|
||||
WearyFace,
|
||||
} from "./Smileys";
|
||||
import SubmitButton from "./SubmitButton";
|
||||
|
||||
interface RatingQuestionProps {
|
||||
question: RatingQuestion;
|
||||
@@ -149,12 +150,12 @@ export default function RatingQuestion({
|
||||
{!question.required && (
|
||||
<div className="fb-mt-4 fb-flex fb-w-full fb-justify-between">
|
||||
<div></div>
|
||||
<button
|
||||
type="submit"
|
||||
className="fb-flex fb-items-center fb-rounded-md fb-border fb-border-transparent fb-px-3 fb-py-3 fb-text-base fb-font-medium fb-leading-4 fb-text-white fb-shadow-sm hover:fb-opacity-90 focus:fb-outline-none focus:fb-ring-2 focus:fb-ring-slate-500 focus:fb-ring-offset-2"
|
||||
style={{ backgroundColor: brandColor }}>
|
||||
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
|
||||
</button>
|
||||
<SubmitButton
|
||||
question={question}
|
||||
lastQuestion={lastQuestion}
|
||||
brandColor={brandColor}
|
||||
onClick={() => {}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</form>
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { h } from "preact";
|
||||
|
||||
import { cn } from "@/../../packages/lib/cn";
|
||||
import { isLight } from "../lib/utils";
|
||||
|
||||
function SubmitButton({ question, lastQuestion, brandColor, onClick, type = "submit" }) {
|
||||
return (
|
||||
<button
|
||||
type={type}
|
||||
className={cn(
|
||||
"fb-flex fb-items-center fb-rounded-md fb-border fb-border-transparent fb-px-3 fb-py-3 fb-text-base fb-font-medium fb-leading-4 fb-shadow-sm hover:fb-opacity-90 focus:fb-outline-none focus:fb-ring-2 focus:fb-ring-slate-500 focus:fb-ring-offset-2",
|
||||
isLight(brandColor) ? "fb-text-black" : "fb-text-white"
|
||||
)}
|
||||
style={{ backgroundColor: brandColor }}
|
||||
onClick={onClick}>
|
||||
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
export default SubmitButton;
|
||||
@@ -1,3 +1,17 @@
|
||||
export const cn = (...classes) => {
|
||||
return classes.filter(Boolean).join(" ");
|
||||
};
|
||||
|
||||
export function isLight(color) {
|
||||
let r, g, b;
|
||||
if (color.length === 4) {
|
||||
r = parseInt(color[1] + color[1], 16);
|
||||
g = parseInt(color[2] + color[2], 16);
|
||||
b = parseInt(color[3] + color[3], 16);
|
||||
} else if (color.length === 7) {
|
||||
r = parseInt(color[1] + color[2], 16);
|
||||
g = parseInt(color[3] + color[4], 16);
|
||||
b = parseInt(color[5] + color[6], 16);
|
||||
}
|
||||
return r * 0.299 + g * 0.587 + b * 0.114 > 128;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user