fix(reports): add error handler and improve error messages for diagnosis

- Add reportsRouter.onError() to catch unhandled Drizzle/DB exceptions
  and return a JSON 500 with the error message instead of an empty response.
  Previously, any thrown error caused a non-OK response that the frontend
  showed only as a generic "Failed to load report data".
- Improve the frontend error to identify which specific report endpoint
  failed (name + HTTP status + first 120 chars of response body), making
  the root cause visible without needing to open the browser network tab.

Closes #49

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Groom Book CTO
2026-03-18 13:28:47 +00:00
parent 87b038d4fd
commit 5e185f0c37
2 changed files with 22 additions and 2 deletions
+5
View File
@@ -16,6 +16,11 @@ import {
export const reportsRouter = new Hono();
reportsRouter.onError((err, c) => {
console.error("[reports] unhandled error:", err);
return c.json({ error: "Internal server error", message: err.message }, 500);
});
// ─── Helpers ──────────────────────────────────────────────────────────────────
function parseDate(value: string | undefined, fallback: Date): Date {
+17 -2
View File
@@ -176,8 +176,23 @@ export function ReportsPage() {
fetch(`/api/reports/clients?${qs}`),
]);
if (!summRes.ok || !revRes.ok || !apptRes.ok || !svcRes.ok || !clientRes.ok) {
throw new Error("Failed to load report data");
const failures = [
["summary", summRes],
["revenue", revRes],
["appointments", apptRes],
["services", svcRes],
["clients", clientRes],
].filter(([, r]) => !(r as Response).ok);
if (failures.length > 0) {
const details = await Promise.all(
failures.map(async ([name, r]) => {
const res = r as Response;
let body = "";
try { body = await res.text(); } catch { /* ignore */ }
return `${name} (HTTP ${res.status}${body ? `: ${body.slice(0, 120)}` : ""})`;
})
);
throw new Error(`Failed to load report data — ${details.join(", ")}`);
}
const [summData, revData, apptData, svcData, clientData] = await Promise.all([