@thanh01.pmt/interactive-quiz-kit 1.0.50 → 1.0.52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/react-ui.mjs
CHANGED
|
@@ -168220,7 +168220,7 @@ function SubjectManager({
|
|
|
168220
168220
|
|
|
168221
168221
|
// src/react-ui/components/metadata/GradeLevelManager.tsx
|
|
168222
168222
|
init_react_shim();
|
|
168223
|
-
function GradeLevelManager() {
|
|
168223
|
+
function GradeLevelManager({ initialData, isLoading: isLoadingProp, onAdd, onUpdate, onDelete }) {
|
|
168224
168224
|
const [items, setItems] = useState([]);
|
|
168225
168225
|
const [isLoading, setIsLoading] = useState(true);
|
|
168226
168226
|
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
|
@@ -168231,19 +168231,27 @@ function GradeLevelManager() {
|
|
|
168231
168231
|
const [itemToDelete, setItemToDelete] = useState(null);
|
|
168232
168232
|
const [isPending, startTransition] = useTransition();
|
|
168233
168233
|
const { toast: toast2 } = useToast();
|
|
168234
|
-
|
|
168235
|
-
|
|
168236
|
-
|
|
168237
|
-
|
|
168238
|
-
|
|
168239
|
-
|
|
168240
|
-
|
|
168241
|
-
|
|
168242
|
-
|
|
168243
|
-
|
|
168244
|
-
|
|
168234
|
+
const isControlled = initialData !== void 0;
|
|
168235
|
+
const refreshData = () => {
|
|
168236
|
+
if (!isControlled) {
|
|
168237
|
+
setIsLoading(true);
|
|
168238
|
+
try {
|
|
168239
|
+
setItems(MetadataService.getGradeLevels());
|
|
168240
|
+
} catch (error) {
|
|
168241
|
+
toast2({ title: "Error", description: "Failed to refresh grade levels.", variant: "destructive" });
|
|
168242
|
+
} finally {
|
|
168243
|
+
setIsLoading(false);
|
|
168244
|
+
}
|
|
168245
168245
|
}
|
|
168246
168246
|
};
|
|
168247
|
+
useEffect(() => {
|
|
168248
|
+
if (isControlled) {
|
|
168249
|
+
setItems(initialData || []);
|
|
168250
|
+
setIsLoading(isLoadingProp || false);
|
|
168251
|
+
} else {
|
|
168252
|
+
refreshData();
|
|
168253
|
+
}
|
|
168254
|
+
}, [isControlled, initialData, isLoadingProp]);
|
|
168247
168255
|
const handleAddItem = () => {
|
|
168248
168256
|
setCurrentItem(null);
|
|
168249
168257
|
setItemName("");
|
|
@@ -168262,13 +168270,17 @@ function GradeLevelManager() {
|
|
|
168262
168270
|
};
|
|
168263
168271
|
const confirmDelete = () => {
|
|
168264
168272
|
if (!itemToDelete) return;
|
|
168265
|
-
startTransition(() => {
|
|
168273
|
+
startTransition(async () => {
|
|
168266
168274
|
try {
|
|
168267
|
-
|
|
168275
|
+
if (isControlled && onDelete) {
|
|
168276
|
+
await onDelete(itemToDelete);
|
|
168277
|
+
} else {
|
|
168278
|
+
MetadataService.deleteGradeLevel(itemToDelete.code);
|
|
168279
|
+
refreshData();
|
|
168280
|
+
}
|
|
168268
168281
|
toast2({ title: "Success", description: `Grade Level "${itemToDelete.name}" deleted.` });
|
|
168269
|
-
fetchItems();
|
|
168270
168282
|
} catch (error) {
|
|
168271
|
-
toast2({ title: "Error", description:
|
|
168283
|
+
toast2({ title: "Error", description: error.message, variant: "destructive" });
|
|
168272
168284
|
} finally {
|
|
168273
168285
|
setIsAlertOpen(false);
|
|
168274
168286
|
setItemToDelete(null);
|
|
@@ -168280,27 +168292,44 @@ function GradeLevelManager() {
|
|
|
168280
168292
|
toast2({ title: "Validation Error", description: "Code and Name are required.", variant: "destructive" });
|
|
168281
168293
|
return;
|
|
168282
168294
|
}
|
|
168283
|
-
startTransition(() => {
|
|
168295
|
+
startTransition(async () => {
|
|
168284
168296
|
try {
|
|
168285
168297
|
if (currentItem) {
|
|
168286
|
-
|
|
168298
|
+
if (isControlled && onUpdate) {
|
|
168299
|
+
await onUpdate({ id: currentItem.id, name: itemName, code: itemCode });
|
|
168300
|
+
} else {
|
|
168301
|
+
MetadataService.updateGradeLevel(currentItem.id, itemName, itemCode);
|
|
168302
|
+
refreshData();
|
|
168303
|
+
}
|
|
168304
|
+
toast2({ title: "Success", description: "Grade Level updated." });
|
|
168287
168305
|
} else {
|
|
168288
|
-
|
|
168306
|
+
if (isControlled && onAdd) {
|
|
168307
|
+
await onAdd({ name: itemName, code: itemCode });
|
|
168308
|
+
} else {
|
|
168309
|
+
MetadataService.addGradeLevel(itemName, itemCode);
|
|
168310
|
+
refreshData();
|
|
168311
|
+
}
|
|
168312
|
+
toast2({ title: "Success", description: "Grade Level added." });
|
|
168289
168313
|
}
|
|
168290
|
-
toast2({ title: "Success", description: `Grade Level saved.` });
|
|
168291
|
-
fetchItems();
|
|
168292
168314
|
setIsDialogOpen(false);
|
|
168293
168315
|
} catch (error) {
|
|
168294
|
-
toast2({ title: "Error", description:
|
|
168316
|
+
toast2({ title: "Error", description: error.message, variant: "destructive" });
|
|
168295
168317
|
}
|
|
168296
168318
|
});
|
|
168297
168319
|
};
|
|
168298
|
-
return /* @__PURE__ */ React163__default.createElement(Card, null, /* @__PURE__ */ React163__default.createElement(CardHeader, null, /* @__PURE__ */ React163__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React163__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React163__default.createElement(Award, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Grade Levels"), /* @__PURE__ */ React163__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React163__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Grade Level"))), /* @__PURE__ */ React163__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React163__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React163__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No grade levels found.") : /* @__PURE__ */ React163__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React163__default.createElement(Table3, null, /* @__PURE__ */ React163__default.createElement(TableHeader, null, /* @__PURE__ */ React163__default.createElement(TableRow, null, /* @__PURE__ */ React163__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React163__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React163__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React163__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-mono text-xs" }, item.code), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-medium" }, item.name), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React163__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React163__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React163__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React163__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React163__default.createElement(DialogHeader, null, /* @__PURE__ */ React163__default.createElement(DialogTitle2, null, currentItem ? "Edit Grade Level" : "Add New Grade Level")), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemCode" }, "Code"), /* @__PURE__ */ React163__default.createElement(Input, { id: "itemCode", value: itemCode, onChange: (e3) => setItemCode(e3.target.value.toUpperCase()), placeholder: "e.g., G9", disabled: !!currentItem })), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemName" }, "Name"), /* @__PURE__ */ React163__default.createElement(Input, { id: "itemName", value: itemName, onChange: (e3) => setItemName(e3.target.value), placeholder: "e.g., Grade 9" }))), /* @__PURE__ */ React163__default.createElement(DialogFooter, null, /* @__PURE__ */ React163__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending || !itemName.trim() || !itemCode.trim() }, isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), "Save")))), /* @__PURE__ */ React163__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React163__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React163__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React163__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React163__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.name, '".')), /* @__PURE__ */ React163__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React163__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), "Delete"))))));
|
|
168320
|
+
return /* @__PURE__ */ React163__default.createElement(Card, null, /* @__PURE__ */ React163__default.createElement(CardHeader, null, /* @__PURE__ */ React163__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React163__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React163__default.createElement(Award, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Grade Levels"), /* @__PURE__ */ React163__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React163__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Grade Level"))), /* @__PURE__ */ React163__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React163__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React163__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No grade levels found.") : /* @__PURE__ */ React163__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React163__default.createElement(Table3, null, /* @__PURE__ */ React163__default.createElement(TableHeader, null, /* @__PURE__ */ React163__default.createElement(TableRow, null, /* @__PURE__ */ React163__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React163__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React163__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React163__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-mono text-xs" }, item.code), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-medium" }, item.name), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React163__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React163__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React163__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React163__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React163__default.createElement(DialogHeader, null, /* @__PURE__ */ React163__default.createElement(DialogTitle2, null, currentItem ? "Edit Grade Level" : "Add New Grade Level")), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemCode" }, "Code"), /* @__PURE__ */ React163__default.createElement(Input, { id: "itemCode", value: itemCode, onChange: (e3) => setItemCode(e3.target.value.toUpperCase()), placeholder: "e.g., G9", disabled: !!currentItem })), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemName" }, "Name"), /* @__PURE__ */ React163__default.createElement(Input, { id: "itemName", value: itemName, onChange: (e3) => setItemName(e3.target.value), placeholder: "e.g., Grade 9" }))), /* @__PURE__ */ React163__default.createElement(DialogFooter, null, /* @__PURE__ */ React163__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending || !itemName.trim() || !itemCode.trim() }, isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Save")))), /* @__PURE__ */ React163__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React163__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React163__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React163__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React163__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.name, '".')), /* @__PURE__ */ React163__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React163__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Delete"))))));
|
|
168299
168321
|
}
|
|
168300
168322
|
|
|
168301
168323
|
// src/react-ui/components/metadata/TopicManager.tsx
|
|
168302
168324
|
init_react_shim();
|
|
168303
|
-
function TopicManager(
|
|
168325
|
+
function TopicManager({
|
|
168326
|
+
initialData,
|
|
168327
|
+
subjects: subjectsProp,
|
|
168328
|
+
isLoading: isLoadingProp,
|
|
168329
|
+
onAdd,
|
|
168330
|
+
onUpdate,
|
|
168331
|
+
onDelete
|
|
168332
|
+
}) {
|
|
168304
168333
|
const [topics, setTopics] = useState([]);
|
|
168305
168334
|
const [subjects, setSubjects] = useState([]);
|
|
168306
168335
|
const [isLoading, setIsLoading] = useState(true);
|
|
@@ -168313,36 +168342,34 @@ function TopicManager() {
|
|
|
168313
168342
|
const [itemToDelete, setItemToDelete] = useState(null);
|
|
168314
168343
|
const [isPending, startTransition] = useTransition();
|
|
168315
168344
|
const { toast: toast2 } = useToast();
|
|
168316
|
-
const
|
|
168317
|
-
|
|
168318
|
-
|
|
168319
|
-
|
|
168320
|
-
|
|
168321
|
-
|
|
168322
|
-
|
|
168323
|
-
|
|
168324
|
-
|
|
168345
|
+
const isControlled = initialData !== void 0;
|
|
168346
|
+
const refreshData = () => {
|
|
168347
|
+
if (!isControlled) {
|
|
168348
|
+
setIsLoading(true);
|
|
168349
|
+
try {
|
|
168350
|
+
setTopics(MetadataService.getTopics());
|
|
168351
|
+
setSubjects(MetadataService.getSubjects());
|
|
168352
|
+
} catch (error) {
|
|
168353
|
+
toast2({ title: "Error", description: "Failed to refresh topics or subjects.", variant: "destructive" });
|
|
168354
|
+
} finally {
|
|
168355
|
+
setIsLoading(false);
|
|
168325
168356
|
}
|
|
168326
|
-
} catch (error) {
|
|
168327
|
-
toast2({
|
|
168328
|
-
title: "Error",
|
|
168329
|
-
description: "Failed to fetch topics or subjects.",
|
|
168330
|
-
variant: "destructive"
|
|
168331
|
-
});
|
|
168332
|
-
} finally {
|
|
168333
|
-
setIsLoading(false);
|
|
168334
168357
|
}
|
|
168335
168358
|
};
|
|
168336
168359
|
useEffect(() => {
|
|
168337
|
-
|
|
168338
|
-
|
|
168360
|
+
if (isControlled) {
|
|
168361
|
+
setTopics(initialData || []);
|
|
168362
|
+
setSubjects(subjectsProp || []);
|
|
168363
|
+
setIsLoading(isLoadingProp || false);
|
|
168364
|
+
} else {
|
|
168365
|
+
refreshData();
|
|
168366
|
+
}
|
|
168367
|
+
}, [isControlled, initialData, subjectsProp, isLoadingProp]);
|
|
168339
168368
|
const handleAddItem = () => {
|
|
168340
168369
|
setCurrentItem(null);
|
|
168341
168370
|
setItemName("");
|
|
168342
168371
|
setItemCode("");
|
|
168343
|
-
|
|
168344
|
-
setSelectedSubjectCode(subjects[0].code);
|
|
168345
|
-
}
|
|
168372
|
+
setSelectedSubjectCode(subjects.length > 0 ? subjects[0].code : "");
|
|
168346
168373
|
setIsDialogOpen(true);
|
|
168347
168374
|
};
|
|
168348
168375
|
const handleEditItem = (topic) => {
|
|
@@ -168358,20 +168385,17 @@ function TopicManager() {
|
|
|
168358
168385
|
};
|
|
168359
168386
|
const confirmDelete = () => {
|
|
168360
168387
|
if (!itemToDelete) return;
|
|
168361
|
-
startTransition(() => {
|
|
168388
|
+
startTransition(async () => {
|
|
168362
168389
|
try {
|
|
168363
|
-
|
|
168364
|
-
|
|
168365
|
-
|
|
168366
|
-
|
|
168367
|
-
|
|
168368
|
-
|
|
168390
|
+
if (isControlled && onDelete) {
|
|
168391
|
+
await onDelete(itemToDelete);
|
|
168392
|
+
} else {
|
|
168393
|
+
MetadataService.deleteTopic(itemToDelete.code);
|
|
168394
|
+
refreshData();
|
|
168395
|
+
}
|
|
168396
|
+
toast2({ title: "Success", description: `Topic "${itemToDelete.name}" deleted.` });
|
|
168369
168397
|
} catch (error) {
|
|
168370
|
-
toast2({
|
|
168371
|
-
title: "Error",
|
|
168372
|
-
description: "Failed to delete topic.",
|
|
168373
|
-
variant: "destructive"
|
|
168374
|
-
});
|
|
168398
|
+
toast2({ title: "Error", description: error.message, variant: "destructive" });
|
|
168375
168399
|
} finally {
|
|
168376
168400
|
setIsAlertOpen(false);
|
|
168377
168401
|
setItemToDelete(null);
|
|
@@ -168380,144 +168404,43 @@ function TopicManager() {
|
|
|
168380
168404
|
};
|
|
168381
168405
|
const handleSubmit = () => {
|
|
168382
168406
|
if (!itemName.trim() || !itemCode.trim() || !selectedSubjectCode) {
|
|
168383
|
-
toast2({
|
|
168384
|
-
title: "Validation Error",
|
|
168385
|
-
description: "Name, Code, and Subject are required.",
|
|
168386
|
-
variant: "destructive"
|
|
168387
|
-
});
|
|
168407
|
+
toast2({ title: "Validation Error", description: "Name, Code, and Subject are required.", variant: "destructive" });
|
|
168388
168408
|
return;
|
|
168389
168409
|
}
|
|
168390
|
-
startTransition(() => {
|
|
168410
|
+
startTransition(async () => {
|
|
168391
168411
|
try {
|
|
168392
168412
|
if (currentItem) {
|
|
168393
|
-
|
|
168394
|
-
currentItem.id,
|
|
168395
|
-
|
|
168396
|
-
itemCode,
|
|
168397
|
-
|
|
168398
|
-
|
|
168413
|
+
if (isControlled && onUpdate) {
|
|
168414
|
+
await onUpdate({ id: currentItem.id, name: itemName, code: itemCode, subjectCode: selectedSubjectCode });
|
|
168415
|
+
} else {
|
|
168416
|
+
MetadataService.updateTopic(currentItem.id, itemName, itemCode, selectedSubjectCode);
|
|
168417
|
+
refreshData();
|
|
168418
|
+
}
|
|
168419
|
+
toast2({ title: "Success", description: "Topic updated." });
|
|
168399
168420
|
} else {
|
|
168400
|
-
|
|
168401
|
-
itemName,
|
|
168402
|
-
|
|
168403
|
-
selectedSubjectCode
|
|
168404
|
-
|
|
168421
|
+
if (isControlled && onAdd) {
|
|
168422
|
+
await onAdd({ name: itemName, code: itemCode, subjectCode: selectedSubjectCode });
|
|
168423
|
+
} else {
|
|
168424
|
+
MetadataService.addTopic(itemName, itemCode, selectedSubjectCode);
|
|
168425
|
+
refreshData();
|
|
168426
|
+
}
|
|
168427
|
+
toast2({ title: "Success", description: "Topic added." });
|
|
168405
168428
|
}
|
|
168406
|
-
toast2({ title: "Success", description: "Topic saved." });
|
|
168407
|
-
fetchData();
|
|
168408
168429
|
setIsDialogOpen(false);
|
|
168409
168430
|
} catch (error) {
|
|
168410
|
-
toast2({
|
|
168411
|
-
title: "Error",
|
|
168412
|
-
description: "Failed to save topic.",
|
|
168413
|
-
variant: "destructive"
|
|
168414
|
-
});
|
|
168431
|
+
toast2({ title: "Error", description: error.message, variant: "destructive" });
|
|
168415
168432
|
}
|
|
168416
168433
|
});
|
|
168417
168434
|
};
|
|
168418
168435
|
const getSubjectName = (subjectCode) => {
|
|
168419
168436
|
return subjects.find((s4) => s4.code === subjectCode)?.name || "N/A";
|
|
168420
168437
|
};
|
|
168421
|
-
return /* @__PURE__ */ React163__default.createElement(Card, null, /* @__PURE__ */ React163__default.createElement(CardHeader, null, /* @__PURE__ */ React163__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React163__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React163__default.createElement(Tag, { className: "mr-2 h-5 w-5 text-primary" }), "Manage Topics"), /* @__PURE__ */ React163__default.createElement(
|
|
168422
|
-
Button,
|
|
168423
|
-
{
|
|
168424
|
-
onClick: handleAddItem,
|
|
168425
|
-
size: "sm",
|
|
168426
|
-
disabled: subjects.length === 0
|
|
168427
|
-
},
|
|
168428
|
-
/* @__PURE__ */ React163__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }),
|
|
168429
|
-
" Add Topic"
|
|
168430
|
-
)), subjects.length === 0 && !isLoading && /* @__PURE__ */ React163__default.createElement("p", { className: "text-sm text-destructive" }, "Please add subjects before adding topics.")), /* @__PURE__ */ React163__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React163__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : topics.length === 0 ? /* @__PURE__ */ React163__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No topics found. Add one to get started!") : /* @__PURE__ */ React163__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React163__default.createElement(Table3, null, /* @__PURE__ */ React163__default.createElement(TableHeader, null, /* @__PURE__ */ React163__default.createElement(TableRow, null, /* @__PURE__ */ React163__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Subject"), /* @__PURE__ */ React163__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React163__default.createElement(TableBody, null, topics.map((topic) => /* @__PURE__ */ React163__default.createElement(TableRow, { key: topic.id }, /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-mono text-xs" }, topic.code), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-medium" }, topic.name), /* @__PURE__ */ React163__default.createElement(TableCell, null, getSubjectName(topic.subjectCode), " ", "(", topic.subjectCode, ")"), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React163__default.createElement(
|
|
168431
|
-
Button,
|
|
168432
|
-
{
|
|
168433
|
-
variant: "ghost",
|
|
168434
|
-
size: "icon",
|
|
168435
|
-
onClick: () => handleEditItem(topic),
|
|
168436
|
-
className: "mr-2"
|
|
168437
|
-
},
|
|
168438
|
-
/* @__PURE__ */ React163__default.createElement(PenLine, { className: "h-4 w-4" })
|
|
168439
|
-
), /* @__PURE__ */ React163__default.createElement(
|
|
168440
|
-
Button,
|
|
168441
|
-
{
|
|
168442
|
-
variant: "ghost",
|
|
168443
|
-
size: "icon",
|
|
168444
|
-
onClick: () => handleDeleteItem(topic),
|
|
168445
|
-
className: "text-destructive hover:text-destructive"
|
|
168446
|
-
},
|
|
168447
|
-
/* @__PURE__ */ React163__default.createElement(Trash2, { className: "h-4 w-4" })
|
|
168448
|
-
))))))), /* @__PURE__ */ React163__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React163__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React163__default.createElement(DialogHeader, null, /* @__PURE__ */ React163__default.createElement(DialogTitle2, null, currentItem ? "Edit Topic" : "Add New Topic")), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemCode" }, "Topic Code"), /* @__PURE__ */ React163__default.createElement(
|
|
168449
|
-
Input,
|
|
168450
|
-
{
|
|
168451
|
-
id: "itemCode",
|
|
168452
|
-
value: itemCode,
|
|
168453
|
-
onChange: (e3) => setItemCode(
|
|
168454
|
-
e3.target.value.toUpperCase()
|
|
168455
|
-
),
|
|
168456
|
-
placeholder: "e.g., ALG-BASICS",
|
|
168457
|
-
disabled: !!currentItem
|
|
168458
|
-
}
|
|
168459
|
-
)), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemName" }, "Topic Name"), /* @__PURE__ */ React163__default.createElement(
|
|
168460
|
-
Input,
|
|
168461
|
-
{
|
|
168462
|
-
id: "itemName",
|
|
168463
|
-
value: itemName,
|
|
168464
|
-
onChange: (e3) => setItemName(e3.target.value),
|
|
168465
|
-
placeholder: "e.g., Algebra Basics"
|
|
168466
|
-
}
|
|
168467
|
-
)), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "subjectCode" }, "Subject"), /* @__PURE__ */ React163__default.createElement(
|
|
168468
|
-
Select2,
|
|
168469
|
-
{
|
|
168470
|
-
value: selectedSubjectCode,
|
|
168471
|
-
onValueChange: setSelectedSubjectCode,
|
|
168472
|
-
disabled: subjects.length === 0
|
|
168473
|
-
},
|
|
168474
|
-
/* @__PURE__ */ React163__default.createElement(SelectTrigger2, { id: "subjectCode" }, /* @__PURE__ */ React163__default.createElement(SelectValue2, { placeholder: "Select a subject" })),
|
|
168475
|
-
/* @__PURE__ */ React163__default.createElement(SelectContent2, null, subjects.map((subject) => /* @__PURE__ */ React163__default.createElement(
|
|
168476
|
-
SelectItem2,
|
|
168477
|
-
{
|
|
168478
|
-
key: subject.code,
|
|
168479
|
-
value: subject.code
|
|
168480
|
-
},
|
|
168481
|
-
subject.name,
|
|
168482
|
-
" (",
|
|
168483
|
-
subject.code,
|
|
168484
|
-
")"
|
|
168485
|
-
)))
|
|
168486
|
-
))), /* @__PURE__ */ React163__default.createElement(DialogFooter, null, /* @__PURE__ */ React163__default.createElement(
|
|
168487
|
-
Button,
|
|
168488
|
-
{
|
|
168489
|
-
type: "button",
|
|
168490
|
-
variant: "outline",
|
|
168491
|
-
onClick: () => setIsDialogOpen(false),
|
|
168492
|
-
disabled: isPending
|
|
168493
|
-
},
|
|
168494
|
-
"Cancel"
|
|
168495
|
-
), /* @__PURE__ */ React163__default.createElement(
|
|
168496
|
-
Button,
|
|
168497
|
-
{
|
|
168498
|
-
type: "submit",
|
|
168499
|
-
onClick: handleSubmit,
|
|
168500
|
-
disabled: isPending || !itemName.trim() || !itemCode.trim() || !selectedSubjectCode
|
|
168501
|
-
},
|
|
168502
|
-
isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }),
|
|
168503
|
-
" ",
|
|
168504
|
-
"Save"
|
|
168505
|
-
)))), /* @__PURE__ */ React163__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React163__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React163__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React163__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React163__default.createElement(AlertDialogDescription2, null, 'This will permanently delete topic "', itemToDelete?.name, '".')), /* @__PURE__ */ React163__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React163__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(
|
|
168506
|
-
AlertDialogAction2,
|
|
168507
|
-
{
|
|
168508
|
-
onClick: confirmDelete,
|
|
168509
|
-
disabled: isPending,
|
|
168510
|
-
className: "bg-destructive hover:bg-destructive/90"
|
|
168511
|
-
},
|
|
168512
|
-
isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }),
|
|
168513
|
-
" ",
|
|
168514
|
-
"Delete"
|
|
168515
|
-
))))));
|
|
168438
|
+
return /* @__PURE__ */ React163__default.createElement(Card, null, /* @__PURE__ */ React163__default.createElement(CardHeader, null, /* @__PURE__ */ React163__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React163__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React163__default.createElement(Tag, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Topics"), /* @__PURE__ */ React163__default.createElement(Button, { onClick: handleAddItem, size: "sm", disabled: subjects.length === 0 }, /* @__PURE__ */ React163__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Topic")), subjects.length === 0 && !isLoading && /* @__PURE__ */ React163__default.createElement("p", { className: "text-sm text-destructive" }, "Please add subjects before adding topics.")), /* @__PURE__ */ React163__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React163__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : topics.length === 0 ? /* @__PURE__ */ React163__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No topics found. Add one to get started!") : /* @__PURE__ */ React163__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React163__default.createElement(Table3, null, /* @__PURE__ */ React163__default.createElement(TableHeader, null, /* @__PURE__ */ React163__default.createElement(TableRow, null, /* @__PURE__ */ React163__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Subject"), /* @__PURE__ */ React163__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React163__default.createElement(TableBody, null, topics.map((topic) => /* @__PURE__ */ React163__default.createElement(TableRow, { key: topic.id }, /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-mono text-xs" }, topic.code), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-medium" }, topic.name), /* @__PURE__ */ React163__default.createElement(TableCell, null, getSubjectName(topic.subjectCode), " (", topic.subjectCode, ")"), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(topic), className: "mr-2" }, /* @__PURE__ */ React163__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(topic), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React163__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React163__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React163__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React163__default.createElement(DialogHeader, null, /* @__PURE__ */ React163__default.createElement(DialogTitle2, null, currentItem ? "Edit Topic" : "Add New Topic")), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemCode" }, "Topic Code"), /* @__PURE__ */ React163__default.createElement(Input, { id: "itemCode", value: itemCode, onChange: (e3) => setItemCode(e3.target.value.toUpperCase()), placeholder: "e.g., ALG-BASICS", disabled: !!currentItem })), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemName" }, "Topic Name"), /* @__PURE__ */ React163__default.createElement(Input, { id: "itemName", value: itemName, onChange: (e3) => setItemName(e3.target.value), placeholder: "e.g., Algebra Basics" })), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "subjectCode" }, "Subject"), /* @__PURE__ */ React163__default.createElement(Select2, { value: selectedSubjectCode, onValueChange: setSelectedSubjectCode, disabled: subjects.length === 0 }, /* @__PURE__ */ React163__default.createElement(SelectTrigger2, { id: "subjectCode" }, /* @__PURE__ */ React163__default.createElement(SelectValue2, { placeholder: "Select a subject" })), /* @__PURE__ */ React163__default.createElement(SelectContent2, null, subjects.map((subject) => /* @__PURE__ */ React163__default.createElement(SelectItem2, { key: subject.code, value: subject.code }, subject.name, " (", subject.code, ")")))))), /* @__PURE__ */ React163__default.createElement(DialogFooter, null, /* @__PURE__ */ React163__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending || !itemName.trim() || !itemCode.trim() || !selectedSubjectCode }, isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Save")))), /* @__PURE__ */ React163__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React163__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React163__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React163__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React163__default.createElement(AlertDialogDescription2, null, 'This will permanently delete topic "', itemToDelete?.name, '".')), /* @__PURE__ */ React163__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React163__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Delete"))))));
|
|
168516
168439
|
}
|
|
168517
168440
|
|
|
168518
168441
|
// src/react-ui/components/metadata/CategoryManager.tsx
|
|
168519
168442
|
init_react_shim();
|
|
168520
|
-
function CategoryManager() {
|
|
168443
|
+
function CategoryManager({ initialData, isLoading: isLoadingProp, onAdd, onUpdate, onDelete }) {
|
|
168521
168444
|
const [items, setItems] = useState([]);
|
|
168522
168445
|
const [isLoading, setIsLoading] = useState(true);
|
|
168523
168446
|
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
|
@@ -168529,19 +168452,27 @@ function CategoryManager() {
|
|
|
168529
168452
|
const [itemToDelete, setItemToDelete] = useState(null);
|
|
168530
168453
|
const [isPending, startTransition] = useTransition();
|
|
168531
168454
|
const { toast: toast2 } = useToast();
|
|
168532
|
-
|
|
168533
|
-
|
|
168534
|
-
|
|
168535
|
-
|
|
168536
|
-
|
|
168537
|
-
|
|
168538
|
-
|
|
168539
|
-
|
|
168540
|
-
|
|
168541
|
-
|
|
168542
|
-
|
|
168455
|
+
const isControlled = initialData !== void 0;
|
|
168456
|
+
const refreshData = () => {
|
|
168457
|
+
if (!isControlled) {
|
|
168458
|
+
setIsLoading(true);
|
|
168459
|
+
try {
|
|
168460
|
+
setItems(MetadataService.getCategories());
|
|
168461
|
+
} catch (error) {
|
|
168462
|
+
toast2({ title: "Error", description: "Failed to refresh categories.", variant: "destructive" });
|
|
168463
|
+
} finally {
|
|
168464
|
+
setIsLoading(false);
|
|
168465
|
+
}
|
|
168543
168466
|
}
|
|
168544
168467
|
};
|
|
168468
|
+
useEffect(() => {
|
|
168469
|
+
if (isControlled) {
|
|
168470
|
+
setItems(initialData || []);
|
|
168471
|
+
setIsLoading(isLoadingProp || false);
|
|
168472
|
+
} else {
|
|
168473
|
+
refreshData();
|
|
168474
|
+
}
|
|
168475
|
+
}, [isControlled, initialData, isLoadingProp]);
|
|
168545
168476
|
const handleAddItem = () => {
|
|
168546
168477
|
setCurrentItem(null);
|
|
168547
168478
|
setItemName("");
|
|
@@ -168562,13 +168493,17 @@ function CategoryManager() {
|
|
|
168562
168493
|
};
|
|
168563
168494
|
const confirmDelete = () => {
|
|
168564
168495
|
if (!itemToDelete) return;
|
|
168565
|
-
startTransition(() => {
|
|
168496
|
+
startTransition(async () => {
|
|
168566
168497
|
try {
|
|
168567
|
-
|
|
168498
|
+
if (isControlled && onDelete) {
|
|
168499
|
+
await onDelete(itemToDelete);
|
|
168500
|
+
} else {
|
|
168501
|
+
MetadataService.deleteCategory(itemToDelete.code);
|
|
168502
|
+
refreshData();
|
|
168503
|
+
}
|
|
168568
168504
|
toast2({ title: "Success", description: `Category "${itemToDelete.name}" deleted.` });
|
|
168569
|
-
fetchItems();
|
|
168570
168505
|
} catch (error) {
|
|
168571
|
-
toast2({ title: "Error", description:
|
|
168506
|
+
toast2({ title: "Error", description: error.message, variant: "destructive" });
|
|
168572
168507
|
} finally {
|
|
168573
168508
|
setIsAlertOpen(false);
|
|
168574
168509
|
setItemToDelete(null);
|
|
@@ -168580,27 +168515,37 @@ function CategoryManager() {
|
|
|
168580
168515
|
toast2({ title: "Validation Error", description: "Code and Name are required.", variant: "destructive" });
|
|
168581
168516
|
return;
|
|
168582
168517
|
}
|
|
168583
|
-
startTransition(() => {
|
|
168518
|
+
startTransition(async () => {
|
|
168584
168519
|
try {
|
|
168585
168520
|
if (currentItem) {
|
|
168586
|
-
|
|
168521
|
+
if (isControlled && onUpdate) {
|
|
168522
|
+
await onUpdate({ id: currentItem.id, name: itemName, code: itemCode, description: itemDescription });
|
|
168523
|
+
} else {
|
|
168524
|
+
MetadataService.updateCategory(currentItem.id, itemName, itemCode, itemDescription);
|
|
168525
|
+
refreshData();
|
|
168526
|
+
}
|
|
168527
|
+
toast2({ title: "Success", description: "Category updated." });
|
|
168587
168528
|
} else {
|
|
168588
|
-
|
|
168529
|
+
if (isControlled && onAdd) {
|
|
168530
|
+
await onAdd({ name: itemName, code: itemCode, description: itemDescription });
|
|
168531
|
+
} else {
|
|
168532
|
+
MetadataService.addCategory(itemName, itemCode, itemDescription);
|
|
168533
|
+
refreshData();
|
|
168534
|
+
}
|
|
168535
|
+
toast2({ title: "Success", description: "Category added." });
|
|
168589
168536
|
}
|
|
168590
|
-
toast2({ title: "Success", description: "Category saved." });
|
|
168591
|
-
fetchItems();
|
|
168592
168537
|
setIsDialogOpen(false);
|
|
168593
168538
|
} catch (error) {
|
|
168594
|
-
toast2({ title: "Error", description:
|
|
168539
|
+
toast2({ title: "Error", description: error.message, variant: "destructive" });
|
|
168595
168540
|
}
|
|
168596
168541
|
});
|
|
168597
168542
|
};
|
|
168598
|
-
return /* @__PURE__ */ React163__default.createElement(Card, null, /* @__PURE__ */ React163__default.createElement(CardHeader, null, /* @__PURE__ */ React163__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React163__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React163__default.createElement(Layers, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Categories"), /* @__PURE__ */ React163__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React163__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Category"))), /* @__PURE__ */ React163__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React163__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React163__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No categories found.") : /* @__PURE__ */ React163__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React163__default.createElement(Table3, null, /* @__PURE__ */ React163__default.createElement(TableHeader, null, /* @__PURE__ */ React163__default.createElement(TableRow, null, /* @__PURE__ */ React163__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Description"), /* @__PURE__ */ React163__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React163__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React163__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-mono text-xs" }, item.code), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-medium" }, item.name), /* @__PURE__ */ React163__default.createElement(TableCell, null, item.description), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React163__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React163__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React163__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React163__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React163__default.createElement(DialogHeader, null, /* @__PURE__ */ React163__default.createElement(DialogTitle2, null, currentItem ? "Edit Category" : "Add New Category")), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemCode" }, "Code"), /* @__PURE__ */ React163__default.createElement(Input, { id: "itemCode", value: itemCode, onChange: (e3) => setItemCode(e3.target.value.toUpperCase()), placeholder: "e.g., CORE_CONCEPT", disabled: !!currentItem })), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemName" }, "Name"), /* @__PURE__ */ React163__default.createElement(Input, { id: "itemName", value: itemName, onChange: (e3) => setItemName(e3.target.value), placeholder: "e.g., Core Concept" })), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemDescription" }, "Description (Optional)"), /* @__PURE__ */ React163__default.createElement(Textarea, { id: "itemDescription", value: itemDescription, onChange: (e3) => setItemDescription(e3.target.value), placeholder: "e.g., Fundamental ideas within a subject." }))), /* @__PURE__ */ React163__default.createElement(DialogFooter, null, /* @__PURE__ */ React163__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending || !itemName.trim() || !itemCode.trim() }, isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), "Save")))), /* @__PURE__ */ React163__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React163__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React163__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React163__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React163__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.name, '".')), /* @__PURE__ */ React163__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React163__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), "Delete"))))));
|
|
168543
|
+
return /* @__PURE__ */ React163__default.createElement(Card, null, /* @__PURE__ */ React163__default.createElement(CardHeader, null, /* @__PURE__ */ React163__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React163__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React163__default.createElement(Layers, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Categories"), /* @__PURE__ */ React163__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React163__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Category"))), /* @__PURE__ */ React163__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React163__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React163__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No categories found.") : /* @__PURE__ */ React163__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React163__default.createElement(Table3, null, /* @__PURE__ */ React163__default.createElement(TableHeader, null, /* @__PURE__ */ React163__default.createElement(TableRow, null, /* @__PURE__ */ React163__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Description"), /* @__PURE__ */ React163__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React163__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React163__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-mono text-xs" }, item.code), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-medium" }, item.name), /* @__PURE__ */ React163__default.createElement(TableCell, null, item.description), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React163__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React163__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React163__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React163__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React163__default.createElement(DialogHeader, null, /* @__PURE__ */ React163__default.createElement(DialogTitle2, null, currentItem ? "Edit Category" : "Add New Category")), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemCode" }, "Code"), /* @__PURE__ */ React163__default.createElement(Input, { id: "itemCode", value: itemCode, onChange: (e3) => setItemCode(e3.target.value.toUpperCase()), placeholder: "e.g., CORE_CONCEPT", disabled: !!currentItem })), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemName" }, "Name"), /* @__PURE__ */ React163__default.createElement(Input, { id: "itemName", value: itemName, onChange: (e3) => setItemName(e3.target.value), placeholder: "e.g., Core Concept" })), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemDescription" }, "Description (Optional)"), /* @__PURE__ */ React163__default.createElement(Textarea, { id: "itemDescription", value: itemDescription, onChange: (e3) => setItemDescription(e3.target.value), placeholder: "e.g., Fundamental ideas within a subject." }))), /* @__PURE__ */ React163__default.createElement(DialogFooter, null, /* @__PURE__ */ React163__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending || !itemName.trim() || !itemCode.trim() }, isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Save")))), /* @__PURE__ */ React163__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React163__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React163__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React163__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React163__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.name, '".')), /* @__PURE__ */ React163__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React163__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Delete"))))));
|
|
168599
168544
|
}
|
|
168600
168545
|
|
|
168601
168546
|
// src/react-ui/components/metadata/BloomLevelManager.tsx
|
|
168602
168547
|
init_react_shim();
|
|
168603
|
-
function BloomLevelManager() {
|
|
168548
|
+
function BloomLevelManager({ initialData, isLoading: isLoadingProp, onAdd, onUpdate, onDelete }) {
|
|
168604
168549
|
const [items, setItems] = useState([]);
|
|
168605
168550
|
const [isLoading, setIsLoading] = useState(true);
|
|
168606
168551
|
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
|
@@ -168612,19 +168557,27 @@ function BloomLevelManager() {
|
|
|
168612
168557
|
const [itemToDelete, setItemToDelete] = useState(null);
|
|
168613
168558
|
const [isPending, startTransition] = useTransition();
|
|
168614
168559
|
const { toast: toast2 } = useToast();
|
|
168615
|
-
|
|
168616
|
-
|
|
168617
|
-
|
|
168618
|
-
|
|
168619
|
-
|
|
168620
|
-
|
|
168621
|
-
|
|
168622
|
-
|
|
168623
|
-
|
|
168624
|
-
|
|
168625
|
-
|
|
168560
|
+
const isControlled = initialData !== void 0;
|
|
168561
|
+
const refreshData = () => {
|
|
168562
|
+
if (!isControlled) {
|
|
168563
|
+
setIsLoading(true);
|
|
168564
|
+
try {
|
|
168565
|
+
setItems(MetadataService.getBloomLevels());
|
|
168566
|
+
} catch (error) {
|
|
168567
|
+
toast2({ title: "Error", description: "Failed to refresh Bloom's Levels.", variant: "destructive" });
|
|
168568
|
+
} finally {
|
|
168569
|
+
setIsLoading(false);
|
|
168570
|
+
}
|
|
168626
168571
|
}
|
|
168627
168572
|
};
|
|
168573
|
+
useEffect(() => {
|
|
168574
|
+
if (isControlled) {
|
|
168575
|
+
setItems(initialData || []);
|
|
168576
|
+
setIsLoading(isLoadingProp || false);
|
|
168577
|
+
} else {
|
|
168578
|
+
refreshData();
|
|
168579
|
+
}
|
|
168580
|
+
}, [isControlled, initialData, isLoadingProp]);
|
|
168628
168581
|
const handleAddItem = () => {
|
|
168629
168582
|
setCurrentItem(null);
|
|
168630
168583
|
setItemCode("");
|
|
@@ -168645,13 +168598,17 @@ function BloomLevelManager() {
|
|
|
168645
168598
|
};
|
|
168646
168599
|
const confirmDelete = () => {
|
|
168647
168600
|
if (!itemToDelete) return;
|
|
168648
|
-
startTransition(() => {
|
|
168601
|
+
startTransition(async () => {
|
|
168649
168602
|
try {
|
|
168650
|
-
|
|
168603
|
+
if (isControlled && onDelete) {
|
|
168604
|
+
await onDelete(itemToDelete);
|
|
168605
|
+
} else {
|
|
168606
|
+
MetadataService.deleteBloomLevel(itemToDelete.code);
|
|
168607
|
+
refreshData();
|
|
168608
|
+
}
|
|
168651
168609
|
toast2({ title: "Success", description: `Bloom's Level "${itemToDelete.name}" deleted.` });
|
|
168652
|
-
fetchItems();
|
|
168653
168610
|
} catch (error) {
|
|
168654
|
-
toast2({ title: "Error", description:
|
|
168611
|
+
toast2({ title: "Error", description: error.message, variant: "destructive" });
|
|
168655
168612
|
} finally {
|
|
168656
168613
|
setIsAlertOpen(false);
|
|
168657
168614
|
setItemToDelete(null);
|
|
@@ -168663,27 +168620,37 @@ function BloomLevelManager() {
|
|
|
168663
168620
|
toast2({ title: "Validation Error", description: "Code and Name are required.", variant: "destructive" });
|
|
168664
168621
|
return;
|
|
168665
168622
|
}
|
|
168666
|
-
startTransition(() => {
|
|
168623
|
+
startTransition(async () => {
|
|
168667
168624
|
try {
|
|
168668
168625
|
if (currentItem) {
|
|
168669
|
-
|
|
168626
|
+
if (isControlled && onUpdate) {
|
|
168627
|
+
await onUpdate({ id: currentItem.id, name: itemName, code: itemCode, description: itemDescription });
|
|
168628
|
+
} else {
|
|
168629
|
+
MetadataService.updateBloomLevel(currentItem.id, itemName, itemCode, itemDescription);
|
|
168630
|
+
refreshData();
|
|
168631
|
+
}
|
|
168632
|
+
toast2({ title: "Success", description: "Bloom's Level updated." });
|
|
168670
168633
|
} else {
|
|
168671
|
-
|
|
168634
|
+
if (isControlled && onAdd) {
|
|
168635
|
+
await onAdd({ name: itemName, code: itemCode, description: itemDescription });
|
|
168636
|
+
} else {
|
|
168637
|
+
MetadataService.addBloomLevel(itemName, itemCode, itemDescription);
|
|
168638
|
+
refreshData();
|
|
168639
|
+
}
|
|
168640
|
+
toast2({ title: "Success", description: "Bloom's Level added." });
|
|
168672
168641
|
}
|
|
168673
|
-
toast2({ title: "Success", description: "Bloom's Level saved." });
|
|
168674
|
-
fetchItems();
|
|
168675
168642
|
setIsDialogOpen(false);
|
|
168676
168643
|
} catch (error) {
|
|
168677
|
-
toast2({ title: "Error", description:
|
|
168644
|
+
toast2({ title: "Error", description: error.message, variant: "destructive" });
|
|
168678
168645
|
}
|
|
168679
168646
|
});
|
|
168680
168647
|
};
|
|
168681
|
-
return /* @__PURE__ */ React163__default.createElement(Card, null, /* @__PURE__ */ React163__default.createElement(CardHeader, null, /* @__PURE__ */ React163__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React163__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React163__default.createElement(Brain, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Bloom's Levels"), /* @__PURE__ */ React163__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React163__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Bloom's Level"))), /* @__PURE__ */ React163__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React163__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React163__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No Bloom's Levels found.") : /* @__PURE__ */ React163__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React163__default.createElement(Table3, null, /* @__PURE__ */ React163__default.createElement(TableHeader, null, /* @__PURE__ */ React163__default.createElement(TableRow, null, /* @__PURE__ */ React163__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Description"), /* @__PURE__ */ React163__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React163__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React163__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-mono text-xs" }, item.code), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-medium" }, item.name), /* @__PURE__ */ React163__default.createElement(TableCell, null, item.description), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React163__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React163__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React163__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React163__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React163__default.createElement(DialogHeader, null, /* @__PURE__ */ React163__default.createElement(DialogTitle2, null, currentItem ? "Edit Bloom's Level" : "Add New Bloom's Level")), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemCode" }, "Code"), /* @__PURE__ */ React163__default.createElement(Input, { id: "itemCode", value: itemCode, onChange: (e3) => setItemCode(e3.target.value.toUpperCase()), placeholder: "e.g., REMEMBER", disabled: !!currentItem })), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemName" }, "Name"), /* @__PURE__ */ React163__default.createElement(Input, { id: "itemName", value: itemName, onChange: (e3) => setItemName(e3.target.value), placeholder: "e.g., Remembering" })), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemDescription" }, "Description (Optional)"), /* @__PURE__ */ React163__default.createElement(Textarea, { id: "itemDescription", value: itemDescription, onChange: (e3) => setItemDescription(e3.target.value), placeholder: "e.g., Recall facts and basic concepts." }))), /* @__PURE__ */ React163__default.createElement(DialogFooter, null, /* @__PURE__ */ React163__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending || !itemCode.trim() || !itemName.trim() }, isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), "Save")))), /* @__PURE__ */ React163__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React163__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React163__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React163__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React163__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.name, '".')), /* @__PURE__ */ React163__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React163__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), "Delete"))))));
|
|
168648
|
+
return /* @__PURE__ */ React163__default.createElement(Card, null, /* @__PURE__ */ React163__default.createElement(CardHeader, null, /* @__PURE__ */ React163__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React163__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React163__default.createElement(Brain, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Bloom's Levels"), /* @__PURE__ */ React163__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React163__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Bloom's Level"))), /* @__PURE__ */ React163__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React163__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React163__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No Bloom's Levels found.") : /* @__PURE__ */ React163__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React163__default.createElement(Table3, null, /* @__PURE__ */ React163__default.createElement(TableHeader, null, /* @__PURE__ */ React163__default.createElement(TableRow, null, /* @__PURE__ */ React163__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Description"), /* @__PURE__ */ React163__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React163__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React163__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-mono text-xs" }, item.code), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-medium" }, item.name), /* @__PURE__ */ React163__default.createElement(TableCell, null, item.description), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React163__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React163__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React163__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React163__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React163__default.createElement(DialogHeader, null, /* @__PURE__ */ React163__default.createElement(DialogTitle2, null, currentItem ? "Edit Bloom's Level" : "Add New Bloom's Level")), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemCode" }, "Code"), /* @__PURE__ */ React163__default.createElement(Input, { id: "itemCode", value: itemCode, onChange: (e3) => setItemCode(e3.target.value.toUpperCase()), placeholder: "e.g., REMEMBER", disabled: !!currentItem })), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemName" }, "Name"), /* @__PURE__ */ React163__default.createElement(Input, { id: "itemName", value: itemName, onChange: (e3) => setItemName(e3.target.value), placeholder: "e.g., Remembering" })), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemDescription" }, "Description (Optional)"), /* @__PURE__ */ React163__default.createElement(Textarea, { id: "itemDescription", value: itemDescription, onChange: (e3) => setItemDescription(e3.target.value), placeholder: "e.g., Recall facts and basic concepts." }))), /* @__PURE__ */ React163__default.createElement(DialogFooter, null, /* @__PURE__ */ React163__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending || !itemCode.trim() || !itemName.trim() }, isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Save")))), /* @__PURE__ */ React163__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React163__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React163__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React163__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React163__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.name, '".')), /* @__PURE__ */ React163__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React163__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Delete"))))));
|
|
168682
168649
|
}
|
|
168683
168650
|
|
|
168684
168651
|
// src/react-ui/components/metadata/QuestionTypeManager.tsx
|
|
168685
168652
|
init_react_shim();
|
|
168686
|
-
function QuestionTypeManager() {
|
|
168653
|
+
function QuestionTypeManager({ initialData, isLoading: isLoadingProp, onAdd, onUpdate, onDelete }) {
|
|
168687
168654
|
const [items, setItems] = useState([]);
|
|
168688
168655
|
const [isLoading, setIsLoading] = useState(true);
|
|
168689
168656
|
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
|
@@ -168695,19 +168662,27 @@ function QuestionTypeManager() {
|
|
|
168695
168662
|
const [itemToDelete, setItemToDelete] = useState(null);
|
|
168696
168663
|
const [isPending, startTransition] = useTransition();
|
|
168697
168664
|
const { toast: toast2 } = useToast();
|
|
168698
|
-
|
|
168699
|
-
|
|
168700
|
-
|
|
168701
|
-
|
|
168702
|
-
|
|
168703
|
-
|
|
168704
|
-
|
|
168705
|
-
|
|
168706
|
-
|
|
168707
|
-
|
|
168708
|
-
|
|
168665
|
+
const isControlled = initialData !== void 0;
|
|
168666
|
+
const refreshData = () => {
|
|
168667
|
+
if (!isControlled) {
|
|
168668
|
+
setIsLoading(true);
|
|
168669
|
+
try {
|
|
168670
|
+
setItems(MetadataService.getQuestionTypes());
|
|
168671
|
+
} catch (error) {
|
|
168672
|
+
toast2({ title: "Error", description: "Failed to refresh Question Types.", variant: "destructive" });
|
|
168673
|
+
} finally {
|
|
168674
|
+
setIsLoading(false);
|
|
168675
|
+
}
|
|
168709
168676
|
}
|
|
168710
168677
|
};
|
|
168678
|
+
useEffect(() => {
|
|
168679
|
+
if (isControlled) {
|
|
168680
|
+
setItems(initialData || []);
|
|
168681
|
+
setIsLoading(isLoadingProp || false);
|
|
168682
|
+
} else {
|
|
168683
|
+
refreshData();
|
|
168684
|
+
}
|
|
168685
|
+
}, [isControlled, initialData, isLoadingProp]);
|
|
168711
168686
|
const handleAddItem = () => {
|
|
168712
168687
|
setCurrentItem(null);
|
|
168713
168688
|
setItemCode("");
|
|
@@ -168728,13 +168703,17 @@ function QuestionTypeManager() {
|
|
|
168728
168703
|
};
|
|
168729
168704
|
const confirmDelete = () => {
|
|
168730
168705
|
if (!itemToDelete) return;
|
|
168731
|
-
startTransition(() => {
|
|
168706
|
+
startTransition(async () => {
|
|
168732
168707
|
try {
|
|
168733
|
-
|
|
168708
|
+
if (isControlled && onDelete) {
|
|
168709
|
+
await onDelete(itemToDelete);
|
|
168710
|
+
} else {
|
|
168711
|
+
MetadataService.deleteQuestionType(itemToDelete.code);
|
|
168712
|
+
refreshData();
|
|
168713
|
+
}
|
|
168734
168714
|
toast2({ title: "Success", description: `Question Type "${itemToDelete.name}" deleted.` });
|
|
168735
|
-
fetchItems();
|
|
168736
168715
|
} catch (error) {
|
|
168737
|
-
toast2({ title: "Error", description:
|
|
168716
|
+
toast2({ title: "Error", description: error.message, variant: "destructive" });
|
|
168738
168717
|
} finally {
|
|
168739
168718
|
setIsAlertOpen(false);
|
|
168740
168719
|
setItemToDelete(null);
|
|
@@ -168746,27 +168725,37 @@ function QuestionTypeManager() {
|
|
|
168746
168725
|
toast2({ title: "Validation Error", description: "Code and Name are required.", variant: "destructive" });
|
|
168747
168726
|
return;
|
|
168748
168727
|
}
|
|
168749
|
-
startTransition(() => {
|
|
168728
|
+
startTransition(async () => {
|
|
168750
168729
|
try {
|
|
168751
168730
|
if (currentItem) {
|
|
168752
|
-
|
|
168731
|
+
if (isControlled && onUpdate) {
|
|
168732
|
+
await onUpdate({ id: currentItem.id, name: itemName, code: itemCode, description: itemDescription });
|
|
168733
|
+
} else {
|
|
168734
|
+
MetadataService.updateQuestionType(currentItem.id, itemName, itemCode, itemDescription);
|
|
168735
|
+
refreshData();
|
|
168736
|
+
}
|
|
168737
|
+
toast2({ title: "Success", description: "Question Type updated." });
|
|
168753
168738
|
} else {
|
|
168754
|
-
|
|
168739
|
+
if (isControlled && onAdd) {
|
|
168740
|
+
await onAdd({ name: itemName, code: itemCode, description: itemDescription });
|
|
168741
|
+
} else {
|
|
168742
|
+
MetadataService.addQuestionType(itemName, itemCode, itemDescription);
|
|
168743
|
+
refreshData();
|
|
168744
|
+
}
|
|
168745
|
+
toast2({ title: "Success", description: "Question Type added." });
|
|
168755
168746
|
}
|
|
168756
|
-
toast2({ title: "Success", description: "Question Type saved." });
|
|
168757
|
-
fetchItems();
|
|
168758
168747
|
setIsDialogOpen(false);
|
|
168759
168748
|
} catch (error) {
|
|
168760
|
-
toast2({ title: "Error", description:
|
|
168749
|
+
toast2({ title: "Error", description: error.message, variant: "destructive" });
|
|
168761
168750
|
}
|
|
168762
168751
|
});
|
|
168763
168752
|
};
|
|
168764
|
-
return /* @__PURE__ */ React163__default.createElement(Card, null, /* @__PURE__ */ React163__default.createElement(CardHeader, null, /* @__PURE__ */ React163__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React163__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React163__default.createElement(CircleHelp, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Question Types"), /* @__PURE__ */ React163__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React163__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Question Type"))), /* @__PURE__ */ React163__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React163__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React163__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No Question Types found.") : /* @__PURE__ */ React163__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React163__default.createElement(Table3, null, /* @__PURE__ */ React163__default.createElement(TableHeader, null, /* @__PURE__ */ React163__default.createElement(TableRow, null, /* @__PURE__ */ React163__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Description"), /* @__PURE__ */ React163__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React163__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React163__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-mono text-xs" }, item.code), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-medium" }, item.name), /* @__PURE__ */ React163__default.createElement(TableCell, null, item.description), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React163__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React163__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React163__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React163__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React163__default.createElement(DialogHeader, null, /* @__PURE__ */ React163__default.createElement(DialogTitle2, null, currentItem ? "Edit Question Type" : "Add New Question Type")), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemCode" }, "Code"), /* @__PURE__ */ React163__default.createElement(Input, { id: "itemCode", value: itemCode, onChange: (e3) => setItemCode(e3.target.value.
|
|
168753
|
+
return /* @__PURE__ */ React163__default.createElement(Card, null, /* @__PURE__ */ React163__default.createElement(CardHeader, null, /* @__PURE__ */ React163__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React163__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React163__default.createElement(CircleHelp, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Question Types"), /* @__PURE__ */ React163__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React163__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Question Type"))), /* @__PURE__ */ React163__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React163__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React163__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No Question Types found.") : /* @__PURE__ */ React163__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React163__default.createElement(Table3, null, /* @__PURE__ */ React163__default.createElement(TableHeader, null, /* @__PURE__ */ React163__default.createElement(TableRow, null, /* @__PURE__ */ React163__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Description"), /* @__PURE__ */ React163__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React163__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React163__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-mono text-xs" }, item.code), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-medium" }, item.name), /* @__PURE__ */ React163__default.createElement(TableCell, null, item.description), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React163__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React163__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React163__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React163__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React163__default.createElement(DialogHeader, null, /* @__PURE__ */ React163__default.createElement(DialogTitle2, null, currentItem ? "Edit Question Type" : "Add New Question Type")), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemCode" }, "Code"), /* @__PURE__ */ React163__default.createElement(Input, { id: "itemCode", value: itemCode, onChange: (e3) => setItemCode(e3.target.value.toLowerCase().replace(/ /g, "_")), placeholder: "e.g., multiple_choice", disabled: !!currentItem })), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemName" }, "Name"), /* @__PURE__ */ React163__default.createElement(Input, { id: "itemName", value: itemName, onChange: (e3) => setItemName(e3.target.value), placeholder: "e.g., Multiple Choice" })), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemDescription" }, "Description (Optional)"), /* @__PURE__ */ React163__default.createElement(Textarea, { id: "itemDescription", value: itemDescription, onChange: (e3) => setItemDescription(e3.target.value), placeholder: "e.g., Select one answer from a list of options." }))), /* @__PURE__ */ React163__default.createElement(DialogFooter, null, /* @__PURE__ */ React163__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending || !itemCode.trim() || !itemName.trim() }, isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Save")))), /* @__PURE__ */ React163__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React163__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React163__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React163__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React163__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.name, '".')), /* @__PURE__ */ React163__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React163__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Delete"))))));
|
|
168765
168754
|
}
|
|
168766
168755
|
|
|
168767
168756
|
// src/react-ui/components/metadata/LearningObjectiveManager.tsx
|
|
168768
168757
|
init_react_shim();
|
|
168769
|
-
function LearningObjectiveManager() {
|
|
168758
|
+
function LearningObjectiveManager({ initialData, subjects: subjectsProp, isLoading: isLoadingProp, onAdd, onUpdate, onDelete }) {
|
|
168770
168759
|
const [items, setItems] = useState([]);
|
|
168771
168760
|
const [subjects, setSubjects] = useState([]);
|
|
168772
168761
|
const [isLoading, setIsLoading] = useState(true);
|
|
@@ -168780,34 +168769,35 @@ function LearningObjectiveManager() {
|
|
|
168780
168769
|
const [itemToDelete, setItemToDelete] = useState(null);
|
|
168781
168770
|
const [isPending, startTransition] = useTransition();
|
|
168782
168771
|
const { toast: toast2 } = useToast();
|
|
168783
|
-
const
|
|
168784
|
-
|
|
168785
|
-
|
|
168786
|
-
|
|
168787
|
-
|
|
168788
|
-
|
|
168789
|
-
|
|
168790
|
-
|
|
168791
|
-
|
|
168792
|
-
|
|
168793
|
-
|
|
168794
|
-
|
|
168795
|
-
});
|
|
168796
|
-
} finally {
|
|
168797
|
-
setIsLoading(false);
|
|
168772
|
+
const isControlled = initialData !== void 0;
|
|
168773
|
+
const refreshData = () => {
|
|
168774
|
+
if (!isControlled) {
|
|
168775
|
+
setIsLoading(true);
|
|
168776
|
+
try {
|
|
168777
|
+
setItems(MetadataService.getLearningObjectives());
|
|
168778
|
+
setSubjects(MetadataService.getSubjects());
|
|
168779
|
+
} catch (error) {
|
|
168780
|
+
toast2({ title: "Error", description: "Failed to refresh data.", variant: "destructive" });
|
|
168781
|
+
} finally {
|
|
168782
|
+
setIsLoading(false);
|
|
168783
|
+
}
|
|
168798
168784
|
}
|
|
168799
168785
|
};
|
|
168800
168786
|
useEffect(() => {
|
|
168801
|
-
|
|
168802
|
-
|
|
168787
|
+
if (isControlled) {
|
|
168788
|
+
setItems(initialData || []);
|
|
168789
|
+
setSubjects(subjectsProp || []);
|
|
168790
|
+
setIsLoading(isLoadingProp || false);
|
|
168791
|
+
} else {
|
|
168792
|
+
refreshData();
|
|
168793
|
+
}
|
|
168794
|
+
}, [isControlled, initialData, subjectsProp, isLoadingProp]);
|
|
168803
168795
|
const handleAddItem = () => {
|
|
168804
168796
|
setCurrentItem(null);
|
|
168805
168797
|
setItemName("");
|
|
168806
168798
|
setItemCode("");
|
|
168807
168799
|
setItemDescription("");
|
|
168808
|
-
setSelectedSubjectCode(
|
|
168809
|
-
subjects.length > 0 ? subjects[0].code : void 0
|
|
168810
|
-
);
|
|
168800
|
+
setSelectedSubjectCode(subjects.length > 0 ? subjects[0].code : void 0);
|
|
168811
168801
|
setIsDialogOpen(true);
|
|
168812
168802
|
};
|
|
168813
168803
|
const handleEditItem = (item) => {
|
|
@@ -168824,20 +168814,17 @@ function LearningObjectiveManager() {
|
|
|
168824
168814
|
};
|
|
168825
168815
|
const confirmDelete = () => {
|
|
168826
168816
|
if (!itemToDelete) return;
|
|
168827
|
-
startTransition(() => {
|
|
168817
|
+
startTransition(async () => {
|
|
168828
168818
|
try {
|
|
168829
|
-
|
|
168830
|
-
|
|
168831
|
-
|
|
168832
|
-
|
|
168833
|
-
|
|
168834
|
-
|
|
168819
|
+
if (isControlled && onDelete) {
|
|
168820
|
+
await onDelete(itemToDelete);
|
|
168821
|
+
} else {
|
|
168822
|
+
MetadataService.deleteLearningObjective(itemToDelete.code);
|
|
168823
|
+
refreshData();
|
|
168824
|
+
}
|
|
168825
|
+
toast2({ title: "Success", description: `Learning Objective "${itemToDelete.name}" deleted.` });
|
|
168835
168826
|
} catch (error) {
|
|
168836
|
-
toast2({
|
|
168837
|
-
title: "Error",
|
|
168838
|
-
description: "Failed to delete Learning Objective.",
|
|
168839
|
-
variant: "destructive"
|
|
168840
|
-
});
|
|
168827
|
+
toast2({ title: "Error", description: error.message, variant: "destructive" });
|
|
168841
168828
|
} finally {
|
|
168842
168829
|
setIsAlertOpen(false);
|
|
168843
168830
|
setItemToDelete(null);
|
|
@@ -168846,43 +168833,31 @@ function LearningObjectiveManager() {
|
|
|
168846
168833
|
};
|
|
168847
168834
|
const handleSubmit = () => {
|
|
168848
168835
|
if (!itemName.trim() || !itemCode.trim()) {
|
|
168849
|
-
toast2({
|
|
168850
|
-
title: "Validation Error",
|
|
168851
|
-
description: "Code and Name are required.",
|
|
168852
|
-
variant: "destructive"
|
|
168853
|
-
});
|
|
168836
|
+
toast2({ title: "Validation Error", description: "Code and Name are required.", variant: "destructive" });
|
|
168854
168837
|
return;
|
|
168855
168838
|
}
|
|
168856
|
-
startTransition(() => {
|
|
168839
|
+
startTransition(async () => {
|
|
168857
168840
|
try {
|
|
168858
168841
|
if (currentItem) {
|
|
168859
|
-
|
|
168860
|
-
currentItem.id,
|
|
168861
|
-
|
|
168862
|
-
itemCode,
|
|
168863
|
-
|
|
168864
|
-
|
|
168865
|
-
);
|
|
168842
|
+
if (isControlled && onUpdate) {
|
|
168843
|
+
await onUpdate({ id: currentItem.id, name: itemName, code: itemCode, subjectCode: selectedSubjectCode, description: itemDescription });
|
|
168844
|
+
} else {
|
|
168845
|
+
MetadataService.updateLearningObjective(currentItem.id, itemName, itemCode, selectedSubjectCode, itemDescription);
|
|
168846
|
+
refreshData();
|
|
168847
|
+
}
|
|
168848
|
+
toast2({ title: "Success", description: "Learning Objective updated." });
|
|
168866
168849
|
} else {
|
|
168867
|
-
|
|
168868
|
-
itemName,
|
|
168869
|
-
|
|
168870
|
-
selectedSubjectCode,
|
|
168871
|
-
|
|
168872
|
-
|
|
168850
|
+
if (isControlled && onAdd) {
|
|
168851
|
+
await onAdd({ name: itemName, code: itemCode, subjectCode: selectedSubjectCode, description: itemDescription });
|
|
168852
|
+
} else {
|
|
168853
|
+
MetadataService.addLearningObjective(itemName, itemCode, selectedSubjectCode, itemDescription);
|
|
168854
|
+
refreshData();
|
|
168855
|
+
}
|
|
168856
|
+
toast2({ title: "Success", description: "Learning Objective added." });
|
|
168873
168857
|
}
|
|
168874
|
-
toast2({
|
|
168875
|
-
title: "Success",
|
|
168876
|
-
description: "Learning Objective saved."
|
|
168877
|
-
});
|
|
168878
|
-
fetchData();
|
|
168879
168858
|
setIsDialogOpen(false);
|
|
168880
168859
|
} catch (error) {
|
|
168881
|
-
toast2({
|
|
168882
|
-
title: "Error",
|
|
168883
|
-
description: "Failed to save Learning Objective.",
|
|
168884
|
-
variant: "destructive"
|
|
168885
|
-
});
|
|
168860
|
+
toast2({ title: "Error", description: error.message, variant: "destructive" });
|
|
168886
168861
|
}
|
|
168887
168862
|
});
|
|
168888
168863
|
};
|
|
@@ -168890,100 +168865,12 @@ function LearningObjectiveManager() {
|
|
|
168890
168865
|
if (!subjectCode) return "N/A";
|
|
168891
168866
|
return subjects.find((s4) => s4.code === subjectCode)?.name || "N/A";
|
|
168892
168867
|
};
|
|
168893
|
-
return /* @__PURE__ */ React163__default.createElement(Card, null, /* @__PURE__ */ React163__default.createElement(CardHeader, null, /* @__PURE__ */ React163__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React163__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React163__default.createElement(Lightbulb, { className: "mr-2 h-5 w-5 text-primary" }), "
|
|
168894
|
-
Button,
|
|
168895
|
-
{
|
|
168896
|
-
variant: "ghost",
|
|
168897
|
-
size: "icon",
|
|
168898
|
-
onClick: () => handleEditItem(item),
|
|
168899
|
-
className: "mr-2"
|
|
168900
|
-
},
|
|
168901
|
-
/* @__PURE__ */ React163__default.createElement(PenLine, { className: "h-4 w-4" })
|
|
168902
|
-
), /* @__PURE__ */ React163__default.createElement(
|
|
168903
|
-
Button,
|
|
168904
|
-
{
|
|
168905
|
-
variant: "ghost",
|
|
168906
|
-
size: "icon",
|
|
168907
|
-
onClick: () => handleDeleteItem(item),
|
|
168908
|
-
className: "text-destructive hover:text-destructive"
|
|
168909
|
-
},
|
|
168910
|
-
/* @__PURE__ */ React163__default.createElement(Trash2, { className: "h-4 w-4" })
|
|
168911
|
-
))))))), /* @__PURE__ */ React163__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React163__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React163__default.createElement(DialogHeader, null, /* @__PURE__ */ React163__default.createElement(DialogTitle2, null, currentItem ? "Edit Learning Objective" : "Add New Learning Objective")), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemCode" }, "Code"), /* @__PURE__ */ React163__default.createElement(
|
|
168912
|
-
Input,
|
|
168913
|
-
{
|
|
168914
|
-
id: "itemCode",
|
|
168915
|
-
value: itemCode,
|
|
168916
|
-
onChange: (e3) => setItemCode(
|
|
168917
|
-
e3.target.value.toUpperCase()
|
|
168918
|
-
),
|
|
168919
|
-
disabled: !!currentItem
|
|
168920
|
-
}
|
|
168921
|
-
)), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemName" }, "Name"), /* @__PURE__ */ React163__default.createElement(
|
|
168922
|
-
Input,
|
|
168923
|
-
{
|
|
168924
|
-
id: "itemName",
|
|
168925
|
-
value: itemName,
|
|
168926
|
-
onChange: (e3) => setItemName(e3.target.value)
|
|
168927
|
-
}
|
|
168928
|
-
)), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemSubject" }, "Subject (Optional)"), /* @__PURE__ */ React163__default.createElement(
|
|
168929
|
-
Select2,
|
|
168930
|
-
{
|
|
168931
|
-
value: selectedSubjectCode || "",
|
|
168932
|
-
onValueChange: (value) => setSelectedSubjectCode(
|
|
168933
|
-
value === "_NONE_" ? void 0 : value
|
|
168934
|
-
)
|
|
168935
|
-
},
|
|
168936
|
-
/* @__PURE__ */ React163__default.createElement(SelectTrigger2, { id: "itemSubject" }, /* @__PURE__ */ React163__default.createElement(SelectValue2, { placeholder: "Select a subject" })),
|
|
168937
|
-
/* @__PURE__ */ React163__default.createElement(SelectContent2, null, /* @__PURE__ */ React163__default.createElement(SelectItem2, { value: "_NONE_" }, "No Specific Subject"), subjects.map((subject) => /* @__PURE__ */ React163__default.createElement(
|
|
168938
|
-
SelectItem2,
|
|
168939
|
-
{
|
|
168940
|
-
key: subject.id,
|
|
168941
|
-
value: subject.code
|
|
168942
|
-
},
|
|
168943
|
-
subject.name
|
|
168944
|
-
)))
|
|
168945
|
-
)), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemDescription" }, "Description (Optional)"), /* @__PURE__ */ React163__default.createElement(
|
|
168946
|
-
Textarea,
|
|
168947
|
-
{
|
|
168948
|
-
id: "itemDescription",
|
|
168949
|
-
value: itemDescription,
|
|
168950
|
-
onChange: (e3) => setItemDescription(e3.target.value)
|
|
168951
|
-
}
|
|
168952
|
-
))), /* @__PURE__ */ React163__default.createElement(DialogFooter, null, /* @__PURE__ */ React163__default.createElement(
|
|
168953
|
-
Button,
|
|
168954
|
-
{
|
|
168955
|
-
type: "button",
|
|
168956
|
-
variant: "outline",
|
|
168957
|
-
onClick: () => setIsDialogOpen(false),
|
|
168958
|
-
disabled: isPending
|
|
168959
|
-
},
|
|
168960
|
-
"Cancel"
|
|
168961
|
-
), /* @__PURE__ */ React163__default.createElement(
|
|
168962
|
-
Button,
|
|
168963
|
-
{
|
|
168964
|
-
type: "submit",
|
|
168965
|
-
onClick: handleSubmit,
|
|
168966
|
-
disabled: isPending || !itemName.trim() || !itemCode.trim()
|
|
168967
|
-
},
|
|
168968
|
-
isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }),
|
|
168969
|
-
" ",
|
|
168970
|
-
"Save"
|
|
168971
|
-
)))), /* @__PURE__ */ React163__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React163__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React163__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React163__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React163__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.name, '".')), /* @__PURE__ */ React163__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React163__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(
|
|
168972
|
-
AlertDialogAction2,
|
|
168973
|
-
{
|
|
168974
|
-
onClick: confirmDelete,
|
|
168975
|
-
disabled: isPending,
|
|
168976
|
-
className: "bg-destructive hover:bg-destructive/90"
|
|
168977
|
-
},
|
|
168978
|
-
isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }),
|
|
168979
|
-
" ",
|
|
168980
|
-
"Delete"
|
|
168981
|
-
))))));
|
|
168868
|
+
return /* @__PURE__ */ React163__default.createElement(Card, null, /* @__PURE__ */ React163__default.createElement(CardHeader, null, /* @__PURE__ */ React163__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React163__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React163__default.createElement(Lightbulb, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Learning Objectives"), /* @__PURE__ */ React163__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React163__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Learning Objective"))), /* @__PURE__ */ React163__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React163__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React163__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No Learning Objectives found.") : /* @__PURE__ */ React163__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React163__default.createElement(Table3, null, /* @__PURE__ */ React163__default.createElement(TableHeader, null, /* @__PURE__ */ React163__default.createElement(TableRow, null, /* @__PURE__ */ React163__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Subject"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Description"), /* @__PURE__ */ React163__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React163__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React163__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-mono text-xs" }, item.code), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-medium" }, item.name), /* @__PURE__ */ React163__default.createElement(TableCell, null, getSubjectName(item.subjectCode)), /* @__PURE__ */ React163__default.createElement(TableCell, null, item.description), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React163__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React163__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React163__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React163__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React163__default.createElement(DialogHeader, null, /* @__PURE__ */ React163__default.createElement(DialogTitle2, null, currentItem ? "Edit Learning Objective" : "Add New Learning Objective")), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemCode" }, "Code"), /* @__PURE__ */ React163__default.createElement(Input, { id: "itemCode", value: itemCode, onChange: (e3) => setItemCode(e3.target.value.toUpperCase()), disabled: !!currentItem })), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemName" }, "Name"), /* @__PURE__ */ React163__default.createElement(Input, { id: "itemName", value: itemName, onChange: (e3) => setItemName(e3.target.value) })), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemSubject" }, "Subject (Optional)"), /* @__PURE__ */ React163__default.createElement(Select2, { value: selectedSubjectCode || "", onValueChange: (value) => setSelectedSubjectCode(value === "_NONE_" ? void 0 : value) }, /* @__PURE__ */ React163__default.createElement(SelectTrigger2, { id: "itemSubject" }, /* @__PURE__ */ React163__default.createElement(SelectValue2, { placeholder: "Select a subject" })), /* @__PURE__ */ React163__default.createElement(SelectContent2, null, /* @__PURE__ */ React163__default.createElement(SelectItem2, { value: "_NONE_" }, "No Specific Subject"), subjects.map((subject) => /* @__PURE__ */ React163__default.createElement(SelectItem2, { key: subject.id, value: subject.code }, subject.name))))), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemDescription" }, "Description (Optional)"), /* @__PURE__ */ React163__default.createElement(Textarea, { id: "itemDescription", value: itemDescription, onChange: (e3) => setItemDescription(e3.target.value) }))), /* @__PURE__ */ React163__default.createElement(DialogFooter, null, /* @__PURE__ */ React163__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending || !itemName.trim() || !itemCode.trim() }, isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Save")))), /* @__PURE__ */ React163__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React163__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React163__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React163__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React163__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.name, '".')), /* @__PURE__ */ React163__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React163__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Delete"))))));
|
|
168982
168869
|
}
|
|
168983
168870
|
|
|
168984
168871
|
// src/react-ui/components/metadata/ContextManager.tsx
|
|
168985
168872
|
init_react_shim();
|
|
168986
|
-
function ContextManager() {
|
|
168873
|
+
function ContextManager({ initialData, isLoading: isLoadingProp, onAdd, onUpdate, onDelete }) {
|
|
168987
168874
|
const [items, setItems] = useState([]);
|
|
168988
168875
|
const [isLoading, setIsLoading] = useState(true);
|
|
168989
168876
|
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
|
@@ -168995,19 +168882,27 @@ function ContextManager() {
|
|
|
168995
168882
|
const [itemToDelete, setItemToDelete] = useState(null);
|
|
168996
168883
|
const [isPending, startTransition] = useTransition();
|
|
168997
168884
|
const { toast: toast2 } = useToast();
|
|
168998
|
-
|
|
168999
|
-
|
|
169000
|
-
|
|
169001
|
-
|
|
169002
|
-
|
|
169003
|
-
|
|
169004
|
-
|
|
169005
|
-
|
|
169006
|
-
|
|
169007
|
-
|
|
169008
|
-
|
|
168885
|
+
const isControlled = initialData !== void 0;
|
|
168886
|
+
const refreshData = () => {
|
|
168887
|
+
if (!isControlled) {
|
|
168888
|
+
setIsLoading(true);
|
|
168889
|
+
try {
|
|
168890
|
+
setItems(MetadataService.getContexts());
|
|
168891
|
+
} catch (error) {
|
|
168892
|
+
toast2({ title: "Error", description: "Failed to refresh Contexts.", variant: "destructive" });
|
|
168893
|
+
} finally {
|
|
168894
|
+
setIsLoading(false);
|
|
168895
|
+
}
|
|
169009
168896
|
}
|
|
169010
168897
|
};
|
|
168898
|
+
useEffect(() => {
|
|
168899
|
+
if (isControlled) {
|
|
168900
|
+
setItems(initialData || []);
|
|
168901
|
+
setIsLoading(isLoadingProp || false);
|
|
168902
|
+
} else {
|
|
168903
|
+
refreshData();
|
|
168904
|
+
}
|
|
168905
|
+
}, [isControlled, initialData, isLoadingProp]);
|
|
169011
168906
|
const handleAddItem = () => {
|
|
169012
168907
|
setCurrentItem(null);
|
|
169013
168908
|
setItemName("");
|
|
@@ -169028,13 +168923,17 @@ function ContextManager() {
|
|
|
169028
168923
|
};
|
|
169029
168924
|
const confirmDelete = () => {
|
|
169030
168925
|
if (!itemToDelete) return;
|
|
169031
|
-
startTransition(() => {
|
|
168926
|
+
startTransition(async () => {
|
|
169032
168927
|
try {
|
|
169033
|
-
|
|
168928
|
+
if (isControlled && onDelete) {
|
|
168929
|
+
await onDelete(itemToDelete);
|
|
168930
|
+
} else {
|
|
168931
|
+
MetadataService.deleteContext(itemToDelete.code);
|
|
168932
|
+
refreshData();
|
|
168933
|
+
}
|
|
169034
168934
|
toast2({ title: "Success", description: `Context "${itemToDelete.name}" deleted.` });
|
|
169035
|
-
fetchItems();
|
|
169036
168935
|
} catch (error) {
|
|
169037
|
-
toast2({ title: "Error", description:
|
|
168936
|
+
toast2({ title: "Error", description: error.message, variant: "destructive" });
|
|
169038
168937
|
} finally {
|
|
169039
168938
|
setIsAlertOpen(false);
|
|
169040
168939
|
setItemToDelete(null);
|
|
@@ -169046,32 +168945,50 @@ function ContextManager() {
|
|
|
169046
168945
|
toast2({ title: "Validation Error", description: "Code and Name are required.", variant: "destructive" });
|
|
169047
168946
|
return;
|
|
169048
168947
|
}
|
|
169049
|
-
startTransition(() => {
|
|
168948
|
+
startTransition(async () => {
|
|
169050
168949
|
try {
|
|
169051
168950
|
if (currentItem) {
|
|
169052
|
-
|
|
168951
|
+
if (isControlled && onUpdate) {
|
|
168952
|
+
await onUpdate({ id: currentItem.id, name: itemName, code: itemCode, description: itemDescription });
|
|
168953
|
+
} else {
|
|
168954
|
+
MetadataService.updateContext(currentItem.id, itemName, itemCode, itemDescription);
|
|
168955
|
+
refreshData();
|
|
168956
|
+
}
|
|
168957
|
+
toast2({ title: "Success", description: "Context updated." });
|
|
169053
168958
|
} else {
|
|
169054
|
-
|
|
168959
|
+
if (isControlled && onAdd) {
|
|
168960
|
+
await onAdd({ name: itemName, code: itemCode, description: itemDescription });
|
|
168961
|
+
} else {
|
|
168962
|
+
MetadataService.addContext(itemName, itemCode, itemDescription);
|
|
168963
|
+
refreshData();
|
|
168964
|
+
}
|
|
168965
|
+
toast2({ title: "Success", description: "Context added." });
|
|
169055
168966
|
}
|
|
169056
|
-
toast2({ title: "Success", description: "Context saved." });
|
|
169057
|
-
fetchItems();
|
|
169058
168967
|
setIsDialogOpen(false);
|
|
169059
168968
|
} catch (error) {
|
|
169060
|
-
toast2({ title: "Error", description:
|
|
168969
|
+
toast2({ title: "Error", description: error.message, variant: "destructive" });
|
|
169061
168970
|
}
|
|
169062
168971
|
});
|
|
169063
168972
|
};
|
|
169064
|
-
return /* @__PURE__ */ React163__default.createElement(Card, null, /* @__PURE__ */ React163__default.createElement(CardHeader, null, /* @__PURE__ */ React163__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React163__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React163__default.createElement(ScanText, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Contexts"), /* @__PURE__ */ React163__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React163__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Context"))), /* @__PURE__ */ React163__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React163__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React163__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No Contexts found.") : /* @__PURE__ */ React163__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React163__default.createElement(Table3, null, /* @__PURE__ */ React163__default.createElement(TableHeader, null, /* @__PURE__ */ React163__default.createElement(TableRow, null, /* @__PURE__ */ React163__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Description"), /* @__PURE__ */ React163__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React163__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React163__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-mono text-xs" }, item.code), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-medium" }, item.name), /* @__PURE__ */ React163__default.createElement(TableCell, null, item.description), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React163__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React163__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React163__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React163__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React163__default.createElement(DialogHeader, null, /* @__PURE__ */ React163__default.createElement(DialogTitle2, null, currentItem ? "Edit Context" : "Add New Context")), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemCode" }, "Code"), /* @__PURE__ */ React163__default.createElement(Input, { id: "itemCode", value: itemCode, onChange: (e3) => setItemCode(e3.target.value.toUpperCase()), placeholder: "e.g., HIST_INQ", disabled: !!currentItem })), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemName" }, "Name"), /* @__PURE__ */ React163__default.createElement(Input, { id: "itemName", value: itemName, onChange: (e3) => setItemName(e3.target.value), placeholder: "e.g., Historical Inquiry" })), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemDescription" }, "Description (Optional)"), /* @__PURE__ */ React163__default.createElement(Textarea, { id: "itemDescription", value: itemDescription, onChange: (e3) => setItemDescription(e3.target.value), placeholder: "e.g., Analyzing primary and secondary sources." }))), /* @__PURE__ */ React163__default.createElement(DialogFooter, null, /* @__PURE__ */ React163__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending || !itemCode.trim() || !itemName.trim() }, isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), "Save")))), /* @__PURE__ */ React163__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React163__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React163__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React163__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React163__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.name, '".')), /* @__PURE__ */ React163__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React163__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), "Delete"))))));
|
|
168973
|
+
return /* @__PURE__ */ React163__default.createElement(Card, null, /* @__PURE__ */ React163__default.createElement(CardHeader, null, /* @__PURE__ */ React163__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React163__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React163__default.createElement(ScanText, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Contexts"), /* @__PURE__ */ React163__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React163__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Context"))), /* @__PURE__ */ React163__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React163__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React163__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No Contexts found.") : /* @__PURE__ */ React163__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React163__default.createElement(Table3, null, /* @__PURE__ */ React163__default.createElement(TableHeader, null, /* @__PURE__ */ React163__default.createElement(TableRow, null, /* @__PURE__ */ React163__default.createElement(TableHead, null, "Code"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Name"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Description"), /* @__PURE__ */ React163__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React163__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React163__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-mono text-xs" }, item.code), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-medium" }, item.name), /* @__PURE__ */ React163__default.createElement(TableCell, null, item.description), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React163__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React163__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React163__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React163__default.createElement(DialogContent2, { className: "sm:max-w-md" }, /* @__PURE__ */ React163__default.createElement(DialogHeader, null, /* @__PURE__ */ React163__default.createElement(DialogTitle2, null, currentItem ? "Edit Context" : "Add New Context")), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemCode" }, "Code"), /* @__PURE__ */ React163__default.createElement(Input, { id: "itemCode", value: itemCode, onChange: (e3) => setItemCode(e3.target.value.toUpperCase()), placeholder: "e.g., HIST_INQ", disabled: !!currentItem })), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemName" }, "Name"), /* @__PURE__ */ React163__default.createElement(Input, { id: "itemName", value: itemName, onChange: (e3) => setItemName(e3.target.value), placeholder: "e.g., Historical Inquiry" })), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-2" }, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "itemDescription" }, "Description (Optional)"), /* @__PURE__ */ React163__default.createElement(Textarea, { id: "itemDescription", value: itemDescription, onChange: (e3) => setItemDescription(e3.target.value), placeholder: "e.g., Analyzing primary and secondary sources." }))), /* @__PURE__ */ React163__default.createElement(DialogFooter, null, /* @__PURE__ */ React163__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending || !itemCode.trim() || !itemName.trim() }, isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Save")))), /* @__PURE__ */ React163__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React163__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React163__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React163__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React163__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.name, '".')), /* @__PURE__ */ React163__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React163__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Delete"))))));
|
|
169065
168974
|
}
|
|
169066
168975
|
|
|
169067
168976
|
// src/react-ui/components/metadata/ApproachManager.tsx
|
|
169068
168977
|
init_react_shim();
|
|
169069
168978
|
var knowledgeDimensions = ["Factual", "Conceptual", "Procedural"];
|
|
169070
168979
|
var rawDifficultyLevels = ["E", "E~M", "M", "M~H", "H"];
|
|
169071
|
-
function ApproachManager(
|
|
168980
|
+
function ApproachManager({
|
|
168981
|
+
initialData,
|
|
168982
|
+
bloomLevels: bloomLevelsProp,
|
|
168983
|
+
questionTypes: questionTypesProp,
|
|
168984
|
+
isLoading: isLoadingProp,
|
|
168985
|
+
onAdd,
|
|
168986
|
+
onUpdate,
|
|
168987
|
+
onDelete
|
|
168988
|
+
}) {
|
|
169072
168989
|
const [items, setItems] = useState([]);
|
|
169073
168990
|
const [bloomLevels, setBloomLevels] = useState([]);
|
|
169074
|
-
const [
|
|
168991
|
+
const [questionTypes, setQuestionTypes] = useState([]);
|
|
169075
168992
|
const [isLoading, setIsLoading] = useState(true);
|
|
169076
168993
|
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
|
169077
168994
|
const [isAlertOpen, setIsAlertOpen] = useState(false);
|
|
@@ -169080,30 +168997,37 @@ function ApproachManager() {
|
|
|
169080
168997
|
const [itemToDelete, setItemToDelete] = useState(null);
|
|
169081
168998
|
const [isPending, startTransition] = useTransition();
|
|
169082
168999
|
const { toast: toast2 } = useToast();
|
|
169083
|
-
const
|
|
169084
|
-
|
|
169085
|
-
|
|
169086
|
-
|
|
169087
|
-
|
|
169088
|
-
|
|
169089
|
-
|
|
169090
|
-
|
|
169091
|
-
|
|
169092
|
-
|
|
169093
|
-
|
|
169094
|
-
|
|
169095
|
-
|
|
169000
|
+
const isControlled = initialData !== void 0;
|
|
169001
|
+
const refreshData = () => {
|
|
169002
|
+
if (!isControlled) {
|
|
169003
|
+
setIsLoading(true);
|
|
169004
|
+
try {
|
|
169005
|
+
setItems(MetadataService.getApproaches());
|
|
169006
|
+
setBloomLevels(MetadataService.getBloomLevels());
|
|
169007
|
+
setQuestionTypes(MetadataService.getQuestionTypes());
|
|
169008
|
+
} catch (error) {
|
|
169009
|
+
toast2({ title: "Error", description: "Failed to refresh metadata for Approaches.", variant: "destructive" });
|
|
169010
|
+
} finally {
|
|
169011
|
+
setIsLoading(false);
|
|
169012
|
+
}
|
|
169096
169013
|
}
|
|
169097
169014
|
};
|
|
169098
169015
|
useEffect(() => {
|
|
169099
|
-
|
|
169100
|
-
|
|
169016
|
+
if (isControlled) {
|
|
169017
|
+
setItems(initialData || []);
|
|
169018
|
+
setBloomLevels(bloomLevelsProp || []);
|
|
169019
|
+
setQuestionTypes(questionTypesProp || []);
|
|
169020
|
+
setIsLoading(isLoadingProp || false);
|
|
169021
|
+
} else {
|
|
169022
|
+
refreshData();
|
|
169023
|
+
}
|
|
169024
|
+
}, [isControlled, initialData, bloomLevelsProp, questionTypesProp, isLoadingProp]);
|
|
169101
169025
|
const resetForm = () => {
|
|
169102
169026
|
setFormState({
|
|
169103
169027
|
knowledgeDimension: "Factual",
|
|
169104
169028
|
rawDifficulty: "E",
|
|
169105
169029
|
bloomLevelCode: bloomLevels.length > 0 ? bloomLevels[0].code : "",
|
|
169106
|
-
iSpringQuizType:
|
|
169030
|
+
iSpringQuizType: questionTypes.length > 0 ? questionTypes[0].code : "multiple_choice"
|
|
169107
169031
|
});
|
|
169108
169032
|
};
|
|
169109
169033
|
const handleAddItem = () => {
|
|
@@ -169133,13 +169057,17 @@ function ApproachManager() {
|
|
|
169133
169057
|
};
|
|
169134
169058
|
const confirmDelete = () => {
|
|
169135
169059
|
if (!itemToDelete) return;
|
|
169136
|
-
startTransition(() => {
|
|
169060
|
+
startTransition(async () => {
|
|
169137
169061
|
try {
|
|
169138
|
-
|
|
169062
|
+
if (isControlled && onDelete) {
|
|
169063
|
+
await onDelete(itemToDelete);
|
|
169064
|
+
} else {
|
|
169065
|
+
MetadataService.deleteApproach(itemToDelete.code);
|
|
169066
|
+
refreshData();
|
|
169067
|
+
}
|
|
169139
169068
|
toast2({ title: "Success", description: `Approach "${itemToDelete.code}" deleted.` });
|
|
169140
|
-
fetchItems();
|
|
169141
169069
|
} catch (error) {
|
|
169142
|
-
toast2({ title: "Error", description:
|
|
169070
|
+
toast2({ title: "Error", description: error.message, variant: "destructive" });
|
|
169143
169071
|
} finally {
|
|
169144
169072
|
setIsAlertOpen(false);
|
|
169145
169073
|
setItemToDelete(null);
|
|
@@ -169147,28 +169075,37 @@ function ApproachManager() {
|
|
|
169147
169075
|
});
|
|
169148
169076
|
};
|
|
169149
169077
|
const handleSubmit = () => {
|
|
169150
|
-
const { code: code4, verbEn, verbVi } = formState;
|
|
169151
|
-
if (!code4?.trim() || !verbEn?.trim() || !verbVi?.trim()) {
|
|
169152
|
-
toast2({ title: "Validation Error", description: "
|
|
169078
|
+
const { code: code4, verbEn, verbVi, bloomLevelCode, iSpringQuizType, knowledgeDimension, rawDifficulty } = formState;
|
|
169079
|
+
if (!code4?.trim() || !verbEn?.trim() || !verbVi?.trim() || !bloomLevelCode || !iSpringQuizType || !knowledgeDimension || !rawDifficulty) {
|
|
169080
|
+
toast2({ title: "Validation Error", description: "All fields except examples and context are required.", variant: "destructive" });
|
|
169153
169081
|
return;
|
|
169154
169082
|
}
|
|
169155
|
-
startTransition(() => {
|
|
169083
|
+
startTransition(async () => {
|
|
169156
169084
|
try {
|
|
169157
169085
|
if (currentItem) {
|
|
169158
|
-
|
|
169086
|
+
if (isControlled && onUpdate) {
|
|
169087
|
+
await onUpdate({ ...currentItem, ...formState });
|
|
169088
|
+
} else {
|
|
169089
|
+
MetadataService.updateApproach(currentItem.id, formState);
|
|
169090
|
+
refreshData();
|
|
169091
|
+
}
|
|
169159
169092
|
toast2({ title: "Success", description: "Approach updated." });
|
|
169160
169093
|
} else {
|
|
169161
|
-
|
|
169094
|
+
if (isControlled && onAdd) {
|
|
169095
|
+
await onAdd(formState);
|
|
169096
|
+
} else {
|
|
169097
|
+
MetadataService.addApproach(formState);
|
|
169098
|
+
refreshData();
|
|
169099
|
+
}
|
|
169162
169100
|
toast2({ title: "Success", description: "Approach added." });
|
|
169163
169101
|
}
|
|
169164
|
-
fetchItems();
|
|
169165
169102
|
setIsDialogOpen(false);
|
|
169166
169103
|
} catch (error) {
|
|
169167
|
-
toast2({ title: "Error", description: error.message
|
|
169104
|
+
toast2({ title: "Error", description: error.message, variant: "destructive" });
|
|
169168
169105
|
}
|
|
169169
169106
|
});
|
|
169170
169107
|
};
|
|
169171
|
-
return /* @__PURE__ */ React163__default.createElement(Card, null, /* @__PURE__ */ React163__default.createElement(CardHeader, null, /* @__PURE__ */ React163__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React163__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React163__default.createElement(Settings2, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Approaches"), /* @__PURE__ */ React163__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React163__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Approach"))), /* @__PURE__ */ React163__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React163__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React163__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No Approaches found.") : /* @__PURE__ */ React163__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React163__default.createElement(Table3, null, /* @__PURE__ */ React163__default.createElement(TableHeader, null, /* @__PURE__ */ React163__default.createElement(TableRow, null, /* @__PURE__ */ React163__default.createElement(TableHead, null, "Approach ID"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Verb (VI)"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Cognitive Level"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "iSpring Type"), /* @__PURE__ */ React163__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React163__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React163__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-medium" }, item.code), /* @__PURE__ */ React163__default.createElement(TableCell, null, item.verbVi), /* @__PURE__ */ React163__default.createElement(TableCell, null, item.bloomLevelCode), /* @__PURE__ */ React163__default.createElement(TableCell, null, item.iSpringQuizType), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React163__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React163__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React163__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React163__default.createElement(DialogContent2, { className: "sm:max-w-2xl max-h-[90vh] overflow-y-auto" }, /* @__PURE__ */ React163__default.createElement(DialogHeader, null, /* @__PURE__ */ React163__default.createElement(DialogTitle2, null, currentItem ? "Edit Approach" : "Add New Approach")), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React163__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React163__default.createElement("div", null, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "code" }, "Approach Code"), /* @__PURE__ */ React163__default.createElement(Input, { id: "code", value: formState.code || "", onChange: (e3) => setFormState((s4) => ({ ...s4, code: e3.target.value.toUpperCase() })), placeholder: "e.g., REM-FAC-IDT-MCQ", disabled: !!currentItem })), /* @__PURE__ */ React163__default.createElement("div", null, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "verbEn" }, "Verb (English)"), /* @__PURE__ */ React163__default.createElement(Input, { id: "verbEn", value: formState.verbEn || "", onChange: (e3) => setFormState((s4) => ({ ...s4, verbEn: e3.target.value })), placeholder: "e.g., Identify" }))), /* @__PURE__ */ React163__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React163__default.createElement("div", null, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "verbVi" }, "Verb (Vietnamese)"), /* @__PURE__ */ React163__default.createElement(Input, { id: "verbVi", value: formState.verbVi || "", onChange: (e3) => setFormState((s4) => ({ ...s4, verbVi: e3.target.value })), placeholder: "e.g., Nh\u1EADn d\u1EA1ng" })), /* @__PURE__ */ React163__default.createElement("div", null, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "bloomLevelCode" }, "Cognitive Level"), /* @__PURE__ */ React163__default.createElement(Select2, { value: formState.bloomLevelCode, onValueChange: (v) => setFormState((s4) => ({ ...s4, bloomLevelCode: v })) }, /* @__PURE__ */ React163__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React163__default.createElement(SelectValue2, null)), /* @__PURE__ */ React163__default.createElement(SelectContent2, null, bloomLevels.map((level) => /* @__PURE__ */ React163__default.createElement(SelectItem2, { key: level.code, value: level.code }, level.name)))))), /* @__PURE__ */ React163__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-4" }, /* @__PURE__ */ React163__default.createElement("div", null, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "knowledgeDimension" }, "Knowledge Dimension"), /* @__PURE__ */ React163__default.createElement(Select2, { value: formState.knowledgeDimension, onValueChange: (v) => setFormState((s4) => ({ ...s4, knowledgeDimension: v })) }, /* @__PURE__ */ React163__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React163__default.createElement(SelectValue2, null)), /* @__PURE__ */ React163__default.createElement(SelectContent2, null, knowledgeDimensions.map((kd) => /* @__PURE__ */ React163__default.createElement(SelectItem2, { key: kd, value: kd }, kd))))), /* @__PURE__ */ React163__default.createElement("div", null, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "iSpringQuizType" }, "iSpring Quiz Type"), /* @__PURE__ */ React163__default.createElement(Select2, { value: formState.iSpringQuizType, onValueChange: (v) => setFormState((s4) => ({ ...s4, iSpringQuizType: v })) }, /* @__PURE__ */ React163__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React163__default.createElement(SelectValue2, null)), /* @__PURE__ */ React163__default.createElement(SelectContent2, null, iSpringQuizTypeOptions.map((qt) => /* @__PURE__ */ React163__default.createElement(SelectItem2, { key: qt.value, value: qt.value }, qt.label))))), /* @__PURE__ */ React163__default.createElement("div", null, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "rawDifficulty" }, "Raw Difficulty"), /* @__PURE__ */ React163__default.createElement(Select2, { value: formState.rawDifficulty, onValueChange: (v) => setFormState((s4) => ({ ...s4, rawDifficulty: v })) }, /* @__PURE__ */ React163__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React163__default.createElement(SelectValue2, null)), /* @__PURE__ */ React163__default.createElement(SelectContent2, null, rawDifficultyLevels.map((rd) => /* @__PURE__ */ React163__default.createElement(SelectItem2, { key: rd, value: rd }, rd)))))), /* @__PURE__ */ React163__default.createElement("div", null, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "suggestContext" }, "Suggest Context (comma-separated codes)"), /* @__PURE__ */ React163__default.createElement(Input, { id: "suggestContext", value: formState.suggestContext || "", onChange: (e3) => setFormState((s4) => ({ ...s4, suggestContext: e3.target.value })), placeholder: "e.g., A, B, D, G, H" })), /* @__PURE__ */ React163__default.createElement("div", null, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "exampleEn" }, "Example (English)"), /* @__PURE__ */ React163__default.createElement(Textarea, { id: "exampleEn", value: formState.exampleEn || "", onChange: (e3) => setFormState((s4) => ({ ...s4, exampleEn: e3.target.value })), placeholder: "English example prompt..." })), /* @__PURE__ */ React163__default.createElement("div", null, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "exampleVi" }, "Example (Vietnamese)"), /* @__PURE__ */ React163__default.createElement(Textarea, { id: "exampleVi", value: formState.exampleVi || "", onChange: (e3) => setFormState((s4) => ({ ...s4, exampleVi: e3.target.value })), placeholder: "Vietnamese example prompt..." }))), /* @__PURE__ */ React163__default.createElement(DialogFooter, null, /* @__PURE__ */ React163__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending || !formState.code?.trim() || !formState.verbEn?.trim() || !formState.verbVi?.trim() }, isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Save")))), /* @__PURE__ */ React163__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React163__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React163__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React163__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React163__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.code, '".')), /* @__PURE__ */ React163__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React163__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Delete"))))));
|
|
169108
|
+
return /* @__PURE__ */ React163__default.createElement(Card, null, /* @__PURE__ */ React163__default.createElement(CardHeader, null, /* @__PURE__ */ React163__default.createElement(CardTitle, { className: "flex justify-between items-center" }, /* @__PURE__ */ React163__default.createElement("span", { className: "flex items-center" }, /* @__PURE__ */ React163__default.createElement(Settings2, { className: "mr-2 h-5 w-5 text-primary" }), " Manage Approaches"), /* @__PURE__ */ React163__default.createElement(Button, { onClick: handleAddItem, size: "sm" }, /* @__PURE__ */ React163__default.createElement(CirclePlus, { className: "mr-2 h-4 w-4" }), " Add Approach"))), /* @__PURE__ */ React163__default.createElement(CardContent, null, isLoading ? /* @__PURE__ */ React163__default.createElement("div", { className: "flex justify-center items-center h-32" }, /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "h-8 w-8 animate-spin text-primary" })) : items.length === 0 ? /* @__PURE__ */ React163__default.createElement("p", { className: "text-center text-muted-foreground py-4" }, "No Approaches found.") : /* @__PURE__ */ React163__default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React163__default.createElement(Table3, null, /* @__PURE__ */ React163__default.createElement(TableHeader, null, /* @__PURE__ */ React163__default.createElement(TableRow, null, /* @__PURE__ */ React163__default.createElement(TableHead, null, "Approach ID"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Verb (VI)"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "Cognitive Level"), /* @__PURE__ */ React163__default.createElement(TableHead, null, "iSpring Type"), /* @__PURE__ */ React163__default.createElement(TableHead, { className: "text-right w-[120px]" }, "Actions"))), /* @__PURE__ */ React163__default.createElement(TableBody, null, items.map((item) => /* @__PURE__ */ React163__default.createElement(TableRow, { key: item.id }, /* @__PURE__ */ React163__default.createElement(TableCell, { className: "font-medium" }, item.code), /* @__PURE__ */ React163__default.createElement(TableCell, null, item.verbVi), /* @__PURE__ */ React163__default.createElement(TableCell, null, item.bloomLevelCode), /* @__PURE__ */ React163__default.createElement(TableCell, null, item.iSpringQuizType), /* @__PURE__ */ React163__default.createElement(TableCell, { className: "text-right" }, /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleEditItem(item), className: "mr-2" }, /* @__PURE__ */ React163__default.createElement(PenLine, { className: "h-4 w-4" })), /* @__PURE__ */ React163__default.createElement(Button, { variant: "ghost", size: "icon", onClick: () => handleDeleteItem(item), className: "text-destructive hover:text-destructive" }, /* @__PURE__ */ React163__default.createElement(Trash2, { className: "h-4 w-4" })))))))), /* @__PURE__ */ React163__default.createElement(Dialog2, { open: isDialogOpen, onOpenChange: setIsDialogOpen }, /* @__PURE__ */ React163__default.createElement(DialogContent2, { className: "sm:max-w-2xl max-h-[90vh] overflow-y-auto" }, /* @__PURE__ */ React163__default.createElement(DialogHeader, null, /* @__PURE__ */ React163__default.createElement(DialogTitle2, null, currentItem ? "Edit Approach" : "Add New Approach")), /* @__PURE__ */ React163__default.createElement("div", { className: "grid gap-4 py-4" }, /* @__PURE__ */ React163__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React163__default.createElement("div", null, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "code" }, "Approach Code"), /* @__PURE__ */ React163__default.createElement(Input, { id: "code", value: formState.code || "", onChange: (e3) => setFormState((s4) => ({ ...s4, code: e3.target.value.toUpperCase() })), placeholder: "e.g., REM-FAC-IDT-MCQ", disabled: !!currentItem })), /* @__PURE__ */ React163__default.createElement("div", null, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "verbEn" }, "Verb (English)"), /* @__PURE__ */ React163__default.createElement(Input, { id: "verbEn", value: formState.verbEn || "", onChange: (e3) => setFormState((s4) => ({ ...s4, verbEn: e3.target.value })), placeholder: "e.g., Identify" }))), /* @__PURE__ */ React163__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, /* @__PURE__ */ React163__default.createElement("div", null, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "verbVi" }, "Verb (Vietnamese)"), /* @__PURE__ */ React163__default.createElement(Input, { id: "verbVi", value: formState.verbVi || "", onChange: (e3) => setFormState((s4) => ({ ...s4, verbVi: e3.target.value })), placeholder: "e.g., Nh\u1EADn d\u1EA1ng" })), /* @__PURE__ */ React163__default.createElement("div", null, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "bloomLevelCode" }, "Cognitive Level"), /* @__PURE__ */ React163__default.createElement(Select2, { value: formState.bloomLevelCode, onValueChange: (v) => setFormState((s4) => ({ ...s4, bloomLevelCode: v })) }, /* @__PURE__ */ React163__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React163__default.createElement(SelectValue2, null)), /* @__PURE__ */ React163__default.createElement(SelectContent2, null, bloomLevels.map((level) => /* @__PURE__ */ React163__default.createElement(SelectItem2, { key: level.code, value: level.code }, level.name)))))), /* @__PURE__ */ React163__default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-4" }, /* @__PURE__ */ React163__default.createElement("div", null, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "knowledgeDimension" }, "Knowledge Dimension"), /* @__PURE__ */ React163__default.createElement(Select2, { value: formState.knowledgeDimension, onValueChange: (v) => setFormState((s4) => ({ ...s4, knowledgeDimension: v })) }, /* @__PURE__ */ React163__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React163__default.createElement(SelectValue2, null)), /* @__PURE__ */ React163__default.createElement(SelectContent2, null, knowledgeDimensions.map((kd) => /* @__PURE__ */ React163__default.createElement(SelectItem2, { key: kd, value: kd }, kd))))), /* @__PURE__ */ React163__default.createElement("div", null, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "iSpringQuizType" }, "iSpring Quiz Type"), /* @__PURE__ */ React163__default.createElement(Select2, { value: formState.iSpringQuizType, onValueChange: (v) => setFormState((s4) => ({ ...s4, iSpringQuizType: v })) }, /* @__PURE__ */ React163__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React163__default.createElement(SelectValue2, null)), /* @__PURE__ */ React163__default.createElement(SelectContent2, null, questionTypes.map((qt) => /* @__PURE__ */ React163__default.createElement(SelectItem2, { key: qt.code, value: qt.code }, qt.name))))), /* @__PURE__ */ React163__default.createElement("div", null, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "rawDifficulty" }, "Raw Difficulty"), /* @__PURE__ */ React163__default.createElement(Select2, { value: formState.rawDifficulty, onValueChange: (v) => setFormState((s4) => ({ ...s4, rawDifficulty: v })) }, /* @__PURE__ */ React163__default.createElement(SelectTrigger2, null, /* @__PURE__ */ React163__default.createElement(SelectValue2, null)), /* @__PURE__ */ React163__default.createElement(SelectContent2, null, rawDifficultyLevels.map((rd) => /* @__PURE__ */ React163__default.createElement(SelectItem2, { key: rd, value: rd }, rd)))))), /* @__PURE__ */ React163__default.createElement("div", null, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "suggestContext" }, "Suggest Context (comma-separated codes)"), /* @__PURE__ */ React163__default.createElement(Input, { id: "suggestContext", value: formState.suggestContext || "", onChange: (e3) => setFormState((s4) => ({ ...s4, suggestContext: e3.target.value })), placeholder: "e.g., A, B, D, G, H" })), /* @__PURE__ */ React163__default.createElement("div", null, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "exampleEn" }, "Example (English)"), /* @__PURE__ */ React163__default.createElement(Textarea, { id: "exampleEn", value: formState.exampleEn || "", onChange: (e3) => setFormState((s4) => ({ ...s4, exampleEn: e3.target.value })), placeholder: "English example prompt..." })), /* @__PURE__ */ React163__default.createElement("div", null, /* @__PURE__ */ React163__default.createElement(Label2, { htmlFor: "exampleVi" }, "Example (Vietnamese)"), /* @__PURE__ */ React163__default.createElement(Textarea, { id: "exampleVi", value: formState.exampleVi || "", onChange: (e3) => setFormState((s4) => ({ ...s4, exampleVi: e3.target.value })), placeholder: "Vietnamese example prompt..." }))), /* @__PURE__ */ React163__default.createElement(DialogFooter, null, /* @__PURE__ */ React163__default.createElement(Button, { type: "button", variant: "outline", onClick: () => setIsDialogOpen(false), disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(Button, { type: "submit", onClick: handleSubmit, disabled: isPending }, isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Save")))), /* @__PURE__ */ React163__default.createElement(AlertDialog2, { open: isAlertOpen, onOpenChange: setIsAlertOpen }, /* @__PURE__ */ React163__default.createElement(AlertDialogContent2, null, /* @__PURE__ */ React163__default.createElement(AlertDialogHeader, null, /* @__PURE__ */ React163__default.createElement(AlertDialogTitle2, null, "Are you sure?"), /* @__PURE__ */ React163__default.createElement(AlertDialogDescription2, null, 'This will permanently delete "', itemToDelete?.code, '".')), /* @__PURE__ */ React163__default.createElement(AlertDialogFooter, null, /* @__PURE__ */ React163__default.createElement(AlertDialogCancel2, { disabled: isPending }, "Cancel"), /* @__PURE__ */ React163__default.createElement(AlertDialogAction2, { onClick: confirmDelete, disabled: isPending, className: "bg-destructive hover:bg-destructive/90" }, isPending && /* @__PURE__ */ React163__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), " Delete"))))));
|
|
169172
169109
|
}
|
|
169173
169110
|
|
|
169174
169111
|
// src/react-ui/components/metadata/MetadataTabs.tsx
|