@thanh01.pmt/interactive-quiz-kit 1.0.51 → 1.0.52

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.
@@ -105623,7 +105623,7 @@ function SubjectManager({
105623
105623
 
105624
105624
  // src/react-ui/components/metadata/GradeLevelManager.tsx
105625
105625
  init_react_shim();
105626
- function GradeLevelManager() {
105626
+ function GradeLevelManager({ initialData, isLoading: isLoadingProp, onAdd, onUpdate, onDelete }) {
105627
105627
  const [items, setItems] = useState([]);
105628
105628
  const [isLoading, setIsLoading] = useState(true);
105629
105629
  const [isDialogOpen, setIsDialogOpen] = useState(false);
@@ -105634,19 +105634,27 @@ function GradeLevelManager() {
105634
105634
  const [itemToDelete, setItemToDelete] = useState(null);
105635
105635
  const [isPending, startTransition] = useTransition();
105636
105636
  const { toast: toast2 } = useToast();
105637
- useEffect(() => {
105638
- fetchItems();
105639
- }, []);
105640
- const fetchItems = () => {
105641
- setIsLoading(true);
105642
- try {
105643
- setItems(MetadataService.getGradeLevels());
105644
- } catch (error) {
105645
- toast2({ title: "Error", description: "Failed to fetch grade levels.", variant: "destructive" });
105646
- } finally {
105647
- setIsLoading(false);
105637
+ const isControlled = initialData !== void 0;
105638
+ const refreshData = () => {
105639
+ if (!isControlled) {
105640
+ setIsLoading(true);
105641
+ try {
105642
+ setItems(MetadataService.getGradeLevels());
105643
+ } catch (error) {
105644
+ toast2({ title: "Error", description: "Failed to refresh grade levels.", variant: "destructive" });
105645
+ } finally {
105646
+ setIsLoading(false);
105647
+ }
105648
105648
  }
105649
105649
  };
105650
+ useEffect(() => {
105651
+ if (isControlled) {
105652
+ setItems(initialData || []);
105653
+ setIsLoading(isLoadingProp || false);
105654
+ } else {
105655
+ refreshData();
105656
+ }
105657
+ }, [isControlled, initialData, isLoadingProp]);
105650
105658
  const handleAddItem = () => {
105651
105659
  setCurrentItem(null);
105652
105660
  setItemName("");
@@ -105665,13 +105673,17 @@ function GradeLevelManager() {
105665
105673
  };
105666
105674
  const confirmDelete = () => {
105667
105675
  if (!itemToDelete) return;
105668
- startTransition(() => {
105676
+ startTransition(async () => {
105669
105677
  try {
105670
- MetadataService.deleteGradeLevel(itemToDelete.code);
105678
+ if (isControlled && onDelete) {
105679
+ await onDelete(itemToDelete);
105680
+ } else {
105681
+ MetadataService.deleteGradeLevel(itemToDelete.code);
105682
+ refreshData();
105683
+ }
105671
105684
  toast2({ title: "Success", description: `Grade Level "${itemToDelete.name}" deleted.` });
105672
- fetchItems();
105673
105685
  } catch (error) {
105674
- toast2({ title: "Error", description: "Failed to delete grade level.", variant: "destructive" });
105686
+ toast2({ title: "Error", description: error.message, variant: "destructive" });
105675
105687
  } finally {
105676
105688
  setIsAlertOpen(false);
105677
105689
  setItemToDelete(null);
@@ -105683,27 +105695,44 @@ function GradeLevelManager() {
105683
105695
  toast2({ title: "Validation Error", description: "Code and Name are required.", variant: "destructive" });
105684
105696
  return;
105685
105697
  }
105686
- startTransition(() => {
105698
+ startTransition(async () => {
105687
105699
  try {
105688
105700
  if (currentItem) {
105689
- MetadataService.updateGradeLevel(currentItem.id, itemName, itemCode);
105701
+ if (isControlled && onUpdate) {
105702
+ await onUpdate({ id: currentItem.id, name: itemName, code: itemCode });
105703
+ } else {
105704
+ MetadataService.updateGradeLevel(currentItem.id, itemName, itemCode);
105705
+ refreshData();
105706
+ }
105707
+ toast2({ title: "Success", description: "Grade Level updated." });
105690
105708
  } else {
105691
- MetadataService.addGradeLevel(itemName, itemCode);
105709
+ if (isControlled && onAdd) {
105710
+ await onAdd({ name: itemName, code: itemCode });
105711
+ } else {
105712
+ MetadataService.addGradeLevel(itemName, itemCode);
105713
+ refreshData();
105714
+ }
105715
+ toast2({ title: "Success", description: "Grade Level added." });
105692
105716
  }
105693
- toast2({ title: "Success", description: `Grade Level saved.` });
105694
- fetchItems();
105695
105717
  setIsDialogOpen(false);
105696
105718
  } catch (error) {
105697
- toast2({ title: "Error", description: "Failed to save grade level.", variant: "destructive" });
105719
+ toast2({ title: "Error", description: error.message, variant: "destructive" });
105698
105720
  }
105699
105721
  });
105700
105722
  };
105701
- return /* @__PURE__ */ React97__default.createElement(Card, null, /* @__PURE__ */ React97__default.createElement(CardHeader, null, /* @__PURE__ */ React97__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React97__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React97__default.createElement(Award, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Grade Levels"), /* @__PURE__ */ React97__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React97__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Grade Level"))), /* @__PURE__ */ React97__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React97__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React97__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No grade levels found.") : /* @__PURE__ */ React97__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React97__default.createElement(Table2, null, /* @__PURE__ */ React97__default.createElement(TableHeader, null, /* @__PURE__ */ React97__default.createElement(TableRow, null, /* @__PURE__ */ React97__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React97__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React97__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React97__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-mono text-xs" }, item.code), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-medium" }, item.name), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React97__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React97__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React97__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React97__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React97__default.createElement(DialogHeader, null, /* @__PURE__ */ React97__default.createElement(DialogTitle2, null, currentItem ? "Edit Grade Level" : "Add New Grade Level")), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemCode" }, "Code"), /* @__PURE__ */ React97__default.createElement(Input, { id: "itemCode", value: itemCode, onChange: (e2) => setItemCode(e2.target.value.toUpperCase()), placeholder: "e.g., G9", disabled: !!currentItem })), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemName" }, "Name"), /* @__PURE__ */ React97__default.createElement(Input, { id: "itemName", value: itemName, onChange: (e2) => setItemName(e2.target.value), placeholder: "e.g., Grade 9" }))), /* @__PURE__ */ React97__default.createElement(DialogFooter, null, /* @__PURE__ */ React97__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending || !itemName.trim() || !itemCode.trim() }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), "Save")))), /* @__PURE__ */ React97__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React97__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React97__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React97__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React97__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.name, '".')), /* @__PURE__ */ React97__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React97__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), "Delete"))))));
105723
+ return /* @__PURE__ */ React97__default.createElement(Card, null, /* @__PURE__ */ React97__default.createElement(CardHeader, null, /* @__PURE__ */ React97__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React97__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React97__default.createElement(Award, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Grade Levels"), /* @__PURE__ */ React97__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React97__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Grade Level"))), /* @__PURE__ */ React97__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React97__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React97__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No grade levels found.") : /* @__PURE__ */ React97__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React97__default.createElement(Table2, null, /* @__PURE__ */ React97__default.createElement(TableHeader, null, /* @__PURE__ */ React97__default.createElement(TableRow, null, /* @__PURE__ */ React97__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React97__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React97__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React97__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-mono text-xs" }, item.code), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-medium" }, item.name), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React97__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React97__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React97__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React97__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React97__default.createElement(DialogHeader, null, /* @__PURE__ */ React97__default.createElement(DialogTitle2, null, currentItem ? "Edit Grade Level" : "Add New Grade Level")), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemCode" }, "Code"), /* @__PURE__ */ React97__default.createElement(Input, { id: "itemCode", value: itemCode, onChange: (e2) => setItemCode(e2.target.value.toUpperCase()), placeholder: "e.g., G9", disabled: !!currentItem })), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemName" }, "Name"), /* @__PURE__ */ React97__default.createElement(Input, { id: "itemName", value: itemName, onChange: (e2) => setItemName(e2.target.value), placeholder: "e.g., Grade 9" }))), /* @__PURE__ */ React97__default.createElement(DialogFooter, null, /* @__PURE__ */ React97__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending || !itemName.trim() || !itemCode.trim() }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Save")))), /* @__PURE__ */ React97__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React97__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React97__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React97__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React97__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.name, '".')), /* @__PURE__ */ React97__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React97__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Delete"))))));
105702
105724
  }
105703
105725
 
105704
105726
  // src/react-ui/components/metadata/TopicManager.tsx
105705
105727
  init_react_shim();
