@thanh01.pmt/interactive-quiz-kit 1.0.73 → 1.0.75

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.
@@ -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(value);
71674
+ const [inputValue, setInputValue] = React119__namespace.useState("");
71675
71675
  React119__namespace.useEffect(() => {
71676
- setInputValue(value);
71677
- }, [value]);
71678
- const handleSelect = (currentValue) => {
71679
- const newValue = currentValue === value ? "" : currentValue;
71680
- onChange(newValue);
71681
- setInputValue(newValue);
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 handleBlur = () => {
71685
- onChange(inputValue);
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: setOpen }, /* @__PURE__ */ React119__namespace.createElement(PopoverTrigger2, { asChild: true }, /* @__PURE__ */ React119__namespace.createElement(
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 [prompt, setPrompt] = React119.useState("");
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
- setPrompt("");
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((t2) => t2.subjectCode === subjectCode);
73050
- }, [subjectCode, topics]);
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 (!prompt.trim()) {
73057
- setError("Please provide a prompt for the question.");
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: prompt,
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: language3,
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: numberOfSequenceItems }, geminiKey);
73130
+ generatedResult = await generateSequenceQuestion({ ...baseClientInput, numberOfItems: 4 }, geminiKey);
73104
73131
  break;
73105
73132
  case "matching":
