fix(campaigns): fix start_date modal — interceptor was losing structured detail
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
client.ts: when FastAPI detail is an object, extract .message for the error string and preserve the full detail on enhancedError.detail so consumers can inspect structured error payloads (e.g. 409 start_date_in_future). CampaignDetailPage: use enhancedErr.status (not response.status) and enhancedErr.detail (not response.data.detail) to detect 409 and show the confirmation modal instead of the toast. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -64,15 +64,27 @@ client.interceptors.response.use(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract error message from response
|
// Extract error message — detail can be a string or a structured object
|
||||||
|
const rawDetail = error.response?.data?.detail;
|
||||||
const message =
|
const message =
|
||||||
error.response?.data?.detail ||
|
typeof rawDetail === "string"
|
||||||
error.message ||
|
? rawDetail
|
||||||
"An unexpected error occurred";
|
: typeof rawDetail === "object" && rawDetail !== null && (rawDetail as { message?: string }).message
|
||||||
|
? (rawDetail as { message: string }).message
|
||||||
|
: error.message || "An unexpected error occurred";
|
||||||
|
|
||||||
const enhancedError = new Error(message);
|
const enhancedError = new Error(message) as Error & {
|
||||||
(enhancedError as Error & { status?: number }).status = status;
|
status?: number;
|
||||||
(enhancedError as Error & { code?: string }).code = error.response?.data?.code;
|
code?: string;
|
||||||
|
detail?: unknown;
|
||||||
|
};
|
||||||
|
enhancedError.status = status;
|
||||||
|
// Preserve the full detail object so consumers can inspect it (e.g. for modal flows)
|
||||||
|
enhancedError.detail = rawDetail;
|
||||||
|
enhancedError.code =
|
||||||
|
typeof rawDetail === "object" && rawDetail !== null
|
||||||
|
? (rawDetail as { code?: string }).code
|
||||||
|
: error.response?.data?.code;
|
||||||
|
|
||||||
return Promise.reject(enhancedError);
|
return Promise.reject(enhancedError);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -98,29 +98,23 @@ export default function CampaignDetailPage() {
|
|||||||
showToast("Campaign activated", "success");
|
showToast("Campaign activated", "success");
|
||||||
},
|
},
|
||||||
onError: (err: unknown) => {
|
onError: (err: unknown) => {
|
||||||
// FastAPI wraps error bodies as: { detail: string | object }
|
// The Axios interceptor (client.ts) transforms errors into enhanced Error objects
|
||||||
type AxiosLike = {
|
// with .status (HTTP status), .detail (raw FastAPI detail), and .message (readable string)
|
||||||
response?: {
|
type EnhancedError = Error & {
|
||||||
status?: number;
|
status?: number;
|
||||||
data?: { detail?: { code?: string; message?: string } | string };
|
detail?: { code?: string; message?: string } | string;
|
||||||
};
|
|
||||||
};
|
};
|
||||||
const axiosErr = err as AxiosLike;
|
const e = err as EnhancedError;
|
||||||
const status = axiosErr?.response?.status;
|
|
||||||
const detail = axiosErr?.response?.data?.detail;
|
|
||||||
|
|
||||||
if (status === 409 && detail && typeof detail === "object" && detail.message) {
|
if (e.status === 409) {
|
||||||
// Future start_date → show confirmation modal
|
// Future start_date — show confirmation modal using the message from detail
|
||||||
setStartDateWarning(detail.message);
|
const warningMsg =
|
||||||
|
typeof e.detail === "object" && e.detail?.message
|
||||||
|
? e.detail.message
|
||||||
|
: e.message;
|
||||||
|
setStartDateWarning(warningMsg);
|
||||||
} else {
|
} else {
|
||||||
// Any other error → extract readable message from FastAPI detail
|
showToast(e.message || "Failed to activate campaign", "error");
|
||||||
const msg =
|
|
||||||
typeof detail === "string"
|
|
||||||
? detail
|
|
||||||
: typeof detail === "object" && detail?.message
|
|
||||||
? detail.message
|
|
||||||
: "Failed to activate campaign";
|
|
||||||
showToast(msg, "error");
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user