mirror of
https://github.com/formbricks/formbricks.git
synced 2026-03-03 12:58:54 -06:00
fix: corner cases for new option empty and duplicates in single and multi select
This commit is contained in:
@@ -34,7 +34,7 @@ export default function MultipleChoiceMultiForm({
|
||||
const [isNew, setIsNew] = useState(true);
|
||||
const [showSubheader, setShowSubheader] = useState(!!question.subheader);
|
||||
const questionRef = useRef<HTMLInputElement>(null);
|
||||
const [isInvalidValue, setIsInvalidValue] = useState<string>("");
|
||||
const [isInvalidValue, setIsInvalidValue] = useState<string | null>(null);
|
||||
|
||||
const shuffleOptionsTypes = {
|
||||
none: {
|
||||
@@ -89,6 +89,13 @@ export default function MultipleChoiceMultiForm({
|
||||
return null;
|
||||
};
|
||||
|
||||
const findEmptyLabel = () => {
|
||||
for (let i = 0; i < question.choices.length; i++) {
|
||||
if (question.choices[i].label.trim() === "") return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const addChoice = (choiceIdx?: number) => {
|
||||
setIsNew(false); // This question is no longer new.
|
||||
let newChoices = !question.choices ? [] : question.choices;
|
||||
@@ -125,6 +132,9 @@ export default function MultipleChoiceMultiForm({
|
||||
const newChoices = !question.choices ? [] : question.choices.filter((_, idx) => idx !== choiceIdx);
|
||||
|
||||
const choiceValue = question.choices[choiceIdx].label;
|
||||
if (isInvalidValue === choiceValue) {
|
||||
setIsInvalidValue(null);
|
||||
}
|
||||
let newLogic: any[] = [];
|
||||
question.logic?.forEach((logic) => {
|
||||
let newL: string | string[] | undefined = logic.value;
|
||||
@@ -215,13 +225,16 @@ export default function MultipleChoiceMultiForm({
|
||||
const duplicateLabel = findDuplicateLabel();
|
||||
if (duplicateLabel) {
|
||||
setIsInvalidValue(duplicateLabel);
|
||||
} else {
|
||||
} else if (findEmptyLabel()) {
|
||||
setIsInvalidValue("");
|
||||
} else {
|
||||
setIsInvalidValue(null);
|
||||
}
|
||||
}}
|
||||
isInvalid={
|
||||
(isInValid != null && question.choices[choiceIdx].label.trim() === "") ||
|
||||
(isInvalidValue !== null && choice.label.trim() === isInvalidValue.trim())
|
||||
isInValid &&
|
||||
((isInvalidValue === "" && choice.label.trim() === "") ||
|
||||
(isInvalidValue !== null && choice.label.trim() === isInvalidValue.trim()))
|
||||
}
|
||||
/>
|
||||
{question.choices && question.choices.length > 2 && (
|
||||
|
||||
@@ -33,6 +33,7 @@ export default function MultipleChoiceSingleForm({
|
||||
const lastChoiceRef = useRef<HTMLInputElement>(null);
|
||||
const [isNew, setIsNew] = useState(true);
|
||||
const [showSubheader, setShowSubheader] = useState(!!question.subheader);
|
||||
const [isInvalidValue, setIsInvalidValue] = useState<string | null>(null);
|
||||
const questionRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const shuffleOptionsTypes = {
|
||||
@@ -53,6 +54,24 @@ export default function MultipleChoiceSingleForm({
|
||||
},
|
||||
};
|
||||
|
||||
const findDuplicateLabel = () => {
|
||||
for (let i = 0; i < question.choices.length; i++) {
|
||||
for (let j = i + 1; j < question.choices.length; j++) {
|
||||
if (question.choices[i].label.trim() === question.choices[j].label.trim()) {
|
||||
return question.choices[i].label.trim(); // Return the duplicate label
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const findEmptyLabel = () => {
|
||||
for (let i = 0; i < question.choices.length; i++) {
|
||||
if (question.choices[i].label.trim() === "") return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const updateChoice = (choiceIdx: number, updatedAttributes: { label: string }) => {
|
||||
const newLabel = updatedAttributes.label;
|
||||
const oldLabel = question.choices[choiceIdx].label;
|
||||
@@ -113,6 +132,9 @@ export default function MultipleChoiceSingleForm({
|
||||
const newChoices = !question.choices ? [] : question.choices.filter((_, idx) => idx !== choiceIdx);
|
||||
|
||||
const choiceValue = question.choices[choiceIdx].label;
|
||||
if (isInvalidValue === choiceValue) {
|
||||
setIsInvalidValue(null);
|
||||
}
|
||||
let newLogic: any[] = [];
|
||||
question.logic?.forEach((logic) => {
|
||||
let newL: string | string[] | undefined = logic.value;
|
||||
@@ -198,15 +220,21 @@ export default function MultipleChoiceSingleForm({
|
||||
value={choice.label}
|
||||
className={cn(choice.id === "other" && "border-dashed")}
|
||||
placeholder={choice.id === "other" ? "Other" : `Option ${choiceIdx + 1}`}
|
||||
onBlur={() => {
|
||||
const duplicateLabel = findDuplicateLabel();
|
||||
if (duplicateLabel) {
|
||||
setIsInvalidValue(duplicateLabel);
|
||||
} else if (findEmptyLabel()) {
|
||||
setIsInvalidValue("");
|
||||
} else {
|
||||
setIsInvalidValue(null);
|
||||
}
|
||||
}}
|
||||
onChange={(e) => updateChoice(choiceIdx, { label: e.target.value })}
|
||||
isInvalid={
|
||||
isInValid &&
|
||||
(choice.label.trim() === "" ||
|
||||
question.choices.some((element, index) =>
|
||||
question.choices
|
||||
.slice(index + 1)
|
||||
.some((nextElement) => nextElement.label.trim() === element.label.trim())
|
||||
))
|
||||
((isInvalidValue === "" && choice.label.trim() === "") ||
|
||||
(isInvalidValue !== null && choice.label.trim() === isInvalidValue.trim()))
|
||||
}
|
||||
/>
|
||||
{question.choices && question.choices.length > 2 && (
|
||||
|
||||
@@ -23,7 +23,7 @@ export default function UpdateQuestionId({ localSurvey, question, questionIdx, u
|
||||
toast.error("IDs have to be unique per survey.");
|
||||
} else if (currentValue.trim() === "" || currentValue.includes(" ")) {
|
||||
setIsInputInvalid(true);
|
||||
toast.error("ID should not contain space.");
|
||||
toast.error("ID should not be empty.");
|
||||
} else {
|
||||
setIsInputInvalid(false);
|
||||
toast.success("Question ID updated.");
|
||||
|
||||
Reference in New Issue
Block a user