fix: resolve critical bugs and improve admin panel reliability
- Fix missing await in pets API route causing empty responses - Fix updateSetting to use upsert pattern instead of update-only - Create missing /api/admin/sounds/upload route (upload was broken) - Wire bulk delete actions in catalog table - Replace native confirm() with useConfirmDialog() across rooms and clone pages - Add error logging to silent catch blocks in radio actions and audit route - Add graceful degradation to devops health endpoint - Add cache eviction to clone icon route to prevent memory leak - Internationalize hardcoded Italian strings to English - Remove placeholder created_at fields from prefix API responses - Remove dead code and fix type errors in translations and import pages - Standardize PERMS import path in analytics export route
This commit is contained in:
1 parent
6f53ca514d
commit
1b817fe434
19 files changed
+255
-89
No files matched your search
@@ -4,6 +4,7 @@ import { eq } from "drizzle-orm";
|
||||
import { revalidatePath } from "next/cache";
|
||||
import { requirePermission } from "@/lib/admin/guard";
|
||||
import { db, RadioBanners, RadioRanks, WebsiteSetting } from "@/lib/db";
|
||||
import { logger } from "@/lib/logger";
|
||||
import { PERMS } from "@/lib/permissions";
|
||||
import { siteSettings } from "@/lib/services/site-settings";
|
||||
|
||||
@@ -50,8 +51,8 @@ export async function saveRadioSetting(formData: FormData): Promise<void> {
|
||||
.values({ key, value, comment: comment || null })
|
||||
.onDuplicateKeyUpdate({ set: { value } });
|
||||
siteSettings.reload();
|
||||
} catch {
|
||||
// DB unavailable — fail soft so the action does not throw.
|
||||
} catch (err) {
|
||||
logger.error("Failed to save radio setting", { err, key });
|
||||
}
|
||||
revalidatePath("/admin/radio/settings");
|
||||
}
|
||||
@@ -81,8 +82,8 @@ export async function saveRadioSettings(formData: FormData): Promise<void> {
|
||||
}),
|
||||
);
|
||||
siteSettings.reload();
|
||||
} catch {
|
||||
// Fail soft.
|
||||
} catch (err) {
|
||||
logger.error("Failed to bulk-save radio settings", { err, keys });
|
||||
}
|
||||
revalidatePath("/admin/radio/settings");
|
||||
}
|
||||
@@ -114,8 +115,8 @@ export async function createRadioBanner(formData: FormData): Promise<void> {
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
});
|
||||
} catch {
|
||||
// Fail soft.
|
||||
} catch (err) {
|
||||
logger.error("Failed to create radio banner", { err, imagePath });
|
||||
}
|
||||
revalidatePath("/admin/radio/banners");
|
||||
}
|
||||
@@ -147,8 +148,8 @@ export async function updateRadioBanner(formData: FormData): Promise<void> {
|
||||
updatedAt: new Date(),
|
||||
})
|
||||
.where(eq(RadioBanners.id, id));
|
||||
} catch {
|
||||
// Row may be gone; ignore.
|
||||
} catch (err) {
|
||||
logger.error("Failed to update radio banner", { err, id: String(id) });
|
||||
}
|
||||
revalidatePath("/admin/radio/banners");
|
||||
}
|
||||
@@ -159,8 +160,8 @@ export async function deleteRadioBanner(formData: FormData): Promise<void> {
|
||||
if (id === null) return;
|
||||
try {
|
||||
await db.delete(RadioBanners).where(eq(RadioBanners.id, id));
|
||||
} catch {
|
||||
// Already deleted; ignore.
|
||||
} catch (err) {
|
||||
logger.error("Failed to delete radio banner", { err, id: String(id) });
|
||||
}
|
||||
revalidatePath("/admin/radio/banners");
|
||||
}
|
||||
@@ -186,8 +187,8 @@ export async function createRadioRank(formData: FormData): Promise<void> {
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
});
|
||||
} catch {
|
||||
// Fail soft.
|
||||
} catch (err) {
|
||||
logger.error("Failed to create radio rank", { err, name });
|
||||
}
|
||||
revalidatePath("/admin/radio/ranks");
|
||||
}
|
||||
@@ -214,8 +215,8 @@ export async function updateRadioRank(formData: FormData): Promise<void> {
|
||||
updatedAt: new Date(),
|
||||
})
|
||||
.where(eq(RadioRanks.id, id));
|
||||
} catch {
|
||||
// Row may be gone; ignore.
|
||||
} catch (err) {
|
||||
logger.error("Failed to update radio rank", { err, id: String(id) });
|
||||
}
|
||||
revalidatePath("/admin/radio/ranks");
|
||||
}
|
||||
@@ -226,8 +227,8 @@ export async function deleteRadioRank(formData: FormData): Promise<void> {
|
||||
if (id === null) return;
|
||||
try {
|
||||
await db.delete(RadioRanks).where(eq(RadioRanks.id, id));
|
||||
} catch {
|
||||
// Already deleted; ignore.
|
||||
} catch (err) {
|
||||
logger.error("Failed to delete radio rank", { err, id: String(id) });
|
||||
}
|
||||
revalidatePath("/admin/radio/ranks");
|
||||
}
|
||||
@@ -77,9 +77,9 @@ export async function updateSetting(formData: FormData): Promise<void> {
|
||||
);
|
||||
if (!key) return;
|
||||
await db
|
||||
.update(WebsiteSetting)
|
||||
.set({ value })
|
||||
.where(eq(WebsiteSetting.key, key));
|
||||
.insert(WebsiteSetting)
|
||||
.values({ key, value })
|
||||
.onDuplicateKeyUpdate({ set: { value } });
|
||||
await siteSettings.reload();
|
||||
bustGamedataCachesIfNeeded(key);
|
||||
revalidatePath("/admin/settings");
|
||||
|
||||
Reference in new issue
Block a user