105706
- function TopicManager() {
105728
+ function TopicManager({
105729
+ initialData,
105730
+ subjects: subjectsProp,
105731
+ isLoading: isLoadingProp,
105732
+ onAdd,
105733
+ onUpdate,
105734
+ onDelete
105735
+ }) {
105707
105736
  const [topics, setTopics] = useState([]);
105708
105737
  const [subjects, setSubjects] = useState([]);
105709
105738
  const [isLoading, setIsLoading] = useState(true);
@@ -105716,36 +105745,34 @@ function TopicManager() {
105716
105745
  const [itemToDelete, setItemToDelete] = useState(null);
105717
105746
  const [isPending, startTransition] = useTransition();
105718
105747
  const { toast: toast2 } = useToast();
105719
- const fetchData = () => {
105720
- setIsLoading(true);
105721
- try {
105722
- const topicsData = MetadataService.getTopics();
105723
- const subjectsData = MetadataService.getSubjects();
105724
- setTopics(topicsData);
105725
- setSubjects(subjectsData);
105726
- if (subjectsData.length > 0 && !selectedSubjectCode) {
105727
- setSelectedSubjectCode(subjectsData[0].code);
105748
+ const isControlled = initialData !== void 0;
105749
+ const refreshData = () => {
105750
+ if (!isControlled) {
105751
+ setIsLoading(true);
105752
+ try {
105753
+ setTopics(MetadataService.getTopics());
105754
+ setSubjects(MetadataService.getSubjects());
105755
+ } catch (error) {
105756
+ toast2({ title: "Error", description: "Failed to refresh topics or subjects.", variant: "destructive" });
105757
+ } finally {
105758
+ setIsLoading(false);
105728
105759
  }
105729
- } catch (error) {
105730
- toast2({
105731
- title: "Error",
105732
- description: "Failed to fetch topics or subjects.",
105733
- variant: "destructive"
105734
- });
105735
- } finally {
105736
- setIsLoading(false);
105737
105760
  }
105738
105761
  };
105739
105762
  useEffect(() => {
105740
- fetchData();
105741
- }, []);
105763
+ if (isControlled) {
105764
+ setTopics(initialData || []);
105765
+ setSubjects(subjectsProp || []);
105766
+ setIsLoading(isLoadingProp || false);
105767
+ } else {
105768
+ refreshData();
105769
+ }
105770
+ }, [isControlled, initialData, subjectsProp, isLoadingProp]);
105742
105771
  const handleAddItem = () => {
105743
105772
  setCurrentItem(null);
105744
105773
  setItemName("");
105745
105774
  setItemCode("");
105746
- if (subjects.length > 0) {
105747
- setSelectedSubjectCode(subjects[0].code);
105748
- }
105775
+ setSelectedSubjectCode(subjects.length > 0 ? subjects[0].code : "");
105749
105776
  setIsDialogOpen(true);
105750
105777
  };
105751
105778
  const handleEditItem = (topic) => {
@@ -105761,20 +105788,17 @@ function TopicManager() {
105761
105788
  };
105762
105789
  const confirmDelete = () => {
105763
105790
  if (!itemToDelete) return;
105764
- startTransition(() => {
105791
+ startTransition(async () => {
105765
105792
  try {
105766
- MetadataService.deleteTopic(itemToDelete.code);
105767
- toast2({
105768
- title: "Success",
105769
- description: `Topic "${itemToDelete.name}" deleted.`
105770
- });
105771
- fetchData();
105793
+ if (isControlled && onDelete) {
105794
+ await onDelete(itemToDelete);
105795
+ } else {
105796
+ MetadataService.deleteTopic(itemToDelete.code);
105797
+ refreshData();
105798
+ }
105799
+ toast2({ title: "Success", description: `Topic "${itemToDelete.name}" deleted.` });
105772
105800
  } catch (error) {
105773
- toast2({
105774
- title: "Error",
105775
- description: "Failed to delete topic.",
105776
- variant: "destructive"
105777
- });
105801
+ toast2({ title: "Error", description: error.message, variant: "destructive" });
105778
105802
  } finally {
105779
105803
  setIsAlertOpen(false);
105780
105804
  setItemToDelete(null);
@@ -105783,144 +105807,43 @@ function TopicManager() {
105783
105807
  };
105784
105808
  const handleSubmit = () => {
105785
105809
  if (!itemName.trim() || !itemCode.trim() || !selectedSubjectCode) {
105786
- toast2({
105787
- title: "Validation Error",
105788
- description: "Name, Code, and Subject are required.",
105789
- variant: "destructive"
105790
- });
105810
+ toast2({ title: "Validation Error", description: "Name, Code, and Subject are required.", variant: "destructive" });
105791
105811
  return;
105792
105812
  }
105793
- startTransition(() => {
105813
+ startTransition(async () => {
105794
105814
  try {
105795
105815
  if (currentItem) {
105796
- MetadataService.updateTopic(
105797
- currentItem.id,
105798
- itemName,
105799
- itemCode,
105800
- selectedSubjectCode
105801
- );
105816
+ if (isControlled && onUpdate) {
105817
+ await onUpdate({ id: currentItem.id, name: itemName, code: itemCode, subjectCode: selectedSubjectCode });
105818
+ } else {
105819
+ MetadataService.updateTopic(currentItem.id, itemName, itemCode, selectedSubjectCode);
105820
+ refreshData();
105821
+ }
105822
+ toast2({ title: "Success", description: "Topic updated." });
105802
105823
  } else {
105803
- MetadataService.addTopic(
105804
- itemName,
105805
- itemCode,
105806
- selectedSubjectCode
105807
- );
105824
+ if (isControlled && onAdd) {
105825
+ await onAdd({ name: itemName, code: itemCode, subjectCode: selectedSubjectCode });
105826
+ } else {
105827
+ MetadataService.addTopic(itemName, itemCode, selectedSubjectCode);
105828
+ refreshData();
105829
+ }
105830
+ toast2({ title: "Success", description: "Topic added." });
105808
105831
  }
105809
- toast2({ title: "Success", description: "Topic saved." });
105810
- fetchData();
105811
105832
  setIsDialogOpen(false);
105812
105833
  } catch (error) {
105813
- toast2({
105814
- title: "Error",
105815
- description: "Failed to save topic.",
105816
- variant: "destructive"
105817
- });
105834
+ toast2({ title: "Error", description: error.message, variant: "destructive" });
105818
105835
  }
105819
105836
  });
105820
105837
  };
105821
105838
  const getSubjectName = (subjectCode) => {
105822
105839
  return subjects.find((s2) => s2.code === subjectCode)?.name || "N/A";
105823
105840
  };
105824
- return /* @__PURE__ */ React97__default.createElement(Card, null, /* @__PURE__ */ React97__default.createElement(CardHeader, null, /* @__PURE__ */ React97__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React97__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React97__default.createElement(Tag, { className: "mr-2 h-5 w-5 text-primary" }), "Manage Topics"), /* @__PURE__ */ React97__default.createElement(
105825
- Button,
105826
- {
105827
- onClick: handleAddItem,
105828
- size: "sm",
105829
- disabled: subjects.length === 0
105830
- },
105831
- /* @__PURE__ */ React97__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }),
105832
- " Add Topic"
105833
- )), subjects.length === 0 && !isLoading && /* @__PURE__ */ React97__default.createElement("p", { className: "text-sm text-destructive" }, "Please add subjects before adding topics.")), /* @__PURE__ */ React97__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React97__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : topics.length === 0 ? /* @__PURE__ */ React97__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No topics found. Add one to get started!") : /* @__PURE__ */ React97__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React97__default.createElement(Table2, null, /* @__PURE__ */ React97__default.createElement(TableHeader, null, /* @__PURE__ */ React97__default.createElement(TableRow, null, /* @__PURE__ */ React97__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Subject"), /* @__PURE__ */ React97__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React97__default.createElement(TableBody, null, topics.map((topic) => /* @__PURE__ */ React97__default.createElement(TableRow, { key: topic.id }, /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-mono text-xs" }, topic.code), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-medium" }, topic.name), /* @__PURE__ */ React97__default.createElement(TableCell, null, getSubjectName(topic.subjectCode), " ", "(", topic.subjectCode, ")"), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React97__default.createElement(
105834
- Button,
105835
- {
105836
- variant: "ghost",
105837
- size: "icon",
105838
- onClick: () => handleEditItem(topic),
105839
- className: "mr-2"
105840
- },
105841
- /* @__PURE__ */ React97__default.createElement(PenLine, { className: "h-4 w-4" })
105842
- ), /* @__PURE__ */ React97__default.createElement(
105843
- Button,
105844
- {
105845
- variant: "ghost",
105846
- size: "icon",
105847
- onClick: () => handleDeleteItem(topic),
105848
- className: "text-destructive hover:text-destructive"
105849
- },
105850
- /* @__PURE__ */ React97__default.createElement(Trash2, { className: "h-4 w-4" })
105851
- ))))))), /* @__PURE__ */ React97__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React97__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React97__default.createElement(DialogHeader, null, /* @__PURE__ */ React97__default.createElement(DialogTitle2, null, currentItem ? "Edit Topic" : "Add New Topic")), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemCode" }, "Topic Code"), /* @__PURE__ */ React97__default.createElement(
105852
- Input,
105853
- {
105854
- id: "itemCode",
105855
- value: itemCode,
105856
- onChange: (e2) => setItemCode(
105857
- e2.target.value.toUpperCase()
105858
- ),
105859
- placeholder: "e.g., ALG-BASICS",
105860
- disabled: !!currentItem
105861
- }
105862
- )), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemName" }, "Topic Name"), /* @__PURE__ */ React97__default.createElement(
105863
- Input,
105864
- {
105865
- id: "itemName",
105866
- value: itemName,
105867
- onChange: (e2) => setItemName(e2.target.value),
105868
- placeholder: "e.g., Algebra Basics"
105869
- }
105870
- )), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "subjectCode" }, "Subject"), /* @__PURE__ */ React97__default.createElement(
105871
- Select2,
105872
- {
105873
- value: selectedSubjectCode,
105874
- onValueChange: setSelectedSubjectCode,
105875
- disabled: subjects.length === 0
105876
- },
105877
- /* @__PURE__ */ React97__default.createElement(SelectTrigger2, { id: "subjectCode" }, /* @__PURE__ */ React97__default.createElement(SelectValue2, { placeholder: "Select a subject" })),
105878
- /* @__PURE__ */ React97__default.createElement(SelectContent2, null, subjects.map((subject) => /* @__PURE__ */ React97__default.createElement(
105879
- SelectItem2,
105880
- {
105881
- key: subject.code,
105882
- value: subject.code
105883
- },
105884
- subject.name,
105885
- " (",
105886
- subject.code,
105887
- ")"
105888
- )))
105889
- ))), /* @__PURE__ */ React97__default.createElement(DialogFooter, null, /* @__PURE__ */ React97__default.createElement(
105890
- Button,
105891
- {
105892
- type: "button",
105893
- variant: "outline",
105894
- onClick: () => setIsDialogOpen(false),
105895
- disabled: isPending
105896
- },
105897
- "Cancel"
105898
- ), /* @__PURE__ */ React97__default.createElement(
105899
- Button,
105900
- {
105901
- type: "submit",
105902
- onClick: handleSubmit,
105903
- disabled: isPending || !itemName.trim() || !itemCode.trim() || !selectedSubjectCode
105904
- },
105905
- isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }),
105906
- " ",
105907
- "Save"
105908
- )))), /* @__PURE__ */ React97__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React97__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React97__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React97__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React97__default.createElement(AlertDialogDescription2, null, 'This will permanently delete topic "', itemToDelete?.name, '".')), /* @__PURE__ */ React97__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React97__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(
105909
- AlertDialogAction2,
105910
- {
105911
- onClick: confirmDelete,
105912
- disabled: isPending,
105913
- className: "bg-destructive hover:bg-destructive/90"
105914
- },
105915
- isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }),
105916
- " ",
105917
- "Delete"
105918
- ))))));
105841
+ return /* @__PURE__ */ React97__default.createElement(Card, null, /* @__PURE__ */ React97__default.createElement(CardHeader, null, /* @__PURE__ */ React97__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React97__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React97__default.createElement(Tag, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Topics"), /* @__PURE__ */ React97__default.createElement(Button, { onClick: handleAddItem, size: "sm", disabled: subjects.length === 0 }, /* @__PURE__ */ React97__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Topic")), subjects.length === 0 && !isLoading && /* @__PURE__ */ React97__default.createElement("p", { className: "text-sm text-destructive" }, "Please add subjects before adding topics.")), /* @__PURE__ */ React97__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React97__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : topics.length === 0 ? /* @__PURE__ */ React97__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No topics found. Add one to get started!") : /* @__PURE__ */ React97__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React97__default.createElement(Table2, null, /* @__PURE__ */ React97__default.createElement(TableHeader, null, /* @__PURE__ */ React97__default.createElement(TableRow, null, /* @__PURE__ */ React97__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Subject"), /* @__PURE__ */ React97__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React97__default.createElement(TableBody, null, topics.map((topic) => /* @__PURE__ */ React97__default.createElement(TableRow, { key: topic.id }, /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-mono text-xs" }, topic.code), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-medium" }, topic.name), /* @__PURE__ */ React97__default.createElement(TableCell, null, getSubjectName(topic.subjectCode), " (", topic.subjectCode, ")"), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(topic), className: "mr-2" }, /* @__PURE__ */ React97__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(topic), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React97__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React97__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React97__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React97__default.createElement(DialogHeader, null, /* @__PURE__ */ React97__default.createElement(DialogTitle2, null, currentItem ? "Edit Topic" : "Add New Topic")), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemCode" }, "Topic Code"), /* @__PURE__ */ React97__default.createElement(Input, { id: "itemCode", value: itemCode, onChange: (e2) => setItemCode(e2.target.value.toUpperCase()), placeholder: "e.g., ALG-BASICS", disabled: !!currentItem })), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemName" }, "Topic Name"), /* @__PURE__ */ React97__default.createElement(Input, { id: "itemName", value: itemName, onChange: (e2) => setItemName(e2.target.value), placeholder: "e.g., Algebra Basics" })), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "subjectCode" }, "Subject"), /* @__PURE__ */ React97__default.createElement(Select2, { value: selectedSubjectCode, onValueChange: setSelectedSubjectCode, disabled: subjects.length === 0 }, /* @__PURE__ */ React97__default.createElement(SelectTrigger2, { id: "subjectCode" }, /* @__PURE__ */ React97__default.createElement(SelectValue2, { placeholder: "Select a subject" })), /* @__PURE__ */ React97__default.createElement(SelectContent2, null, subjects.map((subject) => /* @__PURE__ */ React97__default.createElement(SelectItem2, { key: subject.code, value: subject.code }, subject.name, " (", subject.code, ")")))))), /* @__PURE__ */ React97__default.createElement(DialogFooter, null, /* @__PURE__ */ React97__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending || !itemName.trim() || !itemCode.trim() || !selectedSubjectCode }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Save")))), /* @__PURE__ */ React97__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React97__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React97__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React97__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React97__default.createElement(AlertDialogDescription2, null, 'This will permanently delete topic "', itemToDelete?.name, '".')), /* @__PURE__ */ React97__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React97__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Delete"))))));
105919
105842
  }
105920
105843
 
105921
105844
  // src/react-ui/components/metadata/CategoryManager.tsx
105922
105845
  init_react_shim();
