@thanh01.pmt/interactive-quiz-kit 1.0.75 → 1.0.77
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/authoring.cjs +16 -108
- package/dist/authoring.d.cts +1 -1
- package/dist/authoring.d.ts +1 -1
- package/dist/authoring.mjs +16 -108
- package/dist/react-ui.cjs +95 -185
- package/dist/react-ui.d.cts +9 -5
- package/dist/react-ui.d.ts +9 -5
- package/dist/react-ui.mjs +95 -185
- package/dist/{toaster-B2MPZYhi.d.ts → toaster-Bj78wmSz.d.ts} +2 -0
- package/dist/{toaster-Bvhmyef9.d.cts → toaster-CexT11VU.d.cts} +2 -0
- package/package.json +1 -1
package/dist/authoring.cjs
CHANGED
|
@@ -73195,7 +73195,7 @@ var contextOptions = [
|
|
|
73195
73195
|
];
|
|
73196
73196
|
|
|
73197
73197
|
// src/react-ui/components/authoring/AIFullQuizGeneratorModal.tsx
|
|
73198
|
-
var
|
|
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
|
-
|
|
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 >
|
|
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 >
|
|
73294
|
-
setError(
|
|
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
|
};
|
package/dist/authoring.d.cts
CHANGED
|
@@ -2,7 +2,7 @@ export { B as BaseQuestion, e as BlocklyProgrammingQuestion, C as CodingQuestion
|
|
|
2
2
|
export { APIKeyService, AchievementService, Approach, ApproachTableRawDifficulty, BloomLevelName, BloomLevelType, Category, CodeNamedEntity, Context, GEMINI_API_KEY_SERVICE_NAME, GradeLevel, KnowledgeCardService, KnowledgeDimension, LearningObjective, MetadataService, PracticeHistoryService, QuestionBankService, QuestionImportService, QuestionInBank, QuestionTypeType, QuizEditorService, QuizEngine, QuizEngineCallbacks, QuizEngineConstructorOptions, QuoteService, SCORMService, StandardDifficulty, Subject, Topic, UserConfigService, cn, emptyQuiz, exportQuizAsSCORMZip, generateLauncherHTML, generateSCORMManifest, generateUniqueId, sampleQuiz } from './index.cjs';
|
|
3
3
|
export { i as Achievement, j as AchievementDefinition, r as ActivityCalendarData, u as AnalysisReport, A as AnswerDetail, x as ChatContext, C as ChatMessage, v as DashboardCardConfig, D as DashboardCardId, w as DashboardLayout, y as Goal, G as GoalType, t as ImageContextItem, I as ImportError, K as KnowledgeCard, L as LearningAnalysis, e as PerformanceByBloomLevel, b as PerformanceByCategory, d as PerformanceByDifficulty, P as PerformanceByLearningObjective, c as PerformanceByTopic, f as PerformanceMetric, s as PerformanceSummary, k as PracticeDifficulty, n as PracticeSession, p as PracticeSessionSummary, o as PracticeStats, m as PracticeSuggestion, l as PracticeSuggestionTopic, q as PracticeTopicSummary, g as QuestionReview, Q as QuizResultType, h as QuizReviewContent, R as RoadmapItem, T as TestCaseResult, U as UserAnswerType, a as UserAnswers, W as WeeklyRoadmap } from './ai-ecosystem-DyQYZbyX.cjs';
|
|
4
4
|
export { AssessAndMapDocumentClientInput, AssessAndMapDocumentOutput, BloomLevelStringsForAI, GenerateCodingQuestionClientInput, GenerateCodingQuestionOutput, GenerateFillInTheBlanksQuestionClientInput, GenerateFillInTheBlanksQuestionOutput, GenerateLearningAnalysisClientInput, GenerateLearningAnalysisOutput, GenerateMCQQuestionClientInput, GenerateMCQQuestionOutput, GenerateMRQQuestionClientInput, GenerateMRQQuestionOutput, GenerateMatchingQuestionClientInput, GenerateMatchingQuestionOutput, GenerateMotivationalQuoteClientInput, GenerateMotivationalQuoteOutput, GenerateNumericQuestionClientInput, GenerateNumericQuestionOutput, GeneratePracticeSuggestionClientInput, GeneratePracticeSuggestionOutput, GenerateQuestionsFromQuizPlanClientInput, GenerateQuestionsFromQuizPlanOutput, GenerateQuizFromTextClientInput, GenerateQuizFromTextOutput, GenerateQuizPlanClientInput, GenerateQuizPlanOutput, GenerateQuizReviewClientInput, GenerateQuizReviewOutput, GenerateSequenceQuestionClientInput, GenerateSequenceQuestionOutput, GenerateShortAnswerQuestionClientInput, GenerateShortAnswerQuestionOutput, GenerateSingleKnowledgeCardClientInput, GenerateSingleKnowledgeCardOutput, GenerateTrueFalseQuestionClientInput, GenerateTrueFalseQuestionOutput, PlanKnowledgeCardsClientInput, PlanKnowledgeCardsOutput, PlannedQuestion, assessAndMapDocument, generateCodingQuestion, generateFillInTheBlanksQuestion, generateLearningAnalysis, generateMCQQuestion, generateMRQQuestion, generateMatchingQuestion, generateMotivationalQuote, generateNumericQuestion, generatePracticeSuggestion, generateQuestionsFromQuizPlan, generateQuizFromText, generateQuizPlan, generateQuizReview, generateSequenceQuestion, generateShortAnswerQuestion, generateSingleKnowledgeCard, generateTrueFalseQuestion, planKnowledgeCards } from './ai.cjs';
|
|
5
|
-
export { c as AIFullQuizGeneratorModal, A as AIQuestionGeneratorModal, e as APIKeyManagerModal, f as ApiKeySettings, m as ApproachManager, B as BloomLevelManager, C as CategoryManager, l as ContextManager, E as EditQuestionModal, G as GradeLevelManager, I as ImportQuestionsModal, L as LearningObjectiveManager, n as MetadataImportControls, M as MetadataTabs, h as QuestionFilters, i as QuestionFormDialog, g as QuestionList, a as QuestionPreviewModal, k as QuestionTypeManager, Q as QuizAuthoringTool, b as QuizSettingsForm, d as SCORMExportModal, S as SelectedQuestionsPanel, j as SubjectManager, o as Toaster, T as TopicManager, t as toast, u as useToast } from './toaster-
|
|
5
|
+
export { c as AIFullQuizGeneratorModal, A as AIQuestionGeneratorModal, e as APIKeyManagerModal, f as ApiKeySettings, m as ApproachManager, B as BloomLevelManager, C as CategoryManager, l as ContextManager, E as EditQuestionModal, G as GradeLevelManager, I as ImportQuestionsModal, L as LearningObjectiveManager, n as MetadataImportControls, M as MetadataTabs, h as QuestionFilters, i as QuestionFormDialog, g as QuestionList, a as QuestionPreviewModal, k as QuestionTypeManager, Q as QuizAuthoringTool, b as QuizSettingsForm, d as SCORMExportModal, S as SelectedQuestionsPanel, j as SubjectManager, o as Toaster, T as TopicManager, t as toast, u as useToast } from './toaster-CexT11VU.cjs';
|
|
6
6
|
import 'clsx';
|
|
7
7
|
import 'zod';
|
|
8
8
|
import 'react';
|
package/dist/authoring.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export { B as BaseQuestion, e as BlocklyProgrammingQuestion, C as CodingQuestion
|
|
|
2
2
|
export { APIKeyService, AchievementService, Approach, ApproachTableRawDifficulty, BloomLevelName, BloomLevelType, Category, CodeNamedEntity, Context, GEMINI_API_KEY_SERVICE_NAME, GradeLevel, KnowledgeCardService, KnowledgeDimension, LearningObjective, MetadataService, PracticeHistoryService, QuestionBankService, QuestionImportService, QuestionInBank, QuestionTypeType, QuizEditorService, QuizEngine, QuizEngineCallbacks, QuizEngineConstructorOptions, QuoteService, SCORMService, StandardDifficulty, Subject, Topic, UserConfigService, cn, emptyQuiz, exportQuizAsSCORMZip, generateLauncherHTML, generateSCORMManifest, generateUniqueId, sampleQuiz } from './index.js';
|
|
3
3
|
export { i as Achievement, j as AchievementDefinition, r as ActivityCalendarData, u as AnalysisReport, A as AnswerDetail, x as ChatContext, C as ChatMessage, v as DashboardCardConfig, D as DashboardCardId, w as DashboardLayout, y as Goal, G as GoalType, t as ImageContextItem, I as ImportError, K as KnowledgeCard, L as LearningAnalysis, e as PerformanceByBloomLevel, b as PerformanceByCategory, d as PerformanceByDifficulty, P as PerformanceByLearningObjective, c as PerformanceByTopic, f as PerformanceMetric, s as PerformanceSummary, k as PracticeDifficulty, n as PracticeSession, p as PracticeSessionSummary, o as PracticeStats, m as PracticeSuggestion, l as PracticeSuggestionTopic, q as PracticeTopicSummary, g as QuestionReview, Q as QuizResultType, h as QuizReviewContent, R as RoadmapItem, T as TestCaseResult, U as UserAnswerType, a as UserAnswers, W as WeeklyRoadmap } from './ai-ecosystem-Qa_SdE2T.js';
|
|
4
4
|
export { AssessAndMapDocumentClientInput, AssessAndMapDocumentOutput, BloomLevelStringsForAI, GenerateCodingQuestionClientInput, GenerateCodingQuestionOutput, GenerateFillInTheBlanksQuestionClientInput, GenerateFillInTheBlanksQuestionOutput, GenerateLearningAnalysisClientInput, GenerateLearningAnalysisOutput, GenerateMCQQuestionClientInput, GenerateMCQQuestionOutput, GenerateMRQQuestionClientInput, GenerateMRQQuestionOutput, GenerateMatchingQuestionClientInput, GenerateMatchingQuestionOutput, GenerateMotivationalQuoteClientInput, GenerateMotivationalQuoteOutput, GenerateNumericQuestionClientInput, GenerateNumericQuestionOutput, GeneratePracticeSuggestionClientInput, GeneratePracticeSuggestionOutput, GenerateQuestionsFromQuizPlanClientInput, GenerateQuestionsFromQuizPlanOutput, GenerateQuizFromTextClientInput, GenerateQuizFromTextOutput, GenerateQuizPlanClientInput, GenerateQuizPlanOutput, GenerateQuizReviewClientInput, GenerateQuizReviewOutput, GenerateSequenceQuestionClientInput, GenerateSequenceQuestionOutput, GenerateShortAnswerQuestionClientInput, GenerateShortAnswerQuestionOutput, GenerateSingleKnowledgeCardClientInput, GenerateSingleKnowledgeCardOutput, GenerateTrueFalseQuestionClientInput, GenerateTrueFalseQuestionOutput, PlanKnowledgeCardsClientInput, PlanKnowledgeCardsOutput, PlannedQuestion, assessAndMapDocument, generateCodingQuestion, generateFillInTheBlanksQuestion, generateLearningAnalysis, generateMCQQuestion, generateMRQQuestion, generateMatchingQuestion, generateMotivationalQuote, generateNumericQuestion, generatePracticeSuggestion, generateQuestionsFromQuizPlan, generateQuizFromText, generateQuizPlan, generateQuizReview, generateSequenceQuestion, generateShortAnswerQuestion, generateSingleKnowledgeCard, generateTrueFalseQuestion, planKnowledgeCards } from './ai.js';
|
|
5
|
-
export { c as AIFullQuizGeneratorModal, A as AIQuestionGeneratorModal, e as APIKeyManagerModal, f as ApiKeySettings, m as ApproachManager, B as BloomLevelManager, C as CategoryManager, l as ContextManager, E as EditQuestionModal, G as GradeLevelManager, I as ImportQuestionsModal, L as LearningObjectiveManager, n as MetadataImportControls, M as MetadataTabs, h as QuestionFilters, i as QuestionFormDialog, g as QuestionList, a as QuestionPreviewModal, k as QuestionTypeManager, Q as QuizAuthoringTool, b as QuizSettingsForm, d as SCORMExportModal, S as SelectedQuestionsPanel, j as SubjectManager, o as Toaster, T as TopicManager, t as toast, u as useToast } from './toaster-
|
|
5
|
+
export { c as AIFullQuizGeneratorModal, A as AIQuestionGeneratorModal, e as APIKeyManagerModal, f as ApiKeySettings, m as ApproachManager, B as BloomLevelManager, C as CategoryManager, l as ContextManager, E as EditQuestionModal, G as GradeLevelManager, I as ImportQuestionsModal, L as LearningObjectiveManager, n as MetadataImportControls, M as MetadataTabs, h as QuestionFilters, i as QuestionFormDialog, g as QuestionList, a as QuestionPreviewModal, k as QuestionTypeManager, Q as QuizAuthoringTool, b as QuizSettingsForm, d as SCORMExportModal, S as SelectedQuestionsPanel, j as SubjectManager, o as Toaster, T as TopicManager, t as toast, u as useToast } from './toaster-Bj78wmSz.js';
|
|
6
6
|
import 'clsx';
|
|
7
7
|
import 'zod';
|
|
8
8
|
import 'react';
|
package/dist/authoring.mjs
CHANGED
|
@@ -73130,7 +73130,7 @@ var contextOptions = [
|
|
|
73130
73130
|
];
|
|
73131
73131
|
|
|
73132
73132
|
// src/react-ui/components/authoring/AIFullQuizGeneratorModal.tsx
|
|
73133
|
-
var
|
|
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
|
-
|
|
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 >
|
|
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 >
|
|
73229
|
-
setError(
|
|
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
|
};
|