feat: Implement an admin quest management table, enhance toast notifications with descriptions, and add new agent documentation.

This commit is contained in:
syntaxbullet
2026-01-16 15:58:48 +01:00
parent 4ecbffd617
commit 58f261562a
12 changed files with 589 additions and 44 deletions

View File

@@ -18,6 +18,9 @@ export function AdminQuests() {
const [isInitialLoading, setIsInitialLoading] = React.useState(true);
const [isRefreshing, setIsRefreshing] = React.useState(false);
const [lastCreatedQuestId, setLastCreatedQuestId] = React.useState<number | null>(null);
const [editingQuest, setEditingQuest] = React.useState<QuestListItem | null>(null);
const [isFormModeEdit, setIsFormModeEdit] = React.useState(false);
const formRef = React.useRef<HTMLDivElement>(null);
const fetchQuests = React.useCallback(async (isRefresh = false) => {
if (isRefresh) {
@@ -70,6 +73,52 @@ export function AdminQuests() {
});
};
const handleDeleteQuest = async (id: number) => {
try {
const response = await fetch(`/api/quests/${id}`, {
method: "DELETE",
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(errorData.message || "Failed to delete quest");
}
setQuests((prev) => prev.filter((q) => q.id !== id));
toast.success("Quest deleted", {
description: `Quest #${id} has been successfully deleted.`,
});
} catch (error) {
console.error("Error deleting quest:", error);
toast.error("Failed to delete quest", {
description: error instanceof Error ? error.message : "Unknown error",
});
}
};
const handleEditQuest = (id: number) => {
const quest = quests.find(q => q.id === id);
if (quest) {
setEditingQuest(quest);
setIsFormModeEdit(true);
formRef.current?.scrollIntoView({ behavior: "smooth", block: "center" });
}
};
const handleQuestUpdated = () => {
fetchQuests(true);
setEditingQuest(null);
setIsFormModeEdit(false);
toast.success("Quest list updated", {
description: "The quest inventory has been refreshed.",
});
};
const handleFormCancel = () => {
setEditingQuest(null);
setIsFormModeEdit(false);
};
return (
<main className="pt-8 px-8 pb-12 max-w-7xl mx-auto space-y-12">
<SectionHeader
@@ -84,11 +133,17 @@ export function AdminQuests() {
isInitialLoading={isInitialLoading}
isRefreshing={isRefreshing}
onRefresh={() => fetchQuests(true)}
onDelete={handleDeleteQuest}
onEdit={handleEditQuest}
/>
</div>
<div className="animate-in fade-in slide-up duration-700">
<QuestForm onSuccess={handleQuestCreated} />
<div className="animate-in fade-in slide-up duration-700" ref={formRef}>
<QuestForm
initialData={editingQuest || undefined}
onUpdate={handleQuestUpdated}
onCancel={handleFormCancel}
/>
</div>
</main>
);