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

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.
@@ -73195,7 +73195,7 @@ var contextOptions = [
73195
73195
  ];
73196
73196
 
73197
73197
  // src/react-ui/components/authoring/AIFullQuizGeneratorModal.tsx
73198
- var availableQuestionTypesForFullQuiz = [
73198
+ var ALL_AVAILABLE_QUESTION_TYPES = [
73199
73199
  { value: "true_false", label: "True/False" },
73200
73200
  { value: "multiple_choice", label: "Multiple Choice" },
73201
73201
  { value: "multiple_response", label: "Multiple Response" },
@@ -73210,8 +73210,11 @@ var AIFullQuizGeneratorModal = ({
73210
73210
  isOpen,
73211
73211
  onClose,
73212
73212
  onQuizGenerated,
73213
- language: language3
73214
- // <-- NHẬN PROP
73213
+ language: language3,
73214
+ maxQuestions = 100,
73215
+ // Default value
73216
+ allowedQuestionTypes = ALL_AVAILABLE_QUESTION_TYPES.map((qt) => qt.value)
73217
+ // Default value
73215
73218
  }) => {
73216
73219
  const [totalQuestions, setTotalQuestions] = React119.useState(10);
73217
73220
  const [topics, setTopics] = React119.useState([{ id: generateUniqueId("topic_"), topic: "", ratio: 100 }]);
@@ -73222,9 +73225,7 @@ var AIFullQuizGeneratorModal = ({
73222
73225
  ]);
73223
73226
  const [selectedContextIds, setSelectedContextIds] = React119.useState([]);
73224
73227
  const [customContextInput, setCustomContextInput] = React119.useState("");
73225
- const [selectedQuestionTypes, setSelectedQuestionTypes] = React119.useState(
73226
- availableQuestionTypesForFullQuiz.map((qt) => qt.value)
73227
- );
73228
+ const [selectedQuestionTypes, setSelectedQuestionTypes] = React119.useState([]);
73228
73229
  const [authorizeAISkipReview, setAuthorizeAISkipReview] = React119.useState(false);
73229
73230
  const [isLoading, setIsLoading] = React119.useState(false);
73230
73231
  const [error, setError] = React119.useState(null);
@@ -73233,6 +73234,9 @@ var AIFullQuizGeneratorModal = ({
73233
73234
  const { toast: toast2 } = useToast();
73234
73235
  const [isApiKeyManagerModalOpen, setIsApiKeyManagerModalOpen] = React119.useState(false);
73235
73236
  const [geminiApiKeyExists, setGeminiApiKeyExists] = React119.useState(false);
73237
+ const availableQuestionTypesForFullQuiz = React119.useMemo(() => {
73238
+ return ALL_AVAILABLE_QUESTION_TYPES.filter((qt) => allowedQuestionTypes.includes(qt.value));
73239
+ }, [allowedQuestionTypes]);
73236
73240
  React119.useEffect(() => {
73237
73241
  if (isOpen) {
73238
73242
  setTotalQuestions(10);
@@ -73252,7 +73256,7 @@ var AIFullQuizGeneratorModal = ({
73252
73256
  setAiGeneratedPlan(null);
73253
73257
  setGeminiApiKeyExists(APIKeyService.hasAPIKey(GEMINI_API_KEY_SERVICE_NAME));
73254
73258
  }
73255
- }, [isOpen]);
73259
+ }, [isOpen, availableQuestionTypesForFullQuiz]);
73256
73260
  const handleApiKeyModalClose = () => {
73257
73261
  setIsApiKeyManagerModalOpen(false);
73258
73262
  setGeminiApiKeyExists(APIKeyService.hasAPIKey(GEMINI_API_KEY_SERVICE_NAME));
@@ -73260,7 +73264,7 @@ var AIFullQuizGeneratorModal = ({
73260
73264
  const handleTotalQuestionsChange = (e2) => {
73261
73265
  let num = parseInt(e2.target.value, 10);
73262
73266
  if (isNaN(num) || num < 1) num = 1;
73263
- if (num > 100) num = 100;
73267
+ if (num > maxQuestions) num = maxQuestions;
73264
73268
  setTotalQuestions(num);
73265
73269
  };
73266
73270
  const handleTopicChange = (id2, field, value) => {
@@ -73290,8 +73294,8 @@ var AIFullQuizGeneratorModal = ({
73290
73294
  setError("Gemini API Key is required for AI features. Please set it first.");
73291
73295
  return false;
73292
73296
  }
73293
- if (totalQuestions <= 0 || totalQuestions > 100) {
73294
- setError("Total questions must be between 1 and 100.");
73297
+ if (totalQuestions <= 0 || totalQuestions > maxQuestions) {
73298
+ setError(`Total questions must be between 1 and ${maxQuestions}.`);
73295
73299
  return false;
73296
73300
  }
73297
73301
  if (topics.some((t2) => !t2.topic.trim())) {
@@ -73330,7 +73334,6 @@ var AIFullQuizGeneratorModal = ({
73330
73334
  const stage2Input = {
73331
73335
  quizPlan: plan,
73332
73336
  language: language3,
73333
- // <-- SỬ DỤNG PROP
73334
73337
  imageContexts: []
73335
73338
  };
73336
73339
  const stage2Output = await generateQuestionsFromQuizPlan(stage2Input, apiKey);
@@ -73381,7 +73384,6 @@ var AIFullQuizGeneratorModal = ({
73381
73384
  try {
73382
73385
  const planInput = {
73383
73386
  language: language3,
73384
- // <-- SỬ DỤNG PROP
73385
73387
  totalQuestions,
73386
73388
  numCodingQuestions: 0,
73387
73389
  topics: topics.map((t2) => ({ topic: t2.topic, ratio: t2.ratio })),
@@ -73445,103 +73447,9 @@ var AIFullQuizGeneratorModal = ({
73445
73447
  };
73446
73448
  const renderContent = () => {
73447
73449
  if (currentStage === "review") {
73448
- return /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-4 py-4" }, /* @__PURE__ */ React119__namespace.default.createElement("h3", { className: "text-lg font-Medium mb-2 text-primary flex items-center" }, /* @__PURE__ */ React119__namespace.default.createElement(Eye, { className: "mr-2 h-5 w-5" }), " Review & Adjust AI Generated Quiz Plan"), /* @__PURE__ */ React119__namespace.default.createElement("p", { className: "text-sm text-muted-foreground" }, "The AI has proposed the following plan. You can change question types, reorder, or remove questions before final generation. Note: 'Drag and Drop' type questions in the plan will be created as placeholders and require manual authoring of items/zones/answers."), aiGeneratedPlan && aiGeneratedPlan.length > 0 ? /* @__PURE__ */ React119__namespace.default.createElement(ScrollArea2, { className: "max-h-[calc(60vh - 120px)] pr-3" }, /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-3" }, aiGeneratedPlan.map((plannedQ, index3) => /* @__PURE__ */ React119__namespace.default.createElement(Card, { key: `planned-${index3}-${plannedQ.plannedTopic.replace(/\s/g, "")}`, className: "p-3" }, /* @__PURE__ */ React119__namespace.default.createElement(CardContent, { className: "p-0 space-y-2" }, /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "flex justify-between items-start" }, /* @__PURE__ */ React119__namespace.default.createElement("p", { className: "font-semibold text-sm" }, "Q", index3 + 1, ": ", plannedQ.plannedTopic), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "flex space-x-1" }, /* @__PURE__ */ React119__namespace.default.createElement(Button, { variant: "ghost", size: "icon", className: "h-7 w-7", onClick: () => handleMovePlannedQuestion(index3, "up"), disabled: index3 === 0 }, /* @__PURE__ */ React119__namespace.default.createElement(ArrowUp, { className: "h-4 w-4" })), /* @__PURE__ */ React119__namespace.default.createElement(Button, { variant: "ghost", size: "icon", className: "h-7 w-7", onClick: () => handleMovePlannedQuestion(index3, "down"), disabled: index3 === aiGeneratedPlan.length - 1 }, /* @__PURE__ */ React119__namespace.default.createElement(ArrowDown, { className: "h-4 w-4" })), /* @__PURE__ */ React119__namespace.default.createElement(Button, { variant: "ghost", size: "icon", className: "h-7 w-7 text-destructive", onClick: () => handleRemovePlannedQuestion(index3) }, /* @__PURE__ */ React119__namespace.default.createElement(Trash2, { className: "h-4 w-4" })))), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "grid grid-cols-2 gap-3 items-end" }, /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: `review-qtype-${index3}`, className: "text-xs" }, "Question Type"), /* @__PURE__ */ React119__namespace.default.createElement(
73449
- Select2,
73450
- {
73451
- value: plannedQ.plannedQuestionType,
73452
- onValueChange: (value) => handleChangePlannedQuestionType(index3, value)
73453
- },
73454
- /* @__PURE__ */ React119__namespace.default.createElement(SelectTrigger2, { id: `review-qtype-${index3}`, className: "h-9 text-xs" }, /* @__PURE__ */ React119__namespace.default.createElement(SelectValue2, null)),
73455
- /* @__PURE__ */ React119__namespace.default.createElement(SelectContent2, null, availableQuestionTypesForFullQuiz.map((qType) => /* @__PURE__ */ React119__namespace.default.createElement(SelectItem2, { key: qType.value, value: qType.value, className: "text-xs" }, qType.label)))
73456
- )), /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { className: "text-xs block" }, "Bloom Level"), /* @__PURE__ */ React119__namespace.default.createElement("p", { className: "text-xs p-2 h-9 border rounded-md bg-secondary/50 flex items-center capitalize" }, plannedQ.plannedBloomLevel)))))))) : /* @__PURE__ */ React119__namespace.default.createElement("p", { className: "text-muted-foreground" }, "No quiz plan generated or plan is empty."), 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));
73450
+ return /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-4 py-4" }, /* @__PURE__ */ React119__namespace.default.createElement("h3", { className: "text-lg font-Medium mb-2 text-primary flex items-center" }, /* @__PURE__ */ React119__namespace.default.createElement(Eye, { className: "mr-2 h-5 w-5" }), " Review & Adjust AI Generated Quiz Plan"), /* @__PURE__ */ React119__namespace.default.createElement("p", { className: "text-sm text-muted-foreground" }, "The AI has proposed the following plan. You can change question types, reorder, or remove questions before final generation. Note: 'Drag and Drop' type questions in the plan will be created as placeholders and require manual authoring of items/zones/answers."), aiGeneratedPlan && aiGeneratedPlan.length > 0 ? /* @__PURE__ */ React119__namespace.default.createElement(ScrollArea2, { className: "max-h-[calc(60vh - 120px)] pr-3" }, /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-3" }, aiGeneratedPlan.map((plannedQ, index3) => /* @__PURE__ */ React119__namespace.default.createElement(Card, { key: `planned-${index3}-${plannedQ.plannedTopic.replace(/\s/g, "")}`, className: "p-3" }, /* @__PURE__ */ React119__namespace.default.createElement(CardContent, { className: "p-0 space-y-2" }, /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "flex justify-between items-start" }, /* @__PURE__ */ React119__namespace.default.createElement("p", { className: "font-semibold text-sm" }, "Q", index3 + 1, ": ", plannedQ.plannedTopic), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "flex space-x-1" }, /* @__PURE__ */ React119__namespace.default.createElement(Button, { variant: "ghost", size: "icon", className: "h-7 w-7", onClick: () => handleMovePlannedQuestion(index3, "up"), disabled: index3 === 0 }, /* @__PURE__ */ React119__namespace.default.createElement(ArrowUp, { className: "h-4 w-4" })), /* @__PURE__ */ React119__namespace.default.createElement(Button, { variant: "ghost", size: "icon", className: "h-7 w-7", onClick: () => handleMovePlannedQuestion(index3, "down"), disabled: index3 === aiGeneratedPlan.length - 1 }, /* @__PURE__ */ React119__namespace.default.createElement(ArrowDown, { className: "h-4 w-4" })), /* @__PURE__ */ React119__namespace.default.createElement(Button, { variant: "ghost", size: "icon", className: "h-7 w-7 text-destructive", onClick: () => handleRemovePlannedQuestion(index3) }, /* @__PURE__ */ React119__namespace.default.createElement(Trash2, { className: "h-4 w-4" })))), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "grid grid-cols-2 gap-3 items-end" }, /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: `review-qtype-${index3}`, className: "text-xs" }, "Question Type"), /* @__PURE__ */ React119__namespace.default.createElement(Select2, { value: plannedQ.plannedQuestionType, onValueChange: (value) => handleChangePlannedQuestionType(index3, value) }, /* @__PURE__ */ React119__namespace.default.createElement(SelectTrigger2, { id: `review-qtype-${index3}`, className: "h-9 text-xs" }, /* @__PURE__ */ React119__namespace.default.createElement(SelectValue2, null)), /* @__PURE__ */ React119__namespace.default.createElement(SelectContent2, null, availableQuestionTypesForFullQuiz.map((qType) => /* @__PURE__ */ React119__namespace.default.createElement(SelectItem2, { key: qType.value, value: qType.value, className: "text-xs" }, qType.label))))), /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { className: "text-xs block" }, "Bloom Level"), /* @__PURE__ */ React119__namespace.default.createElement("p", { className: "text-xs p-2 h-9 border rounded-md bg-secondary/50 flex items-center capitalize" }, plannedQ.plannedBloomLevel)))))))) : /* @__PURE__ */ React119__namespace.default.createElement("p", { className: "text-muted-foreground" }, "No quiz plan generated or plan is empty."), 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));
73457
73451
  }
