From 284361aabaefad171e002e9ad4a3a3ecbb0207d0 Mon Sep 17 00:00:00 2001 From: ShubhamPalriwala Date: Wed, 6 Sep 2023 23:33:15 +0530 Subject: [PATCH] fix: corner cases for new option empty and duplicates in single and multi select --- .../edit/MultipleChoiceMultiForm.tsx | 21 ++++++++-- .../edit/MultipleChoiceSingleForm.tsx | 40 ++++++++++++++++--- .../[surveyId]/edit/UpdateQuestionId.tsx | 2 +- 3 files changed, 52 insertions(+), 11 deletions(-) diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/MultipleChoiceMultiForm.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/MultipleChoiceMultiForm.tsx index c19e433bf6..424cb742cb 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/MultipleChoiceMultiForm.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/MultipleChoiceMultiForm.tsx @@ -34,7 +34,7 @@ export default function MultipleChoiceMultiForm({ const [isNew, setIsNew] = useState(true); const [showSubheader, setShowSubheader] = useState(!!question.subheader); const questionRef = useRef(null); - const [isInvalidValue, setIsInvalidValue] = useState(""); + const [isInvalidValue, setIsInvalidValue] = useState(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 && ( diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/MultipleChoiceSingleForm.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/MultipleChoiceSingleForm.tsx index e6d5cbc19d..b88e92c2b4 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/MultipleChoiceSingleForm.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/MultipleChoiceSingleForm.tsx @@ -33,6 +33,7 @@ export default function MultipleChoiceSingleForm({ const lastChoiceRef = useRef(null); const [isNew, setIsNew] = useState(true); const [showSubheader, setShowSubheader] = useState(!!question.subheader); + const [isInvalidValue, setIsInvalidValue] = useState(null); const questionRef = useRef(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 && ( diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/UpdateQuestionId.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/UpdateQuestionId.tsx index 32ad333608..08650618e8 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/UpdateQuestionId.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/edit/UpdateQuestionId.tsx @@ -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.");