105923
- function CategoryManager() {
105846
+ function CategoryManager({ initialData, isLoading: isLoadingProp, onAdd, onUpdate, onDelete }) {
105924
105847
  const [items, setItems] = useState([]);
105925
105848
  const [isLoading, setIsLoading] = useState(true);
105926
105849
  const [isDialogOpen, setIsDialogOpen] = useState(false);
@@ -105932,19 +105855,27 @@ function CategoryManager() {
105932
105855
  const [itemToDelete, setItemToDelete] = useState(null);
105933
105856
  const [isPending, startTransition] = useTransition();
105934
105857
  const { toast: toast2 } = useToast();
105935
- useEffect(() => {
105936
- fetchItems();
105937
- }, []);
105938
- const fetchItems = () => {
105939
- setIsLoading(true);
105940
- try {
105941
- setItems(MetadataService.getCategories());
105942
- } catch (error) {
105943
- toast2({ title: "Error", description: "Failed to fetch categories.", variant: "destructive" });
105944
- } finally {
105945
- setIsLoading(false);
105858
+ const isControlled = initialData !== void 0;
105859
+ const refreshData = () => {
105860
+ if (!isControlled) {
105861
+ setIsLoading(true);
105862
+ try {
105863
+ setItems(MetadataService.getCategories());
105864
+ } catch (error) {
105865
+ toast2({ title: "Error", description: "Failed to refresh categories.", variant: "destructive" });
105866
+ } finally {
105867
+ setIsLoading(false);
105868
+ }
105946
105869
  }
105947
105870
  };
105871
+ useEffect(() => {
105872
+ if (isControlled) {
105873
+ setItems(initialData || []);
105874
+ setIsLoading(isLoadingProp || false);
105875
+ } else {
105876
+ refreshData();
105877
+ }
105878
+ }, [isControlled, initialData, isLoadingProp]);
105948
105879
  const handleAddItem = () => {
105949
105880
  setCurrentItem(null);
105950
105881
  setItemName("");
@@ -105965,13 +105896,17 @@ function CategoryManager() {
105965
105896
  };
105966
105897
  const confirmDelete = () => {
105967
105898
  if (!itemToDelete) return;
105968
- startTransition(() => {
105899
+ startTransition(async () => {
105969
105900
  try {
105970
- MetadataService.deleteCategory(itemToDelete.code);
105901
+ if (isControlled && onDelete) {
105902
+ await onDelete(itemToDelete);
105903
+ } else {
105904
+ MetadataService.deleteCategory(itemToDelete.code);
105905
+ refreshData();
105906
+ }
105971
105907
  toast2({ title: "Success", description: `Category "${itemToDelete.name}" deleted.` });
105972
- fetchItems();
105973
105908
  } catch (error) {
105974
- toast2({ title: "Error", description: "Failed to delete category.", variant: "destructive" });
105909
+ toast2({ title: "Error", description: error.message, variant: "destructive" });
105975
105910
  } finally {
105976
105911
  setIsAlertOpen(false);
105977
105912
  setItemToDelete(null);
@@ -105983,27 +105918,37 @@ function CategoryManager() {
105983
105918
  toast2({ title: "Validation Error", description: "Code and Name are required.", variant: "destructive" });
105984
105919
  return;
105985
105920
  }
105986
- startTransition(() => {
105921
+ startTransition(async () => {
105987
105922
  try {
105988
105923
  if (currentItem) {
105989
- MetadataService.updateCategory(currentItem.id, itemName, itemCode, itemDescription);
105924
+ if (isControlled && onUpdate) {
105925
+ await onUpdate({ id: currentItem.id, name: itemName, code: itemCode, description: itemDescription });
105926
+ } else {
105927
+ MetadataService.updateCategory(currentItem.id, itemName, itemCode, itemDescription);
105928
+ refreshData();
105929
+ }
105930
+ toast2({ title: "Success", description: "Category updated." });
105990
105931
  } else {
105991
- MetadataService.addCategory(itemName, itemCode, itemDescription);
105932
+ if (isControlled && onAdd) {
105933
+ await onAdd({ name: itemName, code: itemCode, description: itemDescription });
105934
+ } else {
105935
+ MetadataService.addCategory(itemName, itemCode, itemDescription);
105936
+ refreshData();
105937
+ }
105938
+ toast2({ title: "Success", description: "Category added." });
105992
105939
  }
105993
- toast2({ title: "Success", description: "Category saved." });
105994
- fetchItems();
105995
105940
  setIsDialogOpen(false);
105996
105941
  } catch (error) {
105997
- toast2({ title: "Error", description: "Failed to save category.", variant: "destructive" });
105942
+ toast2({ title: "Error", description: error.message, variant: "destructive" });
105998
105943
  }
105999
105944
  });
106000
105945
  };
106001
- return /* @__PURE__ */ React97__default.createElement(Card, null, /* @__PURE__ */ React97__default.createElement(CardHeader, null, /* @__PURE__ */ React97__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React97__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React97__default.createElement(Layers, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Categories"), /* @__PURE__ */ React97__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React97__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Category"))), /* @__PURE__ */ React97__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React97__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React97__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No categories found.") : /* @__PURE__ */ React97__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React97__default.createElement(Table2, null, /* @__PURE__ */ React97__default.createElement(TableHeader, null, /* @__PURE__ */ React97__default.createElement(TableRow, null, /* @__PURE__ */ React97__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Description"), /* @__PURE__ */ React97__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React97__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React97__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-mono text-xs" }, item.code), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-medium" }, item.name), /* @__PURE__ */ React97__default.createElement(TableCell, null, item.description), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React97__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React97__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React97__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React97__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React97__default.createElement(DialogHeader, null, /* @__PURE__ */ React97__default.createElement(DialogTitle2, null, currentItem ? "Edit Category" : "Add New Category")), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemCode" }, "Code"), /* @__PURE__ */ React97__default.createElement(Input, { id: "itemCode", value: itemCode, onChange: (e2) => setItemCode(e2.target.value.toUpperCase()), placeholder: "e.g., CORE_CONCEPT", disabled: !!currentItem })), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemName" }, "Name"), /* @__PURE__ */ React97__default.createElement(Input, { id: "itemName", value: itemName, onChange: (e2) => setItemName(e2.target.value), placeholder: "e.g., Core Concept" })), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemDescription" }, "Description (Optional)"), /* @__PURE__ */ React97__default.createElement(Textarea, { id: "itemDescription", value: itemDescription, onChange: (e2) => setItemDescription(e2.target.value), placeholder: "e.g., Fundamental ideas within a subject." }))), /* @__PURE__ */ React97__default.createElement(DialogFooter, null, /* @__PURE__ */ React97__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending || !itemName.trim() || !itemCode.trim() }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), "Save")))), /* @__PURE__ */ React97__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React97__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React97__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React97__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React97__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.name, '".')), /* @__PURE__ */ React97__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React97__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), "Delete"))))));
105946
+ return /* @__PURE__ */ React97__default.createElement(Card, null, /* @__PURE__ */ React97__default.createElement(CardHeader, null, /* @__PURE__ */ React97__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React97__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React97__default.createElement(Layers, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Categories"), /* @__PURE__ */ React97__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React97__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Category"))), /* @__PURE__ */ React97__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React97__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React97__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No categories found.") : /* @__PURE__ */ React97__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React97__default.createElement(Table2, null, /* @__PURE__ */ React97__default.createElement(TableHeader, null, /* @__PURE__ */ React97__default.createElement(TableRow, null, /* @__PURE__ */ React97__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Description"), /* @__PURE__ */ React97__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React97__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React97__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-mono text-xs" }, item.code), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-medium" }, item.name), /* @__PURE__ */ React97__default.createElement(TableCell, null, item.description), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React97__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React97__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React97__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React97__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React97__default.createElement(DialogHeader, null, /* @__PURE__ */ React97__default.createElement(DialogTitle2, null, currentItem ? "Edit Category" : "Add New Category")), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemCode" }, "Code"), /* @__PURE__ */ React97__default.createElement(Input, { id: "itemCode", value: itemCode, onChange: (e2) => setItemCode(e2.target.value.toUpperCase()), placeholder: "e.g., CORE_CONCEPT", disabled: !!currentItem })), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemName" }, "Name"), /* @__PURE__ */ React97__default.createElement(Input, { id: "itemName", value: itemName, onChange: (e2) => setItemName(e2.target.value), placeholder: "e.g., Core Concept" })), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemDescription" }, "Description (Optional)"), /* @__PURE__ */ React97__default.createElement(Textarea, { id: "itemDescription", value: itemDescription, onChange: (e2) => setItemDescription(e2.target.value), placeholder: "e.g., Fundamental ideas within a subject." }))), /* @__PURE__ */ React97__default.createElement(DialogFooter, null, /* @__PURE__ */ React97__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending || !itemName.trim() || !itemCode.trim() }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Save")))), /* @__PURE__ */ React97__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React97__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React97__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React97__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React97__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.name, '".')), /* @__PURE__ */ React97__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React97__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Delete"))))));
106002
105947
  }
106003
105948
 
106004
105949
  // src/react-ui/components/metadata/BloomLevelManager.tsx
106005
105950
  init_react_shim();
