fix: input clear on operand change

This commit is contained in:
Piyush Gupta
2024-09-11 14:10:26 +05:30
parent 6b829744a1
commit af4ae38564
8 changed files with 118 additions and 106 deletions
@@ -25,7 +25,7 @@ export function AdvancedLogicEditor({
isLast,
}: AdvancedLogicEditorProps) {
return (
<div className={cn("no-scrollbar flex w-full grow flex-col gap-4 overflow-x-auto text-sm")}>
<div className={cn("flex w-full grow flex-col gap-4 overflow-x-auto text-sm")}>
<AdvancedLogicEditorConditions
conditions={logicItem.conditions}
updateQuestion={updateQuestion}
@@ -45,7 +45,7 @@ export function AdvancedLogicEditorActions({
const actions = logicItem.actions;
const handleActionsChange = (
operation: "delete" | "addBelow" | "duplicate" | "update",
operation: "remove" | "addBelow" | "duplicate" | "update",
actionIdx: number,
action?: TAction
) => {
@@ -53,7 +53,7 @@ export function AdvancedLogicEditorActions({
const logicItem = logicCopy[logicIdx];
const actionsClone = logicItem.actions;
if (operation === "delete") {
if (operation === "remove") {
actionsClone.splice(actionIdx, 1);
} else if (operation === "addBelow") {
actionsClone.splice(actionIdx + 1, 0, { id: createId(), objective: "jumpToQuestion", target: "" });
@@ -110,7 +110,7 @@ export function AdvancedLogicEditorActions({
target: val,
});
}}
comboboxClasses="w-40"
comboboxClasses="grow"
/>
)}
{action.objective === "calculate" && (
@@ -129,10 +129,11 @@ export function AdvancedLogicEditorActions({
},
});
}}
comboboxClasses="w-40"
comboboxClasses="grow"
emptyDropdownText="Add a variable to calculate"
/>
<InputCombobox
key="attribute"
key="operator"
showSearch={false}
options={getActionOpeartorOptions(
localSurvey.variables.find((v) => v.id === action.variableId)?.type
@@ -145,7 +146,7 @@ export function AdvancedLogicEditorActions({
operator: val,
});
}}
comboboxClasses="w-20"
comboboxClasses="grow"
/>
<InputCombobox
key="value"
@@ -176,6 +177,7 @@ export function AdvancedLogicEditorActions({
});
}
}}
comboboxClasses="grow shrink-0"
/>
</>
)}
@@ -199,7 +201,7 @@ export function AdvancedLogicEditorActions({
className="flex items-center gap-2"
disabled={actions.length === 1}
onClick={() => {
handleActionsChange("delete", idx);
handleActionsChange("remove", idx);
}}>
<TrashIcon className="h-4 w-4" />
Remove
@@ -127,10 +127,12 @@ export function AdvancedLogicEditorConditions({
};
const handleOperatorChange = (condition: TSingleCondition, value: TSurveyLogicCondition) => {
handleUpdateCondition(condition.id, {
operator: value,
rightOperand: undefined,
});
if (value !== condition.operator) {
handleUpdateCondition(condition.id, {
operator: value,
rightOperand: undefined,
});
}
};
const handleRightOperandChange = (
@@ -279,7 +281,7 @@ export function AdvancedLogicEditorConditions({
showSearch={false}
groupedOptions={options}
allowMultiSelect={["equalsOneOf", "includesAllOf", "includesOneOf"].includes(condition.operator)}
comboboxClasses="grow min-w-[100px] max-w-[300px]"
comboboxClasses="grow min-w-[180px] max-w-[300px]"
value={condition.rightOperand?.value}
clearable={true}
onChangeValue={(val, option) => {
@@ -74,7 +74,7 @@ export function ConditionalLogic({
});
};
const handleDeleteLogic = (logicItemIdx: number) => {
const handleRemoveLogic = (logicItemIdx: number) => {
const logicCopy = structuredClone(question.logic || []);
logicCopy.splice(logicItemIdx, 1);
updateQuestion(questionIdx, {
@@ -159,10 +159,10 @@ export function ConditionalLogic({
<DropdownMenuItem
className="flex items-center gap-2"
onClick={() => {
handleDeleteLogic(logicItemIdx);
handleRemoveLogic(logicItemIdx);
}}>
<TrashIcon className="h-4 w-4" />
Delete
Remove
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
@@ -757,8 +757,8 @@ export const getActionTargetOptions = (
return {
label:
ending.type === "endScreen"
? `🙏 ${getLocalizedValue(ending.headline, "default")}`
: `🙏 ${ending.label || "Redirect Thank you card"}`,
? getLocalizedValue(ending.headline, "default")
: ending.label || "Redirect Thank you card",
value: ending.id,
};
});
+15 -25
View File
@@ -40,33 +40,33 @@ const operatorsWithoutRightOperand = [
export const ZDyanmicLogicField = z.enum(["question", "variable", "hiddenField"]);
export const ZActionObjective = z.enum(["calculate", "requireAnswer", "jumpToQuestion"]);
export const ZActionTextVariableCalculateOperator = z.enum(["assign", "concat"], {
message: "Invalid operator for a text variable",
message: "Conditional Logic: Invalid operator for a text variable",
});
export const ZActionNumberVariableCalculateOperator = z.enum(
["add", "subtract", "multiply", "divide", "assign"],
{ message: "Invalid operator for a number variable" }
{ message: "Conditional Logic: Invalid operator for a number variable" }
);
const ZDynamicQuestion = z.object({
type: z.literal("question"),
value: z.string().min(1, "Question id cannot be empty"),
value: z.string().min(1, "Conditional Logic: Question id cannot be empty"),
});
const ZDynamicVariable = z.object({
type: z.literal("variable"),
value: z
.string()
.cuid2({ message: "Variable id must be a valid cuid" })
.min(1, "Variable id cannot be empty"),
.cuid2({ message: "Conditional Logic: Variable id must be a valid cuid" })
.min(1, "Conditional Logic: Variable id cannot be empty"),
});
const ZDynamicHiddenField = z.object({
type: z.literal("hiddenField"),
value: z.string().min(1, "Hidden field id cannot be empty"),
value: z.string().min(1, "Conditional Logic: Hidden field id cannot be empty"),
});
const ZDynamicLogicFieldValue = z.union([ZDynamicQuestion, ZDynamicVariable, ZDynamicHiddenField], {
message: "Invalid dynamic field value",
message: "Conditional Logic: Invalid dynamic field value",
});
export type TSurveyLogicCondition = z.infer<typeof ZSurveyLogicCondition>;
@@ -106,14 +106,14 @@ export const ZSingleCondition = z
if (val.rightOperand === undefined) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: `rightOperand is required for operator "${val.operator}"`,
message: `Conditional Logic: rightOperand is required for operator "${val.operator}"`,
path: ["rightOperand"],
});
}
} else if (val.rightOperand !== undefined) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: `rightOperand should not be present for operator "${val.operator}"`,
message: `Conditional Logic: rightOperand should not be present for operator "${val.operator}"`,
path: ["rightOperand"],
});
}
@@ -157,12 +157,8 @@ export const ZActionCalculateText = ZActionCalculateBase.extend({
z.object({
type: z.literal("static"),
value: z
.string({ message: "Value must be a string for text variable" })
.min(1, "Please enter a value in logic field"),
}),
z.object({
type: z.literal("static"),
value: z.number({ message: "Value must be a number for number variable" }),
.string({ message: "Conditional Logic: Value must be a string for text variable" })
.min(1, "Conditional Logic: Please enter a value in logic field"),
}),
ZDynamicLogicFieldValue,
]),
@@ -173,13 +169,7 @@ export const ZActionCalculateNumber = ZActionCalculateBase.extend({
value: z.union([
z.object({
type: z.literal("static"),
value: z
.string({ message: "Value must be a string for text variable" })
.min(1, "Please enter a value in logic field"),
}),
z.object({
type: z.literal("static"),
value: z.number({ message: "Value must be a number for number variable" }),
value: z.number({ message: "Conditional Logic: Value must be a number for number variable" }),
}),
ZDynamicLogicFieldValue,
]),
@@ -187,7 +177,7 @@ export const ZActionCalculateNumber = ZActionCalculateBase.extend({
if (val.operator === "divide" && val.value.type === "static" && val.value.value === 0) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "Cannot divide by zero",
message: "Conditional Logic: Cannot divide by zero",
path: ["value", "value"],
});
}
@@ -199,13 +189,13 @@ export type TActionCalculate = z.infer<typeof ZActionCalculate>;
const ZActionRequireAnswer = ZActionBase.extend({
objective: z.literal("requireAnswer"),
target: z.string().min(1, "Target question id cannot be empty"),
target: z.string().min(1, "Conditional Logic: Target question id cannot be empty"),
});
export type TActionRequireAnswer = z.infer<typeof ZActionRequireAnswer>;
const ZActionJumpToQuestion = ZActionBase.extend({
objective: z.literal("jumpToQuestion"),
target: z.string().min(1, "Target question id cannot be empty"),
target: z.string().min(1, "Conditional Logic: Target question id cannot be empty"),
});
export type TActionJumpToQuestion = z.infer<typeof ZActionJumpToQuestion>;
+65 -49
View File
@@ -836,7 +836,7 @@ export const ZSurvey = z
const questionIndex = questions.findIndex((q) => q.id === questionId);
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: `Cyclic logic detected 🔃 Please check the logic of question ${String(questionIndex + 1)}.`,
message: `Conditional Logic: Cyclic logic detected 🔃 Please check the logic of question ${String(questionIndex + 1)}.`,
path: ["questions", questionIndex, "logic"],
});
});
@@ -1093,11 +1093,20 @@ const validateConditions = (
// Validate left operand
if (leftOperand.type === "question") {
const questionId = leftOperand.value;
const question = survey.questions.find((q) => q.id === questionId);
const questionIdx = survey.questions.findIndex((q) => q.id === questionId);
const question = questionIdx !== -1 ? survey.questions[questionIdx] : undefined;
if (!question) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Question ID ${questionId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Question ID ${questionId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
return;
} else if (questionIndex < questionIdx) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Conditional Logic: Question ${String(questionIndex + 1)} cannot refer to a question ${String(questionIdx + 1)} that appears later in the survey`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
return;
@@ -1108,7 +1117,7 @@ const validateConditions = (
if (isInvalidOperator) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Invalid operator "${operator}" for question type "${question.type}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Invalid operator "${operator}" for question type "${question.type}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
@@ -1128,7 +1137,7 @@ const validateConditions = (
if (rightOperand !== undefined) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Right operand should not be defined for operator "${operator}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Right operand should not be defined for operator "${operator}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
@@ -1144,7 +1153,7 @@ const validateConditions = (
if (!ques) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Question ID ${questionId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Question ID ${questionId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
} else {
@@ -1159,7 +1168,7 @@ const validateConditions = (
if (!validQuestionTypes.includes(question.type)) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Invalid question type "${question.type}" for right operand in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Invalid question type "${question.type}" for right operand in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
@@ -1171,7 +1180,7 @@ const validateConditions = (
if (!variable) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Variable ID ${variableId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Variable ID ${variableId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
@@ -1182,7 +1191,7 @@ const validateConditions = (
if (!field) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Hidden field ID ${fieldId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Hidden field ID ${fieldId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
@@ -1190,7 +1199,7 @@ const validateConditions = (
if (!rightOperand.value) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Static value is required in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Static value is required in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
@@ -1199,14 +1208,14 @@ const validateConditions = (
if (rightOperand?.type !== "static") {
issues.push({
code: z.ZodIssueCode.custom,
message: `Right operand should be a static value for "${operator}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Right operand should be a static value for "${operator}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
} else if (condition.operator === "equals" || condition.operator === "doesNotEqual") {
if (typeof rightOperand.value !== "string") {
issues.push({
code: z.ZodIssueCode.custom,
message: `Right operand should be a string for "${operator}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Right operand should be a string for "${operator}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
@@ -1214,7 +1223,7 @@ const validateConditions = (
if (!Array.isArray(rightOperand.value)) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Right operand should be an array for "${operator}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Right operand should be an array for "${operator}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
} else {
@@ -1222,7 +1231,7 @@ const validateConditions = (
if (typeof value !== "string") {
issues.push({
code: z.ZodIssueCode.custom,
message: `Right operand should be an array of strings for "${operator}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Right operand should be an array of strings for "${operator}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
@@ -1233,7 +1242,7 @@ const validateConditions = (
if (rightOperand.value.some((value) => !choices.includes(value))) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Choices selected in right operand does not exist in the choices of the question in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Choices selected in right operand does not exist in the choices of the question in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
@@ -1246,14 +1255,14 @@ const validateConditions = (
if (rightOperand?.type !== "static") {
issues.push({
code: z.ZodIssueCode.custom,
message: `Right operand should be amongst the choice values for "${operator}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Right operand should be amongst the choice values for "${operator}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
} else if (condition.operator === "equals" || condition.operator === "doesNotEqual") {
if (typeof rightOperand.value !== "string") {
issues.push({
code: z.ZodIssueCode.custom,
message: `Right operand should be a string for "${operator}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Right operand should be a string for "${operator}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
} else {
@@ -1261,7 +1270,7 @@ const validateConditions = (
if (!choice) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Choice with label "${rightOperand.value}" does not exist in question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Choice with label "${rightOperand.value}" does not exist in question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
@@ -1270,7 +1279,7 @@ const validateConditions = (
if (!Array.isArray(rightOperand.value)) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Right operand should be an array for "${operator}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Right operand should be an array for "${operator}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
} else {
@@ -1278,7 +1287,7 @@ const validateConditions = (
if (typeof value !== "string") {
issues.push({
code: z.ZodIssueCode.custom,
message: `Right operand should be an array of strings for "${operator}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Right operand should be an array of strings for "${operator}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
@@ -1289,7 +1298,7 @@ const validateConditions = (
if (rightOperand.value.some((value) => !choices.includes(value))) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Choices selected in right operand does not exist in the choices of the question in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Choices selected in right operand does not exist in the choices of the question in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
@@ -1306,13 +1315,13 @@ const validateConditions = (
if (!variable) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Variable ID ${variableId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Variable ID ${variableId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
} else if (variable.type !== "number") {
issues.push({
code: z.ZodIssueCode.custom,
message: `Variable type should be number in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Variable type should be number in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
@@ -1320,28 +1329,28 @@ const validateConditions = (
if (typeof rightOperand.value !== "number") {
issues.push({
code: z.ZodIssueCode.custom,
message: `Right operand should be a number for "${operator}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Right operand should be a number for "${operator}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
} else if (question.type === TSurveyQuestionTypeEnum.NPS) {
if (rightOperand.value < 0 || rightOperand.value > 10) {
issues.push({
code: z.ZodIssueCode.custom,
message: `NPS score should be between 0 and 10 for "${operator}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: NPS score should be between 0 and 10 for "${operator}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
} else if (rightOperand.value < 1 || rightOperand.value > question.range) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Rating score should be between 1 and ${String(question.range)} for "${operator}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Rating value should be between 1 and ${String(question.range)} for "${operator}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
} else {
issues.push({
code: z.ZodIssueCode.custom,
message: `Right operand should be a variable or a static value for "${operator}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Right operand should be a variable or a static value for "${operator}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
@@ -1353,7 +1362,7 @@ const validateConditions = (
if (!ques) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Question ID ${questionId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Question ID ${questionId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
} else {
@@ -1361,7 +1370,7 @@ const validateConditions = (
if (!validQuestionTypes.includes(question.type)) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Invalid question type "${question.type}" for right operand in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Invalid question type "${question.type}" for right operand in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
@@ -1373,13 +1382,13 @@ const validateConditions = (
if (!variable) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Variable ID ${variableId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Variable ID ${variableId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
} else if (variable.type !== "text") {
issues.push({
code: z.ZodIssueCode.custom,
message: `Variable type should be text in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Variable type should be text in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
@@ -1390,17 +1399,23 @@ const validateConditions = (
if (!doesFieldExists) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Hidden field ID ${fieldId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Hidden field ID ${fieldId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
} else if (rightOperand?.type === "static") {
const date = rightOperand.value as string;
if (isNaN(new Date(date).getTime())) {
if (!date) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Invalid date format for right operand in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Please select a date value in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
} else if (isNaN(new Date(date).getTime())) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Conditional Logic: Invalid date format for right operand in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
@@ -1412,7 +1427,7 @@ const validateConditions = (
if (!variable) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Variable ID ${variableId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Variable ID ${variableId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
} else {
@@ -1421,7 +1436,7 @@ const validateConditions = (
if (isInvalidOperator) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Invalid operator "${operator}" for variable ${variable.name} of type "${variable.type}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Invalid operator "${operator}" for variable ${variable.name} of type "${variable.type}" in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
@@ -1434,7 +1449,7 @@ const validateConditions = (
if (!question) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Question ID ${questionId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Question ID ${questionId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
} else if (variable.type === "number") {
@@ -1442,7 +1457,7 @@ const validateConditions = (
if (!validQuestionTypes.includes(question.type)) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Invalid question type "${question.type}" for right operand in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Invalid question type "${question.type}" for right operand in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
@@ -1458,7 +1473,7 @@ const validateConditions = (
if (!validQuestionTypes.includes(question.type)) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Invalid question type "${question.type}" for right operand in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Invalid question type "${question.type}" for right operand in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
@@ -1470,13 +1485,13 @@ const validateConditions = (
if (!foundVariable) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Variable ID ${variableId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Variable ID ${variableId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
} else if (variable.type !== foundVariable.type) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Variable type mismatch in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Variable type mismatch in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
@@ -1487,7 +1502,7 @@ const validateConditions = (
if (!field) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Hidden field ID ${fieldId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Hidden field ID ${fieldId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
@@ -1500,7 +1515,7 @@ const validateConditions = (
if (!hiddenField) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Hidden field ID ${hiddenFieldId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Hidden field ID ${hiddenFieldId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
@@ -1510,7 +1525,7 @@ const validateConditions = (
if (isInvalidOperator) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Invalid operator "${operator}" for hidden field in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Invalid operator "${operator}" for hidden field in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
@@ -1523,7 +1538,7 @@ const validateConditions = (
if (!question) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Question ID ${questionId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Question ID ${questionId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
} else {
@@ -1539,7 +1554,7 @@ const validateConditions = (
if (!validQuestionTypes.includes(question.type)) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Invalid question type "${question.type}" for right operand in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Invalid question type "${question.type}" for right operand in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
@@ -1551,7 +1566,7 @@ const validateConditions = (
if (!variable) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Variable ID ${variableId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Variable ID ${variableId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
@@ -1562,7 +1577,7 @@ const validateConditions = (
if (!field) {
issues.push({
code: z.ZodIssueCode.custom,
message: `Hidden field ID ${fieldId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Hidden field ID ${fieldId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex, "conditions"],
});
}
@@ -1600,7 +1615,7 @@ const validateActions = (
if (!variable) {
return {
code: z.ZodIssueCode.custom,
message: `Variable ID ${action.variableId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
message: `Conditional Logic: Variable ID ${action.variableId} does not exist in logic no: ${String(logicIndex + 1)} of question ${String(questionIndex + 1)}`,
path: ["questions", questionIndex, "logic", logicIndex],
};
}
@@ -1614,6 +1629,7 @@ const validateActions = (
path: ["questions", questionIndex, "logic", logicIndex],
};
}
return undefined;
}
const numberVariableParseData = ZActionCalculateNumber.safeParse(action);
+16 -14
View File
@@ -40,6 +40,7 @@ export interface InputComboboxProps {
allowMultiSelect?: boolean;
showCheckIcon?: boolean;
comboboxClasses?: string;
emptyDropdownText?: string;
}
export const InputCombobox = ({
@@ -55,6 +56,7 @@ export const InputCombobox = ({
allowMultiSelect = false,
showCheckIcon = false,
comboboxClasses,
emptyDropdownText = "No option found.",
}: InputComboboxProps) => {
const [open, setOpen] = React.useState(false);
const [localValue, setLocalValue] = React.useState<
@@ -68,7 +70,7 @@ export const InputCombobox = ({
const validOptions = options?.length ? options : groupedOptions?.flatMap((group) => group.options);
if (value === null || value === undefined) {
setLocalValue(null);
setLocalValue("");
setInputType(null);
} else {
if (Array.isArray(value)) {
@@ -161,9 +163,9 @@ export const InputCombobox = ({
));
} else if (localValue && typeof localValue === "object") {
return (
<div className="flex items-center gap-2">
<div className="flex items-center gap-2 truncate">
{localValue.icon && <localValue.icon className="h-5 w-5 shrink-0 text-slate-400" />}
<span>{localValue.label}</span>
<span className="truncate">{localValue.label}</span>
</div>
);
}
@@ -178,14 +180,14 @@ export const InputCombobox = ({
return (
<div
className={cn(
"flex max-w-[450px] overflow-hidden rounded-md border border-slate-300",
"flex max-w-[440px] overflow-hidden rounded-md border border-slate-300",
comboboxClasses
)}>
{withInput && inputType !== "dropdown" && (
<Input
className="min-w-0 rounded-none border-0 border-r border-slate-300 bg-white focus:border-slate-300"
{...inputProps}
value={value as string | number}
value={localValue as string | number}
onChange={onInputChange}
/>
)}
@@ -203,9 +205,9 @@ export const InputCombobox = ({
<div className="ellipsis flex w-full gap-2 truncate px-2">{getDisplayValue}</div>
)}
{clearable && inputType === "dropdown" ? (
<XIcon className="h-5 w-5 shrink-0 text-slate-300" onClick={handleClear} />
<XIcon className="h-5 w-5 shrink-0 text-slate-300 hover:text-slate-400" onClick={handleClear} />
) : (
<ChevronDownIcon className="h-5 w-5 shrink-0 text-slate-300" />
<ChevronDownIcon className="h-5 w-5 shrink-0 text-slate-300 hover:text-slate-400" />
)}
</div>
</PopoverTrigger>
@@ -213,7 +215,7 @@ export const InputCombobox = ({
className={cn(
"w-auto max-w-[400px] overflow-y-auto truncate border border-slate-400 bg-slate-50 p-0 shadow-none",
{
"pt-2": showSearch,
"px-2 pt-2": showSearch,
}
)}>
<Command>
@@ -223,8 +225,8 @@ export const InputCombobox = ({
className="h-8 border-slate-400 bg-white placeholder-slate-300"
/>
)}
<CommandList>
<CommandEmpty>No option found.</CommandEmpty>
<CommandList className="mx-1 my-2">
<CommandEmpty className="mx-2 my-0">{emptyDropdownText}</CommandEmpty>
{options && options.length > 0 ? (
<CommandGroup>
{options.map((option) => (
@@ -232,7 +234,7 @@ export const InputCombobox = ({
key={option.value}
onSelect={() => handleSelect(option)}
title={option.label}
className="cursor-pointer">
className="cursor-pointer truncate hover:text-slate-500">
{showCheckIcon &&
((allowMultiSelect &&
Array.isArray(localValue) &&
@@ -241,7 +243,7 @@ export const InputCombobox = ({
typeof localValue === "object" &&
!Array.isArray(localValue) &&
localValue?.value === option.value)) && (
<CheckIcon className="mr-2 h-4 w-4 text-slate-300" />
<CheckIcon className="mr-2 h-4 w-4 text-slate-300 hover:text-slate-400" />
)}
{option.icon && <option.icon className="mr-2 h-5 w-5 shrink-0 text-slate-400" />}
<span className="truncate">{option.label}</span>
@@ -258,7 +260,7 @@ export const InputCombobox = ({
<CommandItem
key={option.value}
onSelect={() => handleSelect(option)}
className="cursor-pointer truncate">
className="cursor-pointer truncate hover:text-slate-500">
{showCheckIcon &&
((allowMultiSelect &&
Array.isArray(localValue) &&
@@ -267,7 +269,7 @@ export const InputCombobox = ({
typeof localValue === "object" &&
!Array.isArray(localValue) &&
localValue?.value === option.value)) && (
<CheckIcon className="mr-2 h-4 w-4 shrink-0 text-slate-300" />
<CheckIcon className="mr-2 h-4 w-4 shrink-0 text-slate-300 hover:text-slate-400" />
)}
{option.icon && <option.icon className="mr-2 h-5 w-5 shrink-0 text-slate-400" />}
<span className="truncate">{option.label}</span>