@thanh01.pmt/interactive-quiz-kit 1.0.74 → 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
  };
@@ -77888,7 +77796,7 @@ function ApproachManager({
77888
77796
  };
77889
77797
  const handleEditItem = (item) => {
77890
77798
  setCurrentItem(item);
77891
- setFormState(item);
77799
+ setFormState({ ...item, difficulty: Array.isArray(item.difficulty) ? item.difficulty : [item.difficulty] });
77892
77800
  setIsDialogOpen(true);
77893
77801
  };
77894
77802
  const handleDeleteItem = (item) => {
@@ -77981,11 +77889,18 @@ function ApproachManager({
77981
77889
  await onBulkAdd(validatedRecords);
77982
77890
  }
77983
77891
  };
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(Checkbox2, { id: `diff-${diff2}`, checked: (formState.difficulty || []).includes(diff2), onCheckedChange: (checked) => {
77985
- const current = formState.difficulty || [];
77986
- const newDiff = checked ? [...current, diff2] : current.filter((d) => d !== diff2);
77987
- setFormState((s2) => ({ ...s2, difficulty: newDiff }));
77988
- } }), /* @__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"))))));
77892
+ 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(
77893
+ Checkbox2,
77894
+ {
77895
+ id: `diff-${diff2}`,
77896
+ checked: (formState.difficulty || []).includes(diff2),
77897
+ onCheckedChange: (checked) => {
77898
+ const current = formState.difficulty || [];
77899
+ const newDiff = checked ? [...current, diff2] : current.filter((d) => d !== diff2);
77900
+ setFormState((s2) => ({ ...s2, difficulty: newDiff }));
77901
+ }
77902
+ }
77903
+ ), /* @__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"))))));
77989
77904
  }
77990
77905
 
77991
77906
  // 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-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';