73458
- return /* @__PURE__ */ React119__namespace.default.createElement(ScrollArea2, { className: "max-h-[calc(70vh - 100px)] pl-4 pr-3 py-1" }, /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-4 py-1 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" }, /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "flex items-start" }, /* @__PURE__ */ React119__namespace.default.createElement(TriangleAlert, { className: "h-5 w-5 mr-2 mt-0.5 flex-shrink-0" }), /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement("p", { className: "font-semibold" }, "Gemini API Key Required"), /* @__PURE__ */ React119__namespace.default.createElement("p", { className: "text-xs" }, "To use AI quiz generation, please set your Google Gemini API Key."), /* @__PURE__ */ React119__namespace.default.createElement(
73459
- Button,
73460
- {
73461
- variant: "link",
73462
- className: "p-0 h-auto text-xs text-amber-700 hover:text-amber-800 mt-1",
73463
- onClick: () => setIsApiKeyManagerModalOpen(true)
73464
- },
73465
- /* @__PURE__ */ React119__namespace.default.createElement(Settings, { className: "mr-1 h-3 w-3" }),
73466
- " Set API Key Now"
73467
- )))), /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "total-questions" }, "Total Number of Questions (1-100)"), /* @__PURE__ */ React119__namespace.default.createElement(
73468
- Input,
73469
- {
73470
- id: "total-questions",
73471
- type: "number",
73472
- value: totalQuestions,
73473
- onChange: handleTotalQuestionsChange,
73474
- min: "1",
73475
- max: "100"
73476
- }
73477
- )), /* @__PURE__ */ React119__namespace.default.createElement("fieldset", { className: "border p-3 rounded-md" }, /* @__PURE__ */ React119__namespace.default.createElement("legend", { className: "text-sm font-Medium px-1" }, "Topic Distribution"), topics.map((topicItem, index3) => /* @__PURE__ */ React119__namespace.default.createElement("div", { key: topicItem.id, className: "flex items-center gap-2 mb-2" }, /* @__PURE__ */ React119__namespace.default.createElement(
73478
- Input,
73479
- {
73480
- type: "text",
73481
- placeholder: `Topic ${index3 + 1}`,
73482
- value: topicItem.topic,
73483
- onChange: (e2) => handleTopicChange(topicItem.id, "topic", e2.target.value),
73484
- className: "flex-grow"
73485
- }
73486
- ), /* @__PURE__ */ React119__namespace.default.createElement(
73487
- Input,
73488
- {
73489
- type: "number",
73490
- placeholder: "Ratio %",
73491
- value: topicItem.ratio,
73492
- onChange: (e2) => handleTopicChange(topicItem.id, "ratio", parseInt(e2.target.value, 10) || 0),
73493
- className: "w-24",
73494
- min: "0",
73495
- max: "100"
73496
- }
73497
- ), /* @__PURE__ */ React119__namespace.default.createElement(Button, { type: "button", variant: "ghost", size: "icon", onClick: () => removeTopic(topicItem.id), disabled: topics.length <= 1 }, /* @__PURE__ */ React119__namespace.default.createElement(Trash2, { className: "h-4 w-4 text-destructive" })))), /* @__PURE__ */ React119__namespace.default.createElement(Button, { type: "button", variant: "outline", size: "sm", onClick: addTopic }, /* @__PURE__ */ React119__namespace.default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Topic")), /* @__PURE__ */ React119__namespace.default.createElement("fieldset", { className: "border p-3 rounded-md" }, /* @__PURE__ */ React119__namespace.default.createElement("legend", { className: "text-sm font-Medium px-1" }, "Bloom Level Distribution"), bloomLevels.map((bloomItem) => /* @__PURE__ */ React119__namespace.default.createElement("div", { key: bloomItem.id, className: "flex items-center gap-2 mb-2" }, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { className: "w-32 capitalize flex-shrink-0" }, bloomItem.level), /* @__PURE__ */ React119__namespace.default.createElement(
73498
- Input,
73499
- {
73500
- type: "number",
73501
- placeholder: "Ratio %",
73502
- value: bloomItem.ratio,
73503
- onChange: (e2) => handleBloomRatioChange(bloomItem.id, parseInt(e2.target.value, 10) || 0),
73504
- className: "w-24",
73505
- min: "0",
73506
- max: "100"
73507
- }
73508
- )))), /* @__PURE__ */ React119__namespace.default.createElement("fieldset", { className: "border p-3 rounded-md" }, /* @__PURE__ */ React119__namespace.default.createElement("legend", { className: "text-sm font-Medium px-1" }, "Relevant Contexts (Optional, Select Multiple)"), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "grid grid-cols-2 gap-2 mt-2 max-h-40 overflow-y-auto" }, contextOptions.filter((opt) => opt.contextId !== "__none__" && opt.contextId !== "__custom__").map((opt) => /* @__PURE__ */ React119__namespace.default.createElement("div", { key: opt.contextId, className: "flex items-center space-x-2" }, /* @__PURE__ */ React119__namespace.default.createElement(
73509
- Checkbox2,
73510
- {
73511
- id: `ctx-full-${opt.contextId}`,
73512
- checked: selectedContextIds.includes(opt.contextId),
73513
- onCheckedChange: () => handleContextToggle(opt.contextId)
73514
- }
73515
- ), /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: `ctx-full-${opt.contextId}`, className: "text-xs font-normal cursor-pointer" }, opt.contextDescription, " (", opt.shortContextId, ")")))), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "mt-2" }, /* @__PURE__ */ React119__namespace.default.createElement(
73516
- Checkbox2,
73517
- {
73518
- id: `ctx-full-__custom__`,
73519
- checked: selectedContextIds.includes("__custom__"),
73520
- onCheckedChange: () => handleContextToggle("__custom__")
73521
- }
73522
- ), /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: `ctx-full-__custom__`, className: "text-xs font-normal cursor-pointer ml-2" }, "Other (Custom Input)")), selectedContextIds.includes("__custom__") && /* @__PURE__ */ React119__namespace.default.createElement(
73523
- Textarea,
73524
- {
73525
- value: customContextInput,
73526
- onChange: (e2) => setCustomContextInput(e2.target.value),
73527
- placeholder: "Enter your specific custom context here...",
73528
- className: "min-h-[60px] mt-2 text-sm"
73529
- }
73530
- )), /* @__PURE__ */ React119__namespace.default.createElement("fieldset", { className: "border p-3 rounded-md" }, /* @__PURE__ */ React119__namespace.default.createElement("legend", { className: "text-sm font-Medium px-1" }, "Question Types to Use (Select Multiple)"), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "grid grid-cols-2 gap-2 mt-2 max-h-40 overflow-y-auto" }, availableQuestionTypesForFullQuiz.map((qType) => /* @__PURE__ */ React119__namespace.default.createElement("div", { key: qType.value, className: "flex items-center space-x-2" }, /* @__PURE__ */ React119__namespace.default.createElement(
73531
- Checkbox2,
73532
- {
73533
- id: `qtype-full-${qType.value}`,
73534
- checked: selectedQuestionTypes.includes(qType.value),
73535
- onCheckedChange: () => handleQuestionTypeToggle(qType.value)
73536
- }
73537
- ), /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: `qtype-full-${qType.value}`, className: "text-xs font-normal cursor-pointer" }, qType.label))))), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "flex items-center space-x-2 pt-2" }, /* @__PURE__ */ React119__namespace.default.createElement(
73538
- Checkbox2,
73539
- {
73540
- id: "authorize-ai-skip-review",
73541
- checked: authorizeAISkipReview,
73542
- onCheckedChange: (checked) => setAuthorizeAISkipReview(!!checked)
73543
- }
73544
- ), /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "authorize-ai-skip-review", className: "text-sm font-normal" }, "Authorize AI (Skip Review & Generate Directly)")), 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)));
73452
+ return /* @__PURE__ */ React119__namespace.default.createElement(ScrollArea2, { className: "max-h-[calc(70vh - 100px)] pl-4 pr-3 py-1" }, /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-4 py-1 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" }, /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "flex items-start" }, /* @__PURE__ */ React119__namespace.default.createElement(TriangleAlert, { className: "h-5 w-5 mr-2 mt-0.5 flex-shrink-0" }), /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement("p", { className: "font-semibold" }, "Gemini API Key Required"), /* @__PURE__ */ React119__namespace.default.createElement("p", { className: "text-xs" }, "To use AI quiz generation, please set your Google Gemini API Key."), /* @__PURE__ */ React119__namespace.default.createElement(Button, { variant: "link", className: "p-0 h-auto text-xs text-amber-700 hover:text-amber-800 mt-1", onClick: () => setIsApiKeyManagerModalOpen(true) }, /* @__PURE__ */ React119__namespace.default.createElement(Settings, { className: "mr-1 h-3 w-3" }), " Set API Key Now")))), /* @__PURE__ */ React119__namespace.default.createElement("div", null, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "total-questions" }, "Total Number of Questions (1-", maxQuestions, ")"), /* @__PURE__ */ React119__namespace.default.createElement(Input, { id: "total-questions", type: "number", value: totalQuestions, onChange: handleTotalQuestionsChange, min: "1", max: maxQuestions })), /* @__PURE__ */ React119__namespace.default.createElement("fieldset", { className: "border p-3 rounded-md" }, /* @__PURE__ */ React119__namespace.default.createElement("legend", { className: "text-sm font-Medium px-1" }, "Topic Distribution"), topics.map((topicItem, index3) => /* @__PURE__ */ React119__namespace.default.createElement("div", { key: topicItem.id, className: "flex items-center gap-2 mb-2" }, /* @__PURE__ */ React119__namespace.default.createElement(Input, { type: "text", placeholder: `Topic ${index3 + 1}`, value: topicItem.topic, onChange: (e2) => handleTopicChange(topicItem.id, "topic", e2.target.value), className: "flex-grow" }), /* @__PURE__ */ React119__namespace.default.createElement(Input, { type: "number", placeholder: "Ratio %", value: topicItem.ratio, onChange: (e2) => handleTopicChange(topicItem.id, "ratio", parseInt(e2.target.value, 10) || 0), className: "w-24", min: "0", max: "100" }), /* @__PURE__ */ React119__namespace.default.createElement(Button, { type: "button", variant: "ghost", size: "icon", onClick: () => removeTopic(topicItem.id), disabled: topics.length <= 1 }, /* @__PURE__ */ React119__namespace.default.createElement(Trash2, { className: "h-4 w-4 text-destructive" })))), /* @__PURE__ */ React119__namespace.default.createElement(Button, { type: "button", variant: "outline", size: "sm", onClick: addTopic }, /* @__PURE__ */ React119__namespace.default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Topic")), /* @__PURE__ */ React119__namespace.default.createElement("fieldset", { className: "border p-3 rounded-md" }, /* @__PURE__ */ React119__namespace.default.createElement("legend", { className: "text-sm font-Medium px-1" }, "Bloom Level Distribution"), bloomLevels.map((bloomItem) => /* @__PURE__ */ React119__namespace.default.createElement("div", { key: bloomItem.id, className: "flex items-center gap-2 mb-2" }, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { className: "w-32 capitalize flex-shrink-0" }, bloomItem.level), /* @__PURE__ */ React119__namespace.default.createElement(Input, { type: "number", placeholder: "Ratio %", value: bloomItem.ratio, onChange: (e2) => handleBloomRatioChange(bloomItem.id, parseInt(e2.target.value, 10) || 0), className: "w-24", min: "0", max: "100" })))), /* @__PURE__ */ React119__namespace.default.createElement("fieldset", { className: "border p-3 rounded-md" }, /* @__PURE__ */ React119__namespace.default.createElement("legend", { className: "text-sm font-Medium px-1" }, "Relevant Contexts (Optional, Select Multiple)"), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "grid grid-cols-2 gap-2 mt-2 max-h-40 overflow-y-auto" }, contextOptions.filter((opt) => opt.contextId !== "__none__" && opt.contextId !== "__custom__").map((opt) => /* @__PURE__ */ React119__namespace.default.createElement("div", { key: opt.contextId, className: "flex items-center space-x-2" }, /* @__PURE__ */ React119__namespace.default.createElement(Checkbox2, { id: `ctx-full-${opt.contextId}`, checked: selectedContextIds.includes(opt.contextId), onCheckedChange: () => handleContextToggle(opt.contextId) }), /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: `ctx-full-${opt.contextId}`, className: "text-xs font-normal cursor-pointer" }, opt.contextDescription, " (", opt.shortContextId, ")"))), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "mt-2" }, /* @__PURE__ */ React119__namespace.default.createElement(Checkbox2, { id: `ctx-full-__custom__`, checked: selectedContextIds.includes("__custom__"), onCheckedChange: () => handleContextToggle("__custom__") }), /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: `ctx-full-__custom__`, className: "text-xs font-normal cursor-pointer ml-2" }, "Other (Custom Input)")), selectedContextIds.includes("__custom__") && /* @__PURE__ */ React119__namespace.default.createElement(Textarea, { value: customContextInput, onChange: (e2) => setCustomContextInput(e2.target.value), placeholder: "Enter your specific custom context here...", className: "min-h-[60px] mt-2 text-sm" }))), /* @__PURE__ */ React119__namespace.default.createElement("fieldset", { className: "border p-3 rounded-md" }, /* @__PURE__ */ React119__namespace.default.createElement("legend", { className: "text-sm font-Medium px-1" }, "Question Types to Use (Select Multiple)"), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "grid grid-cols-2 gap-2 mt-2 max-h-40 overflow-y-auto" }, availableQuestionTypesForFullQuiz.map((qType) => /* @__PURE__ */ React119__namespace.default.createElement("div", { key: qType.value, className: "flex items-center space-x-2" }, /* @__PURE__ */ React119__namespace.default.createElement(Checkbox2, { id: `qtype-full-${qType.value}`, checked: selectedQuestionTypes.includes(qType.value), onCheckedChange: () => handleQuestionTypeToggle(qType.value) }), /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: `qtype-full-${qType.value}`, className: "text-xs font-normal cursor-pointer" }, qType.label))))), /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "flex items-center space-x-2 pt-2" }, /* @__PURE__ */ React119__namespace.default.createElement(Checkbox2, { id: "authorize-ai-skip-review", checked: authorizeAISkipReview, onCheckedChange: (checked) => setAuthorizeAISkipReview(!!checked) }), /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "authorize-ai-skip-review", className: "text-sm font-normal" }, "Authorize AI (Skip Review & Generate Directly)")), 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)));
73545
73453
  };
