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