Skip to content

Commit e4c6ddf

Browse files
committed
feat(api): improve error handling in API requests for clearer messages
1 parent 01f9a39 commit e4c6ddf

4 files changed

Lines changed: 18 additions & 6 deletions

File tree

apps/management-ui/lib/api/bookings.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ async function bookingRequest<T>(
2020
if (!res.ok) {
2121
let errBody: unknown;
2222
try { errBody = await res.json(); } catch { /* ignore */ }
23-
throw new ApiError(res.status, `${res.status} ${res.statusText}`, errBody);
23+
const msg =
24+
errBody && typeof errBody === "object" && "error" in errBody
25+
? String((errBody as { error: string }).error)
26+
: `${res.status} ${res.statusText}`;
27+
throw new ApiError(res.status, msg, errBody);
2428
}
2529
if (res.status === 204) return undefined as T;
2630
return res.json() as Promise<T>;

apps/management-ui/lib/api/client.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,11 @@ async function request<T>(path: string, opts: RequestOptions = {}): Promise<T> {
3838
if (!res.ok) {
3939
let errBody: unknown;
4040
try { errBody = await res.json(); } catch { /* ignore */ }
41-
throw new ApiError(res.status, `${res.status} ${res.statusText}`, errBody);
41+
const msg =
42+
errBody && typeof errBody === "object" && "error" in errBody
43+
? String((errBody as { error: string }).error)
44+
: `${res.status} ${res.statusText}`;
45+
throw new ApiError(res.status, msg, errBody);
4246
}
4347

4448
if (res.status === 204) return undefined as T;

apps/management-ui/lib/api/config.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ async function configRequest<T>(
2020
if (!res.ok) {
2121
let errBody: unknown;
2222
try { errBody = await res.json(); } catch { /* ignore */ }
23-
throw new ApiError(res.status, `${res.status} ${res.statusText}`, errBody);
23+
const msg =
24+
errBody && typeof errBody === "object" && "error" in errBody
25+
? String((errBody as { error: string }).error)
26+
: `${res.status} ${res.statusText}`;
27+
throw new ApiError(res.status, msg, errBody);
2428
}
2529
if (res.status === 204) return undefined as T;
2630
return res.json() as Promise<T>;

services/booking-service/internal/handler/handler.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,11 @@ func (h *Handler) CreateBooking(w http.ResponseWriter, r *http.Request) {
141141
return
142142
}
143143

144-
// ── Policy: slot duration must be a positive multiple of slotDurationMinutes
144+
// ── Policy: slot must meet the minimum configured duration ─────────────────
145145
slotMinutes := int(req.SlotEnd.Sub(req.SlotStart).Minutes())
146-
if bookCfg.SlotDurationMinutes > 0 && slotMinutes%bookCfg.SlotDurationMinutes != 0 {
146+
if bookCfg.SlotDurationMinutes > 0 && slotMinutes < bookCfg.SlotDurationMinutes {
147147
respondError(w, http.StatusUnprocessableEntity, fmt.Sprintf(
148-
"slot duration (%d min) must be a multiple of the configured slot duration (%d min)",
148+
"slot duration (%d min) is shorter than the minimum slot duration configured for this tenant (%d min)",
149149
slotMinutes, bookCfg.SlotDurationMinutes,
150150
))
151151
return

0 commit comments

Comments
 (0)