mirror of
https://github.com/formbricks/formbricks.git
synced 2026-04-21 03:03:25 -05:00
Component for QuestionTypeSelector
This commit is contained in:
+12
-22
@@ -1,14 +1,14 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React, { useState } from "react";
|
||||
import { TSurveyOpenTextQuestion, TSurveyWithAnalytics } from "@formbricks/types/v1/surveys";
|
||||
import { Button, Input, Label } from "@formbricks/ui";
|
||||
import { Button, Input, Label, QuestionTypeSelector } from "@formbricks/ui";
|
||||
import { TrashIcon, PlusIcon } from "@heroicons/react/24/solid";
|
||||
|
||||
const questionTypes = [
|
||||
{ value: "text", label: "Text" },
|
||||
{ value: "email", label: "Email" },
|
||||
{ value: "url", label: "URL" },
|
||||
{ value: "number", label: "Number" },
|
||||
{ value: "phone", label: "Phone Number" },
|
||||
{ value: "text", label: "Text 📝" },
|
||||
{ value: "email", label: "Email 📧" },
|
||||
{ value: "url", label: "URL 🌐" },
|
||||
{ value: "number", label: "Number 1️⃣" },
|
||||
{ value: "phone", label: "Phone ☎️" },
|
||||
];
|
||||
|
||||
interface OpenQuestionFormProps {
|
||||
@@ -28,15 +28,10 @@ export default function OpenQuestionForm({
|
||||
}: OpenQuestionFormProps): JSX.Element {
|
||||
const [showSubheader, setShowSubheader] = useState(!!question.subheader);
|
||||
|
||||
// Function to handle question type change
|
||||
const handleQuestionTypeChange = (value: string) => {
|
||||
updateQuestion(questionIdx, { inputType: value });
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
handleQuestionTypeChange("text");
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<form>
|
||||
<div className="mt-3">
|
||||
@@ -98,16 +93,11 @@ export default function OpenQuestionForm({
|
||||
<div className="mt-3">
|
||||
<Label htmlFor="questionType">Question Type</Label>
|
||||
<div className="flex items-center">
|
||||
{questionTypes.map((type) => (
|
||||
<div
|
||||
key={type.value}
|
||||
onClick={() => handleQuestionTypeChange(type.value)}
|
||||
className={`mr-2 cursor-pointer rounded-md border p-2 ${
|
||||
question.inputType === type.value ? "bg-slate-50" : "bg-white"
|
||||
}`}>
|
||||
{type.label}
|
||||
</div>
|
||||
))}
|
||||
<QuestionTypeSelector
|
||||
questionTypes={questionTypes}
|
||||
currentType={question.inputType}
|
||||
handleTypeChange={handleQuestionTypeChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -6,7 +6,10 @@ import Subheader from "./Subheader";
|
||||
import SubmitButton from "./SubmitButton";
|
||||
import { useState } from "preact/hooks";
|
||||
|
||||
function validateInput(value: string, questionType: string): boolean {
|
||||
function validateInput(value: string, questionType: string, required: boolean): boolean {
|
||||
if (!required && (value == undefined || value == "" || value == null || value.length <= 0)) {
|
||||
return true;
|
||||
}
|
||||
switch (questionType) {
|
||||
case "email":
|
||||
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
@@ -15,7 +18,8 @@ function validateInput(value: string, questionType: string): boolean {
|
||||
const urlPattern = /^(ftp|http|https):\/\/[^ "]+$/;
|
||||
return urlPattern.test(value);
|
||||
case "number":
|
||||
return !isNaN(parseFloat(value));
|
||||
const numberPattern = /^[0-9]*$/;
|
||||
return numberPattern.test(value);
|
||||
case "phone":
|
||||
const phonePattern = /^\+?[0-9]+$/;
|
||||
return phonePattern.test(value);
|
||||
@@ -47,10 +51,12 @@ export default function OpenTextQuestion({
|
||||
brandColor,
|
||||
autoFocus = true,
|
||||
}: OpenTextQuestionProps) {
|
||||
const [isValid, setIsValid] = useState(true);
|
||||
const [isValid, setIsValid] = useState(
|
||||
validateInput(value as string, question.inputType, question.required)
|
||||
);
|
||||
|
||||
const handleInputChange = (inputValue: string) => {
|
||||
const isValidInput = validateInput(inputValue, question.inputType);
|
||||
const isValidInput = validateInput(inputValue, question.inputType, question.required);
|
||||
setIsValid(isValidInput);
|
||||
onChange({ [question.id]: inputValue });
|
||||
};
|
||||
@@ -59,6 +65,7 @@ export default function OpenTextQuestion({
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
validateInput(value as string, question.inputType, question.required);
|
||||
if (isValid) {
|
||||
onSubmit({ [question.id]: value, inputType: question.inputType });
|
||||
}
|
||||
@@ -94,6 +101,7 @@ export default function OpenTextQuestion({
|
||||
isValid ? "border-slate-100" : "border-red-500" // Apply red border for invalid input
|
||||
} bg-slate-50 p-2 shadow-sm focus:border-slate-500 focus:outline-none focus:ring-0 sm:text-sm`}></textarea>
|
||||
)}
|
||||
{!isValid && <p className="text-red-500">Please enter a valid {question.inputType}</p>}
|
||||
</div>
|
||||
<div className="mt-4 flex w-full justify-between">
|
||||
{!isFirstQuestion && (
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import React from "react";
|
||||
|
||||
interface QuestionType {
|
||||
value: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
interface QuestionTypeSelectorProps {
|
||||
questionTypes: QuestionType[];
|
||||
currentType: string | undefined;
|
||||
handleTypeChange: (value: string) => void;
|
||||
}
|
||||
|
||||
export function QuestionTypeSelector({
|
||||
questionTypes,
|
||||
currentType,
|
||||
handleTypeChange,
|
||||
}: QuestionTypeSelectorProps): JSX.Element {
|
||||
return (
|
||||
<div className="flex items-center rounded-md border p-2">
|
||||
{questionTypes.map((type, index) => (
|
||||
<div
|
||||
key={type.value}
|
||||
onClick={() => handleTypeChange(type.value)}
|
||||
className={`mr-2 cursor-pointer rounded-md ${
|
||||
(currentType === undefined && type.value === "text") || currentType === type.value
|
||||
? "bg-slate-100"
|
||||
: "bg-white"
|
||||
}`}
|
||||
style={{ marginLeft: index !== 0 ? "8px" : "0" }}>
|
||||
{type.label}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -73,6 +73,7 @@ export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./comp
|
||||
export { AddVariablesDropdown, Editor } from "./components/editor";
|
||||
export { Skeleton } from "./components/Skeleton";
|
||||
export { NoMobileOverlay } from "./components/NoMobileOverlay";
|
||||
export { QuestionTypeSelector } from "./components/QuestionTypeSelector";
|
||||
|
||||
/* Icons */
|
||||
export { AngryBirdRage2Icon } from "./components/icons/AngryBirdRage2Icon";
|
||||
|
||||
Reference in New Issue
Block a user