Feedback categories page; treat 204 responses as success

Feedback → Categories: add, rename, reorder, archive/restore, and delete
unused categories. Feedback rows show the category's current label.

The API helper now accepts 204 No Content, which previously surfaced as a
"No Content" error after archive/delete and quiz attempt resets.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
gosangam
2026-10-18 13:47:09 +05:30
co-authored by Claude Opus 5.5
parent b194d4aa03
commit a63c329850
3 changed files with 435 additions and 17 deletions
+42
View File
@@ -36,6 +36,9 @@ async function call<T>(
headers: { "Content-Type": "application/json", ...(init?.headers ?? {}) },
...init,
});
// 204 No Content (archive, delete, reset…) is success with no body —
// there's no JSON to parse.
if (res.status === 204) return { data: undefined as T };
let body: Envelope<T>;
try {
body = (await res.json()) as Envelope<T>;
@@ -191,6 +194,8 @@ export type AdminCollection = {
export type AdminFeedback = {
id: string;
category: string;
/** The category's current display name. */
category_label?: string;
message: string;
contact_email: string | null;
created_at: string;
@@ -748,3 +753,40 @@ export const quizzes = {
resetParticipant: (id: string, userId: string) =>
call<void>(`/admin/quizzes/${id}/participants/${userId}`, { method: "DELETE" }),
};
// ─── Feedback categories ────────────────────────────────────────────────────
/** One option on the app's /feedback form. `key` is fixed once created. */
export type FeedbackCategory = {
key: string;
label: string;
description: string;
sort_order: number;
archived_at?: string | null;
/** How much feedback is filed under it. */
usage_count?: number;
};
export const feedbackCategories = {
list: () =>
call<FeedbackCategory[]>("/admin/feedback/categories").then((r) => r.data),
create: (label: string, description: string) =>
call<FeedbackCategory>("/admin/feedback/categories", {
method: "POST",
body: JSON.stringify({ label, description }),
}).then((r) => r.data),
update: (key: string, v: { label: string; description: string; archived: boolean }) =>
call<void>(`/admin/feedback/categories/${encodeURIComponent(key)}`, {
method: "PUT",
body: JSON.stringify(v),
}),
remove: (key: string) =>
call<void>(`/admin/feedback/categories/${encodeURIComponent(key)}`, {
method: "DELETE",
}),
reorder: (keys: string[]) =>
call<void>("/admin/feedback/categories/order", {
method: "PUT",
body: JSON.stringify({ keys }),
}),
};