106006
- function BloomLevelManager() {
105951
+ function BloomLevelManager({ initialData, isLoading: isLoadingProp, onAdd, onUpdate, onDelete }) {
106007
105952
  const [items, setItems] = useState([]);
106008
105953
  const [isLoading, setIsLoading] = useState(true);
106009
105954
  const [isDialogOpen, setIsDialogOpen] = useState(false);
@@ -106015,19 +105960,27 @@ function BloomLevelManager() {
106015
105960
  const [itemToDelete, setItemToDelete] = useState(null);
106016
105961
  const [isPending, startTransition] = useTransition();
106017
105962
  const { toast: toast2 } = useToast();
106018
- useEffect(() => {
106019
- fetchItems();
106020
- }, []);
106021
- const fetchItems = () => {
106022
- setIsLoading(true);
106023
- try {
106024
- setItems(MetadataService.getBloomLevels());
106025
- } catch (error) {
106026
- toast2({ title: "Error", description: "Failed to fetch Bloom's Levels.", variant: "destructive" });
106027
- } finally {
106028
- setIsLoading(false);
105963
+ const isControlled = initialData !== void 0;
105964
+ const refreshData = () => {
105965
+ if (!isControlled) {
105966
+ setIsLoading(true);
105967
+ try {
105968
+ setItems(MetadataService.getBloomLevels());
105969
+ } catch (error) {
105970
+ toast2({ title: "Error", description: "Failed to refresh Bloom's Levels.", variant: "destructive" });
105971
+ } finally {
105972
+ setIsLoading(false);
105973
+ }
106029
105974
  }
106030
105975
  };
105976
+ useEffect(() => {
105977
+ if (isControlled) {
105978
+ setItems(initialData || []);
105979
+ setIsLoading(isLoadingProp || false);
105980
+ } else {
105981
+ refreshData();
105982
+ }
105983
+ }, [isControlled, initialData, isLoadingProp]);
106031
105984
  const handleAddItem = () => {
106032
105985
  setCurrentItem(null);
106033
105986
  setItemCode("");
@@ -106048,13 +106001,17 @@ function BloomLevelManager() {
106048
106001
  };
106049
106002
  const confirmDelete = () => {
106050
106003
  if (!itemToDelete) return;
106051
- startTransition(() => {
106004
+ startTransition(async () => {
106052
106005
  try {
106053
- MetadataService.deleteBloomLevel(itemToDelete.code);
106006
+ if (isControlled && onDelete) {
106007
+ await onDelete(itemToDelete);
106008
+ } else {
106009
+ MetadataService.deleteBloomLevel(itemToDelete.code);
106010
+ refreshData();
106011
+ }
106054
106012
  toast2({ title: "Success", description: `Bloom's Level "${itemToDelete.name}" deleted.` });
106055
- fetchItems();
106056
106013
  } catch (error) {
106057
- toast2({ title: "Error", description: "Failed to delete Bloom's Level.", variant: "destructive" });
106014
+ toast2({ title: "Error", description: error.message, variant: "destructive" });
106058
106015
  } finally {
106059
106016
  setIsAlertOpen(false);
106060
106017
  setItemToDelete(null);
@@ -106066,27 +106023,37 @@ function BloomLevelManager() {
106066
106023
  toast2({ title: "Validation Error", description: "Code and Name are required.", variant: "destructive" });
106067
106024
  return;
106068
106025
  }
106069
- startTransition(() => {
106026
+ startTransition(async () => {
106070
106027
  try {
106071
106028
  if (currentItem) {
106072
- MetadataService.updateBloomLevel(currentItem.id, itemName, itemCode, itemDescription);
106029
+ if (isControlled && onUpdate) {
106030
+ await onUpdate({ id: currentItem.id, name: itemName, code: itemCode, description: itemDescription });
106031
+ } else {
106032
+ MetadataService.updateBloomLevel(currentItem.id, itemName, itemCode, itemDescription);
106033
+ refreshData();
106034
+ }
106035
+ toast2({ title: "Success", description: "Bloom's Level updated." });
106073
106036
  } else {
106074
- MetadataService.addBloomLevel(itemName, itemCode, itemDescription);
106037
+ if (isControlled && onAdd) {
106038
+ await onAdd({ name: itemName, code: itemCode, description: itemDescription });
106039
+ } else {
106040
+ MetadataService.addBloomLevel(itemName, itemCode, itemDescription);
106041
+ refreshData();
106042
+ }
106043
+ toast2({ title: "Success", description: "Bloom's Level added." });
106075
106044
  }
106076
- toast2({ title: "Success", description: "Bloom's Level saved." });
106077
- fetchItems();
106078
106045
  setIsDialogOpen(false);
106079
106046
  } catch (error) {
106080
- toast2({ title: "Error", description: "Failed to save Bloom's Level.", variant: "destructive" });
106047
+ toast2({ title: "Error", description: error.message, variant: "destructive" });
106081
106048
  }
106082
106049
  });
106083
106050
  };
106084
- return /* @__PURE__ */ React97__default.createElement(Card, null, /* @__PURE__ */ React97__default.createElement(CardHeader, null, /* @__PURE__ */ React97__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React97__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React97__default.createElement(Brain, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Bloom's Levels"), /* @__PURE__ */ React97__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React97__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Bloom's Level"))), /* @__PURE__ */ React97__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React97__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React97__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No Bloom's Levels found.") : /* @__PURE__ */ React97__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React97__default.createElement(Table2, null, /* @__PURE__ */ React97__default.createElement(TableHeader, null, /* @__PURE__ */ React97__default.createElement(TableRow, null, /* @__PURE__ */ React97__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Description"), /* @__PURE__ */ React97__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React97__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React97__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-mono text-xs" }, item.code), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-medium" }, item.name), /* @__PURE__ */ React97__default.createElement(TableCell, null, item.description), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React97__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React97__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React97__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React97__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React97__default.createElement(DialogHeader, null, /* @__PURE__ */ React97__default.createElement(DialogTitle2, null, currentItem ? "Edit Bloom's Level" : "Add New Bloom's Level")), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemCode" }, "Code"), /* @__PURE__ */ React97__default.createElement(Input, { id: "itemCode", value: itemCode, onChange: (e2) => setItemCode(e2.target.value.toUpperCase()), placeholder: "e.g., REMEMBER", disabled: !!currentItem })), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemName" }, "Name"), /* @__PURE__ */ React97__default.createElement(Input, { id: "itemName", value: itemName, onChange: (e2) => setItemName(e2.target.value), placeholder: "e.g., Remembering" })), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemDescription" }, "Description (Optional)"), /* @__PURE__ */ React97__default.createElement(Textarea, { id: "itemDescription", value: itemDescription, onChange: (e2) => setItemDescription(e2.target.value), placeholder: "e.g., Recall facts and basic concepts." }))), /* @__PURE__ */ React97__default.createElement(DialogFooter, null, /* @__PURE__ */ React97__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending || !itemCode.trim() || !itemName.trim() }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), "Save")))), /* @__PURE__ */ React97__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React97__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React97__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React97__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React97__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.name, '".')), /* @__PURE__ */ React97__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React97__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), "Delete"))))));
106051
+ return /* @__PURE__ */ React97__default.createElement(Card, null, /* @__PURE__ */ React97__default.createElement(CardHeader, null, /* @__PURE__ */ React97__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React97__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React97__default.createElement(Brain, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Bloom's Levels"), /* @__PURE__ */ React97__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React97__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Bloom's Level"))), /* @__PURE__ */ React97__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React97__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React97__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No Bloom's Levels found.") : /* @__PURE__ */ React97__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React97__default.createElement(Table2, null, /* @__PURE__ */ React97__default.createElement(TableHeader, null, /* @__PURE__ */ React97__default.createElement(TableRow, null, /* @__PURE__ */ React97__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Description"), /* @__PURE__ */ React97__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React97__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React97__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-mono text-xs" }, item.code), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-medium" }, item.name), /* @__PURE__ */ React97__default.createElement(TableCell, null, item.description), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React97__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React97__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React97__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React97__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React97__default.createElement(DialogHeader, null, /* @__PURE__ */ React97__default.createElement(DialogTitle2, null, currentItem ? "Edit Bloom's Level" : "Add New Bloom's Level")), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemCode" }, "Code"), /* @__PURE__ */ React97__default.createElement(Input, { id: "itemCode", value: itemCode, onChange: (e2) => setItemCode(e2.target.value.toUpperCase()), placeholder: "e.g., REMEMBER", disabled: !!currentItem })), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemName" }, "Name"), /* @__PURE__ */ React97__default.createElement(Input, { id: "itemName", value: itemName, onChange: (e2) => setItemName(e2.target.value), placeholder: "e.g., Remembering" })), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemDescription" }, "Description (Optional)"), /* @__PURE__ */ React97__default.createElement(Textarea, { id: "itemDescription", value: itemDescription, onChange: (e2) => setItemDescription(e2.target.value), placeholder: "e.g., Recall facts and basic concepts." }))), /* @__PURE__ */ React97__default.createElement(DialogFooter, null, /* @__PURE__ */ React97__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending || !itemCode.trim() || !itemName.trim() }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Save")))), /* @__PURE__ */ React97__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React97__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React97__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React97__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React97__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.name, '".')), /* @__PURE__ */ React97__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React97__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Delete"))))));
106085
106052
  }
106086
106053
 
106087
106054
  // src/react-ui/components/metadata/QuestionTypeManager.tsx
106088
106055
  init_react_shim();
106089
- function QuestionTypeManager() {
106056
+ function QuestionTypeManager({ initialData, isLoading: isLoadingProp, onAdd, onUpdate, onDelete }) {
106090
106057
  const [items, setItems] = useState([]);
106091
106058
  const [isLoading, setIsLoading] = useState(true);
106092
106059
  const [isDialogOpen, setIsDialogOpen] = useState(false);
@@ -106098,19 +106065,27 @@ function QuestionTypeManager() {
106098
106065
  const [itemToDelete, setItemToDelete] = useState(null);
106099
106066
  const [isPending, startTransition] = useTransition();
106100
106067
  const { toast: toast2 } = useToast();
106101
- useEffect(() => {
106102
- fetchItems();
106103
- }, []);
106104
- const fetchItems = () => {
106105
- setIsLoading(true);
106106
- try {
106107
- setItems(MetadataService.getQuestionTypes());
106108
- } catch (error) {
106109
- toast2({ title: "Error", description: "Failed to fetch Question Types.", variant: "destructive" });
106110
- } finally {
106111
- setIsLoading(false);
106068
+ const isControlled = initialData !== void 0;
106069
+ const refreshData = () => {
106070
+ if (!isControlled) {
106071
+ setIsLoading(true);
106072
+ try {
106073
+ setItems(MetadataService.getQuestionTypes());
106074
+ } catch (error) {
106075
+ toast2({ title: "Error", description: "Failed to refresh Question Types.", variant: "destructive" });
106076
+ } finally {
106077
+ setIsLoading(false);
106078
+ }
106112
106079
  }
106113
106080
  };
106081
+ useEffect(() => {
106082
+ if (isControlled) {
106083
+ setItems(initialData || []);
106084
+ setIsLoading(isLoadingProp || false);
106085
+ } else {
106086
+ refreshData();
106087
+ }
106088
+ }, [isControlled, initialData, isLoadingProp]);
106114
106089
  const handleAddItem = () => {
106115
106090
  setCurrentItem(null);
106116
106091
  setItemCode("");
@@ -106131,13 +106106,17 @@ function QuestionTypeManager() {
106131
106106
  };
106132
106107
  const confirmDelete = () => {
106133
106108
  if (!itemToDelete) return;
106134
- startTransition(() => {
106109
+ startTransition(async () => {
106135
106110
  try {
106136
- MetadataService.deleteQuestionType(itemToDelete.code);
106111
+ if (isControlled && onDelete) {
106112
+ await onDelete(itemToDelete);
106113
+ } else {
106114
+ MetadataService.deleteQuestionType(itemToDelete.code);
106115
+ refreshData();
106116
+ }
106137
106117
  toast2({ title: "Success", description: `Question Type "${itemToDelete.name}" deleted.` });
106138
- fetchItems();
106139
106118
  } catch (error) {
106140
- toast2({ title: "Error", description: "Failed to delete Question Type.", variant: "destructive" });
106119
+ toast2({ title: "Error", description: error.message, variant: "destructive" });
106141
106120
  } finally {
106142
106121
  setIsAlertOpen(false);
106143
106122
  setItemToDelete(null);
@@ -106149,27 +106128,37 @@ function QuestionTypeManager() {
106149
106128
  toast2({ title: "Validation Error", description: "Code and Name are required.", variant: "destructive" });
106150
106129
  return;
106151
106130
  }
106152
- startTransition(() => {
106131
+ startTransition(async () => {
106153
106132
  try {
106154
106133
  if (currentItem) {
106155
- MetadataService.updateQuestionType(currentItem.id, itemName, itemCode, itemDescription);
106134
+ if (isControlled && onUpdate) {
106135
+ await onUpdate({ id: currentItem.id, name: itemName, code: itemCode, description: itemDescription });
106136
+ } else {
106137
+ MetadataService.updateQuestionType(currentItem.id, itemName, itemCode, itemDescription);
106138
+ refreshData();
106139
+ }
106140
+ toast2({ title: "Success", description: "Question Type updated." });
106156
106141
  } else {
106157
- MetadataService.addQuestionType(itemName, itemCode, itemDescription);
106142
+ if (isControlled && onAdd) {
106143
+ await onAdd({ name: itemName, code: itemCode, description: itemDescription });
106144
+ } else {
106145
+ MetadataService.addQuestionType(itemName, itemCode, itemDescription);
106146
+ refreshData();
106147
+ }
106148
+ toast2({ title: "Success", description: "Question Type added." });
106158
106149
  }
106159
- toast2({ title: "Success", description: "Question Type saved." });
106160
- fetchItems();
106161
106150
  setIsDialogOpen(false);
106162
106151
  } catch (error) {
106163
- toast2({ title: "Error", description: "Failed to save Question Type.", variant: "destructive" });
106152
+ toast2({ title: "Error", description: error.message, variant: "destructive" });
106164
106153
  }
106165
106154
  });
106166
106155
  };
106167
- return /* @__PURE__ */ React97__default.createElement(Card, null, /* @__PURE__ */ React97__default.createElement(CardHeader, null, /* @__PURE__ */ React97__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React97__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React97__default.createElement(CircleHelp, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Question Types"), /* @__PURE__ */ React97__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React97__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Question Type"))), /* @__PURE__ */ React97__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React97__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React97__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No Question Types found.") : /* @__PURE__ */ React97__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React97__default.createElement(Table2, null, /* @__PURE__ */ React97__default.createElement(TableHeader, null, /* @__PURE__ */ React97__default.createElement(TableRow, null, /* @__PURE__ */ React97__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Description"), /* @__PURE__ */ React97__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React97__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React97__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-mono text-xs" }, item.code), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-medium" }, item.name), /* @__PURE__ */ React97__default.createElement(TableCell, null, item.description), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React97__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React97__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React97__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React97__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React97__default.createElement(DialogHeader, null, /* @__PURE__ */ React97__default.createElement(DialogTitle2, null, currentItem ? "Edit Question Type" : "Add New Question Type")), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemCode" }, "Code"), /* @__PURE__ */ React97__default.createElement(Input, { id: "itemCode", value: itemCode, onChange: (e2) => setItemCode(e2.target.value.toUpperCase()), placeholder: "e.g., MCQ", disabled: !!currentItem })), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemName" }, "Name"), /* @__PURE__ */ React97__default.createElement(Input, { id: "itemName", value: itemName, onChange: (e2) => setItemName(e2.target.value), placeholder: "e.g., Multiple Choice" })), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemDescription" }, "Description (Optional)"), /* @__PURE__ */ React97__default.createElement(Textarea, { id: "itemDescription", value: itemDescription, onChange: (e2) => setItemDescription(e2.target.value), placeholder: "e.g., Select one answer from a list of options." }))), /* @__PURE__ */ React97__default.createElement(DialogFooter, null, /* @__PURE__ */ React97__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending || !itemCode.trim() || !itemName.trim() }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), "Save")))), /* @__PURE__ */ React97__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React97__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React97__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React97__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React97__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.name, '".')), /* @__PURE__ */ React97__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React97__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), "Delete"))))));
106156
+ return /* @__PURE__ */ React97__default.createElement(Card, null, /* @__PURE__ */ React97__default.createElement(CardHeader, null, /* @__PURE__ */ React97__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React97__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React97__default.createElement(CircleHelp, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Question Types"), /* @__PURE__ */ React97__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React97__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Question Type"))), /* @__PURE__ */ React97__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React97__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React97__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No Question Types found.") : /* @__PURE__ */ React97__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React97__default.createElement(Table2, null, /* @__PURE__ */ React97__default.createElement(TableHeader, null, /* @__PURE__ */ React97__default.createElement(TableRow, null, /* @__PURE__ */ React97__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Description"), /* @__PURE__ */ React97__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React97__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React97__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-mono text-xs" }, item.code), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-medium" }, item.name), /* @__PURE__ */ React97__default.createElement(TableCell, null, item.description), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React97__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React97__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React97__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React97__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React97__default.createElement(DialogHeader, null, /* @__PURE__ */ React97__default.createElement(DialogTitle2, null, currentItem ? "Edit Question Type" : "Add New Question Type")), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemCode" }, "Code"), /* @__PURE__ */ React97__default.createElement(Input, { id: "itemCode", value: itemCode, onChange: (e2) => setItemCode(e2.target.value.toLowerCase().replace(/ /g, "_")), placeholder: "e.g., multiple_choice", disabled: !!currentItem })), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemName" }, "Name"), /* @__PURE__ */ React97__default.createElement(Input, { id: "itemName", value: itemName, onChange: (e2) => setItemName(e2.target.value), placeholder: "e.g., Multiple Choice" })), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemDescription" }, "Description (Optional)"), /* @__PURE__ */ React97__default.createElement(Textarea, { id: "itemDescription", value: itemDescription, onChange: (e2) => setItemDescription(e2.target.value), placeholder: "e.g., Select one answer from a list of options." }))), /* @__PURE__ */ React97__default.createElement(DialogFooter, null, /* @__PURE__ */ React97__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending || !itemCode.trim() || !itemName.trim() }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Save")))), /* @__PURE__ */ React97__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React97__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React97__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React97__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React97__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.name, '".')), /* @__PURE__ */ React97__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React97__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Delete"))))));
106168
106157
  }