73106
- generatedResult = await generateMatchingQuestion({ ...baseClientInput, numberOfPairs: numberOfMatchingPairs, shuffleOptions: true }, geminiKey);
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-[600px]" }, /* @__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 a prompt and metadata 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" }, !geminiApiKeyExists && /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "p-3 mb-4 border border-amber-500 bg-amber-50 rounded-md text-amber-700" }), !questionTypeProp && /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "ai-q-type-select" }, "Question Type"), /* @__PURE__ */ React119__namespace.default.createElement(Select2, { value: selectedQuestionType, onValueChange: (v) => setSelectedQuestionType(v) }, /* @__PURE__ */ React119__namespace.default.createElement(SelectTrigger2, { id: "ai-q-type-select" }, /* @__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, { htmlFor: "ai-prompt" }, "Prompt / Topic"), /* @__PURE__ */ React119__namespace.default.createElement(
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
@@ -77896,7 +77888,7 @@ function ApproachManager({
77896
77888
  };
77897
77889
  const handleEditItem = (item) => {
77898
77890
  setCurrentItem(item);
77899
- setFormState(item);
77891
+ setFormState({ ...item, difficulty: Array.isArray(item.difficulty) ? item.difficulty : [item.difficulty] });
77900
77892
  setIsDialogOpen(true);
77901
77893
  };
77902
77894
  const handleDeleteItem = (item) => {
@@ -77989,11 +77981,18 @@ function ApproachManager({
77989
77981
  await onBulkAdd(validatedRecords);
77990
77982
  }
77991
77983
  };
77992
- return /* @__PURE__ */ React119__namespace.default.createElement(Card, null, /* @__PURE__ */ React119__namespace.default.createElement(CardHeader, null, /* @__PURE__ */ React119__namespace.default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React119__namespace.default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React119__namespace.default.createElement(Settings2, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Approaches"), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "flex items-center gap-2" }, onBulkAdd && /* @__PURE__ */ React119__namespace.default.createElement(MetadataImportControls, { metadataName: "Approaches", onImport: handleImport }), /* @__PURE__ */ React119__namespace.default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React119__namespace.default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Approach")))), /* @__PURE__ */ React119__namespace.default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React119__namespace.default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React119__namespace.default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No Approaches found.") : /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React119__namespace.default.createElement(Table2, null, /* @__PURE__ */ React119__namespace.default.createElement(TableHeader, null, /* @__PURE__ */ React119__namespace.default.createElement(TableRow, null, /* @__PURE__ */ React119__namespace.default.createElement(TableHead, null, "Approach ID"), /* @__PURE__ */ React119__namespace.default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React119__namespace.default.createElement(TableHead, null, "Verb (VI)"), /* @__PURE__ */ React119__namespace.default.createElement(TableHead, null, "Cognitive Level"), /* @__PURE__ */ React119__namespace.default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React119__namespace.default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React119__namespace.default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React119__namespace.default.createElement(TableCell, { className: "font-Medium" }, item.code), /* @__PURE__ */ React119__namespace.default.createElement(TableCell, null, item.name), /* @__PURE__ */ React119__namespace.default.createElement(TableCell, null, item.verbVi), /* @__PURE__ */ React119__namespace.default.createElement(TableCell, null, item.bloomLevelCode), /* @__PURE__ */ React119__namespace.default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React119__namespace.default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React119__namespace.default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React119__namespace.default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React119__namespace.default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React119__namespace.default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React119__namespace.default.createElement(DialogContent2, { className: "sm:max-w-2xl max-h-[90vh] overflow-y-auto" }, /* @__PURE__ */ React119__namespace.default.createElement(DialogHeader, null, /* @__PURE__ */ React119__namespace.default.createElement(DialogTitle2, null, currentItem ? "Edit Approach" : "Add New Approach")), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "code" }, "Approach Code"), /* @__PURE__ */ React119__namespace.default.createElement(Input, { id: "code", value: formState.code || "", onChange: (e2) => setFormState((s2) => ({ ...s2, code: e2.target.value.toUpperCase() })), placeholder: "e.g., REM-FAC-IDT-MCQ", disabled: !!currentItem })), /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "name" }, "Name / Description"), /* @__PURE__ */ React119__namespace.default.createElement(Input, { id: "name", value: formState.name || "", onChange: (e2) => setFormState((s2) => ({ ...s2, name: e2.target.value })), placeholder: "e.g., Identify a Fact" }))), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "verbEn" }, "Verb (English)"), /* @__PURE__ */ React119__namespace.default.createElement(Input, { id: "verbEn", value: formState.verbEn || "", onChange: (e2) => setFormState((s2) => ({ ...s2, verbEn: e2.target.value })), placeholder: "e.g., Identify" })), /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "verbVi" }, "Verb (Vietnamese)"), /* @__PURE__ */ React119__namespace.default.createElement(Input, { id: "verbVi", value: formState.verbVi || "", onChange: (e2) => setFormState((s2) => ({ ...s2, verbVi: e2.target.value })), placeholder: "e.g., Nh\u1EADn d\u1EA1ng" }))), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-4" }, /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "bloomLevelCode" }, "Cognitive Level"), /* @__PURE__ */ React119__namespace.default.createElement(Select2, { value: formState.bloomLevelCode, onValueChange: (v) => setFormState((s2) => ({ ...s2, bloomLevelCode: v })) }, /* @__PURE__ */ React119__namespace.default.createElement(SelectTrigger2, null, /* @__PURE__ */ React119__namespace.default.createElement(SelectValue2, null)), /* @__PURE__ */ React119__namespace.default.createElement(SelectContent2, null, bloomLevels.map((level) => /* @__PURE__ */ React119__namespace.default.createElement(SelectItem2, { key: level.code, value: level.code }, level.name))))), /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "knowledgeDimension" }, "Knowledge Dimension"), /* @__PURE__ */ React119__namespace.default.createElement(Select2, { value: formState.knowledgeDimension, onValueChange: (v) => setFormState((s2) => ({ ...s2, knowledgeDimension: v })) }, /* @__PURE__ */ React119__namespace.default.createElement(SelectTrigger2, null, /* @__PURE__ */ React119__namespace.default.createElement(SelectValue2, null)), /* @__PURE__ */ React119__namespace.default.createElement(SelectContent2, null, knowledgeDimensions.map((kd) => /* @__PURE__ */ React119__namespace.default.createElement(SelectItem2, { key: kd, value: kd }, kd))))), /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "iSpringQuizType" }, "iSpring Quiz Type"), /* @__PURE__ */ React119__namespace.default.createElement(Select2, { value: formState.iSpringQuizType, onValueChange: (v) => setFormState((s2) => ({ ...s2, iSpringQuizType: v })) }, /* @__PURE__ */ React119__namespace.default.createElement(SelectTrigger2, null, /* @__PURE__ */ React119__namespace.default.createElement(SelectValue2, null)), /* @__PURE__ */ React119__namespace.default.createElement(SelectContent2, null, questionTypes.map((qt) => /* @__PURE__ */ React119__namespace.default.createElement(SelectItem2, { key: qt.code, value: qt.code }, qt.name)))))), /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, null, "Difficulty"), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "flex items-center space-x-4 pt-2" }, standardDifficulties.map((diff2) => /* @__PURE__ */ React119__namespace.default.createElement("div", { key: diff2, className: "flex items-center space-x-2" }, /* @__PURE__ */ React119__namespace.default.createElement(Checkbox2, { id: `diff-${diff2}`, checked: (formState.difficulty || []).includes(diff2), onCheckedChange: (checked) => {
77993
- const current = formState.difficulty || [];
77994
- const newDiff = checked ? [...current, diff2] : current.filter((d) => d !== diff2);
77995
- setFormState((s2) => ({ ...s2, difficulty: newDiff }));
77996
- } }), /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: `diff-${diff2}` }, diff2))))), /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "suggestContext" }, "Suggest Context (comma-separated codes)"), /* @__PURE__ */ React119__namespace.default.createElement(Input, { id: "suggestContext", value: formState.suggestContext || "", onChange: (e2) => setFormState((s2) => ({ ...s2, suggestContext: e2.target.value })), placeholder: "e.g., A, B, D, G, H" })), /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "exampleEn" }, "Example (English)"), /* @__PURE__ */ React119__namespace.default.createElement(Textarea, { id: "exampleEn", value: formState.exampleEn || "", onChange: (e2) => setFormState((s2) => ({ ...s2, exampleEn: e2.target.value })), placeholder: "English example prompt..." })), /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "exampleVi" }, "Example (Vietnamese)"), /* @__PURE__ */ React119__namespace.default.createElement(Textarea, { id: "exampleVi", value: formState.exampleVi || "", onChange: (e2) => setFormState((s2) => ({ ...s2, exampleVi: e2.target.value })), placeholder: "Vietnamese example prompt..." }))), /* @__PURE__ */ React119__namespace.default.createElement(DialogFooter, null, /* @__PURE__ */ React119__namespace.default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React119__namespace.default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending }, isPending && /* @__PURE__ */ React119__namespace.default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Save")))), /* @__PURE__ */ React119__namespace.default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React119__namespace.default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React119__namespace.default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React119__namespace.default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React119__namespace.default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.code, '".')), /* @__PURE__ */ React119__namespace.default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React119__namespace.default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React119__namespace.default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React119__namespace.default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Delete"))))));
77984
+ return /* @__PURE__ */ React119__namespace.default.createElement(Card, null, /* @__PURE__ */ React119__namespace.default.createElement(CardHeader, null, /* @__PURE__ */ React119__namespace.default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React119__namespace.default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React119__namespace.default.createElement(Settings2, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Approaches"), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "flex items-center gap-2" }, onBulkAdd && /* @__PURE__ */ React119__namespace.default.createElement(MetadataImportControls, { metadataName: "Approaches", onImport: handleImport }), /* @__PURE__ */ React119__namespace.default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React119__namespace.default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Approach")))), /* @__PURE__ */ React119__namespace.default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React119__namespace.default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React119__namespace.default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No Approaches found.") : /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React119__namespace.default.createElement(Table2, null, /* @__PURE__ */ React119__namespace.default.createElement(TableHeader, null, /* @__PURE__ */ React119__namespace.default.createElement(TableRow, null, /* @__PURE__ */ React119__namespace.default.createElement(TableHead, null, "Approach ID"), /* @__PURE__ */ React119__namespace.default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React119__namespace.default.createElement(TableHead, null, "Verb (VI)"), /* @__PURE__ */ React119__namespace.default.createElement(TableHead, null, "Cognitive Level"), /* @__PURE__ */ React119__namespace.default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React119__namespace.default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React119__namespace.default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React119__namespace.default.createElement(TableCell, { className: "font-Medium" }, item.code), /* @__PURE__ */ React119__namespace.default.createElement(TableCell, null, item.name), /* @__PURE__ */ React119__namespace.default.createElement(TableCell, null, item.verbVi), /* @__PURE__ */ React119__namespace.default.createElement(TableCell, null, item.bloomLevelCode), /* @__PURE__ */ React119__namespace.default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React119__namespace.default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React119__namespace.default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React119__namespace.default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React119__namespace.default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React119__namespace.default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React119__namespace.default.createElement(DialogContent2, { className: "sm:max-w-2xl max-h-[90vh] overflow-y-auto" }, /* @__PURE__ */ React119__namespace.default.createElement(DialogHeader, null, /* @__PURE__ */ React119__namespace.default.createElement(DialogTitle2, null, currentItem ? "Edit Approach" : "Add New Approach")), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "code" }, "Approach Code"), /* @__PURE__ */ React119__namespace.default.createElement(Input, { id: "code", value: formState.code || "", onChange: (e2) => setFormState((s2) => ({ ...s2, code: e2.target.value.toUpperCase() })), placeholder: "e.g., REM-FAC-IDT-MCQ", disabled: !!currentItem })), /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "name" }, "Name / Description"), /* @__PURE__ */ React119__namespace.default.createElement(Input, { id: "name", value: formState.name || "", onChange: (e2) => setFormState((s2) => ({ ...s2, name: e2.target.value })), placeholder: "e.g., Identify a Fact" }))), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "verbEn" }, "Verb (English)"), /* @__PURE__ */ React119__namespace.default.createElement(Input, { id: "verbEn", value: formState.verbEn || "", onChange: (e2) => setFormState((s2) => ({ ...s2, verbEn: e2.target.value })), placeholder: "e.g., Identify" })), /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "verbVi" }, "Verb (Vietnamese)"), /* @__PURE__ */ React119__namespace.default.createElement(Input, { id: "verbVi", value: formState.verbVi || "", onChange: (e2) => setFormState((s2) => ({ ...s2, verbVi: e2.target.value })), placeholder: "e.g., Nh\u1EADn d\u1EA1ng" }))), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-4" }, /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "bloomLevelCode" }, "Cognitive Level"), /* @__PURE__ */ React119__namespace.default.createElement(Select2, { value: formState.bloomLevelCode, onValueChange: (v) => setFormState((s2) => ({ ...s2, bloomLevelCode: v })) }, /* @__PURE__ */ React119__namespace.default.createElement(SelectTrigger2, null, /* @__PURE__ */ React119__namespace.default.createElement(SelectValue2, null)), /* @__PURE__ */ React119__namespace.default.createElement(SelectContent2, null, bloomLevels.map((level) => /* @__PURE__ */ React119__namespace.default.createElement(SelectItem2, { key: level.code, value: level.code }, level.name))))), /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "knowledgeDimension" }, "Knowledge Dimension"), /* @__PURE__ */ React119__namespace.default.createElement(Select2, { value: formState.knowledgeDimension, onValueChange: (v) => setFormState((s2) => ({ ...s2, knowledgeDimension: v })) }, /* @__PURE__ */ React119__namespace.default.createElement(SelectTrigger2, null, /* @__PURE__ */ React119__namespace.default.createElement(SelectValue2, null)), /* @__PURE__ */ React119__namespace.default.createElement(SelectContent2, null, knowledgeDimensions.map((kd) => /* @__PURE__ */ React119__namespace.default.createElement(SelectItem2, { key: kd, value: kd }, kd))))), /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "iSpringQuizType" }, "iSpring Quiz Type"), /* @__PURE__ */ React119__namespace.default.createElement(Select2, { value: formState.iSpringQuizType, onValueChange: (v) => setFormState((s2) => ({ ...s2, iSpringQuizType: v })) }, /* @__PURE__ */ React119__namespace.default.createElement(SelectTrigger2, null, /* @__PURE__ */ React119__namespace.default.createElement(SelectValue2, null)), /* @__PURE__ */ React119__namespace.default.createElement(SelectContent2, null, questionTypes.map((qt) => /* @__PURE__ */ React119__namespace.default.createElement(SelectItem2, { key: qt.code, value: qt.code }, qt.name)))))), /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, null, "Difficulty"), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "flex items-center space-x-4 pt-2" }, standardDifficulties.map((diff2) => /* @__PURE__ */ React119__namespace.default.createElement("div", { key: diff2, className: "flex items-center space-x-2" }, /* @__PURE__ */ React119__namespace.default.createElement(
77985
+ Checkbox2,
77986
+ {
77987
+ id: `diff-${diff2}`,
77988
+ checked: (formState.difficulty || []).includes(diff2),
77989
+ onCheckedChange: (checked) => {
77990
+ const current = formState.difficulty || [];
77991
+ const newDiff = checked ? [...current, diff2] : current.filter((d) => d !== diff2);
77992
+ setFormState((s2) => ({ ...s2, difficulty: newDiff }));
77993
+ }
77994
+ }
77995
+ ), /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: `diff-${diff2}` }, diff2))))), /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "suggestContext" }, "Suggest Context (comma-separated codes)"), /* @__PURE__ */ React119__namespace.default.createElement(Input, { id: "suggestContext", value: formState.suggestContext || "", onChange: (e2) => setFormState((s2) => ({ ...s2, suggestContext: e2.target.value })), placeholder: "e.g., A, B, D, G, H" })), /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "exampleEn" }, "Example (English)"), /* @__PURE__ */ React119__namespace.default.createElement(Textarea, { id: "exampleEn", value: formState.exampleEn || "", onChange: (e2) => setFormState((s2) => ({ ...s2, exampleEn: e2.target.value })), placeholder: "English example prompt..." })), /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "exampleVi" }, "Example (Vietnamese)"), /* @__PURE__ */ React119__namespace.default.createElement(Textarea, { id: "exampleVi", value: formState.exampleVi || "", onChange: (e2) => setFormState((s2) => ({ ...s2, exampleVi: e2.target.value })), placeholder: "Vietnamese example prompt..." }))), /* @__PURE__ */ React119__namespace.default.createElement(DialogFooter, null, /* @__PURE__ */ React119__namespace.default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React119__namespace.default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending }, isPending && /* @__PURE__ */ React119__namespace.default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Save")))), /* @__PURE__ */ React119__namespace.default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React119__namespace.default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React119__namespace.default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React119__namespace.default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React119__namespace.default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.code, '".')), /* @__PURE__ */ React119__namespace.default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React119__namespace.default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React119__namespace.default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React119__namespace.default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Delete"))))));
77997
77996
  }
77998
77997
 
77999
77998
  // src/react-ui/components/metadata/MetadataTabs.tsx
@@ -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-6AR8w2TO.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-Bvhmyef9.cjs';
6
6
  import 'clsx';
7
7
  import 'zod';
8
8
  import 'react';
@@ -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-DAXYZdrz.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-B2MPZYhi.js';
6
6
  import 'clsx';
7
7
  import 'zod';
8
8
  import 'react';