73546
73454
  return /* @__PURE__ */ React119__namespace.default.createElement(React119__namespace.default.Fragment, null, /* @__PURE__ */ React119__namespace.default.createElement(Dialog2, { open: isOpen, onOpenChange: (open) => !open && onClose() }, /* @__PURE__ */ React119__namespace.default.createElement(DialogContent2, { className: "sm:max-w-[650px] md:max-w-[750px] lg:max-w-[800px] max-h-[90vh] overflow-y-auto" }, /* @__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(FileText, { className: "mr-2 h-6 w-6 text-primary" }), " Generate Full Quiz with AI"), /* @__PURE__ */ React119__namespace.default.createElement(DialogDescription2, null, currentStage === "input" && "Define parameters for AI to generate a quiz plan.", currentStage === "review" && "Review and adjust the AI-generated quiz plan before generating questions.", currentStage === "generating" && "AI is working... Please wait.")), renderContent(), /* @__PURE__ */ React119__namespace.default.createElement(DialogFooter, { className: "pt-4 border-t" }, /* @__PURE__ */ React119__namespace.default.createElement(DialogClose2, { asChild: true }, /* @__PURE__ */ React119__namespace.default.createElement(Button, { type: "button", variant: "outline", onClick: onClose }, "Cancel")), currentStage === "input" && /* @__PURE__ */ React119__namespace.default.createElement(Button, { type: "button", onClick: handleSubmitPlanGeneration, disabled: isLoading || !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" }), authorizeAISkipReview ? "Generate Quiz Directly" : "Generate Quiz Plan"), currentStage === "review" && !isLoading && /* @__PURE__ */ React119__namespace.default.createElement(Button, { type: "button", onClick: handleGenerateQuestionsFromReviewedPlan, disabled: isLoading || !aiGeneratedPlan || aiGeneratedPlan.length === 0 || !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 Questions from Plan"), currentStage === "generating" && isLoading && /* @__PURE__ */ React119__namespace.default.createElement(Button, { type: "button", disabled: true }, /* @__PURE__ */ React119__namespace.default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), "Generating... Please Wait")))), /* @__PURE__ */ React119__namespace.default.createElement(APIKeyManagerModal, { isOpen: isApiKeyManagerModalOpen, onClose: handleApiKeyModalClose }));