106169
106158
 
106170
106159
  // src/react-ui/components/metadata/LearningObjectiveManager.tsx
106171
106160
  init_react_shim();
106172
- function LearningObjectiveManager() {
106161
+ function LearningObjectiveManager({ initialData, subjects: subjectsProp, isLoading: isLoadingProp, onAdd, onUpdate, onDelete }) {
106173
106162
  const [items, setItems] = useState([]);
106174
106163
  const [subjects, setSubjects] = useState([]);
106175
106164
  const [isLoading, setIsLoading] = useState(true);
@@ -106183,34 +106172,35 @@ function LearningObjectiveManager() {
106183
106172
  const [itemToDelete, setItemToDelete] = useState(null);
106184
106173
  const [isPending, startTransition] = useTransition();
106185
106174
  const { toast: toast2 } = useToast();
106186
- const fetchData = () => {
106187
- setIsLoading(true);
106188
- try {
106189
- const loData = MetadataService.getLearningObjectives();
106190
- const subjectsData = MetadataService.getSubjects();
106191
- setItems(loData);
106192
- setSubjects(subjectsData);
106193
- } catch (error) {
106194
- toast2({
106195
- title: "Error",
106196
- description: "Failed to fetch Learning Objectives or Subjects.",
106197
- variant: "destructive"
106198
- });
106199
- } finally {
106200
- setIsLoading(false);
106175
+ const isControlled = initialData !== void 0;
106176
+ const refreshData = () => {
106177
+ if (!isControlled) {
106178
+ setIsLoading(true);
106179
+ try {
106180
+ setItems(MetadataService.getLearningObjectives());
106181
+ setSubjects(MetadataService.getSubjects());
106182
+ } catch (error) {
106183
+ toast2({ title: "Error", description: "Failed to refresh data.", variant: "destructive" });
106184
+ } finally {
106185
+ setIsLoading(false);
106186
+ }
106201
106187
  }
106202
106188
  };
106203
106189
  useEffect(() => {
106204
- fetchData();
106205
- }, []);
106190
+ if (isControlled) {
106191
+ setItems(initialData || []);
106192
+ setSubjects(subjectsProp || []);
106193
+ setIsLoading(isLoadingProp || false);
106194
+ } else {
106195
+ refreshData();
106196
+ }
106197
+ }, [isControlled, initialData, subjectsProp, isLoadingProp]);
106206
106198
  const handleAddItem = () => {
106207
106199
  setCurrentItem(null);
106208
106200
  setItemName("");
106209
106201
  setItemCode("");
106210
106202
  setItemDescription("");
106211
- setSelectedSubjectCode(
106212
- subjects.length > 0 ? subjects[0].code : void 0
106213
- );
106203
+ setSelectedSubjectCode(subjects.length > 0 ? subjects[0].code : void 0);
106214
106204
  setIsDialogOpen(true);
106215
106205
  };
106216
106206
  const handleEditItem = (item) => {
@@ -106227,20 +106217,17 @@ function LearningObjectiveManager() {
106227
106217
  };
106228
106218
  const confirmDelete = () => {
106229
106219
  if (!itemToDelete) return;
106230
- startTransition(() => {
106220
+ startTransition(async () => {
106231
106221
  try {
106232
- MetadataService.deleteLearningObjective(itemToDelete.code);
106233
- toast2({
106234
- title: "Success",
106235
- description: `Learning Objective "${itemToDelete.name}" deleted.`
106236
- });
106237
- fetchData();
106222
+ if (isControlled && onDelete) {
106223
+ await onDelete(itemToDelete);
106224
+ } else {
106225
+ MetadataService.deleteLearningObjective(itemToDelete.code);
106226
+ refreshData();
106227
+ }
106228
+ toast2({ title: "Success", description: `Learning Objective "${itemToDelete.name}" deleted.` });
106238
106229
  } catch (error) {
106239
- toast2({
106240
- title: "Error",
106241
- description: "Failed to delete Learning Objective.",
106242
- variant: "destructive"
106243
- });
106230
+ toast2({ title: "Error", description: error.message, variant: "destructive" });
106244
106231
  } finally {
106245
106232
  setIsAlertOpen(false);
106246
106233
  setItemToDelete(null);
@@ -106249,43 +106236,31 @@ function LearningObjectiveManager() {
106249
106236
  };
106250
106237
  const handleSubmit = () => {
106251
106238
  if (!itemName.trim() || !itemCode.trim()) {
106252
- toast2({
106253
- title: "Validation Error",
106254
- description: "Code and Name are required.",
106255
- variant: "destructive"
106256
- });
106239
+ toast2({ title: "Validation Error", description: "Code and Name are required.", variant: "destructive" });
106257
106240
  return;
106258
106241
  }
106259
- startTransition(() => {
106242
+ startTransition(async () => {
106260
106243
  try {
106261
106244
  if (currentItem) {
106262
- MetadataService.updateLearningObjective(
106263
- currentItem.id,
106264
- itemName,
106265
- itemCode,
106266
- selectedSubjectCode,
106267
- itemDescription
106268
- );
106245
+ if (isControlled && onUpdate) {
106246
+ await onUpdate({ id: currentItem.id, name: itemName, code: itemCode, subjectCode: selectedSubjectCode, description: itemDescription });
106247
+ } else {
106248
+ MetadataService.updateLearningObjective(currentItem.id, itemName, itemCode, selectedSubjectCode, itemDescription);
106249
+ refreshData();
106250
+ }
106251
+ toast2({ title: "Success", description: "Learning Objective updated." });
106269
106252
  } else {
106270
- MetadataService.addLearningObjective(
106271
- itemName,
106272
- itemCode,
106273
- selectedSubjectCode,
106274
- itemDescription
106275
- );
106253
+ if (isControlled && onAdd) {
106254
+ await onAdd({ name: itemName, code: itemCode, subjectCode: selectedSubjectCode, description: itemDescription });
106255
+ } else {
106256
+ MetadataService.addLearningObjective(itemName, itemCode, selectedSubjectCode, itemDescription);
106257
+ refreshData();
106258
+ }
106259
+ toast2({ title: "Success", description: "Learning Objective added." });
106276
106260
  }
106277
- toast2({
106278
- title: "Success",
106279
- description: "Learning Objective saved."
106280
- });
106281
- fetchData();
106282
106261
  setIsDialogOpen(false);
106283
106262
  } catch (error) {
106284
- toast2({
106285
- title: "Error",
106286
- description: "Failed to save Learning Objective.",
106287
- variant: "destructive"
106288
- });
106263
+ toast2({ title: "Error", description: error.message, variant: "destructive" });
106289
106264
  }
106290
106265
  });
106291
106266
  };
@@ -106293,100 +106268,12 @@ function LearningObjectiveManager() {
106293
106268
  if (!subjectCode) return "N/A";
106294
106269
  return subjects.find((s2) => s2.code === subjectCode)?.name || "N/A";
106295
106270
  };
106296
- return /* @__PURE__ */ React97__default.createElement(Card, null, /* @__PURE__ */ React97__default.createElement(CardHeader, null, /* @__PURE__ */ React97__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React97__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React97__default.createElement(Lightbulb, { className: "mr-2 h-5 w-5 text-primary" }), " ", "Manage Learning Objectives"), /* @__PURE__ */ React97__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React97__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Learning Objective"))), /* @__PURE__ */ React97__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React97__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React97__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No Learning Objectives found.") : /* @__PURE__ */ React97__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React97__default.createElement(Table2, null, /* @__PURE__ */ React97__default.createElement(TableHeader, null, /* @__PURE__ */ React97__default.createElement(TableRow, null, /* @__PURE__ */ React97__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Subject"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Description"), /* @__PURE__ */ React97__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React97__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React97__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-mono text-xs" }, item.code), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-medium" }, item.name), /* @__PURE__ */ React97__default.createElement(TableCell, null, getSubjectName(item.subjectCode)), /* @__PURE__ */ React97__default.createElement(TableCell, null, item.description), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React97__default.createElement(
106297
- Button,
106298
- {
106299
- variant: "ghost",
106300
- size: "icon",
106301
- onClick: () => handleEditItem(item),
106302
- className: "mr-2"
106303
- },
106304
- /* @__PURE__ */ React97__default.createElement(PenLine, { className: "h-4 w-4" })
106305
- ), /* @__PURE__ */ React97__default.createElement(
106306
- Button,
106307
- {
106308
- variant: "ghost",
106309
- size: "icon",
106310
- onClick: () => handleDeleteItem(item),
106311
- className: "text-destructive hover:text-destructive"
106312
- },
106313
- /* @__PURE__ */ React97__default.createElement(Trash2, { className: "h-4 w-4" })
106314
- ))))))), /* @__PURE__ */ React97__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React97__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React97__default.createElement(DialogHeader, null, /* @__PURE__ */ React97__default.createElement(DialogTitle2, null, currentItem ? "Edit Learning Objective" : "Add New Learning Objective")), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemCode" }, "Code"), /* @__PURE__ */ React97__default.createElement(
106315
- Input,
106316
- {
106317
- id: "itemCode",
106318
- value: itemCode,
106319
- onChange: (e2) => setItemCode(
106320
- e2.target.value.toUpperCase()
106321
- ),
106322
- disabled: !!currentItem
106323
- }
106324
- )), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemName" }, "Name"), /* @__PURE__ */ React97__default.createElement(
106325
- Input,
106326
- {
106327
- id: "itemName",
106328
- value: itemName,
106329
- onChange: (e2) => setItemName(e2.target.value)
106330
- }
106331
- )), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemSubject" }, "Subject (Optional)"), /* @__PURE__ */ React97__default.createElement(
106332
- Select2,
106333
- {
106334
- value: selectedSubjectCode || "",
106335
- onValueChange: (value) => setSelectedSubjectCode(
106336
- value === "_NONE_" ? void 0 : value
106337
- )
106338
- },
106339
- /* @__PURE__ */ React97__default.createElement(SelectTrigger2, { id: "itemSubject" }, /* @__PURE__ */ React97__default.createElement(SelectValue2, { placeholder: "Select a subject" })),
106340
- /* @__PURE__ */ React97__default.createElement(SelectContent2, null, /* @__PURE__ */ React97__default.createElement(SelectItem2, { value: "_NONE_" }, "No Specific Subject"), subjects.map((subject) => /* @__PURE__ */ React97__default.createElement(
106341
- SelectItem2,
106342
- {
106343
- key: subject.id,
106344
- value: subject.code
106345
- },
106346
- subject.name
106347
- )))
106348
- )), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemDescription" }, "Description (Optional)"), /* @__PURE__ */ React97__default.createElement(
106349
- Textarea,
106350
- {
106351
- id: "itemDescription",
106352
- value: itemDescription,
106353
- onChange: (e2) => setItemDescription(e2.target.value)
106354
- }
106355
- ))), /* @__PURE__ */ React97__default.createElement(DialogFooter, null, /* @__PURE__ */ React97__default.createElement(
106356
- Button,
106357
- {
106358
- type: "button",
106359
- variant: "outline",
106360
- onClick: () => setIsDialogOpen(false),
106361
- disabled: isPending
106362
- },
106363
- "Cancel"
106364
- ), /* @__PURE__ */ React97__default.createElement(
106365
- Button,
106366
- {
106367
- type: "submit",
106368
- onClick: handleSubmit,
106369
- disabled: isPending || !itemName.trim() || !itemCode.trim()
106370
- },
106371
- isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }),
106372
- " ",
106373
- "Save"
106374
- )))), /* @__PURE__ */ React97__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React97__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React97__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React97__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React97__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.name, '".')), /* @__PURE__ */ React97__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React97__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(
106375
- AlertDialogAction2,
106376
- {
106377
- onClick: confirmDelete,
106378
- disabled: isPending,
106379
- className: "bg-destructive hover:bg-destructive/90"
106380
- },
106381
- isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }),
106382
- " ",
106383
- "Delete"
106384
- ))))));
106271
+ return /* @__PURE__ */ React97__default.createElement(Card, null, /* @__PURE__ */ React97__default.createElement(CardHeader, null, /* @__PURE__ */ React97__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React97__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React97__default.createElement(Lightbulb, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Learning Objectives"), /* @__PURE__ */ React97__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React97__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Learning Objective"))), /* @__PURE__ */ React97__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React97__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React97__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No Learning Objectives found.") : /* @__PURE__ */ React97__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React97__default.createElement(Table2, null, /* @__PURE__ */ React97__default.createElement(TableHeader, null, /* @__PURE__ */ React97__default.createElement(TableRow, null, /* @__PURE__ */ React97__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Subject"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Description"), /* @__PURE__ */ React97__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React97__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React97__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-mono text-xs" }, item.code), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-medium" }, item.name), /* @__PURE__ */ React97__default.createElement(TableCell, null, getSubjectName(item.subjectCode)), /* @__PURE__ */ React97__default.createElement(TableCell, null, item.description), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React97__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React97__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React97__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React97__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React97__default.createElement(DialogHeader, null, /* @__PURE__ */ React97__default.createElement(DialogTitle2, null, currentItem ? "Edit Learning Objective" : "Add New Learning Objective")), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemCode" }, "Code"), /* @__PURE__ */ React97__default.createElement(Input, { id: "itemCode", value: itemCode, onChange: (e2) => setItemCode(e2.target.value.toUpperCase()), disabled: !!currentItem })), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemName" }, "Name"), /* @__PURE__ */ React97__default.createElement(Input, { id: "itemName", value: itemName, onChange: (e2) => setItemName(e2.target.value) })), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemSubject" }, "Subject (Optional)"), /* @__PURE__ */ React97__default.createElement(Select2, { value: selectedSubjectCode || "", onValueChange: (value) => setSelectedSubjectCode(value === "_NONE_" ? void 0 : value) }, /* @__PURE__ */ React97__default.createElement(SelectTrigger2, { id: "itemSubject" }, /* @__PURE__ */ React97__default.createElement(SelectValue2, { placeholder: "Select a subject" })), /* @__PURE__ */ React97__default.createElement(SelectContent2, null, /* @__PURE__ */ React97__default.createElement(SelectItem2, { value: "_NONE_" }, "No Specific Subject"), subjects.map((subject) => /* @__PURE__ */ React97__default.createElement(SelectItem2, { key: subject.id, value: subject.code }, subject.name))))), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemDescription" }, "Description (Optional)"), /* @__PURE__ */ React97__default.createElement(Textarea, { id: "itemDescription", value: itemDescription, onChange: (e2) => setItemDescription(e2.target.value) }))), /* @__PURE__ */ React97__default.createElement(DialogFooter, null, /* @__PURE__ */ React97__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending || !itemName.trim() || !itemCode.trim() }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Save")))), /* @__PURE__ */ React97__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React97__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React97__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React97__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React97__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.name, '".')), /* @__PURE__ */ React97__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React97__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Delete"))))));
106385
106272
  }
