mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 07:38:10 +00:00
Implement intercity document handling and rejection notes for contracts
This commit is contained in:
@@ -1,10 +1,7 @@
|
||||
import axios from "axios";
|
||||
import toast from "react-hot-toast";
|
||||
|
||||
import { API_BASE_URL } from "@/constants/apiConfig";
|
||||
import {
|
||||
emitApiError,
|
||||
extractApiErrorPayload,
|
||||
} from "@/components/errors/ApiErrorModal";
|
||||
import { captureApiError } from "@/lib/posthog";
|
||||
import {
|
||||
AUTH_TOKEN_COOKIE,
|
||||
@@ -14,14 +11,16 @@ import {
|
||||
setCookie,
|
||||
} from "./cookies";
|
||||
import type { AuthTokens } from "./types";
|
||||
import { extractApiErrorPayload } from "@/components/errors/ApiErrorModal";
|
||||
|
||||
declare module "axios" {
|
||||
export interface AxiosRequestConfig {
|
||||
/**
|
||||
* When true, the response interceptor does NOT raise the global error modal
|
||||
* for this request's failure. For calls the caller handles itself — e.g. a
|
||||
* probe that is expected to 404 before falling back (GL clearance detail
|
||||
* tries /contracts/:id then /bookings/:id). The rejection still propagates.
|
||||
* When true, the response interceptor does NOT raise the global error
|
||||
* toast for this request's failure. For calls the caller handles itself —
|
||||
* e.g. a probe that is expected to 404 before falling back (GL clearance
|
||||
* detail tries /contracts/:id then /bookings/:id). The rejection still
|
||||
* propagates.
|
||||
*/
|
||||
suppressErrorModal?: boolean;
|
||||
}
|
||||
@@ -96,9 +95,8 @@ api.interceptors.response.use(
|
||||
async (error) => {
|
||||
const originalRequest = error.config as RetriableRequest | undefined;
|
||||
|
||||
// Report the failure to PostHog. Hooked here rather than inside
|
||||
// `emitApiError`, which stays silent on suppressed paths (warehouse /
|
||||
// mile / onboarding) — those failures still need reporting.
|
||||
// Report the failure to PostHog, including on suppressErrorModal paths —
|
||||
// those opt out of the user-facing toast, not of reporting.
|
||||
// 401s are skipped: an expired session is refreshed below, not a defect.
|
||||
if (!error.response || error.response.status !== 401) {
|
||||
captureApiError(error);
|
||||
@@ -112,19 +110,25 @@ api.interceptors.response.use(
|
||||
originalRequest.url?.includes("/auth/mfa-verify") ||
|
||||
originalRequest.url?.includes("/auth/refresh-token")
|
||||
) {
|
||||
// Surface the server's actual error message in the global error modal
|
||||
// (401s are handled by the session-refresh flow, so skip them). A request
|
||||
// may opt out via `suppressErrorModal` when it handles the failure itself.
|
||||
// Surface the server's actual error message in a global toast — never
|
||||
// the error modal (401s are handled by the session-refresh flow, so skip
|
||||
// them). A request may opt out via `suppressErrorModal` when it handles
|
||||
// the failure itself.
|
||||
if (error.response && error.response.status !== 401) {
|
||||
const payload = extractApiErrorPayload(error);
|
||||
// Normalize the error's own `message` to the SERVER's actual message so
|
||||
// every downstream `toast.error(err.message)` / MutationCache handler
|
||||
// shows the real cause instead of "Request failed with status code NNN".
|
||||
// Applies even on suppressErrorModal paths — only the modal is opted out.
|
||||
// every downstream `toast.error(err.message)` handler shows the real
|
||||
// cause instead of "Request failed with status code NNN". Applies even
|
||||
// on suppressErrorModal paths — only the toast is opted out.
|
||||
if (payload?.messages.length) {
|
||||
(error as { message?: string }).message = payload.messages.join("\n");
|
||||
const message = payload.messages.join("\n");
|
||||
(error as { message?: string }).message = message;
|
||||
// Keyed by message so a retried request replaces its toast instead
|
||||
// of stacking duplicates.
|
||||
if (!originalRequest?.suppressErrorModal) {
|
||||
toast.error(message, { id: message });
|
||||
}
|
||||
}
|
||||
if (payload && !originalRequest?.suppressErrorModal) emitApiError(payload);
|
||||
}
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user