73547
73455
  };
@@ -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-Bvhmyef9.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-CexT11VU.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-B2MPZYhi.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-Bj78wmSz.js';
6
6
  import 'clsx';
7
7
  import 'zod';
8
8
  import 'react';
@@ -73130,7 +73130,7 @@ var contextOptions = [
73130
73130
  ];
73131
73131
 
73132
73132
  // src/react-ui/components/authoring/AIFullQuizGeneratorModal.tsx
73133
- var availableQuestionTypesForFullQuiz = [
73133
+ var ALL_AVAILABLE_QUESTION_TYPES = [
73134
73134
  { value: "true_false", label: "True/False" },
73135
73135
  { value: "multiple_choice", label: "Multiple Choice" },
73136
73136
  { value: "multiple_response", label: "Multiple Response" },
@@ -73145,8 +73145,11 @@ var AIFullQuizGeneratorModal = ({
73145
73145
  isOpen,
73146
73146
  onClose,
73147
73147
  onQuizGenerated,
73148
- language: language3
73149
- // <-- NHẬN PROP
73148
+ language: language3,
73149
+ maxQuestions = 100,
73150
+ // Default value
73151
+ allowedQuestionTypes = ALL_AVAILABLE_QUESTION_TYPES.map((qt) => qt.value)
73152
+ // Default value
73150
73153
  }) => {
73151
73154
  const [totalQuestions, setTotalQuestions] = useState(10);
73152
73155
  const [topics, setTopics] = useState([{ id: generateUniqueId("topic_"), topic: "", ratio: 100 }]);
@@ -73157,9 +73160,7 @@ var AIFullQuizGeneratorModal = ({
73157
73160
  ]);
73158
73161
  const [selectedContextIds, setSelectedContextIds] = useState([]);
73159
73162
  const [customContextInput, setCustomContextInput] = useState("");
73160
- const [selectedQuestionTypes, setSelectedQuestionTypes] = useState(
73161
- availableQuestionTypesForFullQuiz.map((qt) => qt.value)
73162
- );
73163
+ const [selectedQuestionTypes, setSelectedQuestionTypes] = useState([]);
73163
73164
  const [authorizeAISkipReview, setAuthorizeAISkipReview] = useState(false);
73164
73165
  const [isLoading, setIsLoading] = useState(false);
73165
73166
  const [error, setError] = useState(null);
@@ -73168,6 +73169,9 @@ var AIFullQuizGeneratorModal = ({
73168
73169
  const { toast: toast2 } = useToast();
73169
73170
  const [isApiKeyManagerModalOpen, setIsApiKeyManagerModalOpen] = useState(false);
73170
73171
  const [geminiApiKeyExists, setGeminiApiKeyExists] = useState(false);
73172
+ const availableQuestionTypesForFullQuiz = useMemo(() => {
73173
+ return ALL_AVAILABLE_QUESTION_TYPES.filter((qt) => allowedQuestionTypes.includes(qt.value));
73174
+ }, [allowedQuestionTypes]);
73171
73175
  useEffect(() => {
73172
73176
  if (isOpen) {
73173
73177
  setTotalQuestions(10);
@@ -73187,7 +73191,7 @@ var AIFullQuizGeneratorModal = ({
73187
73191
  setAiGeneratedPlan(null);
73188
73192
  setGeminiApiKeyExists(APIKeyService.hasAPIKey(GEMINI_API_KEY_SERVICE_NAME));
73189
73193
  }
73190
- }, [isOpen]);
73194
+ }, [isOpen, availableQuestionTypesForFullQuiz]);
73191
73195
  const handleApiKeyModalClose = () => {
73192
73196
  setIsApiKeyManagerModalOpen(false);
73193
73197
  setGeminiApiKeyExists(APIKeyService.hasAPIKey(GEMINI_API_KEY_SERVICE_NAME));
@@ -73195,7 +73199,7 @@ var AIFullQuizGeneratorModal = ({
73195
73199
  const handleTotalQuestionsChange = (e2) => {
73196
73200
  let num = parseInt(e2.target.value, 10);
73197
73201
  if (isNaN(num) || num < 1) num = 1;
73198
- if (num > 100) num = 100;
73202
+ if (num > maxQuestions) num = maxQuestions;
73199
73203
  setTotalQuestions(num);
73200
73204
  };
73201
73205
  const handleTopicChange = (id2, field, value) => {
@@ -73225,8 +73229,8 @@ var AIFullQuizGeneratorModal = ({
73225
73229
  setError("Gemini API Key is required for AI features. Please set it first.");
73226
73230
  return false;
73227
73231
  }
73228
- if (totalQuestions <= 0 || totalQuestions > 100) {
73229
- setError("Total questions must be between 1 and 100.");
73232
+ if (totalQuestions <= 0 || totalQuestions > maxQuestions) {
73233
+ setError(`Total questions must be between 1 and ${maxQuestions}.`);
73230
73234
  return false;
73231
73235
  }
73232
73236
  if (topics.some((t2) => !t2.topic.trim())) {
@@ -73265,7 +73269,6 @@ var AIFullQuizGeneratorModal = ({
73265
73269
  const stage2Input = {
73266
73270
  quizPlan: plan,
73267
73271
  language: language3,
73268
- // <-- SỬ DỤNG PROP
73269
73272
  imageContexts: []
73270
73273
  };
73271
73274
  const stage2Output = await generateQuestionsFromQuizPlan(stage2Input, apiKey);
@@ -73316,7 +73319,6 @@ var AIFullQuizGeneratorModal = ({
73316
73319
  try {
73317
73320
  const planInput = {
73318
73321
  language: language3,
73319
- // <-- SỬ DỤNG PROP
73320
73322
  totalQuestions,
73321
73323
  numCodingQuestions: 0,
73322
73324
  topics: topics.map((t2) => ({ topic: t2.topic, ratio: t2.ratio })),
@@ -73380,103 +73382,9 @@ var AIFullQuizGeneratorModal = ({
73380
73382
  };
73381
73383
  const renderContent = () => {
73382
73384
  if (currentStage === "review") {
73383
- return /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-4 py-4" }, /* @__PURE__ */ React119__default.createElement("h3", { className: "text-lg font-Medium mb-2 text-primary flex items-center" }, /* @__PURE__ */ React119__default.createElement(Eye, { className: "mr-2 h-5 w-5" }), " Review & Adjust AI Generated Quiz Plan"), /* @__PURE__ */ React119__default.createElement("p", { className: "text-sm text-muted-foreground" }, "The AI has proposed the following plan. You can change question types, reorder, or remove questions before final generation. Note: 'Drag and Drop' type questions in the plan will be created as placeholders and require manual authoring of items/zones/answers."), aiGeneratedPlan && aiGeneratedPlan.length > 0 ? /* @__PURE__ */ React119__default.createElement(ScrollArea2, { className: "max-h-[calc(60vh - 120px)] pr-3" }, /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-3" }, aiGeneratedPlan.map((plannedQ, index3) => /* @__PURE__ */ React119__default.createElement(Card, { key: `planned-${index3}-${plannedQ.plannedTopic.replace(/\s/g, "")}`, className: "p-3" }, /* @__PURE__ */ React119__default.createElement(CardContent, { className: "p-0 space-y-2" }, /* @__PURE__ */ React119__default.createElement("div", { className: "flex justify-between items-start" }, /* @__PURE__ */ React119__default.createElement("p", { className: "font-semibold text-sm" }, "Q", index3 + 1, ": ", plannedQ.plannedTopic), /* @__PURE__ */ React119__default.createElement("div", { className: "flex space-x-1" }, /* @__PURE__ */ React119__default.createElement(Button, { variant: "ghost", size: "icon", className: "h-7 w-7", onClick: () => handleMovePlannedQuestion(index3, "up"), disabled: index3 === 0 }, /* @__PURE__ */ React119__default.createElement(ArrowUp, { className: "h-4 w-4" })), /* @__PURE__ */ React119__default.createElement(Button, { variant: "ghost", size: "icon", className: "h-7 w-7", onClick: () => handleMovePlannedQuestion(index3, "down"), disabled: index3 === aiGeneratedPlan.length - 1 }, /* @__PURE__ */ React119__default.createElement(ArrowDown, { className: "h-4 w-4" })), /* @__PURE__ */ React119__default.createElement(Button, { variant: "ghost", size: "icon", className: "h-7 w-7 text-destructive", onClick: () => handleRemovePlannedQuestion(index3) }, /* @__PURE__ */ React119__default.createElement(Trash2, { className: "h-4 w-4" })))), /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-2 gap-3 items-end" }, /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: `review-qtype-${index3}`, className: "text-xs" }, "Question Type"), /* @__PURE__ */ React119__default.createElement(
73384
- Select2,
73385
- {
73386
- value: plannedQ.plannedQuestionType,
73387
- onValueChange: (value) => handleChangePlannedQuestionType(index3, value)
73388
- },
73389
- /* @__PURE__ */ React119__default.createElement(SelectTrigger2, { id: `review-qtype-${index3}`, className: "h-9 text-xs" }, /* @__PURE__ */ React119__default.createElement(SelectValue2, null)),
73390
- /* @__PURE__ */ React119__default.createElement(SelectContent2, null, availableQuestionTypesForFullQuiz.map((qType) => /* @__PURE__ */ React119__default.createElement(SelectItem2, { key: qType.value, value: qType.value, className: "text-xs" }, qType.label)))
73391
- )), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { className: "text-xs block" }, "Bloom Level"), /* @__PURE__ */ React119__default.createElement("p", { className: "text-xs p-2 h-9 border rounded-md bg-secondary/50 flex items-center capitalize" }, plannedQ.plannedBloomLevel)))))))) : /* @__PURE__ */ React119__default.createElement("p", { className: "text-muted-foreground" }, "No quiz plan generated or plan is empty."), 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));
73385
+ return /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-4 py-4" }, /* @__PURE__ */ React119__default.createElement("h3", { className: "text-lg font-Medium mb-2 text-primary flex items-center" }, /* @__PURE__ */ React119__default.createElement(Eye, { className: "mr-2 h-5 w-5" }), " Review & Adjust AI Generated Quiz Plan"), /* @__PURE__ */ React119__default.createElement("p", { className: "text-sm text-muted-foreground" }, "The AI has proposed the following plan. You can change question types, reorder, or remove questions before final generation. Note: 'Drag and Drop' type questions in the plan will be created as placeholders and require manual authoring of items/zones/answers."), aiGeneratedPlan && aiGeneratedPlan.length > 0 ? /* @__PURE__ */ React119__default.createElement(ScrollArea2, { className: "max-h-[calc(60vh - 120px)] pr-3" }, /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-3" }, aiGeneratedPlan.map((plannedQ, index3) => /* @__PURE__ */ React119__default.createElement(Card, { key: `planned-${index3}-${plannedQ.plannedTopic.replace(/\s/g, "")}`, className: "p-3" }, /* @__PURE__ */ React119__default.createElement(CardContent, { className: "p-0 space-y-2" }, /* @__PURE__ */ React119__default.createElement("div", { className: "flex justify-between items-start" }, /* @__PURE__ */ React119__default.createElement("p", { className: "font-semibold text-sm" }, "Q", index3 + 1, ": ", plannedQ.plannedTopic), /* @__PURE__ */ React119__default.createElement("div", { className: "flex space-x-1" }, /* @__PURE__ */ React119__default.createElement(Button, { variant: "ghost", size: "icon", className: "h-7 w-7", onClick: () => handleMovePlannedQuestion(index3, "up"), disabled: index3 === 0 }, /* @__PURE__ */ React119__default.createElement(ArrowUp, { className: "h-4 w-4" })), /* @__PURE__ */ React119__default.createElement(Button, { variant: "ghost", size: "icon", className: "h-7 w-7", onClick: () => handleMovePlannedQuestion(index3, "down"), disabled: index3 === aiGeneratedPlan.length - 1 }, /* @__PURE__ */ React119__default.createElement(ArrowDown, { className: "h-4 w-4" })), /* @__PURE__ */ React119__default.createElement(Button, { variant: "ghost", size: "icon", className: "h-7 w-7 text-destructive", onClick: () => handleRemovePlannedQuestion(index3) }, /* @__PURE__ */ React119__default.createElement(Trash2, { className: "h-4 w-4" })))), /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-2 gap-3 items-end" }, /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: `review-qtype-${index3}`, className: "text-xs" }, "Question Type"), /* @__PURE__ */ React119__default.createElement(Select2, { value: plannedQ.plannedQuestionType, onValueChange: (value) => handleChangePlannedQuestionType(index3, value) }, /* @__PURE__ */ React119__default.createElement(SelectTrigger2, { id: `review-qtype-${index3}`, className: "h-9 text-xs" }, /* @__PURE__ */ React119__default.createElement(SelectValue2, null)), /* @__PURE__ */ React119__default.createElement(SelectContent2, null, availableQuestionTypesForFullQuiz.map((qType) => /* @__PURE__ */ React119__default.createElement(SelectItem2, { key: qType.value, value: qType.value, className: "text-xs" }, qType.label))))), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { className: "text-xs block" }, "Bloom Level"), /* @__PURE__ */ React119__default.createElement("p", { className: "text-xs p-2 h-9 border rounded-md bg-secondary/50 flex items-center capitalize" }, plannedQ.plannedBloomLevel)))))))) : /* @__PURE__ */ React119__default.createElement("p", { className: "text-muted-foreground" }, "No quiz plan generated or plan is empty."), 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));
73392
73386
  }
73393
- return /* @__PURE__ */ React119__default.createElement(ScrollArea2, { className: "max-h-[calc(70vh - 100px)] pl-4 pr-3 py-1" }, /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-4 py-1 px-2" }, !geminiApiKeyExists && /* @__PURE__ */ React119__default.createElement("div", { className: "p-3 mb-4 border border-amber-500 bg-amber-50 rounded-md text-amber-700" }, /* @__PURE__ */ React119__default.createElement("div", { className: "flex items-start" }, /* @__PURE__ */ React119__default.createElement(TriangleAlert, { className: "h-5 w-5 mr-2 mt-0.5 flex-shrink-0" }), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement("p", { className: "font-semibold" }, "Gemini API Key Required"), /* @__PURE__ */ React119__default.createElement("p", { className: "text-xs" }, "To use AI quiz generation, please set your Google Gemini API Key."), /* @__PURE__ */ React119__default.createElement(
73394
- Button,
73395
- {
73396
- variant: "link",
73397
- className: "p-0 h-auto text-xs text-amber-700 hover:text-amber-800 mt-1",
73398
- onClick: () => setIsApiKeyManagerModalOpen(true)
73399
- },
73400
- /* @__PURE__ */ React119__default.createElement(Settings, { className: "mr-1 h-3 w-3" }),
73401
- " Set API Key Now"
73402
- )))), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "total-questions" }, "Total Number of Questions (1-100)"), /* @__PURE__ */ React119__default.createElement(
73403
- Input,
73404
- {
73405
- id: "total-questions",
73406
- type: "number",
73407
- value: totalQuestions,
73408
- onChange: handleTotalQuestionsChange,
73409
- min: "1",
73410
- max: "100"
73411
- }
73412
- )), /* @__PURE__ */ React119__default.createElement("fieldset", { className: "border p-3 rounded-md" }, /* @__PURE__ */ React119__default.createElement("legend", { className: "text-sm font-Medium px-1" }, "Topic Distribution"), topics.map((topicItem, index3) => /* @__PURE__ */ React119__default.createElement("div", { key: topicItem.id, className: "flex items-center gap-2 mb-2" }, /* @__PURE__ */ React119__default.createElement(
73413
- Input,
73414
- {
73415
- type: "text",
73416
- placeholder: `Topic ${index3 + 1}`,
73417
- value: topicItem.topic,
73418
- onChange: (e2) => handleTopicChange(topicItem.id, "topic", e2.target.value),
73419
- className: "flex-grow"
73420
- }
73421
- ), /* @__PURE__ */ React119__default.createElement(
73422
- Input,
73423
- {
73424
- type: "number",
73425
- placeholder: "Ratio %",
73426
- value: topicItem.ratio,
73427
- onChange: (e2) => handleTopicChange(topicItem.id, "ratio", parseInt(e2.target.value, 10) || 0),
73428
- className: "w-24",
73429
- min: "0",
73430
- max: "100"
73431
- }
73432
- ), /* @__PURE__ */ React119__default.createElement(Button, { type: "button", variant: "ghost", size: "icon", onClick: () => removeTopic(topicItem.id), disabled: topics.length <= 1 }, /* @__PURE__ */ React119__default.createElement(Trash2, { className: "h-4 w-4 text-destructive" })))), /* @__PURE__ */ React119__default.createElement(Button, { type: "button", variant: "outline", size: "sm", onClick: addTopic }, /* @__PURE__ */ React119__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Topic")), /* @__PURE__ */ React119__default.createElement("fieldset", { className: "border p-3 rounded-md" }, /* @__PURE__ */ React119__default.createElement("legend", { className: "text-sm font-Medium px-1" }, "Bloom Level Distribution"), bloomLevels.map((bloomItem) => /* @__PURE__ */ React119__default.createElement("div", { key: bloomItem.id, className: "flex items-center gap-2 mb-2" }, /* @__PURE__ */ React119__default.createElement(Label2, { className: "w-32 capitalize flex-shrink-0" }, bloomItem.level), /* @__PURE__ */ React119__default.createElement(
73433
- Input,
73434
- {
73435
- type: "number",
73436
- placeholder: "Ratio %",
73437
- value: bloomItem.ratio,
73438
- onChange: (e2) => handleBloomRatioChange(bloomItem.id, parseInt(e2.target.value, 10) || 0),
73439
- className: "w-24",
73440
- min: "0",
73441
- max: "100"
73442
- }
73443
- )))), /* @__PURE__ */ React119__default.createElement("fieldset", { className: "border p-3 rounded-md" }, /* @__PURE__ */ React119__default.createElement("legend", { className: "text-sm font-Medium px-1" }, "Relevant Contexts (Optional, Select Multiple)"), /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-2 gap-2 mt-2 max-h-40 overflow-y-auto" }, contextOptions.filter((opt) => opt.contextId !== "__none__" && opt.contextId !== "__custom__").map((opt) => /* @__PURE__ */ React119__default.createElement("div", { key: opt.contextId, className: "flex items-center space-x-2" }, /* @__PURE__ */ React119__default.createElement(
73444
- Checkbox2,
73445
- {
73446
- id: `ctx-full-${opt.contextId}`,
73447
- checked: selectedContextIds.includes(opt.contextId),
73448
- onCheckedChange: () => handleContextToggle(opt.contextId)
73449
- }
73450
- ), /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: `ctx-full-${opt.contextId}`, className: "text-xs font-normal cursor-pointer" }, opt.contextDescription, " (", opt.shortContextId, ")")))), /* @__PURE__ */ React119__default.createElement("div", { className: "mt-2" }, /* @__PURE__ */ React119__default.createElement(
73451
- Checkbox2,
73452
- {
73453
- id: `ctx-full-__custom__`,
73454
- checked: selectedContextIds.includes("__custom__"),
73455
- onCheckedChange: () => handleContextToggle("__custom__")
73456
- }
73457
- ), /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: `ctx-full-__custom__`, className: "text-xs font-normal cursor-pointer ml-2" }, "Other (Custom Input)")), selectedContextIds.includes("__custom__") && /* @__PURE__ */ React119__default.createElement(
73458
- Textarea,
73459
- {
73460
- value: customContextInput,
73461
- onChange: (e2) => setCustomContextInput(e2.target.value),
73462
- placeholder: "Enter your specific custom context here...",
73463
- className: "min-h-[60px] mt-2 text-sm"
73464
- }
73465
- )), /* @__PURE__ */ React119__default.createElement("fieldset", { className: "border p-3 rounded-md" }, /* @__PURE__ */ React119__default.createElement("legend", { className: "text-sm font-Medium px-1" }, "Question Types to Use (Select Multiple)"), /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-2 gap-2 mt-2 max-h-40 overflow-y-auto" }, availableQuestionTypesForFullQuiz.map((qType) => /* @__PURE__ */ React119__default.createElement("div", { key: qType.value, className: "flex items-center space-x-2" }, /* @__PURE__ */ React119__default.createElement(
73466
- Checkbox2,
73467
- {
73468
- id: `qtype-full-${qType.value}`,
73469
- checked: selectedQuestionTypes.includes(qType.value),
73470
- onCheckedChange: () => handleQuestionTypeToggle(qType.value)
73471
- }
73472
- ), /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: `qtype-full-${qType.value}`, className: "text-xs font-normal cursor-pointer" }, qType.label))))), /* @__PURE__ */ React119__default.createElement("div", { className: "flex items-center space-x-2 pt-2" }, /* @__PURE__ */ React119__default.createElement(
73473
- Checkbox2,
73474
- {
73475
- id: "authorize-ai-skip-review",
73476
- checked: authorizeAISkipReview,
73477
- onCheckedChange: (checked) => setAuthorizeAISkipReview(!!checked)
73478
- }
73479
- ), /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "authorize-ai-skip-review", className: "text-sm font-normal" }, "Authorize AI (Skip Review & Generate Directly)")), 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)));
73387
+ return /* @__PURE__ */ React119__default.createElement(ScrollArea2, { className: "max-h-[calc(70vh - 100px)] pl-4 pr-3 py-1" }, /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-4 py-1 px-2" }, !geminiApiKeyExists && /* @__PURE__ */ React119__default.createElement("div", { className: "p-3 mb-4 border border-amber-500 bg-amber-50 rounded-md text-amber-700" }, /* @__PURE__ */ React119__default.createElement("div", { className: "flex items-start" }, /* @__PURE__ */ React119__default.createElement(TriangleAlert, { className: "h-5 w-5 mr-2 mt-0.5 flex-shrink-0" }), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement("p", { className: "font-semibold" }, "Gemini API Key Required"), /* @__PURE__ */ React119__default.createElement("p", { className: "text-xs" }, "To use AI quiz generation, please set your Google Gemini API Key."), /* @__PURE__ */ React119__default.createElement(Button, { variant: "link", className: "p-0 h-auto text-xs text-amber-700 hover:text-amber-800 mt-1", onClick: () => setIsApiKeyManagerModalOpen(true) }, /* @__PURE__ */ React119__default.createElement(Settings, { className: "mr-1 h-3 w-3" }), " Set API Key Now")))), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "total-questions" }, "Total Number of Questions (1-", maxQuestions, ")"), /* @__PURE__ */ React119__default.createElement(Input, { id: "total-questions", type: "number", value: totalQuestions, onChange: handleTotalQuestionsChange, min: "1", max: maxQuestions })), /* @__PURE__ */ React119__default.createElement("fieldset", { className: "border p-3 rounded-md" }, /* @__PURE__ */ React119__default.createElement("legend", { className: "text-sm font-Medium px-1" }, "Topic Distribution"), topics.map((topicItem, index3) => /* @__PURE__ */ React119__default.createElement("div", { key: topicItem.id, className: "flex items-center gap-2 mb-2" }, /* @__PURE__ */ React119__default.createElement(Input, { type: "text", placeholder: `Topic ${index3 + 1}`, value: topicItem.topic, onChange: (e2) => handleTopicChange(topicItem.id, "topic", e2.target.value), className: "flex-grow" }), /* @__PURE__ */ React119__default.createElement(Input, { type: "number", placeholder: "Ratio %", value: topicItem.ratio, onChange: (e2) => handleTopicChange(topicItem.id, "ratio", parseInt(e2.target.value, 10) || 0), className: "w-24", min: "0", max: "100" }), /* @__PURE__ */ React119__default.createElement(Button, { type: "button", variant: "ghost", size: "icon", onClick: () => removeTopic(topicItem.id), disabled: topics.length <= 1 }, /* @__PURE__ */ React119__default.createElement(Trash2, { className: "h-4 w-4 text-destructive" })))), /* @__PURE__ */ React119__default.createElement(Button, { type: "button", variant: "outline", size: "sm", onClick: addTopic }, /* @__PURE__ */ React119__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Topic")), /* @__PURE__ */ React119__default.createElement("fieldset", { className: "border p-3 rounded-md" }, /* @__PURE__ */ React119__default.createElement("legend", { className: "text-sm font-Medium px-1" }, "Bloom Level Distribution"), bloomLevels.map((bloomItem) => /* @__PURE__ */ React119__default.createElement("div", { key: bloomItem.id, className: "flex items-center gap-2 mb-2" }, /* @__PURE__ */ React119__default.createElement(Label2, { className: "w-32 capitalize flex-shrink-0" }, bloomItem.level), /* @__PURE__ */ React119__default.createElement(Input, { type: "number", placeholder: "Ratio %", value: bloomItem.ratio, onChange: (e2) => handleBloomRatioChange(bloomItem.id, parseInt(e2.target.value, 10) || 0), className: "w-24", min: "0", max: "100" })))), /* @__PURE__ */ React119__default.createElement("fieldset", { className: "border p-3 rounded-md" }, /* @__PURE__ */ React119__default.createElement("legend", { className: "text-sm font-Medium px-1" }, "Relevant Contexts (Optional, Select Multiple)"), /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-2 gap-2 mt-2 max-h-40 overflow-y-auto" }, contextOptions.filter((opt) => opt.contextId !== "__none__" && opt.contextId !== "__custom__").map((opt) => /* @__PURE__ */ React119__default.createElement("div", { key: opt.contextId, className: "flex items-center space-x-2" }, /* @__PURE__ */ React119__default.createElement(Checkbox2, { id: `ctx-full-${opt.contextId}`, checked: selectedContextIds.includes(opt.contextId), onCheckedChange: () => handleContextToggle(opt.contextId) }), /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: `ctx-full-${opt.contextId}`, className: "text-xs font-normal cursor-pointer" }, opt.contextDescription, " (", opt.shortContextId, ")"))), /* @__PURE__ */ React119__default.createElement("div", { className: "mt-2" }, /* @__PURE__ */ React119__default.createElement(Checkbox2, { id: `ctx-full-__custom__`, checked: selectedContextIds.includes("__custom__"), onCheckedChange: () => handleContextToggle("__custom__") }), /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: `ctx-full-__custom__`, className: "text-xs font-normal cursor-pointer ml-2" }, "Other (Custom Input)")), selectedContextIds.includes("__custom__") && /* @__PURE__ */ React119__default.createElement(Textarea, { value: customContextInput, onChange: (e2) => setCustomContextInput(e2.target.value), placeholder: "Enter your specific custom context here...", className: "min-h-[60px] mt-2 text-sm" }))), /* @__PURE__ */ React119__default.createElement("fieldset", { className: "border p-3 rounded-md" }, /* @__PURE__ */ React119__default.createElement("legend", { className: "text-sm font-Medium px-1" }, "Question Types to Use (Select Multiple)"), /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-2 gap-2 mt-2 max-h-40 overflow-y-auto" }, availableQuestionTypesForFullQuiz.map((qType) => /* @__PURE__ */ React119__default.createElement("div", { key: qType.value, className: "flex items-center space-x-2" }, /* @__PURE__ */ React119__default.createElement(Checkbox2, { id: `qtype-full-${qType.value}`, checked: selectedQuestionTypes.includes(qType.value), onCheckedChange: () => handleQuestionTypeToggle(qType.value) }), /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: `qtype-full-${qType.value}`, className: "text-xs font-normal cursor-pointer" }, qType.label))))), /* @__PURE__ */ React119__default.createElement("div", { className: "flex items-center space-x-2 pt-2" }, /* @__PURE__ */ React119__default.createElement(Checkbox2, { id: "authorize-ai-skip-review", checked: authorizeAISkipReview, onCheckedChange: (checked) => setAuthorizeAISkipReview(!!checked) }), /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "authorize-ai-skip-review", className: "text-sm font-normal" }, "Authorize AI (Skip Review & Generate Directly)")), 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)));
73480
73388
  };