106386
106273
 
106387
106274
  // src/react-ui/components/metadata/ContextManager.tsx
106388
106275
  init_react_shim();
106389
- function ContextManager() {
106276
+ function ContextManager({ initialData, isLoading: isLoadingProp, onAdd, onUpdate, onDelete }) {
106390
106277
  const [items, setItems] = useState([]);
106391
106278
  const [isLoading, setIsLoading] = useState(true);
106392
106279
  const [isDialogOpen, setIsDialogOpen] = useState(false);
@@ -106398,19 +106285,27 @@ function ContextManager() {
106398
106285
  const [itemToDelete, setItemToDelete] = useState(null);
106399
106286
  const [isPending, startTransition] = useTransition();
106400
106287
  const { toast: toast2 } = useToast();
106401
- useEffect(() => {
106402
- fetchItems();
106403
- }, []);
106404
- const fetchItems = () => {
106405
- setIsLoading(true);
106406
- try {
106407
- setItems(MetadataService.getContexts());
106408
- } catch (error) {
106409
- toast2({ title: "Error", description: "Failed to fetch Contexts.", variant: "destructive" });
106410
- } finally {
106411
- setIsLoading(false);
106288
+ const isControlled = initialData !== void 0;
106289
+ const refreshData = () => {
106290
+ if (!isControlled) {
106291
+ setIsLoading(true);
106292
+ try {
106293
+ setItems(MetadataService.getContexts());
106294
+ } catch (error) {
106295
+ toast2({ title: "Error", description: "Failed to refresh Contexts.", variant: "destructive" });
106296
+ } finally {
106297
+ setIsLoading(false);
106298
+ }
106412
106299
  }
106413
106300
  };
106301
+ useEffect(() => {
106302
+ if (isControlled) {
106303
+ setItems(initialData || []);
106304
+ setIsLoading(isLoadingProp || false);
106305
+ } else {
106306
+ refreshData();
106307
+ }
106308
+ }, [isControlled, initialData, isLoadingProp]);
106414
106309
  const handleAddItem = () => {
106415
106310
  setCurrentItem(null);
106416
106311
  setItemName("");
@@ -106431,13 +106326,17 @@ function ContextManager() {
106431
106326
  };
106432
106327
  const confirmDelete = () => {
106433
106328
  if (!itemToDelete) return;
106434
- startTransition(() => {
106329
+ startTransition(async () => {
106435
106330
  try {
106436
- MetadataService.deleteContext(itemToDelete.code);
106331
+ if (isControlled && onDelete) {
106332
+ await onDelete(itemToDelete);
106333
+ } else {
106334
+ MetadataService.deleteContext(itemToDelete.code);
106335
+ refreshData();
106336
+ }
106437
106337
  toast2({ title: "Success", description: `Context "${itemToDelete.name}" deleted.` });
106438
- fetchItems();
106439
106338
  } catch (error) {
106440
- toast2({ title: "Error", description: "Failed to delete Context.", variant: "destructive" });
106339
+ toast2({ title: "Error", description: error.message, variant: "destructive" });
106441
106340
  } finally {
106442
106341
  setIsAlertOpen(false);
106443
106342
  setItemToDelete(null);
@@ -106449,32 +106348,50 @@ function ContextManager() {
106449
106348
  toast2({ title: "Validation Error", description: "Code and Name are required.", variant: "destructive" });
106450
106349
  return;
106451
106350
  }
106452
- startTransition(() => {
106351
+ startTransition(async () => {
106453
106352
  try {
106454
106353
  if (currentItem) {
106455
- MetadataService.updateContext(currentItem.id, itemName, itemCode, itemDescription);
106354
+ if (isControlled && onUpdate) {
106355
+ await onUpdate({ id: currentItem.id, name: itemName, code: itemCode, description: itemDescription });
106356
+ } else {
106357
+ MetadataService.updateContext(currentItem.id, itemName, itemCode, itemDescription);
106358
+ refreshData();
106359
+ }
106360
+ toast2({ title: "Success", description: "Context updated." });
106456
106361
  } else {
106457
- MetadataService.addContext(itemName, itemCode, itemDescription);
106362
+ if (isControlled && onAdd) {
106363
+ await onAdd({ name: itemName, code: itemCode, description: itemDescription });
106364
+ } else {
106365
+ MetadataService.addContext(itemName, itemCode, itemDescription);
106366
+ refreshData();
106367
+ }
106368
+ toast2({ title: "Success", description: "Context added." });
106458
106369
  }
106459
- toast2({ title: "Success", description: "Context saved." });
106460
- fetchItems();
106461
106370
  setIsDialogOpen(false);
106462
106371
  } catch (error) {
106463
- toast2({ title: "Error", description: "Failed to save Context.", variant: "destructive" });
106372
+ toast2({ title: "Error", description: error.message, variant: "destructive" });
106464
106373
  }
106465
106374
  });
106466
106375
  };
106467
- return /* @__PURE__ */ React97__default.createElement(Card, null, /* @__PURE__ */ React97__default.createElement(CardHeader, null, /* @__PURE__ */ React97__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React97__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React97__default.createElement(ScanText, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Contexts"), /* @__PURE__ */ React97__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React97__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Context"))), /* @__PURE__ */ React97__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React97__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React97__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No Contexts found.") : /* @__PURE__ */ React97__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React97__default.createElement(Table2, null, /* @__PURE__ */ React97__default.createElement(TableHeader, null, /* @__PURE__ */ React97__default.createElement(TableRow, null, /* @__PURE__ */ React97__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Description"), /* @__PURE__ */ React97__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React97__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React97__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-mono text-xs" }, item.code), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-medium" }, item.name), /* @__PURE__ */ React97__default.createElement(TableCell, null, item.description), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React97__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React97__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React97__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React97__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React97__default.createElement(DialogHeader, null, /* @__PURE__ */ React97__default.createElement(DialogTitle2, null, currentItem ? "Edit Context" : "Add New Context")), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemCode" }, "Code"), /* @__PURE__ */ React97__default.createElement(Input, { id: "itemCode", value: itemCode, onChange: (e2) => setItemCode(e2.target.value.toUpperCase()), placeholder: "e.g., HIST_INQ", disabled: !!currentItem })), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemName" }, "Name"), /* @__PURE__ */ React97__default.createElement(Input, { id: "itemName", value: itemName, onChange: (e2) => setItemName(e2.target.value), placeholder: "e.g., Historical Inquiry" })), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemDescription" }, "Description (Optional)"), /* @__PURE__ */ React97__default.createElement(Textarea, { id: "itemDescription", value: itemDescription, onChange: (e2) => setItemDescription(e2.target.value), placeholder: "e.g., Analyzing primary and secondary sources." }))), /* @__PURE__ */ React97__default.createElement(DialogFooter, null, /* @__PURE__ */ React97__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending || !itemCode.trim() || !itemName.trim() }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), "Save")))), /* @__PURE__ */ React97__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React97__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React97__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React97__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React97__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.name, '".')), /* @__PURE__ */ React97__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React97__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), "Delete"))))));
106376
+ return /* @__PURE__ */ React97__default.createElement(Card, null, /* @__PURE__ */ React97__default.createElement(CardHeader, null, /* @__PURE__ */ React97__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React97__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React97__default.createElement(ScanText, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Contexts"), /* @__PURE__ */ React97__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React97__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Context"))), /* @__PURE__ */ React97__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React97__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React97__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No Contexts found.") : /* @__PURE__ */ React97__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React97__default.createElement(Table2, null, /* @__PURE__ */ React97__default.createElement(TableHeader, null, /* @__PURE__ */ React97__default.createElement(TableRow, null, /* @__PURE__ */ React97__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Description"), /* @__PURE__ */ React97__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React97__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React97__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-mono text-xs" }, item.code), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-medium" }, item.name), /* @__PURE__ */ React97__default.createElement(TableCell, null, item.description), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React97__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React97__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React97__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React97__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React97__default.createElement(DialogHeader, null, /* @__PURE__ */ React97__default.createElement(DialogTitle2, null, currentItem ? "Edit Context" : "Add New Context")), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemCode" }, "Code"), /* @__PURE__ */ React97__default.createElement(Input, { id: "itemCode", value: itemCode, onChange: (e2) => setItemCode(e2.target.value.toUpperCase()), placeholder: "e.g., HIST_INQ", disabled: !!currentItem })), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemName" }, "Name"), /* @__PURE__ */ React97__default.createElement(Input, { id: "itemName", value: itemName, onChange: (e2) => setItemName(e2.target.value), placeholder: "e.g., Historical Inquiry" })), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "itemDescription" }, "Description (Optional)"), /* @__PURE__ */ React97__default.createElement(Textarea, { id: "itemDescription", value: itemDescription, onChange: (e2) => setItemDescription(e2.target.value), placeholder: "e.g., Analyzing primary and secondary sources." }))), /* @__PURE__ */ React97__default.createElement(DialogFooter, null, /* @__PURE__ */ React97__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending || !itemCode.trim() || !itemName.trim() }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Save")))), /* @__PURE__ */ React97__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React97__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React97__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React97__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React97__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.name, '".')), /* @__PURE__ */ React97__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React97__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Delete"))))));
106468
106377
  }
