@thanh01.pmt/interactive-quiz-kit 1.0.73 → 1.0.74
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/authoring.cjs +65 -73
- package/dist/authoring.d.cts +1 -1
- package/dist/authoring.d.ts +1 -1
- package/dist/authoring.mjs +65 -73
- package/dist/react-ui.cjs +65 -73
- package/dist/react-ui.d.cts +1 -1
- package/dist/react-ui.d.ts +1 -1
- package/dist/react-ui.mjs +65 -73
- package/dist/{toaster-DAXYZdrz.d.ts → toaster-B2MPZYhi.d.ts} +2 -1
- package/dist/{toaster-6AR8w2TO.d.cts → toaster-Bvhmyef9.d.cts} +2 -1
- package/package.json +1 -1
package/dist/authoring.cjs
CHANGED
|
@@ -71671,21 +71671,30 @@ var EditableCombobox = ({
|
|
|
71671
71671
|
disabled = false
|
|
71672
71672
|
}) => {
|
|
71673
71673
|
const [open, setOpen] = React119__namespace.useState(false);
|
|
71674
|
-
const [inputValue, setInputValue] = React119__namespace.useState(
|
|
71674
|
+
const [inputValue, setInputValue] = React119__namespace.useState("");
|
|
71675
71675
|
React119__namespace.useEffect(() => {
|
|
71676
|
-
|
|
71677
|
-
|
|
71678
|
-
|
|
71679
|
-
|
|
71680
|
-
|
|
71681
|
-
|
|
71676
|
+
if (value) {
|
|
71677
|
+
const selectedOption = options.find((option) => option.value.toLowerCase() === value.toLowerCase());
|
|
71678
|
+
setInputValue(selectedOption ? selectedOption.label : value);
|
|
71679
|
+
} else {
|
|
71680
|
+
setInputValue("");
|
|
71681
|
+
}
|
|
71682
|
+
}, [value, options, open]);
|
|
71683
|
+
const handleSelect = (selectedValue) => {
|
|
71684
|
+
onChange(selectedValue);
|
|
71682
71685
|
setOpen(false);
|
|
71683
71686
|
};
|
|
71684
|
-
const
|
|
71685
|
-
|
|
71687
|
+
const handleOpenChange = (isOpen) => {
|
|
71688
|
+
if (!isOpen) {
|
|
71689
|
+
const match2 = options.find((option) => option.label.toLowerCase() === inputValue.toLowerCase());
|
|
71690
|
+
if (!match2 && inputValue !== (options.find((opt) => opt.value === value)?.label || value)) {
|
|
71691
|
+
onChange(inputValue);
|
|
71692
|
+
}
|
|
71693
|
+
}
|
|
71694
|
+
setOpen(isOpen);
|
|
71686
71695
|
};
|
|
71687
71696
|
const displayLabel = options.find((option) => option.value.toLowerCase() === value?.toLowerCase())?.label || value;
|
|
71688
|
-
return /* @__PURE__ */ React119__namespace.createElement(Popover2, { open, onOpenChange:
|
|
71697
|
+
return /* @__PURE__ */ React119__namespace.createElement(Popover2, { open, onOpenChange: handleOpenChange }, /* @__PURE__ */ React119__namespace.createElement(PopoverTrigger2, { asChild: true }, /* @__PURE__ */ React119__namespace.createElement(
|
|
71689
71698
|
Button,
|
|
71690
71699
|
{
|
|
71691
71700
|
variant: "outline",
|
|
@@ -71701,8 +71710,7 @@ var EditableCombobox = ({
|
|
|
71701
71710
|
{
|
|
71702
71711
|
placeholder: searchPlaceholder,
|
|
71703
71712
|
value: inputValue,
|
|
71704
|
-
onValueChange: setInputValue
|
|
71705
|
-
onBlur: handleBlur
|
|
71713
|
+
onValueChange: setInputValue
|
|
71706
71714
|
}
|
|
71707
71715
|
), /* @__PURE__ */ React119__namespace.createElement(CommandList, null, /* @__PURE__ */ React119__namespace.createElement(CommandEmpty, null, noResultsMessage), /* @__PURE__ */ React119__namespace.createElement(CommandGroup, null, options.map((option) => /* @__PURE__ */ React119__namespace.createElement(
|
|
71708
71716
|
CommandItem,
|
|
@@ -73001,6 +73009,10 @@ var supportedQuestionTypesForAI = [
|
|
|
73001
73009
|
{ value: "sequence", label: "Sequence" },
|
|
73002
73010
|
{ value: "matching", label: "Matching" }
|
|
73003
73011
|
];
|
|
73012
|
+
var availableLanguages = [
|
|
73013
|
+
{ value: "English", label: "English" },
|
|
73014
|
+
{ value: "Vietnamese", label: "Ti\u1EBFng Vi\u1EC7t" }
|
|
73015
|
+
];
|
|
73004
73016
|
var AIQuestionGeneratorModal = ({
|
|
73005
73017
|
isOpen,
|
|
73006
73018
|
onClose,
|
|
@@ -73010,51 +73022,65 @@ var AIQuestionGeneratorModal = ({
|
|
|
73010
73022
|
subjects = [],
|
|
73011
73023
|
topics = [],
|
|
73012
73024
|
gradeLevels = [],
|
|
73013
|
-
bloomLevels = []
|
|
73025
|
+
bloomLevels = [],
|
|
73026
|
+
categories = []
|
|
73014
73027
|
}) => {
|
|
73015
|
-
const [
|
|
73028
|
+
const [additionalInfo, setAdditionalInfo] = React119.useState("");
|
|
73016
73029
|
const [isLoading, setIsLoading] = React119.useState(false);
|
|
73017
73030
|
const [error, setError] = React119.useState(null);
|
|
73018
73031
|
const { toast: toast2 } = useToast();
|
|
73019
73032
|
const [subjectCode, setSubjectCode] = React119.useState("");
|
|
73033
|
+
const [categoryCode, setCategoryCode] = React119.useState("");
|
|
73020
73034
|
const [topicCode, setTopicCode] = React119.useState("");
|
|
73021
73035
|
const [gradeBand, setGradeBand] = React119.useState("");
|
|
73022
73036
|
const [bloomLevelCode, setBloomLevelCode] = React119.useState("");
|
|
73023
73037
|
const [selectedQuestionType, setSelectedQuestionType] = React119.useState("multiple_choice");
|
|
73038
|
+
const [selectedLanguage, setSelectedLanguage] = React119.useState(language3);
|
|
73024
73039
|
const [numberOfOptions, setNumberOfOptions] = React119.useState(4);
|
|
73025
|
-
const [minCorrectAnswers, setMinCorrectAnswers] = React119.useState(2);
|
|
73026
|
-
const [maxCorrectAnswers, setMaxCorrectAnswers] = React119.useState(3);
|
|
73027
|
-
const [isCaseSensitive, setIsCaseSensitive] = React119.useState(false);
|
|
73028
|
-
const [numberOfBlanks, setNumberOfBlanks] = React119.useState(2);
|
|
73029
|
-
const [numberOfSequenceItems, setNumberOfSequenceItems] = React119.useState(4);
|
|
73030
|
-
const [numberOfMatchingPairs, setNumberOfMatchingPairs] = React119.useState(4);
|
|
73031
73040
|
const [isApiKeyManagerModalOpen, setIsApiKeyManagerModalOpen] = React119.useState(false);
|
|
73032
73041
|
const [geminiApiKeyExists, setGeminiApiKeyExists] = React119.useState(false);
|
|
73033
73042
|
const finalQuestionType = questionTypeProp || selectedQuestionType;
|
|
73034
73043
|
React119.useEffect(() => {
|
|
73035
73044
|
if (isOpen) {
|
|
73036
|
-
|
|
73045
|
+
setAdditionalInfo("");
|
|
73037
73046
|
setError(null);
|
|
73038
73047
|
setIsLoading(false);
|
|
73039
73048
|
setSubjectCode("");
|
|
73049
|
+
setCategoryCode("");
|
|
73040
73050
|
setTopicCode("");
|
|
73041
73051
|
setGradeBand("");
|
|
73042
73052
|
setBloomLevelCode("");
|
|
73043
73053
|
setSelectedQuestionType(questionTypeProp || "multiple_choice");
|
|
73054
|
+
setSelectedLanguage(language3);
|
|
73044
73055
|
setGeminiApiKeyExists(APIKeyService.hasAPIKey(GEMINI_API_KEY_SERVICE_NAME));
|
|
73045
73056
|
}
|
|
73046
|
-
}, [isOpen, questionTypeProp]);
|
|
73057
|
+
}, [isOpen, questionTypeProp, language3]);
|
|
73058
|
+
const filteredCategories = React119.useMemo(() => {
|
|
73059
|
+
return categories;
|
|
73060
|
+
}, [categories]);
|
|
73047
73061
|
const filteredTopics = React119.useMemo(() => {
|
|
73048
|
-
if (!subjectCode) return [];
|
|
73049
|
-
return topics.filter(
|
|
73050
|
-
|
|
73062
|
+
if (!subjectCode || !categoryCode) return [];
|
|
73063
|
+
return topics.filter(
|
|
73064
|
+
(t2) => t2.subjectCode === subjectCode
|
|
73065
|
+
/* && t.categoryCode === categoryCode */
|
|
73066
|
+
);
|
|
73067
|
+
}, [subjectCode, categoryCode, topics]);
|
|
73068
|
+
const handleSubjectChange = (newSubjectCode) => {
|
|
73069
|
+
setSubjectCode(newSubjectCode);
|
|
73070
|
+
setCategoryCode("");
|
|
73071
|
+
setTopicCode("");
|
|
73072
|
+
};
|
|
73073
|
+
const handleCategoryChange = (newCategoryCode) => {
|
|
73074
|
+
setCategoryCode(newCategoryCode);
|
|
73075
|
+
setTopicCode("");
|
|
73076
|
+
};
|
|
73051
73077
|
const handleApiKeyModalClose = () => {
|
|
73052
73078
|
setIsApiKeyManagerModalOpen(false);
|
|
73053
73079
|
setGeminiApiKeyExists(APIKeyService.hasAPIKey(GEMINI_API_KEY_SERVICE_NAME));
|
|
73054
73080
|
};
|
|
73055
73081
|
const handleSubmit = async () => {
|
|
73056
|
-
if (!
|
|
73057
|
-
setError("Please
|
|
73082
|
+
if (!subjectCode || !categoryCode || !topicCode || !gradeBand || !bloomLevelCode) {
|
|
73083
|
+
setError("Please fill in all required metadata fields: Subject, Category, Topic, Grade Level, and Bloom's Level.");
|
|
73058
73084
|
return;
|
|
73059
73085
|
}
|
|
73060
73086
|
const geminiKey = APIKeyService.getAPIKey(GEMINI_API_KEY_SERVICE_NAME);
|
|
@@ -73068,14 +73094,15 @@ var AIQuestionGeneratorModal = ({
|
|
|
73068
73094
|
setIsLoading(true);
|
|
73069
73095
|
try {
|
|
73070
73096
|
const quizContext = {
|
|
73071
|
-
plannedTopic:
|
|
73097
|
+
plannedTopic: additionalInfo.trim() || topicCode,
|
|
73072
73098
|
originalSubject: subjectCode,
|
|
73073
73099
|
originalTopic: topicCode,
|
|
73100
|
+
originalCategory: categoryCode,
|
|
73074
73101
|
gradeBand,
|
|
73075
73102
|
plannedBloomLevel: bloomLevelCode
|
|
73076
73103
|
};
|
|
73077
73104
|
const baseClientInput = {
|
|
73078
|
-
language:
|
|
73105
|
+
language: selectedLanguage,
|
|
73079
73106
|
difficulty: "Medium",
|
|
73080
73107
|
quizContext
|
|
73081
73108
|
};
|
|
@@ -73088,33 +73115,32 @@ var AIQuestionGeneratorModal = ({
|
|
|
73088
73115
|
generatedResult = await generateMCQQuestion({ ...baseClientInput, numberOfOptions }, geminiKey);
|
|
73089
73116
|
break;
|
|
73090
73117
|
case "multiple_response":
|
|
73091
|
-
generatedResult = await generateMRQQuestion({ ...baseClientInput, numberOfOptions, minCorrectAnswers, maxCorrectAnswers }, geminiKey);
|
|
73118
|
+
generatedResult = await generateMRQQuestion({ ...baseClientInput, numberOfOptions: 5, minCorrectAnswers: 2, maxCorrectAnswers: 3 }, geminiKey);
|
|
73092
73119
|
break;
|
|
73093
73120
|
case "short_answer":
|
|
73094
|
-
generatedResult = await generateShortAnswerQuestion({ ...baseClientInput, isCaseSensitive }, geminiKey);
|
|
73121
|
+
generatedResult = await generateShortAnswerQuestion({ ...baseClientInput, isCaseSensitive: false }, geminiKey);
|
|
73095
73122
|
break;
|
|
73096
73123
|
case "numeric":
|
|
73097
73124
|
generatedResult = await generateNumericQuestion({ ...baseClientInput, allowDecimals: true, tolerance: 0 }, geminiKey);
|
|
73098
73125
|
break;
|
|
73099
73126
|
case "fill_in_the_blanks":
|
|
73100
|
-
generatedResult = await generateFillInTheBlanksQuestion({ ...baseClientInput, numberOfBlanks, isCaseSensitive }, geminiKey);
|
|
73127
|
+
generatedResult = await generateFillInTheBlanksQuestion({ ...baseClientInput, numberOfBlanks: 2, isCaseSensitive: false }, geminiKey);
|
|
73101
73128
|
break;
|
|
73102
73129
|
case "sequence":
|
|
73103
|
-
generatedResult = await generateSequenceQuestion({ ...baseClientInput, numberOfItems:
|
|
73130
|
+
generatedResult = await generateSequenceQuestion({ ...baseClientInput, numberOfItems: 4 }, geminiKey);
|
|
73104
73131
|
break;
|
|
73105
73132
|
case "matching":
|
|
73106
|
-
generatedResult = await generateMatchingQuestion({ ...baseClientInput, numberOfPairs:
|
|
73133
|
+
generatedResult = await generateMatchingQuestion({ ...baseClientInput, numberOfPairs: 4, shuffleOptions: true }, geminiKey);
|
|
73107
73134
|
break;
|
|
73108
73135
|
default:
|
|
73109
73136
|
throw new Error(`AI generation for '${finalQuestionType}' is not implemented in this flow.`);
|
|
73110
73137
|
}
|
|
73111
|
-
if (generatedResult.error)
|
|
73112
|
-
throw new Error(generatedResult.error);
|
|
73113
|
-
}
|
|
73138
|
+
if (generatedResult.error) throw new Error(generatedResult.error);
|
|
73114
73139
|
if (generatedResult.question) {
|
|
73115
73140
|
const completeQuestion = generatedResult.question;
|
|
73116
73141
|
completeQuestion.subject = subjectCode;
|
|
73117
73142
|
completeQuestion.topic = topicCode;
|
|
73143
|
+
completeQuestion.category = categoryCode;
|
|
73118
73144
|
completeQuestion.gradeBand = gradeBand;
|
|
73119
73145
|
completeQuestion.bloomLevel = bloomLevelCode;
|
|
73120
73146
|
if (completeQuestion.points === void 0) completeQuestion.points = 10;
|
|
@@ -73140,47 +73166,13 @@ var AIQuestionGeneratorModal = ({
|
|
|
73140
73166
|
const comboboxOptions = {
|
|
73141
73167
|
subjects: subjects.map((s2) => ({ value: s2.code, label: s2.name })),
|
|
73142
73168
|
topics: filteredTopics.map((t2) => ({ value: t2.code, label: t2.name })),
|
|
73169
|
+
categories: filteredCategories.map((c2) => ({ value: c2.code, label: c2.name })),
|
|
73143
73170
|
gradeLevels: gradeLevels.map((g) => ({ value: g.code, label: g.name })),
|
|
73144
73171
|
bloomLevels: bloomLevels.map((b) => ({ value: b.code, label: b.name }))
|
|
73145
73172
|
};
|
|
73146
|
-
const renderSpecificParams = () => {
|
|
73147
|
-
switch (finalQuestionType) {
|
|
73148
|
-
case "multiple_choice":
|
|
73149
|
-
case "multiple_response":
|
|
73150
|
-
return /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-2 pt-4 border-t" }, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "ai-num-options" }, "Number of Options (2-8)"), /* @__PURE__ */ React119__namespace.default.createElement(
|
|
73151
|
-
Input,
|
|
73152
|
-
{
|
|
73153
|
-
id: "ai-num-options",
|
|
73154
|
-
type: "number",
|
|
73155
|
-
value: numberOfOptions,
|
|
73156
|
-
onChange: (e2) => setNumberOfOptions(parseInt(e2.target.value, 10)),
|
|
73157
|
-
min: 2,
|
|
73158
|
-
max: 8
|
|
73159
|
-
}
|
|
73160
|
-
), finalQuestionType === "multiple_response" && /* @__PURE__ */ React119__namespace.default.createElement(React119__namespace.default.Fragment, null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "ai-min-correct" }, "Min Correct Answers"), /* @__PURE__ */ React119__namespace.default.createElement(Input, { id: "ai-min-correct", type: "number", value: minCorrectAnswers, onChange: (e2) => setMinCorrectAnswers(parseInt(e2.target.value, 10)), min: 1, max: numberOfOptions }), /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "ai-max-correct" }, "Max Correct Answers"), /* @__PURE__ */ React119__namespace.default.createElement(Input, { id: "ai-max-correct", type: "number", value: maxCorrectAnswers, onChange: (e2) => setMaxCorrectAnswers(parseInt(e2.target.value, 10)), min: minCorrectAnswers, max: numberOfOptions })));
|
|
73161
|
-
case "short_answer":
|
|
73162
|
-
case "fill_in_the_blanks":
|
|
73163
|
-
return /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "flex items-center space-x-2 pt-4 border-t" }, /* @__PURE__ */ React119__namespace.default.createElement("input", { type: "checkbox", id: "ai-case-sensitive", checked: isCaseSensitive, onChange: (e2) => setIsCaseSensitive(e2.target.checked), className: "h-4 w-4 rounded border-gray-300 text-primary focus:ring-primary" }), /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "ai-case-sensitive" }, "Case Sensitive Answers"), finalQuestionType === "fill_in_the_blanks" && /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-1 ml-4" }, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "ai-num-blanks" }, "Number of Blanks (1-5)"), /* @__PURE__ */ React119__namespace.default.createElement(Input, { id: "ai-num-blanks", type: "number", value: numberOfBlanks, onChange: (e2) => setNumberOfBlanks(parseInt(e2.target.value, 10)), min: 1, max: 5 })));
|
|
73164
|
-
case "sequence":
|
|
73165
|
-
return /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-2 pt-4 border-t" }, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "ai-num-seq-items" }, "Number of Items to Sequence (2-10)"), /* @__PURE__ */ React119__namespace.default.createElement(Input, { id: "ai-num-seq-items", type: "number", value: numberOfSequenceItems, onChange: (e2) => setNumberOfSequenceItems(parseInt(e2.target.value, 10)), min: 2, max: 10 }));
|
|
73166
|
-
case "matching":
|
|
73167
|
-
return /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-2 pt-4 border-t" }, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "ai-num-match-pairs" }, "Number of Pairs to Match (2-8)"), /* @__PURE__ */ React119__namespace.default.createElement(Input, { id: "ai-num-match-pairs", type: "number", value: numberOfMatchingPairs, onChange: (e2) => setNumberOfMatchingPairs(parseInt(e2.target.value, 10)), min: 2, max: 8 }));
|
|
73168
|
-
default:
|
|
73169
|
-
return null;
|
|
73170
|
-
}
|
|
73171
|
-
};
|
|
73172
73173
|
return /* @__PURE__ */ React119__namespace.default.createElement(React119__namespace.default.Fragment, null, /* @__PURE__ */ React119__namespace.default.createElement(Dialog2, { open: isOpen, onOpenChange: (open) => {
|
|
73173
73174
|
if (!open) onClose();
|
|
73174
|
-
} }, /* @__PURE__ */ React119__namespace.default.createElement(DialogContent2, { className: "sm:max-w-[
|
|
73175
|
-
Textarea,
|
|
73176
|
-
{
|
|
73177
|
-
id: "ai-prompt",
|
|
73178
|
-
value: prompt,
|
|
73179
|
-
onChange: (e2) => setPrompt(e2.target.value),
|
|
73180
|
-
placeholder: "e.g., The process of photosynthesis, The causes of World War II, Basic Algebra Equations",
|
|
73181
|
-
className: "min-h-[100px]"
|
|
73182
|
-
}
|
|
73183
|
-
)), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "grid grid-cols-2 gap-4" }, /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React119__namespace.default.createElement(Label2, null, "Subject"), /* @__PURE__ */ React119__namespace.default.createElement(EditableCombobox, { options: comboboxOptions.subjects, value: subjectCode, onChange: setSubjectCode, placeholder: "Select or type a Subject..." })), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React119__namespace.default.createElement(Label2, null, "Topic"), /* @__PURE__ */ React119__namespace.default.createElement(EditableCombobox, { options: comboboxOptions.topics, value: topicCode, onChange: setTopicCode, placeholder: "Select or type a Topic...", disabled: !subjectCode })), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React119__namespace.default.createElement(Label2, null, "Grade Level"), /* @__PURE__ */ React119__namespace.default.createElement(EditableCombobox, { options: comboboxOptions.gradeLevels, value: gradeBand, onChange: setGradeBand, placeholder: "Select or type a Grade..." })), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React119__namespace.default.createElement(Label2, null, "Bloom's Level"), /* @__PURE__ */ React119__namespace.default.createElement(EditableCombobox, { options: comboboxOptions.bloomLevels, value: bloomLevelCode, onChange: setBloomLevelCode, placeholder: "Select a Bloom's Level..." }))), renderSpecificParams(), error && /* @__PURE__ */ React119__namespace.default.createElement("p", { className: "text-sm text-destructive flex items-center mt-2" }, /* @__PURE__ */ React119__namespace.default.createElement(TriangleAlert, { className: "mr-1 h-4 w-4" }), " ", error)), /* @__PURE__ */ React119__namespace.default.createElement(DialogFooter, null, /* @__PURE__ */ React119__namespace.default.createElement(DialogClose2, { asChild: true }, /* @__PURE__ */ React119__namespace.default.createElement(Button, { type: "button", variant: "outline" }, "Cancel")), /* @__PURE__ */ React119__namespace.default.createElement(Button, { type: "button", onClick: handleSubmit, disabled: isLoading || !prompt.trim() || !geminiApiKeyExists }, isLoading ? /* @__PURE__ */ React119__namespace.default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ React119__namespace.default.createElement(WandSparkles, { className: "mr-2 h-4 w-4" }), "Generate Question")))), /* @__PURE__ */ React119__namespace.default.createElement(APIKeyManagerModal, { isOpen: isApiKeyManagerModalOpen, onClose: handleApiKeyModalClose }));
|
|
73175
|
+
} }, /* @__PURE__ */ React119__namespace.default.createElement(DialogContent2, { className: "sm:max-w-[700px]" }, /* @__PURE__ */ React119__namespace.default.createElement(DialogHeader, null, /* @__PURE__ */ React119__namespace.default.createElement(DialogTitle2, { className: "flex items-center font-headline text-2xl" }, /* @__PURE__ */ React119__namespace.default.createElement(WandSparkles, { className: "mr-2 h-6 w-6 text-primary" }), " AI Question Generator"), /* @__PURE__ */ React119__namespace.default.createElement(DialogDescription2, null, "Provide metadata and optional info to generate a '", finalQuestionType, "' question.")), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-4 py-4 max-h-[60vh] overflow-y-auto px-2" }, /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "grid grid-cols-2 gap-4" }, !questionTypeProp && /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React119__namespace.default.createElement(Label2, null, "Question Type"), /* @__PURE__ */ React119__namespace.default.createElement(Select2, { value: selectedQuestionType, onValueChange: (v) => setSelectedQuestionType(v) }, /* @__PURE__ */ React119__namespace.default.createElement(SelectTrigger2, null, /* @__PURE__ */ React119__namespace.default.createElement(SelectValue2, null)), /* @__PURE__ */ React119__namespace.default.createElement(SelectContent2, null, supportedQuestionTypesForAI.map((type) => /* @__PURE__ */ React119__namespace.default.createElement(SelectItem2, { key: type.value, value: type.value }, type.label))))), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React119__namespace.default.createElement(Label2, null, "Language"), /* @__PURE__ */ React119__namespace.default.createElement(Select2, { value: selectedLanguage, onValueChange: setSelectedLanguage }, /* @__PURE__ */ React119__namespace.default.createElement(SelectTrigger2, null, /* @__PURE__ */ React119__namespace.default.createElement(SelectValue2, null)), /* @__PURE__ */ React119__namespace.default.createElement(SelectContent2, null, availableLanguages.map((lang) => /* @__PURE__ */ React119__namespace.default.createElement(SelectItem2, { key: lang.value, value: lang.value }, lang.label)))))), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "ai-additional-info" }, "Additional Info (Optional)"), /* @__PURE__ */ React119__namespace.default.createElement(Textarea, { id: "ai-additional-info", value: additionalInfo, onChange: (e2) => setAdditionalInfo(e2.target.value), placeholder: "Provide extra context, a specific topic, or a detailed prompt for the AI...", className: "min-h-[100px]" })), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "grid grid-cols-2 gap-4" }, /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React119__namespace.default.createElement(Label2, null, "Subject *"), /* @__PURE__ */ React119__namespace.default.createElement(EditableCombobox, { options: comboboxOptions.subjects, value: subjectCode, onChange: handleSubjectChange, placeholder: "Select Subject..." })), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React119__namespace.default.createElement(Label2, null, "Category *"), /* @__PURE__ */ React119__namespace.default.createElement(EditableCombobox, { options: comboboxOptions.categories, value: categoryCode, onChange: handleCategoryChange, placeholder: "Select Category...", disabled: !subjectCode })), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React119__namespace.default.createElement(Label2, null, "Topic *"), /* @__PURE__ */ React119__namespace.default.createElement(EditableCombobox, { options: comboboxOptions.topics, value: topicCode, onChange: setTopicCode, placeholder: "Select Topic...", disabled: !categoryCode })), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React119__namespace.default.createElement(Label2, null, "Grade Level *"), /* @__PURE__ */ React119__namespace.default.createElement(EditableCombobox, { options: comboboxOptions.gradeLevels, value: gradeBand, onChange: setGradeBand, placeholder: "Select Grade..." })), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React119__namespace.default.createElement(Label2, null, "Bloom's Level *"), /* @__PURE__ */ React119__namespace.default.createElement(EditableCombobox, { options: comboboxOptions.bloomLevels, value: bloomLevelCode, onChange: setBloomLevelCode, placeholder: "Select Bloom's Level..." }))), finalQuestionType === "multiple_choice" && /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-2 pt-4 border-t" }, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "ai-num-options" }, "Number of Options (2-8)"), /* @__PURE__ */ React119__namespace.default.createElement(Input, { id: "ai-num-options", type: "number", value: numberOfOptions, onChange: (e2) => setNumberOfOptions(parseInt(e2.target.value, 10)), min: 2, max: 8 })), error && /* @__PURE__ */ React119__namespace.default.createElement("p", { className: "text-sm text-destructive flex items-center mt-2" }, /* @__PURE__ */ React119__namespace.default.createElement(TriangleAlert, { className: "mr-1 h-4 w-4" }), " ", error)), /* @__PURE__ */ React119__namespace.default.createElement(DialogFooter, null, /* @__PURE__ */ React119__namespace.default.createElement(DialogClose2, { asChild: true }, /* @__PURE__ */ React119__namespace.default.createElement(Button, { type: "button", variant: "outline" }, "Cancel")), /* @__PURE__ */ React119__namespace.default.createElement(Button, { type: "button", onClick: handleSubmit, disabled: isLoading || !geminiApiKeyExists || !subjectCode || !categoryCode || !topicCode || !gradeBand || !bloomLevelCode }, isLoading ? /* @__PURE__ */ React119__namespace.default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ React119__namespace.default.createElement(WandSparkles, { className: "mr-2 h-4 w-4" }), "Generate Question")))), /* @__PURE__ */ React119__namespace.default.createElement(APIKeyManagerModal, { isOpen: isApiKeyManagerModalOpen, onClose: handleApiKeyModalClose }));
|
|
73184
73176
|
};
|
|
73185
73177
|
|
|
73186
73178
|
// src/react-ui/components/authoring/AIFullQuizGeneratorModal.tsx
|
package/dist/authoring.d.cts
CHANGED
|
@@ -2,7 +2,7 @@ export { B as BaseQuestion, e as BlocklyProgrammingQuestion, C as CodingQuestion
|
|
|
2
2
|
export { APIKeyService, AchievementService, Approach, ApproachTableRawDifficulty, BloomLevelName, BloomLevelType, Category, CodeNamedEntity, Context, GEMINI_API_KEY_SERVICE_NAME, GradeLevel, KnowledgeCardService, KnowledgeDimension, LearningObjective, MetadataService, PracticeHistoryService, QuestionBankService, QuestionImportService, QuestionInBank, QuestionTypeType, QuizEditorService, QuizEngine, QuizEngineCallbacks, QuizEngineConstructorOptions, QuoteService, SCORMService, StandardDifficulty, Subject, Topic, UserConfigService, cn, emptyQuiz, exportQuizAsSCORMZip, generateLauncherHTML, generateSCORMManifest, generateUniqueId, sampleQuiz } from './index.cjs';
|
|
3
3
|
export { i as Achievement, j as AchievementDefinition, r as ActivityCalendarData, u as AnalysisReport, A as AnswerDetail, x as ChatContext, C as ChatMessage, v as DashboardCardConfig, D as DashboardCardId, w as DashboardLayout, y as Goal, G as GoalType, t as ImageContextItem, I as ImportError, K as KnowledgeCard, L as LearningAnalysis, e as PerformanceByBloomLevel, b as PerformanceByCategory, d as PerformanceByDifficulty, P as PerformanceByLearningObjective, c as PerformanceByTopic, f as PerformanceMetric, s as PerformanceSummary, k as PracticeDifficulty, n as PracticeSession, p as PracticeSessionSummary, o as PracticeStats, m as PracticeSuggestion, l as PracticeSuggestionTopic, q as PracticeTopicSummary, g as QuestionReview, Q as QuizResultType, h as QuizReviewContent, R as RoadmapItem, T as TestCaseResult, U as UserAnswerType, a as UserAnswers, W as WeeklyRoadmap } from './ai-ecosystem-DyQYZbyX.cjs';
|
|
4
4
|
export { AssessAndMapDocumentClientInput, AssessAndMapDocumentOutput, BloomLevelStringsForAI, GenerateCodingQuestionClientInput, GenerateCodingQuestionOutput, GenerateFillInTheBlanksQuestionClientInput, GenerateFillInTheBlanksQuestionOutput, GenerateLearningAnalysisClientInput, GenerateLearningAnalysisOutput, GenerateMCQQuestionClientInput, GenerateMCQQuestionOutput, GenerateMRQQuestionClientInput, GenerateMRQQuestionOutput, GenerateMatchingQuestionClientInput, GenerateMatchingQuestionOutput, GenerateMotivationalQuoteClientInput, GenerateMotivationalQuoteOutput, GenerateNumericQuestionClientInput, GenerateNumericQuestionOutput, GeneratePracticeSuggestionClientInput, GeneratePracticeSuggestionOutput, GenerateQuestionsFromQuizPlanClientInput, GenerateQuestionsFromQuizPlanOutput, GenerateQuizFromTextClientInput, GenerateQuizFromTextOutput, GenerateQuizPlanClientInput, GenerateQuizPlanOutput, GenerateQuizReviewClientInput, GenerateQuizReviewOutput, GenerateSequenceQuestionClientInput, GenerateSequenceQuestionOutput, GenerateShortAnswerQuestionClientInput, GenerateShortAnswerQuestionOutput, GenerateSingleKnowledgeCardClientInput, GenerateSingleKnowledgeCardOutput, GenerateTrueFalseQuestionClientInput, GenerateTrueFalseQuestionOutput, PlanKnowledgeCardsClientInput, PlanKnowledgeCardsOutput, PlannedQuestion, assessAndMapDocument, generateCodingQuestion, generateFillInTheBlanksQuestion, generateLearningAnalysis, generateMCQQuestion, generateMRQQuestion, generateMatchingQuestion, generateMotivationalQuote, generateNumericQuestion, generatePracticeSuggestion, generateQuestionsFromQuizPlan, generateQuizFromText, generateQuizPlan, generateQuizReview, generateSequenceQuestion, generateShortAnswerQuestion, generateSingleKnowledgeCard, generateTrueFalseQuestion, planKnowledgeCards } from './ai.cjs';
|
|
5
|
-
export { c as AIFullQuizGeneratorModal, A as AIQuestionGeneratorModal, e as APIKeyManagerModal, f as ApiKeySettings, m as ApproachManager, B as BloomLevelManager, C as CategoryManager, l as ContextManager, E as EditQuestionModal, G as GradeLevelManager, I as ImportQuestionsModal, L as LearningObjectiveManager, n as MetadataImportControls, M as MetadataTabs, h as QuestionFilters, i as QuestionFormDialog, g as QuestionList, a as QuestionPreviewModal, k as QuestionTypeManager, Q as QuizAuthoringTool, b as QuizSettingsForm, d as SCORMExportModal, S as SelectedQuestionsPanel, j as SubjectManager, o as Toaster, T as TopicManager, t as toast, u as useToast } from './toaster-
|
|
5
|
+
export { c as AIFullQuizGeneratorModal, A as AIQuestionGeneratorModal, e as APIKeyManagerModal, f as ApiKeySettings, m as ApproachManager, B as BloomLevelManager, C as CategoryManager, l as ContextManager, E as EditQuestionModal, G as GradeLevelManager, I as ImportQuestionsModal, L as LearningObjectiveManager, n as MetadataImportControls, M as MetadataTabs, h as QuestionFilters, i as QuestionFormDialog, g as QuestionList, a as QuestionPreviewModal, k as QuestionTypeManager, Q as QuizAuthoringTool, b as QuizSettingsForm, d as SCORMExportModal, S as SelectedQuestionsPanel, j as SubjectManager, o as Toaster, T as TopicManager, t as toast, u as useToast } from './toaster-Bvhmyef9.cjs';
|
|
6
6
|
import 'clsx';
|
|
7
7
|
import 'zod';
|
|
8
8
|
import 'react';
|
package/dist/authoring.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export { B as BaseQuestion, e as BlocklyProgrammingQuestion, C as CodingQuestion
|
|
|
2
2
|
export { APIKeyService, AchievementService, Approach, ApproachTableRawDifficulty, BloomLevelName, BloomLevelType, Category, CodeNamedEntity, Context, GEMINI_API_KEY_SERVICE_NAME, GradeLevel, KnowledgeCardService, KnowledgeDimension, LearningObjective, MetadataService, PracticeHistoryService, QuestionBankService, QuestionImportService, QuestionInBank, QuestionTypeType, QuizEditorService, QuizEngine, QuizEngineCallbacks, QuizEngineConstructorOptions, QuoteService, SCORMService, StandardDifficulty, Subject, Topic, UserConfigService, cn, emptyQuiz, exportQuizAsSCORMZip, generateLauncherHTML, generateSCORMManifest, generateUniqueId, sampleQuiz } from './index.js';
|
|
3
3
|
export { i as Achievement, j as AchievementDefinition, r as ActivityCalendarData, u as AnalysisReport, A as AnswerDetail, x as ChatContext, C as ChatMessage, v as DashboardCardConfig, D as DashboardCardId, w as DashboardLayout, y as Goal, G as GoalType, t as ImageContextItem, I as ImportError, K as KnowledgeCard, L as LearningAnalysis, e as PerformanceByBloomLevel, b as PerformanceByCategory, d as PerformanceByDifficulty, P as PerformanceByLearningObjective, c as PerformanceByTopic, f as PerformanceMetric, s as PerformanceSummary, k as PracticeDifficulty, n as PracticeSession, p as PracticeSessionSummary, o as PracticeStats, m as PracticeSuggestion, l as PracticeSuggestionTopic, q as PracticeTopicSummary, g as QuestionReview, Q as QuizResultType, h as QuizReviewContent, R as RoadmapItem, T as TestCaseResult, U as UserAnswerType, a as UserAnswers, W as WeeklyRoadmap } from './ai-ecosystem-Qa_SdE2T.js';
|
|
4
4
|
export { AssessAndMapDocumentClientInput, AssessAndMapDocumentOutput, BloomLevelStringsForAI, GenerateCodingQuestionClientInput, GenerateCodingQuestionOutput, GenerateFillInTheBlanksQuestionClientInput, GenerateFillInTheBlanksQuestionOutput, GenerateLearningAnalysisClientInput, GenerateLearningAnalysisOutput, GenerateMCQQuestionClientInput, GenerateMCQQuestionOutput, GenerateMRQQuestionClientInput, GenerateMRQQuestionOutput, GenerateMatchingQuestionClientInput, GenerateMatchingQuestionOutput, GenerateMotivationalQuoteClientInput, GenerateMotivationalQuoteOutput, GenerateNumericQuestionClientInput, GenerateNumericQuestionOutput, GeneratePracticeSuggestionClientInput, GeneratePracticeSuggestionOutput, GenerateQuestionsFromQuizPlanClientInput, GenerateQuestionsFromQuizPlanOutput, GenerateQuizFromTextClientInput, GenerateQuizFromTextOutput, GenerateQuizPlanClientInput, GenerateQuizPlanOutput, GenerateQuizReviewClientInput, GenerateQuizReviewOutput, GenerateSequenceQuestionClientInput, GenerateSequenceQuestionOutput, GenerateShortAnswerQuestionClientInput, GenerateShortAnswerQuestionOutput, GenerateSingleKnowledgeCardClientInput, GenerateSingleKnowledgeCardOutput, GenerateTrueFalseQuestionClientInput, GenerateTrueFalseQuestionOutput, PlanKnowledgeCardsClientInput, PlanKnowledgeCardsOutput, PlannedQuestion, assessAndMapDocument, generateCodingQuestion, generateFillInTheBlanksQuestion, generateLearningAnalysis, generateMCQQuestion, generateMRQQuestion, generateMatchingQuestion, generateMotivationalQuote, generateNumericQuestion, generatePracticeSuggestion, generateQuestionsFromQuizPlan, generateQuizFromText, generateQuizPlan, generateQuizReview, generateSequenceQuestion, generateShortAnswerQuestion, generateSingleKnowledgeCard, generateTrueFalseQuestion, planKnowledgeCards } from './ai.js';
|
|
5
|
-
export { c as AIFullQuizGeneratorModal, A as AIQuestionGeneratorModal, e as APIKeyManagerModal, f as ApiKeySettings, m as ApproachManager, B as BloomLevelManager, C as CategoryManager, l as ContextManager, E as EditQuestionModal, G as GradeLevelManager, I as ImportQuestionsModal, L as LearningObjectiveManager, n as MetadataImportControls, M as MetadataTabs, h as QuestionFilters, i as QuestionFormDialog, g as QuestionList, a as QuestionPreviewModal, k as QuestionTypeManager, Q as QuizAuthoringTool, b as QuizSettingsForm, d as SCORMExportModal, S as SelectedQuestionsPanel, j as SubjectManager, o as Toaster, T as TopicManager, t as toast, u as useToast } from './toaster-
|
|
5
|
+
export { c as AIFullQuizGeneratorModal, A as AIQuestionGeneratorModal, e as APIKeyManagerModal, f as ApiKeySettings, m as ApproachManager, B as BloomLevelManager, C as CategoryManager, l as ContextManager, E as EditQuestionModal, G as GradeLevelManager, I as ImportQuestionsModal, L as LearningObjectiveManager, n as MetadataImportControls, M as MetadataTabs, h as QuestionFilters, i as QuestionFormDialog, g as QuestionList, a as QuestionPreviewModal, k as QuestionTypeManager, Q as QuizAuthoringTool, b as QuizSettingsForm, d as SCORMExportModal, S as SelectedQuestionsPanel, j as SubjectManager, o as Toaster, T as TopicManager, t as toast, u as useToast } from './toaster-B2MPZYhi.js';
|
|
6
6
|
import 'clsx';
|
|
7
7
|
import 'zod';
|
|
8
8
|
import 'react';
|
package/dist/authoring.mjs
CHANGED
|
@@ -71606,21 +71606,30 @@ var EditableCombobox = ({
|
|
|
71606
71606
|
disabled = false
|
|
71607
71607
|
}) => {
|
|
71608
71608
|
const [open, setOpen] = React119.useState(false);
|
|
71609
|
-
const [inputValue, setInputValue] = React119.useState(
|
|
71609
|
+
const [inputValue, setInputValue] = React119.useState("");
|
|
71610
71610
|
React119.useEffect(() => {
|
|
71611
|
-
|
|
71612
|
-
|
|
71613
|
-
|
|
71614
|
-
|
|
71615
|
-
|
|
71616
|
-
|
|
71611
|
+
if (value) {
|
|
71612
|
+
const selectedOption = options.find((option) => option.value.toLowerCase() === value.toLowerCase());
|
|
71613
|
+
setInputValue(selectedOption ? selectedOption.label : value);
|
|
71614
|
+
} else {
|
|
71615
|
+
setInputValue("");
|
|
71616
|
+
}
|
|
71617
|
+
}, [value, options, open]);
|
|
71618
|
+
const handleSelect = (selectedValue) => {
|
|
71619
|
+
onChange(selectedValue);
|
|
71617
71620
|
setOpen(false);
|
|
71618
71621
|
};
|
|
71619
|
-
const
|
|
71620
|
-
|
|
71622
|
+
const handleOpenChange = (isOpen) => {
|
|
71623
|
+
if (!isOpen) {
|
|
71624
|
+
const match2 = options.find((option) => option.label.toLowerCase() === inputValue.toLowerCase());
|
|
71625
|
+
if (!match2 && inputValue !== (options.find((opt) => opt.value === value)?.label || value)) {
|
|
71626
|
+
onChange(inputValue);
|
|
71627
|
+
}
|
|
71628
|
+
}
|
|
71629
|
+
setOpen(isOpen);
|
|
71621
71630
|
};
|
|
71622
71631
|
const displayLabel = options.find((option) => option.value.toLowerCase() === value?.toLowerCase())?.label || value;
|
|
71623
|
-
return /* @__PURE__ */ React119.createElement(Popover2, { open, onOpenChange:
|
|
71632
|
+
return /* @__PURE__ */ React119.createElement(Popover2, { open, onOpenChange: handleOpenChange }, /* @__PURE__ */ React119.createElement(PopoverTrigger2, { asChild: true }, /* @__PURE__ */ React119.createElement(
|
|
71624
71633
|
Button,
|
|
71625
71634
|
{
|
|
71626
71635
|
variant: "outline",
|
|
@@ -71636,8 +71645,7 @@ var EditableCombobox = ({
|
|
|
71636
71645
|
{
|
|
71637
71646
|
placeholder: searchPlaceholder,
|
|
71638
71647
|
value: inputValue,
|
|
71639
|
-
onValueChange: setInputValue
|
|
71640
|
-
onBlur: handleBlur
|
|
71648
|
+
onValueChange: setInputValue
|
|
71641
71649
|
}
|
|
71642
71650
|
), /* @__PURE__ */ React119.createElement(CommandList, null, /* @__PURE__ */ React119.createElement(CommandEmpty, null, noResultsMessage), /* @__PURE__ */ React119.createElement(CommandGroup, null, options.map((option) => /* @__PURE__ */ React119.createElement(
|
|
71643
71651
|
CommandItem,
|
|
@@ -72936,6 +72944,10 @@ var supportedQuestionTypesForAI = [
|
|
|
72936
72944
|
{ value: "sequence", label: "Sequence" },
|
|
72937
72945
|
{ value: "matching", label: "Matching" }
|
|
72938
72946
|
];
|
|
72947
|
+
var availableLanguages = [
|
|
72948
|
+
{ value: "English", label: "English" },
|
|
72949
|
+
{ value: "Vietnamese", label: "Ti\u1EBFng Vi\u1EC7t" }
|
|
72950
|
+
];
|
|
72939
72951
|
var AIQuestionGeneratorModal = ({
|
|
72940
72952
|
isOpen,
|
|
72941
72953
|
onClose,
|
|
@@ -72945,51 +72957,65 @@ var AIQuestionGeneratorModal = ({
|
|
|
72945
72957
|
subjects = [],
|
|
72946
72958
|
topics = [],
|
|
72947
72959
|
gradeLevels = [],
|
|
72948
|
-
bloomLevels = []
|
|
72960
|
+
bloomLevels = [],
|
|
72961
|
+
categories = []
|
|
72949
72962
|
}) => {
|
|
72950
|
-
const [
|
|
72963
|
+
const [additionalInfo, setAdditionalInfo] = useState("");
|
|
72951
72964
|
const [isLoading, setIsLoading] = useState(false);
|
|
72952
72965
|
const [error, setError] = useState(null);
|
|
72953
72966
|
const { toast: toast2 } = useToast();
|
|
72954
72967
|
const [subjectCode, setSubjectCode] = useState("");
|
|
72968
|
+
const [categoryCode, setCategoryCode] = useState("");
|
|
72955
72969
|
const [topicCode, setTopicCode] = useState("");
|
|
72956
72970
|
const [gradeBand, setGradeBand] = useState("");
|
|
72957
72971
|
const [bloomLevelCode, setBloomLevelCode] = useState("");
|
|
72958
72972
|
const [selectedQuestionType, setSelectedQuestionType] = useState("multiple_choice");
|
|
72973
|
+
const [selectedLanguage, setSelectedLanguage] = useState(language3);
|
|
72959
72974
|
const [numberOfOptions, setNumberOfOptions] = useState(4);
|
|
72960
|
-
const [minCorrectAnswers, setMinCorrectAnswers] = useState(2);
|
|
72961
|
-
const [maxCorrectAnswers, setMaxCorrectAnswers] = useState(3);
|
|
72962
|
-
const [isCaseSensitive, setIsCaseSensitive] = useState(false);
|
|
72963
|
-
const [numberOfBlanks, setNumberOfBlanks] = useState(2);
|
|
72964
|
-
const [numberOfSequenceItems, setNumberOfSequenceItems] = useState(4);
|
|
72965
|
-
const [numberOfMatchingPairs, setNumberOfMatchingPairs] = useState(4);
|
|
72966
72975
|
const [isApiKeyManagerModalOpen, setIsApiKeyManagerModalOpen] = useState(false);
|
|
72967
72976
|
const [geminiApiKeyExists, setGeminiApiKeyExists] = useState(false);
|
|
72968
72977
|
const finalQuestionType = questionTypeProp || selectedQuestionType;
|
|
72969
72978
|
useEffect(() => {
|
|
72970
72979
|
if (isOpen) {
|
|
72971
|
-
|
|
72980
|
+
setAdditionalInfo("");
|
|
72972
72981
|
setError(null);
|
|
72973
72982
|
setIsLoading(false);
|
|
72974
72983
|
setSubjectCode("");
|
|
72984
|
+
setCategoryCode("");
|
|
72975
72985
|
setTopicCode("");
|
|
72976
72986
|
setGradeBand("");
|
|
72977
72987
|
setBloomLevelCode("");
|
|
72978
72988
|
setSelectedQuestionType(questionTypeProp || "multiple_choice");
|
|
72989
|
+
setSelectedLanguage(language3);
|
|
72979
72990
|
setGeminiApiKeyExists(APIKeyService.hasAPIKey(GEMINI_API_KEY_SERVICE_NAME));
|
|
72980
72991
|
}
|
|
72981
|
-
}, [isOpen, questionTypeProp]);
|
|
72992
|
+
}, [isOpen, questionTypeProp, language3]);
|
|
72993
|
+
const filteredCategories = useMemo(() => {
|
|
72994
|
+
return categories;
|
|
72995
|
+
}, [categories]);
|
|
72982
72996
|
const filteredTopics = useMemo(() => {
|
|
72983
|
-
if (!subjectCode) return [];
|
|
72984
|
-
return topics.filter(
|
|
72985
|
-
|
|
72997
|
+
if (!subjectCode || !categoryCode) return [];
|
|
72998
|
+
return topics.filter(
|
|
72999
|
+
(t2) => t2.subjectCode === subjectCode
|
|
73000
|
+
/* && t.categoryCode === categoryCode */
|
|
73001
|
+
);
|
|
73002
|
+
}, [subjectCode, categoryCode, topics]);
|
|
73003
|
+
const handleSubjectChange = (newSubjectCode) => {
|
|
73004
|
+
setSubjectCode(newSubjectCode);
|
|
73005
|
+
setCategoryCode("");
|
|
73006
|
+
setTopicCode("");
|
|
73007
|
+
};
|
|
73008
|
+
const handleCategoryChange = (newCategoryCode) => {
|
|
73009
|
+
setCategoryCode(newCategoryCode);
|
|
73010
|
+
setTopicCode("");
|
|
73011
|
+
};
|
|
72986
73012
|
const handleApiKeyModalClose = () => {
|
|
72987
73013
|
setIsApiKeyManagerModalOpen(false);
|
|
72988
73014
|
setGeminiApiKeyExists(APIKeyService.hasAPIKey(GEMINI_API_KEY_SERVICE_NAME));
|
|
72989
73015
|
};
|
|
72990
73016
|
const handleSubmit = async () => {
|
|
72991
|
-
if (!
|
|
72992
|
-
setError("Please
|
|
73017
|
+
if (!subjectCode || !categoryCode || !topicCode || !gradeBand || !bloomLevelCode) {
|
|
73018
|
+
setError("Please fill in all required metadata fields: Subject, Category, Topic, Grade Level, and Bloom's Level.");
|
|
72993
73019
|
return;
|
|
72994
73020
|
}
|
|
72995
73021
|
const geminiKey = APIKeyService.getAPIKey(GEMINI_API_KEY_SERVICE_NAME);
|
|
@@ -73003,14 +73029,15 @@ var AIQuestionGeneratorModal = ({
|
|
|
73003
73029
|
setIsLoading(true);
|
|
73004
73030
|
try {
|
|
73005
73031
|
const quizContext = {
|
|
73006
|
-
plannedTopic:
|
|
73032
|
+
plannedTopic: additionalInfo.trim() || topicCode,
|
|
73007
73033
|
originalSubject: subjectCode,
|
|
73008
73034
|
originalTopic: topicCode,
|
|
73035
|
+
originalCategory: categoryCode,
|
|
73009
73036
|
gradeBand,
|
|
73010
73037
|
plannedBloomLevel: bloomLevelCode
|
|
73011
73038
|
};
|
|
73012
73039
|
const baseClientInput = {
|
|
73013
|
-
language:
|
|
73040
|
+
language: selectedLanguage,
|
|
73014
73041
|
difficulty: "Medium",
|
|
73015
73042
|
quizContext
|
|
73016
73043
|
};
|
|
@@ -73023,33 +73050,32 @@ var AIQuestionGeneratorModal = ({
|
|
|
73023
73050
|
generatedResult = await generateMCQQuestion({ ...baseClientInput, numberOfOptions }, geminiKey);
|
|
73024
73051
|
break;
|
|
73025
73052
|
case "multiple_response":
|
|
73026
|
-
generatedResult = await generateMRQQuestion({ ...baseClientInput, numberOfOptions, minCorrectAnswers, maxCorrectAnswers }, geminiKey);
|
|
73053
|
+
generatedResult = await generateMRQQuestion({ ...baseClientInput, numberOfOptions: 5, minCorrectAnswers: 2, maxCorrectAnswers: 3 }, geminiKey);
|
|
73027
73054
|
break;
|
|
73028
73055
|
case "short_answer":
|
|
73029
|
-
generatedResult = await generateShortAnswerQuestion({ ...baseClientInput, isCaseSensitive }, geminiKey);
|
|
73056
|
+
generatedResult = await generateShortAnswerQuestion({ ...baseClientInput, isCaseSensitive: false }, geminiKey);
|
|
73030
73057
|
break;
|
|
73031
73058
|
case "numeric":
|
|
73032
73059
|
generatedResult = await generateNumericQuestion({ ...baseClientInput, allowDecimals: true, tolerance: 0 }, geminiKey);
|
|
73033
73060
|
break;
|
|
73034
73061
|
case "fill_in_the_blanks":
|
|
73035
|
-
generatedResult = await generateFillInTheBlanksQuestion({ ...baseClientInput, numberOfBlanks, isCaseSensitive }, geminiKey);
|
|
73062
|
+
generatedResult = await generateFillInTheBlanksQuestion({ ...baseClientInput, numberOfBlanks: 2, isCaseSensitive: false }, geminiKey);
|
|
73036
73063
|
break;
|
|
73037
73064
|
case "sequence":
|
|
73038
|
-
generatedResult = await generateSequenceQuestion({ ...baseClientInput, numberOfItems:
|
|
73065
|
+
generatedResult = await generateSequenceQuestion({ ...baseClientInput, numberOfItems: 4 }, geminiKey);
|
|
73039
73066
|
break;
|
|
73040
73067
|
case "matching":
|
|
73041
|
-
generatedResult = await generateMatchingQuestion({ ...baseClientInput, numberOfPairs:
|
|
73068
|
+
generatedResult = await generateMatchingQuestion({ ...baseClientInput, numberOfPairs: 4, shuffleOptions: true }, geminiKey);
|
|
73042
73069
|
break;
|
|
73043
73070
|
default:
|
|
73044
73071
|
throw new Error(`AI generation for '${finalQuestionType}' is not implemented in this flow.`);
|
|
73045
73072
|
}
|
|
73046
|
-
if (generatedResult.error)
|
|
73047
|
-
throw new Error(generatedResult.error);
|
|
73048
|
-
}
|
|
73073
|
+
if (generatedResult.error) throw new Error(generatedResult.error);
|
|
73049
73074
|
if (generatedResult.question) {
|
|
73050
73075
|
const completeQuestion = generatedResult.question;
|
|
73051
73076
|
completeQuestion.subject = subjectCode;
|
|
73052
73077
|
completeQuestion.topic = topicCode;
|
|
73078
|
+
completeQuestion.category = categoryCode;
|
|
73053
73079
|
completeQuestion.gradeBand = gradeBand;
|
|
73054
73080
|
completeQuestion.bloomLevel = bloomLevelCode;
|
|
73055
73081
|
if (completeQuestion.points === void 0) completeQuestion.points = 10;
|
|
@@ -73075,47 +73101,13 @@ var AIQuestionGeneratorModal = ({
|
|
|
73075
73101
|
const comboboxOptions = {
|
|
73076
73102
|
subjects: subjects.map((s2) => ({ value: s2.code, label: s2.name })),
|
|
73077
73103
|
topics: filteredTopics.map((t2) => ({ value: t2.code, label: t2.name })),
|
|
73104
|
+
categories: filteredCategories.map((c2) => ({ value: c2.code, label: c2.name })),
|
|
73078
73105
|
gradeLevels: gradeLevels.map((g) => ({ value: g.code, label: g.name })),
|
|
73079
73106
|
bloomLevels: bloomLevels.map((b) => ({ value: b.code, label: b.name }))
|
|
73080
73107
|
};
|
|
73081
|
-
const renderSpecificParams = () => {
|
|
73082
|
-
switch (finalQuestionType) {
|
|
73083
|
-
case "multiple_choice":
|
|
73084
|
-
case "multiple_response":
|
|
73085
|
-
return /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-2 pt-4 border-t" }, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "ai-num-options" }, "Number of Options (2-8)"), /* @__PURE__ */ React119__default.createElement(
|
|
73086
|
-
Input,
|
|
73087
|
-
{
|
|
73088
|
-
id: "ai-num-options",
|
|
73089
|
-
type: "number",
|
|
73090
|
-
value: numberOfOptions,
|
|
73091
|
-
onChange: (e2) => setNumberOfOptions(parseInt(e2.target.value, 10)),
|
|
73092
|
-
min: 2,
|
|
73093
|
-
max: 8
|
|
73094
|
-
}
|
|
73095
|
-
), finalQuestionType === "multiple_response" && /* @__PURE__ */ React119__default.createElement(React119__default.Fragment, null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "ai-min-correct" }, "Min Correct Answers"), /* @__PURE__ */ React119__default.createElement(Input, { id: "ai-min-correct", type: "number", value: minCorrectAnswers, onChange: (e2) => setMinCorrectAnswers(parseInt(e2.target.value, 10)), min: 1, max: numberOfOptions }), /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "ai-max-correct" }, "Max Correct Answers"), /* @__PURE__ */ React119__default.createElement(Input, { id: "ai-max-correct", type: "number", value: maxCorrectAnswers, onChange: (e2) => setMaxCorrectAnswers(parseInt(e2.target.value, 10)), min: minCorrectAnswers, max: numberOfOptions })));
|
|
73096
|
-
case "short_answer":
|
|
73097
|
-
case "fill_in_the_blanks":
|
|
73098
|
-
return /* @__PURE__ */ React119__default.createElement("div", { className: "flex items-center space-x-2 pt-4 border-t" }, /* @__PURE__ */ React119__default.createElement("input", { type: "checkbox", id: "ai-case-sensitive", checked: isCaseSensitive, onChange: (e2) => setIsCaseSensitive(e2.target.checked), className: "h-4 w-4 rounded border-gray-300 text-primary focus:ring-primary" }), /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "ai-case-sensitive" }, "Case Sensitive Answers"), finalQuestionType === "fill_in_the_blanks" && /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-1 ml-4" }, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "ai-num-blanks" }, "Number of Blanks (1-5)"), /* @__PURE__ */ React119__default.createElement(Input, { id: "ai-num-blanks", type: "number", value: numberOfBlanks, onChange: (e2) => setNumberOfBlanks(parseInt(e2.target.value, 10)), min: 1, max: 5 })));
|
|
73099
|
-
case "sequence":
|
|
73100
|
-
return /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-2 pt-4 border-t" }, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "ai-num-seq-items" }, "Number of Items to Sequence (2-10)"), /* @__PURE__ */ React119__default.createElement(Input, { id: "ai-num-seq-items", type: "number", value: numberOfSequenceItems, onChange: (e2) => setNumberOfSequenceItems(parseInt(e2.target.value, 10)), min: 2, max: 10 }));
|
|
73101
|
-
case "matching":
|
|
73102
|
-
return /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-2 pt-4 border-t" }, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "ai-num-match-pairs" }, "Number of Pairs to Match (2-8)"), /* @__PURE__ */ React119__default.createElement(Input, { id: "ai-num-match-pairs", type: "number", value: numberOfMatchingPairs, onChange: (e2) => setNumberOfMatchingPairs(parseInt(e2.target.value, 10)), min: 2, max: 8 }));
|
|
73103
|
-
default:
|
|
73104
|
-
return null;
|
|
73105
|
-
}
|
|
73106
|
-
};
|
|
73107
73108
|
return /* @__PURE__ */ React119__default.createElement(React119__default.Fragment, null, /* @__PURE__ */ React119__default.createElement(Dialog2, { open: isOpen, onOpenChange: (open) => {
|
|
73108
73109
|
if (!open) onClose();
|
|
73109
|
-
} }, /* @__PURE__ */ React119__default.createElement(DialogContent2, { className: "sm:max-w-[
|
|
73110
|
-
Textarea,
|
|
73111
|
-
{
|
|
73112
|
-
id: "ai-prompt",
|
|
73113
|
-
value: prompt,
|
|
73114
|
-
onChange: (e2) => setPrompt(e2.target.value),
|
|
73115
|
-
placeholder: "e.g., The process of photosynthesis, The causes of World War II, Basic Algebra Equations",
|
|
73116
|
-
className: "min-h-[100px]"
|
|
73117
|
-
}
|
|
73118
|
-
)), /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-2 gap-4" }, /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React119__default.createElement(Label2, null, "Subject"), /* @__PURE__ */ React119__default.createElement(EditableCombobox, { options: comboboxOptions.subjects, value: subjectCode, onChange: setSubjectCode, placeholder: "Select or type a Subject..." })), /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React119__default.createElement(Label2, null, "Topic"), /* @__PURE__ */ React119__default.createElement(EditableCombobox, { options: comboboxOptions.topics, value: topicCode, onChange: setTopicCode, placeholder: "Select or type a Topic...", disabled: !subjectCode })), /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React119__default.createElement(Label2, null, "Grade Level"), /* @__PURE__ */ React119__default.createElement(EditableCombobox, { options: comboboxOptions.gradeLevels, value: gradeBand, onChange: setGradeBand, placeholder: "Select or type a Grade..." })), /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React119__default.createElement(Label2, null, "Bloom's Level"), /* @__PURE__ */ React119__default.createElement(EditableCombobox, { options: comboboxOptions.bloomLevels, value: bloomLevelCode, onChange: setBloomLevelCode, placeholder: "Select a Bloom's Level..." }))), renderSpecificParams(), error && /* @__PURE__ */ React119__default.createElement("p", { className: "text-sm text-destructive flex items-center mt-2" }, /* @__PURE__ */ React119__default.createElement(TriangleAlert, { className: "mr-1 h-4 w-4" }), " ", error)), /* @__PURE__ */ React119__default.createElement(DialogFooter, null, /* @__PURE__ */ React119__default.createElement(DialogClose2, { asChild: true }, /* @__PURE__ */ React119__default.createElement(Button, { type: "button", variant: "outline" }, "Cancel")), /* @__PURE__ */ React119__default.createElement(Button, { type: "button", onClick: handleSubmit, disabled: isLoading || !prompt.trim() || !geminiApiKeyExists }, isLoading ? /* @__PURE__ */ React119__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ React119__default.createElement(WandSparkles, { className: "mr-2 h-4 w-4" }), "Generate Question")))), /* @__PURE__ */ React119__default.createElement(APIKeyManagerModal, { isOpen: isApiKeyManagerModalOpen, onClose: handleApiKeyModalClose }));
|
|
73110
|
+
} }, /* @__PURE__ */ React119__default.createElement(DialogContent2, { className: "sm:max-w-[700px]" }, /* @__PURE__ */ React119__default.createElement(DialogHeader, null, /* @__PURE__ */ React119__default.createElement(DialogTitle2, { className: "flex items-center font-headline text-2xl" }, /* @__PURE__ */ React119__default.createElement(WandSparkles, { className: "mr-2 h-6 w-6 text-primary" }), " AI Question Generator"), /* @__PURE__ */ React119__default.createElement(DialogDescription2, null, "Provide metadata and optional info to generate a '", finalQuestionType, "' question.")), /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-4 py-4 max-h-[60vh] overflow-y-auto px-2" }, /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-2 gap-4" }, !questionTypeProp && /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React119__default.createElement(Label2, null, "Question Type"), /* @__PURE__ */ React119__default.createElement(Select2, { value: selectedQuestionType, onValueChange: (v) => setSelectedQuestionType(v) }, /* @__PURE__ */ React119__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React119__default.createElement(SelectValue2, null)), /* @__PURE__ */ React119__default.createElement(SelectContent2, null, supportedQuestionTypesForAI.map((type) => /* @__PURE__ */ React119__default.createElement(SelectItem2, { key: type.value, value: type.value }, type.label))))), /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React119__default.createElement(Label2, null, "Language"), /* @__PURE__ */ React119__default.createElement(Select2, { value: selectedLanguage, onValueChange: setSelectedLanguage }, /* @__PURE__ */ React119__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React119__default.createElement(SelectValue2, null)), /* @__PURE__ */ React119__default.createElement(SelectContent2, null, availableLanguages.map((lang) => /* @__PURE__ */ React119__default.createElement(SelectItem2, { key: lang.value, value: lang.value }, lang.label)))))), /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "ai-additional-info" }, "Additional Info (Optional)"), /* @__PURE__ */ React119__default.createElement(Textarea, { id: "ai-additional-info", value: additionalInfo, onChange: (e2) => setAdditionalInfo(e2.target.value), placeholder: "Provide extra context, a specific topic, or a detailed prompt for the AI...", className: "min-h-[100px]" })), /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-2 gap-4" }, /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React119__default.createElement(Label2, null, "Subject *"), /* @__PURE__ */ React119__default.createElement(EditableCombobox, { options: comboboxOptions.subjects, value: subjectCode, onChange: handleSubjectChange, placeholder: "Select Subject..." })), /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React119__default.createElement(Label2, null, "Category *"), /* @__PURE__ */ React119__default.createElement(EditableCombobox, { options: comboboxOptions.categories, value: categoryCode, onChange: handleCategoryChange, placeholder: "Select Category...", disabled: !subjectCode })), /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React119__default.createElement(Label2, null, "Topic *"), /* @__PURE__ */ React119__default.createElement(EditableCombobox, { options: comboboxOptions.topics, value: topicCode, onChange: setTopicCode, placeholder: "Select Topic...", disabled: !categoryCode })), /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React119__default.createElement(Label2, null, "Grade Level *"), /* @__PURE__ */ React119__default.createElement(EditableCombobox, { options: comboboxOptions.gradeLevels, value: gradeBand, onChange: setGradeBand, placeholder: "Select Grade..." })), /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React119__default.createElement(Label2, null, "Bloom's Level *"), /* @__PURE__ */ React119__default.createElement(EditableCombobox, { options: comboboxOptions.bloomLevels, value: bloomLevelCode, onChange: setBloomLevelCode, placeholder: "Select Bloom's Level..." }))), finalQuestionType === "multiple_choice" && /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-2 pt-4 border-t" }, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "ai-num-options" }, "Number of Options (2-8)"), /* @__PURE__ */ React119__default.createElement(Input, { id: "ai-num-options", type: "number", value: numberOfOptions, onChange: (e2) => setNumberOfOptions(parseInt(e2.target.value, 10)), min: 2, max: 8 })), error && /* @__PURE__ */ React119__default.createElement("p", { className: "text-sm text-destructive flex items-center mt-2" }, /* @__PURE__ */ React119__default.createElement(TriangleAlert, { className: "mr-1 h-4 w-4" }), " ", error)), /* @__PURE__ */ React119__default.createElement(DialogFooter, null, /* @__PURE__ */ React119__default.createElement(DialogClose2, { asChild: true }, /* @__PURE__ */ React119__default.createElement(Button, { type: "button", variant: "outline" }, "Cancel")), /* @__PURE__ */ React119__default.createElement(Button, { type: "button", onClick: handleSubmit, disabled: isLoading || !geminiApiKeyExists || !subjectCode || !categoryCode || !topicCode || !gradeBand || !bloomLevelCode }, isLoading ? /* @__PURE__ */ React119__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ React119__default.createElement(WandSparkles, { className: "mr-2 h-4 w-4" }), "Generate Question")))), /* @__PURE__ */ React119__default.createElement(APIKeyManagerModal, { isOpen: isApiKeyManagerModalOpen, onClose: handleApiKeyModalClose }));
|
|
73119
73111
|
};
|
|
73120
73112
|
|
|
73121
73113
|
// src/react-ui/components/authoring/AIFullQuizGeneratorModal.tsx
|
package/dist/react-ui.cjs
CHANGED
|
@@ -98269,21 +98269,30 @@ var EditableCombobox = ({
|
|
|
98269
98269
|
disabled = false
|
|
98270
98270
|
}) => {
|
|
98271
98271
|
const [open, setOpen] = React169__namespace.useState(false);
|
|
98272
|
-
const [inputValue, setInputValue] = React169__namespace.useState(
|
|
98272
|
+
const [inputValue, setInputValue] = React169__namespace.useState("");
|
|
98273
98273
|
React169__namespace.useEffect(() => {
|
|
98274
|
-
|
|
98275
|
-
|
|
98276
|
-
|
|
98277
|
-
|
|
98278
|
-
|
|
98279
|
-
|
|
98274
|
+
if (value) {
|
|
98275
|
+
const selectedOption = options.find((option) => option.value.toLowerCase() === value.toLowerCase());
|
|
98276
|
+
setInputValue(selectedOption ? selectedOption.label : value);
|
|
98277
|
+
} else {
|
|
98278
|
+
setInputValue("");
|
|
98279
|
+
}
|
|
98280
|
+
}, [value, options, open]);
|
|
98281
|
+
const handleSelect = (selectedValue) => {
|
|
98282
|
+
onChange(selectedValue);
|
|
98280
98283
|
setOpen(false);
|
|
98281
98284
|
};
|
|
98282
|
-
const
|
|
98283
|
-
|
|
98285
|
+
const handleOpenChange = (isOpen) => {
|
|
98286
|
+
if (!isOpen) {
|
|
98287
|
+
const match2 = options.find((option) => option.label.toLowerCase() === inputValue.toLowerCase());
|
|
98288
|
+
if (!match2 && inputValue !== (options.find((opt) => opt.value === value)?.label || value)) {
|
|
98289
|
+
onChange(inputValue);
|
|
98290
|
+
}
|
|
98291
|
+
}
|
|
98292
|
+
setOpen(isOpen);
|
|
98284
98293
|
};
|
|
98285
98294
|
const displayLabel = options.find((option) => option.value.toLowerCase() === value?.toLowerCase())?.label || value;
|
|
98286
|
-
return /* @__PURE__ */ React169__namespace.createElement(Popover2, { open, onOpenChange:
|
|
98295
|
+
return /* @__PURE__ */ React169__namespace.createElement(Popover2, { open, onOpenChange: handleOpenChange }, /* @__PURE__ */ React169__namespace.createElement(PopoverTrigger2, { asChild: true }, /* @__PURE__ */ React169__namespace.createElement(
|
|
98287
98296
|
Button,
|
|
98288
98297
|
{
|
|
98289
98298
|
variant: "outline",
|
|
@@ -98299,8 +98308,7 @@ var EditableCombobox = ({
|
|
|
98299
98308
|
{
|
|
98300
98309
|
placeholder: searchPlaceholder,
|
|
98301
98310
|
value: inputValue,
|
|
98302
|
-
onValueChange: setInputValue
|
|
98303
|
-
onBlur: handleBlur
|
|
98311
|
+
onValueChange: setInputValue
|
|
98304
98312
|
}
|
|
98305
98313
|
), /* @__PURE__ */ React169__namespace.createElement(CommandList, null, /* @__PURE__ */ React169__namespace.createElement(CommandEmpty, null, noResultsMessage), /* @__PURE__ */ React169__namespace.createElement(CommandGroup, null, options.map((option) => /* @__PURE__ */ React169__namespace.createElement(
|
|
98306
98314
|
CommandItem,
|
|
@@ -101237,6 +101245,10 @@ var supportedQuestionTypesForAI = [
|
|
|
101237
101245
|
{ value: "sequence", label: "Sequence" },
|
|
101238
101246
|
{ value: "matching", label: "Matching" }
|
|
101239
101247
|
];
|
|
101248
|
+
var availableLanguages = [
|
|
101249
|
+
{ value: "English", label: "English" },
|
|
101250
|
+
{ value: "Vietnamese", label: "Ti\u1EBFng Vi\u1EC7t" }
|
|
101251
|
+
];
|
|
101240
101252
|
var AIQuestionGeneratorModal = ({
|
|
101241
101253
|
isOpen,
|
|
101242
101254
|
onClose,
|
|
@@ -101246,51 +101258,65 @@ var AIQuestionGeneratorModal = ({
|
|
|
101246
101258
|
subjects = [],
|
|
101247
101259
|
topics = [],
|
|
101248
101260
|
gradeLevels = [],
|
|
101249
|
-
bloomLevels = []
|
|
101261
|
+
bloomLevels = [],
|
|
101262
|
+
categories = []
|
|
101250
101263
|
}) => {
|
|
101251
|
-
const [
|
|
101264
|
+
const [additionalInfo, setAdditionalInfo] = React169.useState("");
|
|
101252
101265
|
const [isLoading, setIsLoading] = React169.useState(false);
|
|
101253
101266
|
const [error, setError] = React169.useState(null);
|
|
101254
101267
|
const { toast: toast2 } = useToast();
|
|
101255
101268
|
const [subjectCode, setSubjectCode] = React169.useState("");
|
|
101269
|
+
const [categoryCode, setCategoryCode] = React169.useState("");
|
|
101256
101270
|
const [topicCode, setTopicCode] = React169.useState("");
|
|
101257
101271
|
const [gradeBand, setGradeBand] = React169.useState("");
|
|
101258
101272
|
const [bloomLevelCode, setBloomLevelCode] = React169.useState("");
|
|
101259
101273
|
const [selectedQuestionType, setSelectedQuestionType] = React169.useState("multiple_choice");
|
|
101274
|
+
const [selectedLanguage, setSelectedLanguage] = React169.useState(language3);
|
|
101260
101275
|
const [numberOfOptions, setNumberOfOptions] = React169.useState(4);
|
|
101261
|
-
const [minCorrectAnswers, setMinCorrectAnswers] = React169.useState(2);
|
|
101262
|
-
const [maxCorrectAnswers, setMaxCorrectAnswers] = React169.useState(3);
|
|
101263
|
-
const [isCaseSensitive, setIsCaseSensitive] = React169.useState(false);
|
|
101264
|
-
const [numberOfBlanks, setNumberOfBlanks] = React169.useState(2);
|
|
101265
|
-
const [numberOfSequenceItems, setNumberOfSequenceItems] = React169.useState(4);
|
|
101266
|
-
const [numberOfMatchingPairs, setNumberOfMatchingPairs] = React169.useState(4);
|
|
101267
101276
|
const [isApiKeyManagerModalOpen, setIsApiKeyManagerModalOpen] = React169.useState(false);
|
|
101268
101277
|
const [geminiApiKeyExists, setGeminiApiKeyExists] = React169.useState(false);
|
|
101269
101278
|
const finalQuestionType = questionTypeProp || selectedQuestionType;
|
|
101270
101279
|
React169.useEffect(() => {
|
|
101271
101280
|
if (isOpen) {
|
|
101272
|
-
|
|
101281
|
+
setAdditionalInfo("");
|
|
101273
101282
|
setError(null);
|
|
101274
101283
|
setIsLoading(false);
|
|
101275
101284
|
setSubjectCode("");
|
|
101285
|
+
setCategoryCode("");
|
|
101276
101286
|
setTopicCode("");
|
|
101277
101287
|
setGradeBand("");
|
|
101278
101288
|
setBloomLevelCode("");
|
|
101279
101289
|
setSelectedQuestionType(questionTypeProp || "multiple_choice");
|
|
101290
|
+
setSelectedLanguage(language3);
|
|
101280
101291
|
setGeminiApiKeyExists(APIKeyService.hasAPIKey(GEMINI_API_KEY_SERVICE_NAME));
|
|
101281
101292
|
}
|
|
101282
|
-
}, [isOpen, questionTypeProp]);
|
|
101293
|
+
}, [isOpen, questionTypeProp, language3]);
|
|
101294
|
+
const filteredCategories = React169.useMemo(() => {
|
|
101295
|
+
return categories;
|
|
101296
|
+
}, [categories]);
|
|
101283
101297
|
const filteredTopics = React169.useMemo(() => {
|
|
101284
|
-
if (!subjectCode) return [];
|
|
101285
|
-
return topics.filter(
|
|
101286
|
-
|
|
101298
|
+
if (!subjectCode || !categoryCode) return [];
|
|
101299
|
+
return topics.filter(
|
|
101300
|
+
(t4) => t4.subjectCode === subjectCode
|
|
101301
|
+
/* && t.categoryCode === categoryCode */
|
|
101302
|
+
);
|
|
101303
|
+
}, [subjectCode, categoryCode, topics]);
|
|
101304
|
+
const handleSubjectChange = (newSubjectCode) => {
|
|
101305
|
+
setSubjectCode(newSubjectCode);
|
|
101306
|
+
setCategoryCode("");
|
|
101307
|
+
setTopicCode("");
|
|
101308
|
+
};
|
|
101309
|
+
const handleCategoryChange = (newCategoryCode) => {
|
|
101310
|
+
setCategoryCode(newCategoryCode);
|
|
101311
|
+
setTopicCode("");
|
|
101312
|
+
};
|
|
101287
101313
|
const handleApiKeyModalClose = () => {
|
|
101288
101314
|
setIsApiKeyManagerModalOpen(false);
|
|
101289
101315
|
setGeminiApiKeyExists(APIKeyService.hasAPIKey(GEMINI_API_KEY_SERVICE_NAME));
|
|
101290
101316
|
};
|
|
101291
101317
|
const handleSubmit = async () => {
|
|
101292
|
-
if (!
|
|
101293
|
-
setError("Please
|
|
101318
|
+
if (!subjectCode || !categoryCode || !topicCode || !gradeBand || !bloomLevelCode) {
|
|
101319
|
+
setError("Please fill in all required metadata fields: Subject, Category, Topic, Grade Level, and Bloom's Level.");
|
|
101294
101320
|
return;
|
|
101295
101321
|
}
|
|
101296
101322
|
const geminiKey = APIKeyService.getAPIKey(GEMINI_API_KEY_SERVICE_NAME);
|
|
@@ -101304,14 +101330,15 @@ var AIQuestionGeneratorModal = ({
|
|
|
101304
101330
|
setIsLoading(true);
|
|
101305
101331
|
try {
|
|
101306
101332
|
const quizContext = {
|
|
101307
|
-
plannedTopic:
|
|
101333
|
+
plannedTopic: additionalInfo.trim() || topicCode,
|
|
101308
101334
|
originalSubject: subjectCode,
|
|
101309
101335
|
originalTopic: topicCode,
|
|
101336
|
+
originalCategory: categoryCode,
|
|
101310
101337
|
gradeBand,
|
|
101311
101338
|
plannedBloomLevel: bloomLevelCode
|
|
101312
101339
|
};
|
|
101313
101340
|
const baseClientInput = {
|
|
101314
|
-
language:
|
|
101341
|
+
language: selectedLanguage,
|
|
101315
101342
|
difficulty: "Medium",
|
|
101316
101343
|
quizContext
|
|
101317
101344
|
};
|
|
@@ -101324,33 +101351,32 @@ var AIQuestionGeneratorModal = ({
|
|
|
101324
101351
|
generatedResult = await generateMCQQuestion({ ...baseClientInput, numberOfOptions }, geminiKey);
|
|
101325
101352
|
break;
|
|
101326
101353
|
case "multiple_response":
|
|
101327
|
-
generatedResult = await generateMRQQuestion({ ...baseClientInput, numberOfOptions, minCorrectAnswers, maxCorrectAnswers }, geminiKey);
|
|
101354
|
+
generatedResult = await generateMRQQuestion({ ...baseClientInput, numberOfOptions: 5, minCorrectAnswers: 2, maxCorrectAnswers: 3 }, geminiKey);
|
|
101328
101355
|
break;
|
|
101329
101356
|
case "short_answer":
|
|
101330
|
-
generatedResult = await generateShortAnswerQuestion({ ...baseClientInput, isCaseSensitive }, geminiKey);
|
|
101357
|
+
generatedResult = await generateShortAnswerQuestion({ ...baseClientInput, isCaseSensitive: false }, geminiKey);
|
|
101331
101358
|
break;
|
|
101332
101359
|
case "numeric":
|
|
101333
101360
|
generatedResult = await generateNumericQuestion({ ...baseClientInput, allowDecimals: true, tolerance: 0 }, geminiKey);
|
|
101334
101361
|
break;
|
|
101335
101362
|
case "fill_in_the_blanks":
|
|
101336
|
-
generatedResult = await generateFillInTheBlanksQuestion({ ...baseClientInput, numberOfBlanks, isCaseSensitive }, geminiKey);
|
|
101363
|
+
generatedResult = await generateFillInTheBlanksQuestion({ ...baseClientInput, numberOfBlanks: 2, isCaseSensitive: false }, geminiKey);
|
|
101337
101364
|
break;
|
|
101338
101365
|
case "sequence":
|
|
101339
|
-
generatedResult = await generateSequenceQuestion({ ...baseClientInput, numberOfItems:
|
|
101366
|
+
generatedResult = await generateSequenceQuestion({ ...baseClientInput, numberOfItems: 4 }, geminiKey);
|
|
101340
101367
|
break;
|
|
101341
101368
|
case "matching":
|
|
101342
|
-
generatedResult = await generateMatchingQuestion({ ...baseClientInput, numberOfPairs:
|
|
101369
|
+
generatedResult = await generateMatchingQuestion({ ...baseClientInput, numberOfPairs: 4, shuffleOptions: true }, geminiKey);
|
|
101343
101370
|
break;
|
|
101344
101371
|
default:
|
|
101345
101372
|
throw new Error(`AI generation for '${finalQuestionType}' is not implemented in this flow.`);
|
|
101346
101373
|
}
|
|
101347
|
-
if (generatedResult.error)
|
|
101348
|
-
throw new Error(generatedResult.error);
|
|
101349
|
-
}
|
|
101374
|
+
if (generatedResult.error) throw new Error(generatedResult.error);
|
|
101350
101375
|
if (generatedResult.question) {
|
|
101351
101376
|
const completeQuestion = generatedResult.question;
|
|
101352
101377
|
completeQuestion.subject = subjectCode;
|
|
101353
101378
|
completeQuestion.topic = topicCode;
|
|
101379
|
+
completeQuestion.category = categoryCode;
|
|
101354
101380
|
completeQuestion.gradeBand = gradeBand;
|
|
101355
101381
|
completeQuestion.bloomLevel = bloomLevelCode;
|
|
101356
101382
|
if (completeQuestion.points === void 0) completeQuestion.points = 10;
|
|
@@ -101376,47 +101402,13 @@ var AIQuestionGeneratorModal = ({
|
|
|
101376
101402
|
const comboboxOptions = {
|
|
101377
101403
|
subjects: subjects.map((s4) => ({ value: s4.code, label: s4.name })),
|
|
101378
101404
|
topics: filteredTopics.map((t4) => ({ value: t4.code, label: t4.name })),
|
|
101405
|
+
categories: filteredCategories.map((c4) => ({ value: c4.code, label: c4.name })),
|
|
101379
101406
|
gradeLevels: gradeLevels.map((g) => ({ value: g.code, label: g.name })),
|
|
101380
101407
|
bloomLevels: bloomLevels.map((b2) => ({ value: b2.code, label: b2.name }))
|
|
101381
101408
|
};
|
|
101382
|
-
const renderSpecificParams = () => {
|
|
101383
|
-
switch (finalQuestionType) {
|
|
101384
|
-
case "multiple_choice":
|
|
101385
|
-
case "multiple_response":
|
|
101386
|
-
return /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2 pt-4 border-t" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: "ai-num-options" }, "Number of Options (2-8)"), /* @__PURE__ */ React169__namespace.default.createElement(
|
|
101387
|
-
Input,
|
|
101388
|
-
{
|
|
101389
|
-
id: "ai-num-options",
|
|
101390
|
-
type: "number",
|
|
101391
|
-
value: numberOfOptions,
|
|
101392
|
-
onChange: (e3) => setNumberOfOptions(parseInt(e3.target.value, 10)),
|
|
101393
|
-
min: 2,
|
|
101394
|
-
max: 8
|
|
101395
|
-
}
|
|
101396
|
-
), finalQuestionType === "multiple_response" && /* @__PURE__ */ React169__namespace.default.createElement(React169__namespace.default.Fragment, null, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: "ai-min-correct" }, "Min Correct Answers"), /* @__PURE__ */ React169__namespace.default.createElement(Input, { id: "ai-min-correct", type: "number", value: minCorrectAnswers, onChange: (e3) => setMinCorrectAnswers(parseInt(e3.target.value, 10)), min: 1, max: numberOfOptions }), /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: "ai-max-correct" }, "Max Correct Answers"), /* @__PURE__ */ React169__namespace.default.createElement(Input, { id: "ai-max-correct", type: "number", value: maxCorrectAnswers, onChange: (e3) => setMaxCorrectAnswers(parseInt(e3.target.value, 10)), min: minCorrectAnswers, max: numberOfOptions })));
|
|
101397
|
-
case "short_answer":
|
|
101398
|
-
case "fill_in_the_blanks":
|
|
101399
|
-
return /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "flex items-center space-x-2 pt-4 border-t" }, /* @__PURE__ */ React169__namespace.default.createElement("input", { type: "checkbox", id: "ai-case-sensitive", checked: isCaseSensitive, onChange: (e3) => setIsCaseSensitive(e3.target.checked), className: "h-4 w-4 rounded border-gray-300 text-primary focus:ring-primary" }), /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: "ai-case-sensitive" }, "Case Sensitive Answers"), finalQuestionType === "fill_in_the_blanks" && /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-1 ml-4" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: "ai-num-blanks" }, "Number of Blanks (1-5)"), /* @__PURE__ */ React169__namespace.default.createElement(Input, { id: "ai-num-blanks", type: "number", value: numberOfBlanks, onChange: (e3) => setNumberOfBlanks(parseInt(e3.target.value, 10)), min: 1, max: 5 })));
|
|
101400
|
-
case "sequence":
|
|
101401
|
-
return /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2 pt-4 border-t" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: "ai-num-seq-items" }, "Number of Items to Sequence (2-10)"), /* @__PURE__ */ React169__namespace.default.createElement(Input, { id: "ai-num-seq-items", type: "number", value: numberOfSequenceItems, onChange: (e3) => setNumberOfSequenceItems(parseInt(e3.target.value, 10)), min: 2, max: 10 }));
|
|
101402
|
-
case "matching":
|
|
101403
|
-
return /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2 pt-4 border-t" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: "ai-num-match-pairs" }, "Number of Pairs to Match (2-8)"), /* @__PURE__ */ React169__namespace.default.createElement(Input, { id: "ai-num-match-pairs", type: "number", value: numberOfMatchingPairs, onChange: (e3) => setNumberOfMatchingPairs(parseInt(e3.target.value, 10)), min: 2, max: 8 }));
|
|
101404
|
-
default:
|
|
101405
|
-
return null;
|
|
101406
|
-
}
|
|
101407
|
-
};
|
|
101408
101409
|
return /* @__PURE__ */ React169__namespace.default.createElement(React169__namespace.default.Fragment, null, /* @__PURE__ */ React169__namespace.default.createElement(Dialog2, { open: isOpen, onOpenChange: (open) => {
|
|
101409
101410
|
if (!open) onClose();
|
|
101410
|
-
} }, /* @__PURE__ */ React169__namespace.default.createElement(DialogContent2, { className: "sm:max-w-[
|
|
101411
|
-
Textarea,
|
|
101412
|
-
{
|
|
101413
|
-
id: "ai-prompt",
|
|
101414
|
-
value: prompt,
|
|
101415
|
-
onChange: (e3) => setPrompt(e3.target.value),
|
|
101416
|
-
placeholder: "e.g., The process of photosynthesis, The causes of World War II, Basic Algebra Equations",
|
|
101417
|
-
className: "min-h-[100px]"
|
|
101418
|
-
}
|
|
101419
|
-
)), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "grid grid-cols-2 gap-4" }, /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, null, "Subject"), /* @__PURE__ */ React169__namespace.default.createElement(EditableCombobox, { options: comboboxOptions.subjects, value: subjectCode, onChange: setSubjectCode, placeholder: "Select or type a Subject..." })), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, null, "Topic"), /* @__PURE__ */ React169__namespace.default.createElement(EditableCombobox, { options: comboboxOptions.topics, value: topicCode, onChange: setTopicCode, placeholder: "Select or type a Topic...", disabled: !subjectCode })), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, null, "Grade Level"), /* @__PURE__ */ React169__namespace.default.createElement(EditableCombobox, { options: comboboxOptions.gradeLevels, value: gradeBand, onChange: setGradeBand, placeholder: "Select or type a Grade..." })), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, null, "Bloom's Level"), /* @__PURE__ */ React169__namespace.default.createElement(EditableCombobox, { options: comboboxOptions.bloomLevels, value: bloomLevelCode, onChange: setBloomLevelCode, placeholder: "Select a Bloom's Level..." }))), renderSpecificParams(), error && /* @__PURE__ */ React169__namespace.default.createElement("p", { className: "text-sm text-destructive flex items-center mt-2" }, /* @__PURE__ */ React169__namespace.default.createElement(TriangleAlert, { className: "mr-1 h-4 w-4" }), " ", error)), /* @__PURE__ */ React169__namespace.default.createElement(DialogFooter, null, /* @__PURE__ */ React169__namespace.default.createElement(DialogClose2, { asChild: true }, /* @__PURE__ */ React169__namespace.default.createElement(Button, { type: "button", variant: "outline" }, "Cancel")), /* @__PURE__ */ React169__namespace.default.createElement(Button, { type: "button", onClick: handleSubmit, disabled: isLoading || !prompt.trim() || !geminiApiKeyExists }, isLoading ? /* @__PURE__ */ React169__namespace.default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ React169__namespace.default.createElement(WandSparkles, { className: "mr-2 h-4 w-4" }), "Generate Question")))), /* @__PURE__ */ React169__namespace.default.createElement(APIKeyManagerModal, { isOpen: isApiKeyManagerModalOpen, onClose: handleApiKeyModalClose }));
|
|
101411
|
+
} }, /* @__PURE__ */ React169__namespace.default.createElement(DialogContent2, { className: "sm:max-w-[700px]" }, /* @__PURE__ */ React169__namespace.default.createElement(DialogHeader, null, /* @__PURE__ */ React169__namespace.default.createElement(DialogTitle2, { className: "flex items-center font-headline text-2xl" }, /* @__PURE__ */ React169__namespace.default.createElement(WandSparkles, { className: "mr-2 h-6 w-6 text-primary" }), " AI Question Generator"), /* @__PURE__ */ React169__namespace.default.createElement(DialogDescription2, null, "Provide metadata and optional info to generate a '", finalQuestionType, "' question.")), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-4 py-4 max-h-[60vh] overflow-y-auto px-2" }, /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "grid grid-cols-2 gap-4" }, !questionTypeProp && /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, null, "Question Type"), /* @__PURE__ */ React169__namespace.default.createElement(Select2, { value: selectedQuestionType, onValueChange: (v) => setSelectedQuestionType(v) }, /* @__PURE__ */ React169__namespace.default.createElement(SelectTrigger2, null, /* @__PURE__ */ React169__namespace.default.createElement(SelectValue2, null)), /* @__PURE__ */ React169__namespace.default.createElement(SelectContent2, null, supportedQuestionTypesForAI.map((type) => /* @__PURE__ */ React169__namespace.default.createElement(SelectItem2, { key: type.value, value: type.value }, type.label))))), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, null, "Language"), /* @__PURE__ */ React169__namespace.default.createElement(Select2, { value: selectedLanguage, onValueChange: setSelectedLanguage }, /* @__PURE__ */ React169__namespace.default.createElement(SelectTrigger2, null, /* @__PURE__ */ React169__namespace.default.createElement(SelectValue2, null)), /* @__PURE__ */ React169__namespace.default.createElement(SelectContent2, null, availableLanguages.map((lang) => /* @__PURE__ */ React169__namespace.default.createElement(SelectItem2, { key: lang.value, value: lang.value }, lang.label)))))), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: "ai-additional-info" }, "Additional Info (Optional)"), /* @__PURE__ */ React169__namespace.default.createElement(Textarea, { id: "ai-additional-info", value: additionalInfo, onChange: (e3) => setAdditionalInfo(e3.target.value), placeholder: "Provide extra context, a specific topic, or a detailed prompt for the AI...", className: "min-h-[100px]" })), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "grid grid-cols-2 gap-4" }, /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, null, "Subject *"), /* @__PURE__ */ React169__namespace.default.createElement(EditableCombobox, { options: comboboxOptions.subjects, value: subjectCode, onChange: handleSubjectChange, placeholder: "Select Subject..." })), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, null, "Category *"), /* @__PURE__ */ React169__namespace.default.createElement(EditableCombobox, { options: comboboxOptions.categories, value: categoryCode, onChange: handleCategoryChange, placeholder: "Select Category...", disabled: !subjectCode })), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, null, "Topic *"), /* @__PURE__ */ React169__namespace.default.createElement(EditableCombobox, { options: comboboxOptions.topics, value: topicCode, onChange: setTopicCode, placeholder: "Select Topic...", disabled: !categoryCode })), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, null, "Grade Level *"), /* @__PURE__ */ React169__namespace.default.createElement(EditableCombobox, { options: comboboxOptions.gradeLevels, value: gradeBand, onChange: setGradeBand, placeholder: "Select Grade..." })), /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, null, "Bloom's Level *"), /* @__PURE__ */ React169__namespace.default.createElement(EditableCombobox, { options: comboboxOptions.bloomLevels, value: bloomLevelCode, onChange: setBloomLevelCode, placeholder: "Select Bloom's Level..." }))), finalQuestionType === "multiple_choice" && /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-2 pt-4 border-t" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: "ai-num-options" }, "Number of Options (2-8)"), /* @__PURE__ */ React169__namespace.default.createElement(Input, { id: "ai-num-options", type: "number", value: numberOfOptions, onChange: (e3) => setNumberOfOptions(parseInt(e3.target.value, 10)), min: 2, max: 8 })), error && /* @__PURE__ */ React169__namespace.default.createElement("p", { className: "text-sm text-destructive flex items-center mt-2" }, /* @__PURE__ */ React169__namespace.default.createElement(TriangleAlert, { className: "mr-1 h-4 w-4" }), " ", error)), /* @__PURE__ */ React169__namespace.default.createElement(DialogFooter, null, /* @__PURE__ */ React169__namespace.default.createElement(DialogClose2, { asChild: true }, /* @__PURE__ */ React169__namespace.default.createElement(Button, { type: "button", variant: "outline" }, "Cancel")), /* @__PURE__ */ React169__namespace.default.createElement(Button, { type: "button", onClick: handleSubmit, disabled: isLoading || !geminiApiKeyExists || !subjectCode || !categoryCode || !topicCode || !gradeBand || !bloomLevelCode }, isLoading ? /* @__PURE__ */ React169__namespace.default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ React169__namespace.default.createElement(WandSparkles, { className: "mr-2 h-4 w-4" }), "Generate Question")))), /* @__PURE__ */ React169__namespace.default.createElement(APIKeyManagerModal, { isOpen: isApiKeyManagerModalOpen, onClose: handleApiKeyModalClose }));
|
|
101420
101412
|
};
|
|
101421
101413
|
|
|
101422
101414
|
// src/react-ui/components/authoring/AIFullQuizGeneratorModal.tsx
|
package/dist/react-ui.d.cts
CHANGED
|
@@ -5,7 +5,7 @@ import { Q as QuizResultType, U as UserAnswerType, n as PracticeSession, o as Pr
|
|
|
5
5
|
export { j as AchievementDefinition, r as ActivityCalendarData, u as AnalysisReport, A as AnswerDetail, x as ChatContext, C as ChatMessage, v as DashboardCardConfig, D as DashboardCardId, w as DashboardLayout, y as Goal, G as GoalType, t as ImageContextItem, I as ImportError, K as KnowledgeCard, L as LearningAnalysis, e as PerformanceByBloomLevel, b as PerformanceByCategory, d as PerformanceByDifficulty, P as PerformanceByLearningObjective, c as PerformanceByTopic, f as PerformanceMetric, s as PerformanceSummary, k as PracticeDifficulty, q as PracticeTopicSummary, g as QuestionReview, R as RoadmapItem, T as TestCaseResult, a as UserAnswers, W as WeeklyRoadmap } from './ai-ecosystem-DyQYZbyX.cjs';
|
|
6
6
|
import * as React$1 from 'react';
|
|
7
7
|
import React__default, { ReactNode } from 'react';
|
|
8
|
-
export { c as AIFullQuizGeneratorModal, A as AIQuestionGeneratorModal, e as APIKeyManagerModal, f as ApiKeySettings, m as ApproachManager, B as BloomLevelManager, C as CategoryManager, l as ContextManager, E as EditQuestionModal, G as GradeLevelManager, I as ImportQuestionsModal, L as LearningObjectiveManager, n as MetadataImportControls, M as MetadataTabs, h as QuestionFilters, i as QuestionFormDialog, g as QuestionList, a as QuestionPreviewModal, k as QuestionTypeManager, Q as QuizAuthoringTool, b as QuizSettingsForm, d as SCORMExportModal, S as SelectedQuestionsPanel, j as SubjectManager, o as Toaster, T as TopicManager, t as toast, u as useToast } from './toaster-
|
|
8
|
+
export { c as AIFullQuizGeneratorModal, A as AIQuestionGeneratorModal, e as APIKeyManagerModal, f as ApiKeySettings, m as ApproachManager, B as BloomLevelManager, C as CategoryManager, l as ContextManager, E as EditQuestionModal, G as GradeLevelManager, I as ImportQuestionsModal, L as LearningObjectiveManager, n as MetadataImportControls, M as MetadataTabs, h as QuestionFilters, i as QuestionFormDialog, g as QuestionList, a as QuestionPreviewModal, k as QuestionTypeManager, Q as QuizAuthoringTool, b as QuizSettingsForm, d as SCORMExportModal, S as SelectedQuestionsPanel, j as SubjectManager, o as Toaster, T as TopicManager, t as toast, u as useToast } from './toaster-Bvhmyef9.cjs';
|
|
9
9
|
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
10
10
|
import { VariantProps } from 'class-variance-authority';
|
|
11
11
|
import * as LabelPrimitive from '@radix-ui/react-label';
|
package/dist/react-ui.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { Q as QuizResultType, U as UserAnswerType, n as PracticeSession, o as Pr
|
|
|
5
5
|
export { j as AchievementDefinition, r as ActivityCalendarData, u as AnalysisReport, A as AnswerDetail, x as ChatContext, C as ChatMessage, v as DashboardCardConfig, D as DashboardCardId, w as DashboardLayout, y as Goal, G as GoalType, t as ImageContextItem, I as ImportError, K as KnowledgeCard, L as LearningAnalysis, e as PerformanceByBloomLevel, b as PerformanceByCategory, d as PerformanceByDifficulty, P as PerformanceByLearningObjective, c as PerformanceByTopic, f as PerformanceMetric, s as PerformanceSummary, k as PracticeDifficulty, q as PracticeTopicSummary, g as QuestionReview, R as RoadmapItem, T as TestCaseResult, a as UserAnswers, W as WeeklyRoadmap } from './ai-ecosystem-Qa_SdE2T.js';
|
|
6
6
|
import * as React$1 from 'react';
|
|
7
7
|
import React__default, { ReactNode } from 'react';
|
|
8
|
-
export { c as AIFullQuizGeneratorModal, A as AIQuestionGeneratorModal, e as APIKeyManagerModal, f as ApiKeySettings, m as ApproachManager, B as BloomLevelManager, C as CategoryManager, l as ContextManager, E as EditQuestionModal, G as GradeLevelManager, I as ImportQuestionsModal, L as LearningObjectiveManager, n as MetadataImportControls, M as MetadataTabs, h as QuestionFilters, i as QuestionFormDialog, g as QuestionList, a as QuestionPreviewModal, k as QuestionTypeManager, Q as QuizAuthoringTool, b as QuizSettingsForm, d as SCORMExportModal, S as SelectedQuestionsPanel, j as SubjectManager, o as Toaster, T as TopicManager, t as toast, u as useToast } from './toaster-
|
|
8
|
+
export { c as AIFullQuizGeneratorModal, A as AIQuestionGeneratorModal, e as APIKeyManagerModal, f as ApiKeySettings, m as ApproachManager, B as BloomLevelManager, C as CategoryManager, l as ContextManager, E as EditQuestionModal, G as GradeLevelManager, I as ImportQuestionsModal, L as LearningObjectiveManager, n as MetadataImportControls, M as MetadataTabs, h as QuestionFilters, i as QuestionFormDialog, g as QuestionList, a as QuestionPreviewModal, k as QuestionTypeManager, Q as QuizAuthoringTool, b as QuizSettingsForm, d as SCORMExportModal, S as SelectedQuestionsPanel, j as SubjectManager, o as Toaster, T as TopicManager, t as toast, u as useToast } from './toaster-B2MPZYhi.js';
|
|
9
9
|
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
10
10
|
import { VariantProps } from 'class-variance-authority';
|
|
11
11
|
import * as LabelPrimitive from '@radix-ui/react-label';
|
package/dist/react-ui.mjs
CHANGED
|
@@ -98203,21 +98203,30 @@ var EditableCombobox = ({
|
|
|
98203
98203
|
disabled = false
|
|
98204
98204
|
}) => {
|
|
98205
98205
|
const [open, setOpen] = React169.useState(false);
|
|
98206
|
-
const [inputValue, setInputValue] = React169.useState(
|
|
98206
|
+
const [inputValue, setInputValue] = React169.useState("");
|
|
98207
98207
|
React169.useEffect(() => {
|
|
98208
|
-
|
|
98209
|
-
|
|
98210
|
-
|
|
98211
|
-
|
|
98212
|
-
|
|
98213
|
-
|
|
98208
|
+
if (value) {
|
|
98209
|
+
const selectedOption = options.find((option) => option.value.toLowerCase() === value.toLowerCase());
|
|
98210
|
+
setInputValue(selectedOption ? selectedOption.label : value);
|
|
98211
|
+
} else {
|
|
98212
|
+
setInputValue("");
|
|
98213
|
+
}
|
|
98214
|
+
}, [value, options, open]);
|
|
98215
|
+
const handleSelect = (selectedValue) => {
|
|
98216
|
+
onChange(selectedValue);
|
|
98214
98217
|
setOpen(false);
|
|
98215
98218
|
};
|
|
98216
|
-
const
|
|
98217
|
-
|
|
98219
|
+
const handleOpenChange = (isOpen) => {
|
|
98220
|
+
if (!isOpen) {
|
|
98221
|
+
const match2 = options.find((option) => option.label.toLowerCase() === inputValue.toLowerCase());
|
|
98222
|
+
if (!match2 && inputValue !== (options.find((opt) => opt.value === value)?.label || value)) {
|
|
98223
|
+
onChange(inputValue);
|
|
98224
|
+
}
|
|
98225
|
+
}
|
|
98226
|
+
setOpen(isOpen);
|
|
98218
98227
|
};
|
|
98219
98228
|
const displayLabel = options.find((option) => option.value.toLowerCase() === value?.toLowerCase())?.label || value;
|
|
98220
|
-
return /* @__PURE__ */ React169.createElement(Popover2, { open, onOpenChange:
|
|
98229
|
+
return /* @__PURE__ */ React169.createElement(Popover2, { open, onOpenChange: handleOpenChange }, /* @__PURE__ */ React169.createElement(PopoverTrigger2, { asChild: true }, /* @__PURE__ */ React169.createElement(
|
|
98221
98230
|
Button,
|
|
98222
98231
|
{
|
|
98223
98232
|
variant: "outline",
|
|
@@ -98233,8 +98242,7 @@ var EditableCombobox = ({
|
|
|
98233
98242
|
{
|
|
98234
98243
|
placeholder: searchPlaceholder,
|
|
98235
98244
|
value: inputValue,
|
|
98236
|
-
onValueChange: setInputValue
|
|
98237
|
-
onBlur: handleBlur
|
|
98245
|
+
onValueChange: setInputValue
|
|
98238
98246
|
}
|
|
98239
98247
|
), /* @__PURE__ */ React169.createElement(CommandList, null, /* @__PURE__ */ React169.createElement(CommandEmpty, null, noResultsMessage), /* @__PURE__ */ React169.createElement(CommandGroup, null, options.map((option) => /* @__PURE__ */ React169.createElement(
|
|
98240
98248
|
CommandItem,
|
|
@@ -101171,6 +101179,10 @@ var supportedQuestionTypesForAI = [
|
|
|
101171
101179
|
{ value: "sequence", label: "Sequence" },
|
|
101172
101180
|
{ value: "matching", label: "Matching" }
|
|
101173
101181
|
];
|
|
101182
|
+
var availableLanguages = [
|
|
101183
|
+
{ value: "English", label: "English" },
|
|
101184
|
+
{ value: "Vietnamese", label: "Ti\u1EBFng Vi\u1EC7t" }
|
|
101185
|
+
];
|
|
101174
101186
|
var AIQuestionGeneratorModal = ({
|
|
101175
101187
|
isOpen,
|
|
101176
101188
|
onClose,
|
|
@@ -101180,51 +101192,65 @@ var AIQuestionGeneratorModal = ({
|
|
|
101180
101192
|
subjects = [],
|
|
101181
101193
|
topics = [],
|
|
101182
101194
|
gradeLevels = [],
|
|
101183
|
-
bloomLevels = []
|
|
101195
|
+
bloomLevels = [],
|
|
101196
|
+
categories = []
|
|
101184
101197
|
}) => {
|
|
101185
|
-
const [
|
|
101198
|
+
const [additionalInfo, setAdditionalInfo] = useState("");
|
|
101186
101199
|
const [isLoading, setIsLoading] = useState(false);
|
|
101187
101200
|
const [error, setError] = useState(null);
|
|
101188
101201
|
const { toast: toast2 } = useToast();
|
|
101189
101202
|
const [subjectCode, setSubjectCode] = useState("");
|
|
101203
|
+
const [categoryCode, setCategoryCode] = useState("");
|
|
101190
101204
|
const [topicCode, setTopicCode] = useState("");
|
|
101191
101205
|
const [gradeBand, setGradeBand] = useState("");
|
|
101192
101206
|
const [bloomLevelCode, setBloomLevelCode] = useState("");
|
|
101193
101207
|
const [selectedQuestionType, setSelectedQuestionType] = useState("multiple_choice");
|
|
101208
|
+
const [selectedLanguage, setSelectedLanguage] = useState(language3);
|
|
101194
101209
|
const [numberOfOptions, setNumberOfOptions] = useState(4);
|
|
101195
|
-
const [minCorrectAnswers, setMinCorrectAnswers] = useState(2);
|
|
101196
|
-
const [maxCorrectAnswers, setMaxCorrectAnswers] = useState(3);
|
|
101197
|
-
const [isCaseSensitive, setIsCaseSensitive] = useState(false);
|
|
101198
|
-
const [numberOfBlanks, setNumberOfBlanks] = useState(2);
|
|
101199
|
-
const [numberOfSequenceItems, setNumberOfSequenceItems] = useState(4);
|
|
101200
|
-
const [numberOfMatchingPairs, setNumberOfMatchingPairs] = useState(4);
|
|
101201
101210
|
const [isApiKeyManagerModalOpen, setIsApiKeyManagerModalOpen] = useState(false);
|
|
101202
101211
|
const [geminiApiKeyExists, setGeminiApiKeyExists] = useState(false);
|
|
101203
101212
|
const finalQuestionType = questionTypeProp || selectedQuestionType;
|
|
101204
101213
|
useEffect(() => {
|
|
101205
101214
|
if (isOpen) {
|
|
101206
|
-
|
|
101215
|
+
setAdditionalInfo("");
|
|
101207
101216
|
setError(null);
|
|
101208
101217
|
setIsLoading(false);
|
|
101209
101218
|
setSubjectCode("");
|
|
101219
|
+
setCategoryCode("");
|
|
101210
101220
|
setTopicCode("");
|
|
101211
101221
|
setGradeBand("");
|
|
101212
101222
|
setBloomLevelCode("");
|
|
101213
101223
|
setSelectedQuestionType(questionTypeProp || "multiple_choice");
|
|
101224
|
+
setSelectedLanguage(language3);
|
|
101214
101225
|
setGeminiApiKeyExists(APIKeyService.hasAPIKey(GEMINI_API_KEY_SERVICE_NAME));
|
|
101215
101226
|
}
|
|
101216
|
-
}, [isOpen, questionTypeProp]);
|
|
101227
|
+
}, [isOpen, questionTypeProp, language3]);
|
|
101228
|
+
const filteredCategories = useMemo(() => {
|
|
101229
|
+
return categories;
|
|
101230
|
+
}, [categories]);
|
|
101217
101231
|
const filteredTopics = useMemo(() => {
|
|
101218
|
-
if (!subjectCode) return [];
|
|
101219
|
-
return topics.filter(
|
|
101220
|
-
|
|
101232
|
+
if (!subjectCode || !categoryCode) return [];
|
|
101233
|
+
return topics.filter(
|
|
101234
|
+
(t4) => t4.subjectCode === subjectCode
|
|
101235
|
+
/* && t.categoryCode === categoryCode */
|
|
101236
|
+
);
|
|
101237
|
+
}, [subjectCode, categoryCode, topics]);
|
|
101238
|
+
const handleSubjectChange = (newSubjectCode) => {
|
|
101239
|
+
setSubjectCode(newSubjectCode);
|
|
101240
|
+
setCategoryCode("");
|
|
101241
|
+
setTopicCode("");
|
|
101242
|
+
};
|
|
101243
|
+
const handleCategoryChange = (newCategoryCode) => {
|
|
101244
|
+
setCategoryCode(newCategoryCode);
|
|
101245
|
+
setTopicCode("");
|
|
101246
|
+
};
|
|
101221
101247
|
const handleApiKeyModalClose = () => {
|
|
101222
101248
|
setIsApiKeyManagerModalOpen(false);
|
|
101223
101249
|
setGeminiApiKeyExists(APIKeyService.hasAPIKey(GEMINI_API_KEY_SERVICE_NAME));
|
|
101224
101250
|
};
|
|
101225
101251
|
const handleSubmit = async () => {
|
|
101226
|
-
if (!
|
|
101227
|
-
setError("Please
|
|
101252
|
+
if (!subjectCode || !categoryCode || !topicCode || !gradeBand || !bloomLevelCode) {
|
|
101253
|
+
setError("Please fill in all required metadata fields: Subject, Category, Topic, Grade Level, and Bloom's Level.");
|
|
101228
101254
|
return;
|
|
101229
101255
|
}
|
|
101230
101256
|
const geminiKey = APIKeyService.getAPIKey(GEMINI_API_KEY_SERVICE_NAME);
|
|
@@ -101238,14 +101264,15 @@ var AIQuestionGeneratorModal = ({
|
|
|
101238
101264
|
setIsLoading(true);
|
|
101239
101265
|
try {
|
|
101240
101266
|
const quizContext = {
|
|
101241
|
-
plannedTopic:
|
|
101267
|
+
plannedTopic: additionalInfo.trim() || topicCode,
|
|
101242
101268
|
originalSubject: subjectCode,
|
|
101243
101269
|
originalTopic: topicCode,
|
|
101270
|
+
originalCategory: categoryCode,
|
|
101244
101271
|
gradeBand,
|
|
101245
101272
|
plannedBloomLevel: bloomLevelCode
|
|
101246
101273
|
};
|
|
101247
101274
|
const baseClientInput = {
|
|
101248
|
-
language:
|
|
101275
|
+
language: selectedLanguage,
|
|
101249
101276
|
difficulty: "Medium",
|
|
101250
101277
|
quizContext
|
|
101251
101278
|
};
|
|
@@ -101258,33 +101285,32 @@ var AIQuestionGeneratorModal = ({
|
|
|
101258
101285
|
generatedResult = await generateMCQQuestion({ ...baseClientInput, numberOfOptions }, geminiKey);
|
|
101259
101286
|
break;
|
|
101260
101287
|
case "multiple_response":
|
|
101261
|
-
generatedResult = await generateMRQQuestion({ ...baseClientInput, numberOfOptions, minCorrectAnswers, maxCorrectAnswers }, geminiKey);
|
|
101288
|
+
generatedResult = await generateMRQQuestion({ ...baseClientInput, numberOfOptions: 5, minCorrectAnswers: 2, maxCorrectAnswers: 3 }, geminiKey);
|
|
101262
101289
|
break;
|
|
101263
101290
|
case "short_answer":
|
|
101264
|
-
generatedResult = await generateShortAnswerQuestion({ ...baseClientInput, isCaseSensitive }, geminiKey);
|
|
101291
|
+
generatedResult = await generateShortAnswerQuestion({ ...baseClientInput, isCaseSensitive: false }, geminiKey);
|
|
101265
101292
|
break;
|
|
101266
101293
|
case "numeric":
|
|
101267
101294
|
generatedResult = await generateNumericQuestion({ ...baseClientInput, allowDecimals: true, tolerance: 0 }, geminiKey);
|
|
101268
101295
|
break;
|
|
101269
101296
|
case "fill_in_the_blanks":
|
|
101270
|
-
generatedResult = await generateFillInTheBlanksQuestion({ ...baseClientInput, numberOfBlanks, isCaseSensitive }, geminiKey);
|
|
101297
|
+
generatedResult = await generateFillInTheBlanksQuestion({ ...baseClientInput, numberOfBlanks: 2, isCaseSensitive: false }, geminiKey);
|
|
101271
101298
|
break;
|
|
101272
101299
|
case "sequence":
|
|
101273
|
-
generatedResult = await generateSequenceQuestion({ ...baseClientInput, numberOfItems:
|
|
101300
|
+
generatedResult = await generateSequenceQuestion({ ...baseClientInput, numberOfItems: 4 }, geminiKey);
|
|
101274
101301
|
break;
|
|
101275
101302
|
case "matching":
|
|
101276
|
-
generatedResult = await generateMatchingQuestion({ ...baseClientInput, numberOfPairs:
|
|
101303
|
+
generatedResult = await generateMatchingQuestion({ ...baseClientInput, numberOfPairs: 4, shuffleOptions: true }, geminiKey);
|
|
101277
101304
|
break;
|
|
101278
101305
|
default:
|
|
101279
101306
|
throw new Error(`AI generation for '${finalQuestionType}' is not implemented in this flow.`);
|
|
101280
101307
|
}
|
|
101281
|
-
if (generatedResult.error)
|
|
101282
|
-
throw new Error(generatedResult.error);
|
|
101283
|
-
}
|
|
101308
|
+
if (generatedResult.error) throw new Error(generatedResult.error);
|
|
101284
101309
|
if (generatedResult.question) {
|
|
101285
101310
|
const completeQuestion = generatedResult.question;
|
|
101286
101311
|
completeQuestion.subject = subjectCode;
|
|
101287
101312
|
completeQuestion.topic = topicCode;
|
|
101313
|
+
completeQuestion.category = categoryCode;
|
|
101288
101314
|
completeQuestion.gradeBand = gradeBand;
|
|
101289
101315
|
completeQuestion.bloomLevel = bloomLevelCode;
|
|
101290
101316
|
if (completeQuestion.points === void 0) completeQuestion.points = 10;
|
|
@@ -101310,47 +101336,13 @@ var AIQuestionGeneratorModal = ({
|
|
|
101310
101336
|
const comboboxOptions = {
|
|
101311
101337
|
subjects: subjects.map((s4) => ({ value: s4.code, label: s4.name })),
|
|
101312
101338
|
topics: filteredTopics.map((t4) => ({ value: t4.code, label: t4.name })),
|
|
101339
|
+
categories: filteredCategories.map((c4) => ({ value: c4.code, label: c4.name })),
|
|
101313
101340
|
gradeLevels: gradeLevels.map((g) => ({ value: g.code, label: g.name })),
|
|
101314
101341
|
bloomLevels: bloomLevels.map((b2) => ({ value: b2.code, label: b2.name }))
|
|
101315
101342
|
};
|
|
101316
|
-
const renderSpecificParams = () => {
|
|
101317
|
-
switch (finalQuestionType) {
|
|
101318
|
-
case "multiple_choice":
|
|
101319
|
-
case "multiple_response":
|
|
101320
|
-
return /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2 pt-4 border-t" }, /* @__PURE__ */ React169__default.createElement(Label2, { htmlFor: "ai-num-options" }, "Number of Options (2-8)"), /* @__PURE__ */ React169__default.createElement(
|
|
101321
|
-
Input,
|
|
101322
|
-
{
|
|
101323
|
-
id: "ai-num-options",
|
|
101324
|
-
type: "number",
|
|
101325
|
-
value: numberOfOptions,
|
|
101326
|
-
onChange: (e3) => setNumberOfOptions(parseInt(e3.target.value, 10)),
|
|
101327
|
-
min: 2,
|
|
101328
|
-
max: 8
|
|
101329
|
-
}
|
|
101330
|
-
), finalQuestionType === "multiple_response" && /* @__PURE__ */ React169__default.createElement(React169__default.Fragment, null, /* @__PURE__ */ React169__default.createElement(Label2, { htmlFor: "ai-min-correct" }, "Min Correct Answers"), /* @__PURE__ */ React169__default.createElement(Input, { id: "ai-min-correct", type: "number", value: minCorrectAnswers, onChange: (e3) => setMinCorrectAnswers(parseInt(e3.target.value, 10)), min: 1, max: numberOfOptions }), /* @__PURE__ */ React169__default.createElement(Label2, { htmlFor: "ai-max-correct" }, "Max Correct Answers"), /* @__PURE__ */ React169__default.createElement(Input, { id: "ai-max-correct", type: "number", value: maxCorrectAnswers, onChange: (e3) => setMaxCorrectAnswers(parseInt(e3.target.value, 10)), min: minCorrectAnswers, max: numberOfOptions })));
|
|
101331
|
-
case "short_answer":
|
|
101332
|
-
case "fill_in_the_blanks":
|
|
101333
|
-
return /* @__PURE__ */ React169__default.createElement("div", { className: "flex items-center space-x-2 pt-4 border-t" }, /* @__PURE__ */ React169__default.createElement("input", { type: "checkbox", id: "ai-case-sensitive", checked: isCaseSensitive, onChange: (e3) => setIsCaseSensitive(e3.target.checked), className: "h-4 w-4 rounded border-gray-300 text-primary focus:ring-primary" }), /* @__PURE__ */ React169__default.createElement(Label2, { htmlFor: "ai-case-sensitive" }, "Case Sensitive Answers"), finalQuestionType === "fill_in_the_blanks" && /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-1 ml-4" }, /* @__PURE__ */ React169__default.createElement(Label2, { htmlFor: "ai-num-blanks" }, "Number of Blanks (1-5)"), /* @__PURE__ */ React169__default.createElement(Input, { id: "ai-num-blanks", type: "number", value: numberOfBlanks, onChange: (e3) => setNumberOfBlanks(parseInt(e3.target.value, 10)), min: 1, max: 5 })));
|
|
101334
|
-
case "sequence":
|
|
101335
|
-
return /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2 pt-4 border-t" }, /* @__PURE__ */ React169__default.createElement(Label2, { htmlFor: "ai-num-seq-items" }, "Number of Items to Sequence (2-10)"), /* @__PURE__ */ React169__default.createElement(Input, { id: "ai-num-seq-items", type: "number", value: numberOfSequenceItems, onChange: (e3) => setNumberOfSequenceItems(parseInt(e3.target.value, 10)), min: 2, max: 10 }));
|
|
101336
|
-
case "matching":
|
|
101337
|
-
return /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2 pt-4 border-t" }, /* @__PURE__ */ React169__default.createElement(Label2, { htmlFor: "ai-num-match-pairs" }, "Number of Pairs to Match (2-8)"), /* @__PURE__ */ React169__default.createElement(Input, { id: "ai-num-match-pairs", type: "number", value: numberOfMatchingPairs, onChange: (e3) => setNumberOfMatchingPairs(parseInt(e3.target.value, 10)), min: 2, max: 8 }));
|
|
101338
|
-
default:
|
|
101339
|
-
return null;
|
|
101340
|
-
}
|
|
101341
|
-
};
|
|
101342
101343
|
return /* @__PURE__ */ React169__default.createElement(React169__default.Fragment, null, /* @__PURE__ */ React169__default.createElement(Dialog2, { open: isOpen, onOpenChange: (open) => {
|
|
101343
101344
|
if (!open) onClose();
|
|
101344
|
-
} }, /* @__PURE__ */ React169__default.createElement(DialogContent2, { className: "sm:max-w-[
|
|
101345
|
-
Textarea,
|
|
101346
|
-
{
|
|
101347
|
-
id: "ai-prompt",
|
|
101348
|
-
value: prompt,
|
|
101349
|
-
onChange: (e3) => setPrompt(e3.target.value),
|
|
101350
|
-
placeholder: "e.g., The process of photosynthesis, The causes of World War II, Basic Algebra Equations",
|
|
101351
|
-
className: "min-h-[100px]"
|
|
101352
|
-
}
|
|
101353
|
-
)), /* @__PURE__ */ React169__default.createElement("div", { className: "grid grid-cols-2 gap-4" }, /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__default.createElement(Label2, null, "Subject"), /* @__PURE__ */ React169__default.createElement(EditableCombobox, { options: comboboxOptions.subjects, value: subjectCode, onChange: setSubjectCode, placeholder: "Select or type a Subject..." })), /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__default.createElement(Label2, null, "Topic"), /* @__PURE__ */ React169__default.createElement(EditableCombobox, { options: comboboxOptions.topics, value: topicCode, onChange: setTopicCode, placeholder: "Select or type a Topic...", disabled: !subjectCode })), /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__default.createElement(Label2, null, "Grade Level"), /* @__PURE__ */ React169__default.createElement(EditableCombobox, { options: comboboxOptions.gradeLevels, value: gradeBand, onChange: setGradeBand, placeholder: "Select or type a Grade..." })), /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__default.createElement(Label2, null, "Bloom's Level"), /* @__PURE__ */ React169__default.createElement(EditableCombobox, { options: comboboxOptions.bloomLevels, value: bloomLevelCode, onChange: setBloomLevelCode, placeholder: "Select a Bloom's Level..." }))), renderSpecificParams(), error && /* @__PURE__ */ React169__default.createElement("p", { className: "text-sm text-destructive flex items-center mt-2" }, /* @__PURE__ */ React169__default.createElement(TriangleAlert, { className: "mr-1 h-4 w-4" }), " ", error)), /* @__PURE__ */ React169__default.createElement(DialogFooter, null, /* @__PURE__ */ React169__default.createElement(DialogClose2, { asChild: true }, /* @__PURE__ */ React169__default.createElement(Button, { type: "button", variant: "outline" }, "Cancel")), /* @__PURE__ */ React169__default.createElement(Button, { type: "button", onClick: handleSubmit, disabled: isLoading || !prompt.trim() || !geminiApiKeyExists }, isLoading ? /* @__PURE__ */ React169__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ React169__default.createElement(WandSparkles, { className: "mr-2 h-4 w-4" }), "Generate Question")))), /* @__PURE__ */ React169__default.createElement(APIKeyManagerModal, { isOpen: isApiKeyManagerModalOpen, onClose: handleApiKeyModalClose }));
|
|
101345
|
+
} }, /* @__PURE__ */ React169__default.createElement(DialogContent2, { className: "sm:max-w-[700px]" }, /* @__PURE__ */ React169__default.createElement(DialogHeader, null, /* @__PURE__ */ React169__default.createElement(DialogTitle2, { className: "flex items-center font-headline text-2xl" }, /* @__PURE__ */ React169__default.createElement(WandSparkles, { className: "mr-2 h-6 w-6 text-primary" }), " AI Question Generator"), /* @__PURE__ */ React169__default.createElement(DialogDescription2, null, "Provide metadata and optional info to generate a '", finalQuestionType, "' question.")), /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-4 py-4 max-h-[60vh] overflow-y-auto px-2" }, /* @__PURE__ */ React169__default.createElement("div", { className: "grid grid-cols-2 gap-4" }, !questionTypeProp && /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__default.createElement(Label2, null, "Question Type"), /* @__PURE__ */ React169__default.createElement(Select2, { value: selectedQuestionType, onValueChange: (v) => setSelectedQuestionType(v) }, /* @__PURE__ */ React169__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React169__default.createElement(SelectValue2, null)), /* @__PURE__ */ React169__default.createElement(SelectContent2, null, supportedQuestionTypesForAI.map((type) => /* @__PURE__ */ React169__default.createElement(SelectItem2, { key: type.value, value: type.value }, type.label))))), /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__default.createElement(Label2, null, "Language"), /* @__PURE__ */ React169__default.createElement(Select2, { value: selectedLanguage, onValueChange: setSelectedLanguage }, /* @__PURE__ */ React169__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React169__default.createElement(SelectValue2, null)), /* @__PURE__ */ React169__default.createElement(SelectContent2, null, availableLanguages.map((lang) => /* @__PURE__ */ React169__default.createElement(SelectItem2, { key: lang.value, value: lang.value }, lang.label)))))), /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__default.createElement(Label2, { htmlFor: "ai-additional-info" }, "Additional Info (Optional)"), /* @__PURE__ */ React169__default.createElement(Textarea, { id: "ai-additional-info", value: additionalInfo, onChange: (e3) => setAdditionalInfo(e3.target.value), placeholder: "Provide extra context, a specific topic, or a detailed prompt for the AI...", className: "min-h-[100px]" })), /* @__PURE__ */ React169__default.createElement("div", { className: "grid grid-cols-2 gap-4" }, /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__default.createElement(Label2, null, "Subject *"), /* @__PURE__ */ React169__default.createElement(EditableCombobox, { options: comboboxOptions.subjects, value: subjectCode, onChange: handleSubjectChange, placeholder: "Select Subject..." })), /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__default.createElement(Label2, null, "Category *"), /* @__PURE__ */ React169__default.createElement(EditableCombobox, { options: comboboxOptions.categories, value: categoryCode, onChange: handleCategoryChange, placeholder: "Select Category...", disabled: !subjectCode })), /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__default.createElement(Label2, null, "Topic *"), /* @__PURE__ */ React169__default.createElement(EditableCombobox, { options: comboboxOptions.topics, value: topicCode, onChange: setTopicCode, placeholder: "Select Topic...", disabled: !categoryCode })), /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__default.createElement(Label2, null, "Grade Level *"), /* @__PURE__ */ React169__default.createElement(EditableCombobox, { options: comboboxOptions.gradeLevels, value: gradeBand, onChange: setGradeBand, placeholder: "Select Grade..." })), /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React169__default.createElement(Label2, null, "Bloom's Level *"), /* @__PURE__ */ React169__default.createElement(EditableCombobox, { options: comboboxOptions.bloomLevels, value: bloomLevelCode, onChange: setBloomLevelCode, placeholder: "Select Bloom's Level..." }))), finalQuestionType === "multiple_choice" && /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-2 pt-4 border-t" }, /* @__PURE__ */ React169__default.createElement(Label2, { htmlFor: "ai-num-options" }, "Number of Options (2-8)"), /* @__PURE__ */ React169__default.createElement(Input, { id: "ai-num-options", type: "number", value: numberOfOptions, onChange: (e3) => setNumberOfOptions(parseInt(e3.target.value, 10)), min: 2, max: 8 })), error && /* @__PURE__ */ React169__default.createElement("p", { className: "text-sm text-destructive flex items-center mt-2" }, /* @__PURE__ */ React169__default.createElement(TriangleAlert, { className: "mr-1 h-4 w-4" }), " ", error)), /* @__PURE__ */ React169__default.createElement(DialogFooter, null, /* @__PURE__ */ React169__default.createElement(DialogClose2, { asChild: true }, /* @__PURE__ */ React169__default.createElement(Button, { type: "button", variant: "outline" }, "Cancel")), /* @__PURE__ */ React169__default.createElement(Button, { type: "button", onClick: handleSubmit, disabled: isLoading || !geminiApiKeyExists || !subjectCode || !categoryCode || !topicCode || !gradeBand || !bloomLevelCode }, isLoading ? /* @__PURE__ */ React169__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ React169__default.createElement(WandSparkles, { className: "mr-2 h-4 w-4" }), "Generate Question")))), /* @__PURE__ */ React169__default.createElement(APIKeyManagerModal, { isOpen: isApiKeyManagerModalOpen, onClose: handleApiKeyModalClose }));
|
|
101354
101346
|
};
|
|
101355
101347
|
|
|
101356
101348
|
// src/react-ui/components/authoring/AIFullQuizGeneratorModal.tsx
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import React__default from 'react';
|
|
3
3
|
import { s as QuizConfig, g as QuizQuestion, Q as QuestionTypeStrings, r as QuizSettings } from './quiz-config-CwaP-pBs.js';
|
|
4
|
-
import { Subject, Topic, GradeLevel, BloomLevelType, QuestionInBank, QuestionFilters as QuestionFilters$1,
|
|
4
|
+
import { Subject, Topic, GradeLevel, BloomLevelType, Category, QuestionInBank, QuestionFilters as QuestionFilters$1, QuestionTypeType, LearningObjective, Context, Approach } from './index.js';
|
|
5
5
|
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
6
6
|
import * as ToastPrimitives from '@radix-ui/react-toast';
|
|
7
7
|
import { VariantProps } from 'class-variance-authority';
|
|
@@ -23,6 +23,7 @@ interface AIQuestionGeneratorModalProps {
|
|
|
23
23
|
topics?: Topic[];
|
|
24
24
|
gradeLevels?: GradeLevel[];
|
|
25
25
|
bloomLevels?: BloomLevelType[];
|
|
26
|
+
categories?: Category[];
|
|
26
27
|
}
|
|
27
28
|
declare const AIQuestionGeneratorModal: React__default.FC<AIQuestionGeneratorModalProps>;
|
|
28
29
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import React__default from 'react';
|
|
3
3
|
import { s as QuizConfig, g as QuizQuestion, Q as QuestionTypeStrings, r as QuizSettings } from './quiz-config-CwaP-pBs.cjs';
|
|
4
|
-
import { Subject, Topic, GradeLevel, BloomLevelType, QuestionInBank, QuestionFilters as QuestionFilters$1,
|
|
4
|
+
import { Subject, Topic, GradeLevel, BloomLevelType, Category, QuestionInBank, QuestionFilters as QuestionFilters$1, QuestionTypeType, LearningObjective, Context, Approach } from './index.cjs';
|
|
5
5
|
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
6
6
|
import * as ToastPrimitives from '@radix-ui/react-toast';
|
|
7
7
|
import { VariantProps } from 'class-variance-authority';
|
|
@@ -23,6 +23,7 @@ interface AIQuestionGeneratorModalProps {
|
|
|
23
23
|
topics?: Topic[];
|
|
24
24
|
gradeLevels?: GradeLevel[];
|
|
25
25
|
bloomLevels?: BloomLevelType[];
|
|
26
|
+
categories?: Category[];
|
|
26
27
|
}
|
|
27
28
|
declare const AIQuestionGeneratorModal: React__default.FC<AIQuestionGeneratorModalProps>;
|
|
28
29
|
|
package/package.json
CHANGED