73481
73389
  return /* @__PURE__ */ React119__default.createElement(React119__default.Fragment, null, /* @__PURE__ */ React119__default.createElement(Dialog2, { open: isOpen, onOpenChange: (open) => !open && onClose() }, /* @__PURE__ */ React119__default.createElement(DialogContent2, { className: "sm:max-w-[650px] md:max-w-[750px] lg:max-w-[800px] max-h-[90vh] overflow-y-auto" }, /* @__PURE__ */ React119__default.createElement(DialogHeader, null, /* @__PURE__ */ React119__default.createElement(DialogTitle2, { className: "flex items-center font-headline text-2xl" }, /* @__PURE__ */ React119__default.createElement(FileText, { className: "mr-2 h-6 w-6 text-primary" }), " Generate Full Quiz with AI"), /* @__PURE__ */ React119__default.createElement(DialogDescription2, null, currentStage === "input" && "Define parameters for AI to generate a quiz plan.", currentStage === "review" && "Review and adjust the AI-generated quiz plan before generating questions.", currentStage === "generating" && "AI is working... Please wait.")), renderContent(), /* @__PURE__ */ React119__default.createElement(DialogFooter, { className: "pt-4 border-t" }, /* @__PURE__ */ React119__default.createElement(DialogClose2, { asChild: true }, /* @__PURE__ */ React119__default.createElement(Button, { type: "button", variant: "outline", onClick: onClose }, "Cancel")), currentStage === "input" && /* @__PURE__ */ React119__default.createElement(Button, { type: "button", onClick: handleSubmitPlanGeneration, disabled: isLoading || !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" }), authorizeAISkipReview ? "Generate Quiz Directly" : "Generate Quiz Plan"), currentStage === "review" && !isLoading && /* @__PURE__ */ React119__default.createElement(Button, { type: "button", onClick: handleGenerateQuestionsFromReviewedPlan, disabled: isLoading || !aiGeneratedPlan || aiGeneratedPlan.length === 0 || !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 Questions from Plan"), currentStage === "generating" && isLoading && /* @__PURE__ */ React119__default.createElement(Button, { type: "button", disabled: true }, /* @__PURE__ */ React119__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), "Generating... Please Wait")))), /* @__PURE__ */ React119__default.createElement(APIKeyManagerModal, { isOpen: isApiKeyManagerModalOpen, onClose: handleApiKeyModalClose }));
73482
73390
  };