@thanh01.pmt/interactive-quiz-kit 1.0.70 → 1.0.72
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 +315 -15
- package/dist/authoring.d.cts +1 -1
- package/dist/authoring.d.ts +1 -1
- package/dist/authoring.mjs +315 -15
- package/dist/react-ui.cjs +315 -15
- package/dist/react-ui.d.cts +1 -1
- package/dist/react-ui.d.ts +1 -1
- package/dist/react-ui.mjs +315 -15
- package/dist/{toaster-BWaJj0l-.d.cts → toaster-6AR8w2TO.d.cts} +3 -3
- package/dist/{toaster-BVaUJA6E.d.ts → toaster-DAXYZdrz.d.ts} +3 -3
- package/package.json +1 -1
package/dist/authoring.mjs
CHANGED
|
@@ -76365,11 +76365,17 @@ function MetadataImportControls({ metadataName, onImport }) {
|
|
|
76365
76365
|
const fileInputRef = useRef(null);
|
|
76366
76366
|
const { toast: toast2 } = useToast();
|
|
76367
76367
|
const processAndImportRecords = async (records, importSource) => {
|
|
76368
|
+
console.log(`[ImportControls] Processing ${records.length} records from ${importSource} for ${metadataName}.`);
|
|
76368
76369
|
if (records.length === 0) {
|
|
76369
76370
|
toast2({ title: "No Data", description: `The selected ${importSource === "file" ? "file" : "JSON string"} contains no data to import.`, variant: "destructive" });
|
|
76370
76371
|
return;
|
|
76371
76372
|
}
|
|
76372
|
-
|
|
76373
|
+
try {
|
|
76374
|
+
await onImport(records);
|
|
76375
|
+
} catch (error) {
|
|
76376
|
+
console.error(`[ImportControls] Error during onImport callback for ${metadataName}:`, error);
|
|
76377
|
+
toast2({ title: "Import Failed", description: `An error occurred while saving the data: ${error instanceof Error ? error.message : String(error)}`, variant: "destructive" });
|
|
76378
|
+
}
|
|
76373
76379
|
setIsOpen(false);
|
|
76374
76380
|
setJsonString("");
|
|
76375
76381
|
};
|
|
@@ -76401,8 +76407,10 @@ function MetadataImportControls({ metadataName, onImport }) {
|
|
|
76401
76407
|
return record;
|
|
76402
76408
|
});
|
|
76403
76409
|
}
|
|
76410
|
+
console.log(`[ImportControls] File parsed successfully. Found ${records.length} records.`);
|
|
76404
76411
|
await processAndImportRecords(records, "file");
|
|
76405
76412
|
} catch (err) {
|
|
76413
|
+
console.error("[ImportControls] Error parsing file:", err);
|
|
76406
76414
|
toast2({ title: "Import Error", description: `Failed to process file: ${err.message}`, variant: "destructive" });
|
|
76407
76415
|
}
|
|
76408
76416
|
});
|
|
@@ -77221,15 +77229,27 @@ function QuestionTypeManager({ initialData, isLoading: isLoadingProp, onAdd, onU
|
|
|
77221
77229
|
|
|
77222
77230
|
// src/react-ui/components/metadata/LearningObjectiveManager.tsx
|
|
77223
77231
|
init_react_shim();
|
|
77224
|
-
function LearningObjectiveManager({
|
|
77232
|
+
function LearningObjectiveManager({
|
|
77233
|
+
initialData,
|
|
77234
|
+
subjects: subjectsProp,
|
|
77235
|
+
isLoading: isLoadingProp,
|
|
77236
|
+
onAdd,
|
|
77237
|
+
onUpdate,
|
|
77238
|
+
onDelete,
|
|
77239
|
+
onBulkAdd
|
|
77240
|
+
}) {
|
|
77225
77241
|
const [items, setItems] = useState([]);
|
|
77226
77242
|
const [subjects, setSubjects] = useState([]);
|
|
77227
77243
|
const [isLoading, setIsLoading] = useState(true);
|
|
77228
77244
|
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
|
77229
77245
|
const [isAlertOpen, setIsAlertOpen] = useState(false);
|
|
77230
|
-
const [currentItem, setCurrentItem] = useState(
|
|
77246
|
+
const [currentItem, setCurrentItem] = useState(
|
|
77247
|
+
null
|
|
77248
|
+
);
|
|
77231
77249
|
const [formState, setFormState] = useState({});
|
|
77232
|
-
const [itemToDelete, setItemToDelete] = useState(
|
|
77250
|
+
const [itemToDelete, setItemToDelete] = useState(
|
|
77251
|
+
null
|
|
77252
|
+
);
|
|
77233
77253
|
const [isPending, startTransition] = useTransition();
|
|
77234
77254
|
const { toast: toast2 } = useToast();
|
|
77235
77255
|
const isControlled = initialData !== void 0;
|
|
@@ -77240,7 +77260,11 @@ function LearningObjectiveManager({ initialData, subjects: subjectsProp, isLoadi
|
|
|
77240
77260
|
setItems(MetadataService.getLearningObjectives());
|
|
77241
77261
|
setSubjects(MetadataService.getSubjects());
|
|
77242
77262
|
} catch (error) {
|
|
77243
|
-
toast2({
|
|
77263
|
+
toast2({
|
|
77264
|
+
title: "Error",
|
|
77265
|
+
description: "Failed to refresh data.",
|
|
77266
|
+
variant: "destructive"
|
|
77267
|
+
});
|
|
77244
77268
|
} finally {
|
|
77245
77269
|
setIsLoading(false);
|
|
77246
77270
|
}
|
|
@@ -77260,7 +77284,9 @@ function LearningObjectiveManager({ initialData, subjects: subjectsProp, isLoadi
|
|
|
77260
77284
|
};
|
|
77261
77285
|
const handleAddItem = () => {
|
|
77262
77286
|
setCurrentItem(null);
|
|
77263
|
-
setFormState({
|
|
77287
|
+
setFormState({
|
|
77288
|
+
subjectCode: subjects.length > 0 ? subjects[0].code : ""
|
|
77289
|
+
});
|
|
77264
77290
|
setIsDialogOpen(true);
|
|
77265
77291
|
};
|
|
77266
77292
|
const handleEditItem = (item) => {
|
|
@@ -77282,9 +77308,16 @@ function LearningObjectiveManager({ initialData, subjects: subjectsProp, isLoadi
|
|
|
77282
77308
|
MetadataService.deleteLearningObjective(itemToDelete.code);
|
|
77283
77309
|
refreshData();
|
|
77284
77310
|
}
|
|
77285
|
-
toast2({
|
|
77311
|
+
toast2({
|
|
77312
|
+
title: "Success",
|
|
77313
|
+
description: `Learning Objective "${itemToDelete.name}" deleted.`
|
|
77314
|
+
});
|
|
77286
77315
|
} catch (error) {
|
|
77287
|
-
toast2({
|
|
77316
|
+
toast2({
|
|
77317
|
+
title: "Error",
|
|
77318
|
+
description: error.message,
|
|
77319
|
+
variant: "destructive"
|
|
77320
|
+
});
|
|
77288
77321
|
} finally {
|
|
77289
77322
|
setIsAlertOpen(false);
|
|
77290
77323
|
setItemToDelete(null);
|
|
@@ -77293,7 +77326,11 @@ function LearningObjectiveManager({ initialData, subjects: subjectsProp, isLoadi
|
|
|
77293
77326
|
};
|
|
77294
77327
|
const handleSubmit = () => {
|
|
77295
77328
|
if (!formState.name?.trim() || !formState.code?.trim()) {
|
|
77296
|
-
toast2({
|
|
77329
|
+
toast2({
|
|
77330
|
+
title: "Validation Error",
|
|
77331
|
+
description: "Code and Name are required.",
|
|
77332
|
+
variant: "destructive"
|
|
77333
|
+
});
|
|
77297
77334
|
return;
|
|
77298
77335
|
}
|
|
77299
77336
|
startTransition(async () => {
|
|
@@ -77302,28 +77339,291 @@ function LearningObjectiveManager({ initialData, subjects: subjectsProp, isLoadi
|
|
|
77302
77339
|
if (isControlled && onUpdate) {
|
|
77303
77340
|
await onUpdate({ ...currentItem, ...formState });
|
|
77304
77341
|
} else {
|
|
77305
|
-
MetadataService.updateLearningObjective(
|
|
77342
|
+
MetadataService.updateLearningObjective(
|
|
77343
|
+
currentItem.id,
|
|
77344
|
+
formState
|
|
77345
|
+
);
|
|
77306
77346
|
refreshData();
|
|
77307
77347
|
}
|
|
77308
|
-
toast2({
|
|
77348
|
+
toast2({
|
|
77349
|
+
title: "Success",
|
|
77350
|
+
description: "Learning Objective updated."
|
|
77351
|
+
});
|
|
77309
77352
|
} else {
|
|
77310
77353
|
if (isControlled && onAdd) {
|
|
77311
77354
|
await onAdd(formState);
|
|
77312
77355
|
} else {
|
|
77313
|
-
MetadataService.addLearningObjective(
|
|
77356
|
+
MetadataService.addLearningObjective(
|
|
77357
|
+
formState
|
|
77358
|
+
);
|
|
77314
77359
|
refreshData();
|
|
77315
77360
|
}
|
|
77316
|
-
toast2({
|
|
77361
|
+
toast2({
|
|
77362
|
+
title: "Success",
|
|
77363
|
+
description: "Learning Objective added."
|
|
77364
|
+
});
|
|
77317
77365
|
}
|
|
77318
77366
|
setIsDialogOpen(false);
|
|
77319
77367
|
} catch (error) {
|
|
77320
|
-
toast2({
|
|
77368
|
+
toast2({
|
|
77369
|
+
title: "Error",
|
|
77370
|
+
description: error.message,
|
|
77371
|
+
variant: "destructive"
|
|
77372
|
+
});
|
|
77321
77373
|
}
|
|
77322
77374
|
});
|
|
77323
77375
|
};
|
|
77324
77376
|
const handleImport = async (records) => {
|
|
77377
|
+
console.log(
|
|
77378
|
+
`[LO Manager] handleImport called with ${records.length} raw records.`
|
|
77379
|
+
);
|
|
77380
|
+
if (!onBulkAdd) {
|
|
77381
|
+
console.error("[LO Manager] onBulkAdd handler is not provided.");
|
|
77382
|
+
return;
|
|
77383
|
+
}
|
|
77384
|
+
const parseStringToArray = (input) => {
|
|
77385
|
+
if (Array.isArray(input)) return input;
|
|
77386
|
+
if (typeof input === "string")
|
|
77387
|
+
return input.split(",").map((s2) => s2.trim()).filter(Boolean);
|
|
77388
|
+
return [];
|
|
77389
|
+
};
|
|
77390
|
+
const validationResult = records.reduce(
|
|
77391
|
+
(acc, rec) => {
|
|
77392
|
+
if (typeof rec["LO ID"] === "string" && rec["LO ID"].trim() && typeof rec["LO Description"] === "string" && rec["LO Description"].trim()) {
|
|
77393
|
+
acc.valid.push({
|
|
77394
|
+
code: rec["LO ID"],
|
|
77395
|
+
name: rec["LO ID"],
|
|
77396
|
+
description: rec["LO Description"],
|
|
77397
|
+
subject: rec["Subject"] || "",
|
|
77398
|
+
subjectCode: rec["Subject Code"] || rec["Subject"],
|
|
77399
|
+
category: rec["Category"] || "",
|
|
77400
|
+
categoryCode: rec["Category Code"] || rec["Category"],
|
|
77401
|
+
topic: rec["Topic"] || "",
|
|
77402
|
+
topicCode: rec["Topic Code"] || rec["Topic"],
|
|
77403
|
+
grade: rec["Grade"] || "",
|
|
77404
|
+
gradeCode: rec["Grade Code"] || rec["Grade"],
|
|
77405
|
+
keywords: parseStringToArray(rec["Keywords"]),
|
|
77406
|
+
stemElements: parseStringToArray(
|
|
77407
|
+
rec["STEM Element(s)"]
|
|
77408
|
+
),
|
|
77409
|
+
bloomLevelsGuideline: parseStringToArray(
|
|
77410
|
+
rec["Bloom\u2019s Level(s) Guideline"]
|
|
77411
|
+
)
|
|
77412
|
+
});
|
|
77413
|
+
} else {
|
|
77414
|
+
acc.invalidCount++;
|
|
77415
|
+
}
|
|
77416
|
+
return acc;
|
|
77417
|
+
},
|
|
77418
|
+
{ valid: [], invalidCount: 0 }
|
|
77419
|
+
);
|
|
77420
|
+
console.log(
|
|
77421
|
+
`[LO Manager] Validation complete. ${validationResult.valid.length} valid records found.`
|
|
77422
|
+
);
|
|
77423
|
+
if (validationResult.invalidCount > 0) {
|
|
77424
|
+
toast2({
|
|
77425
|
+
title: "Import Warning",
|
|
77426
|
+
description: `${validationResult.invalidCount} records had invalid or missing 'LO ID' or 'LO Description' fields and were ignored.`,
|
|
77427
|
+
variant: "destructive"
|
|
77428
|
+
});
|
|
77429
|
+
}
|
|
77430
|
+
if (validationResult.valid.length > 0) {
|
|
77431
|
+
console.log(
|
|
77432
|
+
"[LO Manager] Calling onBulkAdd prop with validated data..."
|
|
77433
|
+
);
|
|
77434
|
+
await onBulkAdd(validationResult.valid);
|
|
77435
|
+
} else {
|
|
77436
|
+
console.log("[LO Manager] No valid records to import.");
|
|
77437
|
+
}
|
|
77325
77438
|
};
|
|
77326
|
-
return /* @__PURE__ */ React119__default.createElement(Card, null, /* @__PURE__ */ React119__default.createElement(CardHeader, null, /* @__PURE__ */ React119__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React119__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React119__default.createElement(Lightbulb, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Learning Objectives"), /* @__PURE__ */ React119__default.createElement("div", { className: "flex items-center gap-2" }, onBulkAdd && /* @__PURE__ */ React119__default.createElement(MetadataImportControls, { metadataName: "Learning Objectives", onImport: handleImport }), /* @__PURE__ */ React119__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React119__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Learning Objective")))), /* @__PURE__ */ React119__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React119__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React119__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React119__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No Learning Objectives found.") : /* @__PURE__ */ React119__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React119__default.createElement(Table2, null, /* @__PURE__ */ React119__default.createElement(TableHeader, null, /* @__PURE__ */ React119__default.createElement(TableRow, null, /* @__PURE__ */ React119__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React119__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React119__default.createElement(TableHead, null, "Subject"), /* @__PURE__ */ React119__default.createElement(TableHead, null, "Topic"), /* @__PURE__ */ React119__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React119__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React119__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React119__default.createElement(TableCell, { className: "font-mono text-xs" }, item.code), /* @__PURE__ */ React119__default.createElement(TableCell, { className: "font-medium" }, item.name), /* @__PURE__ */ React119__default.createElement(TableCell, null, item.subject || item.subjectCode), /* @__PURE__ */ React119__default.createElement(TableCell, null, item.topic || item.topicCode), /* @__PURE__ */ React119__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React119__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React119__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React119__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React119__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React119__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React119__default.createElement(DialogContent2, { className: "sm:max-w-2xl max-h-[90vh] overflow-y-auto" }, /* @__PURE__ */ React119__default.createElement(DialogHeader, null, /* @__PURE__ */ React119__default.createElement(DialogTitle2, null, currentItem ? "Edit Learning Objective" : "Add New Learning Objective")), /* @__PURE__ */ React119__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "code" }, "Code"), /* @__PURE__ */ React119__default.createElement(Input, { id: "code", value: formState.code || "", onChange: (e2) => handleFormChange("code", e2.target.value.toUpperCase()), disabled: !!currentItem })), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "name" }, "Name (Description)"), /* @__PURE__ */ React119__default.createElement(Input, { id: "name", value: formState.name || "", onChange: (e2) => handleFormChange("name", e2.target.value) }))), /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "subject" }, "Subject Name"), /* @__PURE__ */ React119__default.createElement(Input, { id: "subject", value: formState.subject || "", onChange: (e2) => handleFormChange("subject", e2.target.value) })), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "subjectCode" }, "Subject Code"), /* @__PURE__ */ React119__default.createElement(EditableCombobox, { options: subjects.map((s2) => ({ value: s2.code, label: s2.name })), value: formState.subjectCode || "", onChange: (val) => handleFormChange("subjectCode", val), placeholder: "Select a subject..." }))), /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "category" }, "Category Name"), /* @__PURE__ */ React119__default.createElement(Input, { id: "category", value: formState.category || "", onChange: (e2) => handleFormChange("category", e2.target.value) })), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "categoryCode" }, "Category Code"), /* @__PURE__ */ React119__default.createElement(Input, { id: "categoryCode", value: formState.categoryCode || "", onChange: (e2) => handleFormChange("categoryCode", e2.target.value) }))), /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "topic" }, "Topic Name"), /* @__PURE__ */ React119__default.createElement(Input, { id: "topic", value: formState.topic || "", onChange: (e2) => handleFormChange("topic", e2.target.value) })), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "topicCode" }, "Topic Code"), /* @__PURE__ */ React119__default.createElement(Input, { id: "topicCode", value: formState.topicCode || "", onChange: (e2) => handleFormChange("topicCode", e2.target.value) }))), /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "grade" }, "Grade Name"), /* @__PURE__ */ React119__default.createElement(Input, { id: "grade", value: formState.grade || "", onChange: (e2) => handleFormChange("grade", e2.target.value) })), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "gradeCode" }, "Grade Code"), /* @__PURE__ */ React119__default.createElement(Input, { id: "gradeCode", value: formState.gradeCode || "", onChange: (e2) => handleFormChange("gradeCode", e2.target.value) }))), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "keywords" }, "Keywords (comma-separated)"), /* @__PURE__ */ React119__default.createElement(Textarea, { id: "keywords", value: formState.keywords?.join(", ") || "", onChange: (e2) => handleFormChange("keywords", e2.target.value.split(",").map((s2) => s2.trim())) })), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "stemElements" }, "STEM Elements (comma-separated)"), /* @__PURE__ */ React119__default.createElement(Textarea, { id: "stemElements", value: formState.stemElements?.join(", ") || "", onChange: (e2) => handleFormChange("stemElements", e2.target.value.split(",").map((s2) => s2.trim())) })), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "bloomLevelsGuideline" }, "Bloom's Guideline (comma-separated)"), /* @__PURE__ */ React119__default.createElement(Textarea, { id: "bloomLevelsGuideline", value: formState.bloomLevelsGuideline?.join(", ") || "", onChange: (e2) => handleFormChange("bloomLevelsGuideline", e2.target.value.split(",").map((s2) => s2.trim())) }))), /* @__PURE__ */ React119__default.createElement(DialogFooter, null, /* @__PURE__ */ React119__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React119__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending || !formState.name?.trim() || !formState.code?.trim() }, isPending && /* @__PURE__ */ React119__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Save")))), /* @__PURE__ */ React119__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React119__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React119__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React119__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React119__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.name, '".')), /* @__PURE__ */ React119__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React119__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React119__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React119__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Delete"))))));
|
|
77439
|
+
return /* @__PURE__ */ React119__default.createElement(Card, null, /* @__PURE__ */ React119__default.createElement(CardHeader, null, /* @__PURE__ */ React119__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React119__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React119__default.createElement(Lightbulb, { className: "mr-2 h-5 w-5 text-primary" }), " ", "Manage Learning Objectives"), /* @__PURE__ */ React119__default.createElement("div", { className: "flex items-center gap-2" }, onBulkAdd && /* @__PURE__ */ React119__default.createElement(
|
|
77440
|
+
MetadataImportControls,
|
|
77441
|
+
{
|
|
77442
|
+
metadataName: "Learning Objectives",
|
|
77443
|
+
onImport: handleImport
|
|
77444
|
+
}
|
|
77445
|
+
), /* @__PURE__ */ React119__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React119__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Learning Objective")))), /* @__PURE__ */ React119__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React119__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React119__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React119__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No Learning Objectives found.") : /* @__PURE__ */ React119__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React119__default.createElement(Table2, null, /* @__PURE__ */ React119__default.createElement(TableHeader, null, /* @__PURE__ */ React119__default.createElement(TableRow, null, /* @__PURE__ */ React119__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React119__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React119__default.createElement(TableHead, null, "Subject"), /* @__PURE__ */ React119__default.createElement(TableHead, null, "Topic"), /* @__PURE__ */ React119__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React119__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React119__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React119__default.createElement(TableCell, { className: "font-mono text-xs" }, item.code), /* @__PURE__ */ React119__default.createElement(TableCell, { className: "font-medium" }, item.name), /* @__PURE__ */ React119__default.createElement(TableCell, null, item.subject || item.subjectCode), /* @__PURE__ */ React119__default.createElement(TableCell, null, item.topic || item.topicCode), /* @__PURE__ */ React119__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React119__default.createElement(
|
|
77446
|
+
Button,
|
|
77447
|
+
{
|
|
77448
|
+
variant: "ghost",
|
|
77449
|
+
size: "icon",
|
|
77450
|
+
onClick: () => handleEditItem(item),
|
|
77451
|
+
className: "mr-2"
|
|
77452
|
+
},
|
|
77453
|
+
/* @__PURE__ */ React119__default.createElement(PenLine, { className: "h-4 w-4" })
|
|
77454
|
+
), /* @__PURE__ */ React119__default.createElement(
|
|
77455
|
+
Button,
|
|
77456
|
+
{
|
|
77457
|
+
variant: "ghost",
|
|
77458
|
+
size: "icon",
|
|
77459
|
+
onClick: () => handleDeleteItem(item),
|
|
77460
|
+
className: "text-destructive hover:text-destructive"
|
|
77461
|
+
},
|
|
77462
|
+
/* @__PURE__ */ React119__default.createElement(Trash2, { className: "h-4 w-4" })
|
|
77463
|
+
))))))), /* @__PURE__ */ React119__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React119__default.createElement(DialogContent2, { className: "sm:max-w-2xl max-h-[90vh] overflow-y-auto" }, /* @__PURE__ */ React119__default.createElement(DialogHeader, null, /* @__PURE__ */ React119__default.createElement(DialogTitle2, null, currentItem ? "Edit Learning Objective" : "Add New Learning Objective")), /* @__PURE__ */ React119__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "code" }, "Code"), /* @__PURE__ */ React119__default.createElement(
|
|
77464
|
+
Input,
|
|
77465
|
+
{
|
|
77466
|
+
id: "code",
|
|
77467
|
+
value: formState.code || "",
|
|
77468
|
+
onChange: (e2) => handleFormChange(
|
|
77469
|
+
"code",
|
|
77470
|
+
e2.target.value.toUpperCase()
|
|
77471
|
+
),
|
|
77472
|
+
disabled: !!currentItem
|
|
77473
|
+
}
|
|
77474
|
+
)), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "name" }, "Name (Description)"), /* @__PURE__ */ React119__default.createElement(
|
|
77475
|
+
Input,
|
|
77476
|
+
{
|
|
77477
|
+
id: "name",
|
|
77478
|
+
value: formState.name || "",
|
|
77479
|
+
onChange: (e2) => handleFormChange(
|
|
77480
|
+
"name",
|
|
77481
|
+
e2.target.value
|
|
77482
|
+
)
|
|
77483
|
+
}
|
|
77484
|
+
))), /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "subject" }, "Subject Name"), /* @__PURE__ */ React119__default.createElement(
|
|
77485
|
+
Input,
|
|
77486
|
+
{
|
|
77487
|
+
id: "subject",
|
|
77488
|
+
value: formState.subject || "",
|
|
77489
|
+
onChange: (e2) => handleFormChange(
|
|
77490
|
+
"subject",
|
|
77491
|
+
e2.target.value
|
|
77492
|
+
)
|
|
77493
|
+
}
|
|
77494
|
+
)), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "subjectCode" }, "Subject Code"), /* @__PURE__ */ React119__default.createElement(
|
|
77495
|
+
EditableCombobox,
|
|
77496
|
+
{
|
|
77497
|
+
options: subjects.map((s2) => ({
|
|
77498
|
+
value: s2.code,
|
|
77499
|
+
label: s2.name
|
|
77500
|
+
})),
|
|
77501
|
+
value: formState.subjectCode || "",
|
|
77502
|
+
onChange: (val) => handleFormChange("subjectCode", val),
|
|
77503
|
+
placeholder: "Select a subject..."
|
|
77504
|
+
}
|
|
77505
|
+
))), /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "category" }, "Category Name"), /* @__PURE__ */ React119__default.createElement(
|
|
77506
|
+
Input,
|
|
77507
|
+
{
|
|
77508
|
+
id: "category",
|
|
77509
|
+
value: formState.category || "",
|
|
77510
|
+
onChange: (e2) => handleFormChange(
|
|
77511
|
+
"category",
|
|
77512
|
+
e2.target.value
|
|
77513
|
+
)
|
|
77514
|
+
}
|
|
77515
|
+
)), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "categoryCode" }, "Category Code"), /* @__PURE__ */ React119__default.createElement(
|
|
77516
|
+
Input,
|
|
77517
|
+
{
|
|
77518
|
+
id: "categoryCode",
|
|
77519
|
+
value: formState.categoryCode || "",
|
|
77520
|
+
onChange: (e2) => handleFormChange(
|
|
77521
|
+
"categoryCode",
|
|
77522
|
+
e2.target.value
|
|
77523
|
+
)
|
|
77524
|
+
}
|
|
77525
|
+
))), /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "topic" }, "Topic Name"), /* @__PURE__ */ React119__default.createElement(
|
|
77526
|
+
Input,
|
|
77527
|
+
{
|
|
77528
|
+
id: "topic",
|
|
77529
|
+
value: formState.topic || "",
|
|
77530
|
+
onChange: (e2) => handleFormChange(
|
|
77531
|
+
"topic",
|
|
77532
|
+
e2.target.value
|
|
77533
|
+
)
|
|
77534
|
+
}
|
|
77535
|
+
)), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "topicCode" }, "Topic Code"), /* @__PURE__ */ React119__default.createElement(
|
|
77536
|
+
Input,
|
|
77537
|
+
{
|
|
77538
|
+
id: "topicCode",
|
|
77539
|
+
value: formState.topicCode || "",
|
|
77540
|
+
onChange: (e2) => handleFormChange(
|
|
77541
|
+
"topicCode",
|
|
77542
|
+
e2.target.value
|
|
77543
|
+
)
|
|
77544
|
+
}
|
|
77545
|
+
))), /* @__PURE__ */ React119__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "grade" }, "Grade Name"), /* @__PURE__ */ React119__default.createElement(
|
|
77546
|
+
Input,
|
|
77547
|
+
{
|
|
77548
|
+
id: "grade",
|
|
77549
|
+
value: formState.grade || "",
|
|
77550
|
+
onChange: (e2) => handleFormChange(
|
|
77551
|
+
"grade",
|
|
77552
|
+
e2.target.value
|
|
77553
|
+
)
|
|
77554
|
+
}
|
|
77555
|
+
)), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "gradeCode" }, "Grade Code"), /* @__PURE__ */ React119__default.createElement(
|
|
77556
|
+
Input,
|
|
77557
|
+
{
|
|
77558
|
+
id: "gradeCode",
|
|
77559
|
+
value: formState.gradeCode || "",
|
|
77560
|
+
onChange: (e2) => handleFormChange(
|
|
77561
|
+
"gradeCode",
|
|
77562
|
+
e2.target.value
|
|
77563
|
+
)
|
|
77564
|
+
}
|
|
77565
|
+
))), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "keywords" }, "Keywords (comma-separated)"), /* @__PURE__ */ React119__default.createElement(
|
|
77566
|
+
Textarea,
|
|
77567
|
+
{
|
|
77568
|
+
id: "keywords",
|
|
77569
|
+
value: formState.keywords?.join(", ") || "",
|
|
77570
|
+
onChange: (e2) => handleFormChange(
|
|
77571
|
+
"keywords",
|
|
77572
|
+
e2.target.value.split(",").map((s2) => s2.trim())
|
|
77573
|
+
)
|
|
77574
|
+
}
|
|
77575
|
+
)), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "stemElements" }, "STEM Elements (comma-separated)"), /* @__PURE__ */ React119__default.createElement(
|
|
77576
|
+
Textarea,
|
|
77577
|
+
{
|
|
77578
|
+
id: "stemElements",
|
|
77579
|
+
value: formState.stemElements?.join(", ") || "",
|
|
77580
|
+
onChange: (e2) => handleFormChange(
|
|
77581
|
+
"stemElements",
|
|
77582
|
+
e2.target.value.split(",").map((s2) => s2.trim())
|
|
77583
|
+
)
|
|
77584
|
+
}
|
|
77585
|
+
)), /* @__PURE__ */ React119__default.createElement("div", null, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "bloomLevelsGuideline" }, "Bloom's Guideline (comma-separated)"), /* @__PURE__ */ React119__default.createElement(
|
|
77586
|
+
Textarea,
|
|
77587
|
+
{
|
|
77588
|
+
id: "bloomLevelsGuideline",
|
|
77589
|
+
value: formState.bloomLevelsGuideline?.join(
|
|
77590
|
+
", "
|
|
77591
|
+
) || "",
|
|
77592
|
+
onChange: (e2) => handleFormChange(
|
|
77593
|
+
"bloomLevelsGuideline",
|
|
77594
|
+
e2.target.value.split(",").map((s2) => s2.trim())
|
|
77595
|
+
)
|
|
77596
|
+
}
|
|
77597
|
+
))), /* @__PURE__ */ React119__default.createElement(DialogFooter, null, /* @__PURE__ */ React119__default.createElement(
|
|
77598
|
+
Button,
|
|
77599
|
+
{
|
|
77600
|
+
type: "button",
|
|
77601
|
+
variant: "outline",
|
|
77602
|
+
onClick: () => setIsDialogOpen(false),
|
|
77603
|
+
disabled: isPending
|
|
77604
|
+
},
|
|
77605
|
+
"Cancel"
|
|
77606
|
+
), /* @__PURE__ */ React119__default.createElement(
|
|
77607
|
+
Button,
|
|
77608
|
+
{
|
|
77609
|
+
type: "submit",
|
|
77610
|
+
onClick: handleSubmit,
|
|
77611
|
+
disabled: isPending || !formState.name?.trim() || !formState.code?.trim()
|
|
77612
|
+
},
|
|
77613
|
+
isPending && /* @__PURE__ */ React119__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }),
|
|
77614
|
+
" ",
|
|
77615
|
+
"Save"
|
|
77616
|
+
)))), /* @__PURE__ */ React119__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React119__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React119__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React119__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React119__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.name, '".')), /* @__PURE__ */ React119__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React119__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React119__default.createElement(
|
|
77617
|
+
AlertDialogAction2,
|
|
77618
|
+
{
|
|
77619
|
+
onClick: confirmDelete,
|
|
77620
|
+
disabled: isPending,
|
|
77621
|
+
className: "bg-destructive hover:bg-destructive/90"
|
|
77622
|
+
},
|
|
77623
|
+
isPending && /* @__PURE__ */ React119__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }),
|
|
77624
|
+
" ",
|
|
77625
|
+
"Delete"
|
|
77626
|
+
))))));
|
|
77327
77627
|
}
|
|
77328
77628
|
|
|
77329
77629
|
// src/react-ui/components/metadata/ContextManager.tsx
|