@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.
@@ -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
- await onImport(records);
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({ initialData, subjects: subjectsProp, isLoading: isLoadingProp, onAdd, onUpdate, onDelete, onBulkAdd }) {
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(null);
77246
+ const [currentItem, setCurrentItem] = useState(
77247
+ null
77248
+ );
77231
77249
  const [formState, setFormState] = useState({});
77232
- const [itemToDelete, setItemToDelete] = useState(null);
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({ title: "Error", description: "Failed to refresh data.", variant: "destructive" });
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({ subjectCode: subjects.length > 0 ? subjects[0].code : "" });
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({ title: "Success", description: `Learning Objective "${itemToDelete.name}" deleted.` });
77311
+ toast2({
77312
+ title: "Success",
77313
+ description: `Learning Objective "${itemToDelete.name}" deleted.`
77314
+ });
77286
77315
  } catch (error) {
77287
- toast2({ title: "Error", description: error.message, variant: "destructive" });
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({ title: "Validation Error", description: "Code and Name are required.", variant: "destructive" });
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(currentItem.id, formState);
77342
+ MetadataService.updateLearningObjective(
77343
+ currentItem.id,
77344
+ formState
77345
+ );
77306
77346
  refreshData();
77307
77347
  }
77308
- toast2({ title: "Success", description: "Learning Objective updated." });
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(formState);
77356
+ MetadataService.addLearningObjective(
77357
+ formState
77358
+ );
77314
77359
  refreshData();
77315
77360
  }
77316
- toast2({ title: "Success", description: "Learning Objective added." });
77361
+ toast2({
77362
+ title: "Success",
77363
+ description: "Learning Objective added."
77364
+ });
77317
77365
  }
77318
77366
  setIsDialogOpen(false);
77319
77367
  } catch (error) {
77320
- toast2({ title: "Error", description: error.message, variant: "destructive" });
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