106469
106378
 
106470
106379
  // src/react-ui/components/metadata/ApproachManager.tsx
106471
106380
  init_react_shim();
106472
106381
  var knowledgeDimensions = ["Factual", "Conceptual", "Procedural"];
106473
106382
  var rawDifficultyLevels = ["E", "E~M", "M", "M~H", "H"];
106474
- function ApproachManager() {
106383
+ function ApproachManager({
106384
+ initialData,
106385
+ bloomLevels: bloomLevelsProp,
106386
+ questionTypes: questionTypesProp,
106387
+ isLoading: isLoadingProp,
106388
+ onAdd,
106389
+ onUpdate,
106390
+ onDelete
106391
+ }) {
106475
106392
  const [items, setItems] = useState([]);
106476
106393
  const [bloomLevels, setBloomLevels] = useState([]);
106477
- const [iSpringQuizTypeOptions, setISpringQuizTypeOptions] = useState([]);
106394
+ const [questionTypes, setQuestionTypes] = useState([]);
106478
106395
  const [isLoading, setIsLoading] = useState(true);
106479
106396
  const [isDialogOpen, setIsDialogOpen] = useState(false);
106480
106397
  const [isAlertOpen, setIsAlertOpen] = useState(false);
@@ -106483,30 +106400,37 @@ function ApproachManager() {
106483
106400
  const [itemToDelete, setItemToDelete] = useState(null);
106484
106401
  const [isPending, startTransition] = useTransition();
106485
106402
  const { toast: toast2 } = useToast();
106486
- const fetchItems = () => {
106487
- setIsLoading(true);
106488
- try {
106489
- const approaches = MetadataService.getApproaches();
106490
- const bloomLevelsData = MetadataService.getBloomLevels();
106491
- const questionTypesData = MetadataService.getQuestionTypes();
106492
- setItems(approaches);
106493
- setBloomLevels(bloomLevelsData);
106494
- setISpringQuizTypeOptions(questionTypesData.map((qt) => ({ label: qt.name, value: qt.code })));
106495
- } catch (error) {
106496
- toast2({ title: "Error", description: "Failed to fetch metadata.", variant: "destructive" });
106497
- } finally {
106498
- setIsLoading(false);
106403
+ const isControlled = initialData !== void 0;
106404
+ const refreshData = () => {
106405
+ if (!isControlled) {
106406
+ setIsLoading(true);
106407
+ try {
106408
+ setItems(MetadataService.getApproaches());
106409
+ setBloomLevels(MetadataService.getBloomLevels());
106410
+ setQuestionTypes(MetadataService.getQuestionTypes());
106411
+ } catch (error) {
106412
+ toast2({ title: "Error", description: "Failed to refresh metadata for Approaches.", variant: "destructive" });
106413
+ } finally {
106414
+ setIsLoading(false);
106415
+ }
106499
106416
  }
106500
106417
  };
106501
106418
  useEffect(() => {
106502
- fetchItems();
106503
- }, []);
106419
+ if (isControlled) {
106420
+ setItems(initialData || []);
106421
+ setBloomLevels(bloomLevelsProp || []);
106422
+ setQuestionTypes(questionTypesProp || []);
106423
+ setIsLoading(isLoadingProp || false);
106424
+ } else {
106425
+ refreshData();
106426
+ }
106427
+ }, [isControlled, initialData, bloomLevelsProp, questionTypesProp, isLoadingProp]);
106504
106428
  const resetForm = () => {
106505
106429
  setFormState({
106506
106430
  knowledgeDimension: "Factual",
106507
106431
  rawDifficulty: "E",
106508
106432
  bloomLevelCode: bloomLevels.length > 0 ? bloomLevels[0].code : "",
106509
- iSpringQuizType: iSpringQuizTypeOptions.length > 0 ? iSpringQuizTypeOptions[0].value : "multiple_choice"
106433
+ iSpringQuizType: questionTypes.length > 0 ? questionTypes[0].code : "multiple_choice"
106510
106434
  });
106511
106435
  };
106512
106436
  const handleAddItem = () => {
@@ -106536,13 +106460,17 @@ function ApproachManager() {
106536
106460
  };
106537
106461
  const confirmDelete = () => {
106538
106462
  if (!itemToDelete) return;
106539
- startTransition(() => {
106463
+ startTransition(async () => {
106540
106464
  try {
106541
- MetadataService.deleteApproach(itemToDelete.code);
106465
+ if (isControlled && onDelete) {
106466
+ await onDelete(itemToDelete);
106467
+ } else {
106468
+ MetadataService.deleteApproach(itemToDelete.code);
106469
+ refreshData();
106470
+ }
106542
106471
  toast2({ title: "Success", description: `Approach "${itemToDelete.code}" deleted.` });
106543
- fetchItems();
106544
106472
  } catch (error) {
106545
- toast2({ title: "Error", description: "Failed to delete Approach.", variant: "destructive" });
106473
+ toast2({ title: "Error", description: error.message, variant: "destructive" });
106546
106474
  } finally {
106547
106475
  setIsAlertOpen(false);
106548
106476
  setItemToDelete(null);
@@ -106550,28 +106478,37 @@ function ApproachManager() {
106550
106478
  });
106551
106479
  };
106552
106480
  const handleSubmit = () => {
106553
- const { code: code4, verbEn, verbVi } = formState;
106554
- if (!code4?.trim() || !verbEn?.trim() || !verbVi?.trim()) {
106555
- toast2({ title: "Validation Error", description: "Code, Verb (EN), and Verb (VI) are required.", variant: "destructive" });
106481
+ const { code: code4, verbEn, verbVi, bloomLevelCode, iSpringQuizType, knowledgeDimension, rawDifficulty } = formState;
106482
+ if (!code4?.trim() || !verbEn?.trim() || !verbVi?.trim() || !bloomLevelCode || !iSpringQuizType || !knowledgeDimension || !rawDifficulty) {
106483
+ toast2({ title: "Validation Error", description: "All fields except examples and context are required.", variant: "destructive" });
106556
106484
  return;
106557
106485
  }
106558
- startTransition(() => {
106486
+ startTransition(async () => {
106559
106487
  try {
106560
106488
  if (currentItem) {
106561
- MetadataService.updateApproach(currentItem.id, formState);
106489
+ if (isControlled && onUpdate) {
106490
+ await onUpdate({ ...currentItem, ...formState });
106491
+ } else {
106492
+ MetadataService.updateApproach(currentItem.id, formState);
106493
+ refreshData();
106494
+ }
106562
106495
  toast2({ title: "Success", description: "Approach updated." });
106563
106496
  } else {
106564
- MetadataService.addApproach(formState);
106497
+ if (isControlled && onAdd) {
106498
+ await onAdd(formState);
106499
+ } else {
106500
+ MetadataService.addApproach(formState);
106501
+ refreshData();
106502
+ }
106565
106503
  toast2({ title: "Success", description: "Approach added." });
106566
106504
  }
106567
- fetchItems();
106568
106505
  setIsDialogOpen(false);
106569
106506
  } catch (error) {
106570
- toast2({ title: "Error", description: error.message || "Failed to save Approach.", variant: "destructive" });
106507
+ toast2({ title: "Error", description: error.message, variant: "destructive" });
106571
106508
  }
106572
106509
  });
106573
106510
  };
106574
- return /* @__PURE__ */ React97__default.createElement(Card, null, /* @__PURE__ */ React97__default.createElement(CardHeader, null, /* @__PURE__ */ React97__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React97__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React97__default.createElement(Settings2, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Approaches"), /* @__PURE__ */ React97__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React97__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Approach"))), /* @__PURE__ */ React97__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React97__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React97__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No Approaches found.") : /* @__PURE__ */ React97__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React97__default.createElement(Table2, null, /* @__PURE__ */ React97__default.createElement(TableHeader, null, /* @__PURE__ */ React97__default.createElement(TableRow, null, /* @__PURE__ */ React97__default.createElement(TableHead, null, "Approach ID"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Verb (VI)"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Cognitive Level"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "iSpring Type"), /* @__PURE__ */ React97__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React97__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React97__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-medium" }, item.code), /* @__PURE__ */ React97__default.createElement(TableCell, null, item.verbVi), /* @__PURE__ */ React97__default.createElement(TableCell, null, item.bloomLevelCode), /* @__PURE__ */ React97__default.createElement(TableCell, null, item.iSpringQuizType), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React97__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React97__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React97__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React97__default.createElement(DialogContent2, { className: "sm:max-w-2xl max-h-[90vh] overflow-y-auto" }, /* @__PURE__ */ React97__default.createElement(DialogHeader, null, /* @__PURE__ */ React97__default.createElement(DialogTitle2, null, currentItem ? "Edit Approach" : "Add New Approach")), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React97__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React97__default.createElement("div", null, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "code" }, "Approach Code"), /* @__PURE__ */ React97__default.createElement(Input, { id: "code", value: formState.code || "", onChange: (e2) => setFormState((s2) => ({ ...s2, code: e2.target.value.toUpperCase() })), placeholder: "e.g., REM-FAC-IDT-MCQ", disabled: !!currentItem })), /* @__PURE__ */ React97__default.createElement("div", null, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "verbEn" }, "Verb (English)"), /* @__PURE__ */ React97__default.createElement(Input, { id: "verbEn", value: formState.verbEn || "", onChange: (e2) => setFormState((s2) => ({ ...s2, verbEn: e2.target.value })), placeholder: "e.g., Identify" }))), /* @__PURE__ */ React97__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React97__default.createElement("div", null, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "verbVi" }, "Verb (Vietnamese)"), /* @__PURE__ */ React97__default.createElement(Input, { id: "verbVi", value: formState.verbVi || "", onChange: (e2) => setFormState((s2) => ({ ...s2, verbVi: e2.target.value })), placeholder: "e.g., Nh\u1EADn d\u1EA1ng" })), /* @__PURE__ */ React97__default.createElement("div", null, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "bloomLevelCode" }, "Cognitive Level"), /* @__PURE__ */ React97__default.createElement(Select2, { value: formState.bloomLevelCode, onValueChange: (v) => setFormState((s2) => ({ ...s2, bloomLevelCode: v })) }, /* @__PURE__ */ React97__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React97__default.createElement(SelectValue2, null)), /* @__PURE__ */ React97__default.createElement(SelectContent2, null, bloomLevels.map((level) => /* @__PURE__ */ React97__default.createElement(SelectItem2, { key: level.code, value: level.code }, level.name)))))), /* @__PURE__ */ React97__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-4" }, /* @__PURE__ */ React97__default.createElement("div", null, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "knowledgeDimension" }, "Knowledge Dimension"), /* @__PURE__ */ React97__default.createElement(Select2, { value: formState.knowledgeDimension, onValueChange: (v) => setFormState((s2) => ({ ...s2, knowledgeDimension: v })) }, /* @__PURE__ */ React97__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React97__default.createElement(SelectValue2, null)), /* @__PURE__ */ React97__default.createElement(SelectContent2, null, knowledgeDimensions.map((kd) => /* @__PURE__ */ React97__default.createElement(SelectItem2, { key: kd, value: kd }, kd))))), /* @__PURE__ */ React97__default.createElement("div", null, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "iSpringQuizType" }, "iSpring Quiz Type"), /* @__PURE__ */ React97__default.createElement(Select2, { value: formState.iSpringQuizType, onValueChange: (v) => setFormState((s2) => ({ ...s2, iSpringQuizType: v })) }, /* @__PURE__ */ React97__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React97__default.createElement(SelectValue2, null)), /* @__PURE__ */ React97__default.createElement(SelectContent2, null, iSpringQuizTypeOptions.map((qt) => /* @__PURE__ */ React97__default.createElement(SelectItem2, { key: qt.value, value: qt.value }, qt.label))))), /* @__PURE__ */ React97__default.createElement("div", null, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "rawDifficulty" }, "Raw Difficulty"), /* @__PURE__ */ React97__default.createElement(Select2, { value: formState.rawDifficulty, onValueChange: (v) => setFormState((s2) => ({ ...s2, rawDifficulty: v })) }, /* @__PURE__ */ React97__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React97__default.createElement(SelectValue2, null)), /* @__PURE__ */ React97__default.createElement(SelectContent2, null, rawDifficultyLevels.map((rd) => /* @__PURE__ */ React97__default.createElement(SelectItem2, { key: rd, value: rd }, rd)))))), /* @__PURE__ */ React97__default.createElement("div", null, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "suggestContext" }, "Suggest Context (comma-separated codes)"), /* @__PURE__ */ React97__default.createElement(Input, { id: "suggestContext", value: formState.suggestContext || "", onChange: (e2) => setFormState((s2) => ({ ...s2, suggestContext: e2.target.value })), placeholder: "e.g., A, B, D, G, H" })), /* @__PURE__ */ React97__default.createElement("div", null, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "exampleEn" }, "Example (English)"), /* @__PURE__ */ React97__default.createElement(Textarea, { id: "exampleEn", value: formState.exampleEn || "", onChange: (e2) => setFormState((s2) => ({ ...s2, exampleEn: e2.target.value })), placeholder: "English example prompt..." })), /* @__PURE__ */ React97__default.createElement("div", null, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "exampleVi" }, "Example (Vietnamese)"), /* @__PURE__ */ React97__default.createElement(Textarea, { id: "exampleVi", value: formState.exampleVi || "", onChange: (e2) => setFormState((s2) => ({ ...s2, exampleVi: e2.target.value })), placeholder: "Vietnamese example prompt..." }))), /* @__PURE__ */ React97__default.createElement(DialogFooter, null, /* @__PURE__ */ React97__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending || !formState.code?.trim() || !formState.verbEn?.trim() || !formState.verbVi?.trim() }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Save")))), /* @__PURE__ */ React97__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React97__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React97__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React97__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React97__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.code, '".')), /* @__PURE__ */ React97__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React97__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Delete"))))));
106511
+ return /* @__PURE__ */ React97__default.createElement(Card, null, /* @__PURE__ */ React97__default.createElement(CardHeader, null, /* @__PURE__ */ React97__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React97__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React97__default.createElement(Settings2, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Approaches"), /* @__PURE__ */ React97__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React97__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Approach"))), /* @__PURE__ */ React97__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React97__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React97__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No Approaches found.") : /* @__PURE__ */ React97__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React97__default.createElement(Table2, null, /* @__PURE__ */ React97__default.createElement(TableHeader, null, /* @__PURE__ */ React97__default.createElement(TableRow, null, /* @__PURE__ */ React97__default.createElement(TableHead, null, "Approach ID"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Verb (VI)"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "Cognitive Level"), /* @__PURE__ */ React97__default.createElement(TableHead, null, "iSpring Type"), /* @__PURE__ */ React97__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React97__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React97__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React97__default.createElement(TableCell, { className: "font-medium" }, item.code), /* @__PURE__ */ React97__default.createElement(TableCell, null, item.verbVi), /* @__PURE__ */ React97__default.createElement(TableCell, null, item.bloomLevelCode), /* @__PURE__ */ React97__default.createElement(TableCell, null, item.iSpringQuizType), /* @__PURE__ */ React97__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React97__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React97__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React97__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React97__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React97__default.createElement(DialogContent2, { className: "sm:max-w-2xl max-h-[90vh] overflow-y-auto" }, /* @__PURE__ */ React97__default.createElement(DialogHeader, null, /* @__PURE__ */ React97__default.createElement(DialogTitle2, null, currentItem ? "Edit Approach" : "Add New Approach")), /* @__PURE__ */ React97__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React97__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React97__default.createElement("div", null, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "code" }, "Approach Code"), /* @__PURE__ */ React97__default.createElement(Input, { id: "code", value: formState.code || "", onChange: (e2) => setFormState((s2) => ({ ...s2, code: e2.target.value.toUpperCase() })), placeholder: "e.g., REM-FAC-IDT-MCQ", disabled: !!currentItem })), /* @__PURE__ */ React97__default.createElement("div", null, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "verbEn" }, "Verb (English)"), /* @__PURE__ */ React97__default.createElement(Input, { id: "verbEn", value: formState.verbEn || "", onChange: (e2) => setFormState((s2) => ({ ...s2, verbEn: e2.target.value })), placeholder: "e.g., Identify" }))), /* @__PURE__ */ React97__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React97__default.createElement("div", null, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "verbVi" }, "Verb (Vietnamese)"), /* @__PURE__ */ React97__default.createElement(Input, { id: "verbVi", value: formState.verbVi || "", onChange: (e2) => setFormState((s2) => ({ ...s2, verbVi: e2.target.value })), placeholder: "e.g., Nh\u1EADn d\u1EA1ng" })), /* @__PURE__ */ React97__default.createElement("div", null, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "bloomLevelCode" }, "Cognitive Level"), /* @__PURE__ */ React97__default.createElement(Select2, { value: formState.bloomLevelCode, onValueChange: (v) => setFormState((s2) => ({ ...s2, bloomLevelCode: v })) }, /* @__PURE__ */ React97__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React97__default.createElement(SelectValue2, null)), /* @__PURE__ */ React97__default.createElement(SelectContent2, null, bloomLevels.map((level) => /* @__PURE__ */ React97__default.createElement(SelectItem2, { key: level.code, value: level.code }, level.name)))))), /* @__PURE__ */ React97__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-4" }, /* @__PURE__ */ React97__default.createElement("div", null, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "knowledgeDimension" }, "Knowledge Dimension"), /* @__PURE__ */ React97__default.createElement(Select2, { value: formState.knowledgeDimension, onValueChange: (v) => setFormState((s2) => ({ ...s2, knowledgeDimension: v })) }, /* @__PURE__ */ React97__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React97__default.createElement(SelectValue2, null)), /* @__PURE__ */ React97__default.createElement(SelectContent2, null, knowledgeDimensions.map((kd) => /* @__PURE__ */ React97__default.createElement(SelectItem2, { key: kd, value: kd }, kd))))), /* @__PURE__ */ React97__default.createElement("div", null, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "iSpringQuizType" }, "iSpring Quiz Type"), /* @__PURE__ */ React97__default.createElement(Select2, { value: formState.iSpringQuizType, onValueChange: (v) => setFormState((s2) => ({ ...s2, iSpringQuizType: v })) }, /* @__PURE__ */ React97__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React97__default.createElement(SelectValue2, null)), /* @__PURE__ */ React97__default.createElement(SelectContent2, null, questionTypes.map((qt) => /* @__PURE__ */ React97__default.createElement(SelectItem2, { key: qt.code, value: qt.code }, qt.name))))), /* @__PURE__ */ React97__default.createElement("div", null, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "rawDifficulty" }, "Raw Difficulty"), /* @__PURE__ */ React97__default.createElement(Select2, { value: formState.rawDifficulty, onValueChange: (v) => setFormState((s2) => ({ ...s2, rawDifficulty: v })) }, /* @__PURE__ */ React97__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React97__default.createElement(SelectValue2, null)), /* @__PURE__ */ React97__default.createElement(SelectContent2, null, rawDifficultyLevels.map((rd) => /* @__PURE__ */ React97__default.createElement(SelectItem2, { key: rd, value: rd }, rd)))))), /* @__PURE__ */ React97__default.createElement("div", null, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "suggestContext" }, "Suggest Context (comma-separated codes)"), /* @__PURE__ */ React97__default.createElement(Input, { id: "suggestContext", value: formState.suggestContext || "", onChange: (e2) => setFormState((s2) => ({ ...s2, suggestContext: e2.target.value })), placeholder: "e.g., A, B, D, G, H" })), /* @__PURE__ */ React97__default.createElement("div", null, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "exampleEn" }, "Example (English)"), /* @__PURE__ */ React97__default.createElement(Textarea, { id: "exampleEn", value: formState.exampleEn || "", onChange: (e2) => setFormState((s2) => ({ ...s2, exampleEn: e2.target.value })), placeholder: "English example prompt..." })), /* @__PURE__ */ React97__default.createElement("div", null, /* @__PURE__ */ React97__default.createElement(Label2, { htmlFor: "exampleVi" }, "Example (Vietnamese)"), /* @__PURE__ */ React97__default.createElement(Textarea, { id: "exampleVi", value: formState.exampleVi || "", onChange: (e2) => setFormState((s2) => ({ ...s2, exampleVi: e2.target.value })), placeholder: "Vietnamese example prompt..." }))), /* @__PURE__ */ React97__default.createElement(DialogFooter, null, /* @__PURE__ */ React97__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Save")))), /* @__PURE__ */ React97__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React97__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React97__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React97__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React97__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.code, '".')), /* @__PURE__ */ React97__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React97__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React97__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React97__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Delete"))))));
106575
106512
  }
106576
106513
 
106577
106514
  // src/react-ui/components/metadata/MetadataTabs.tsx