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