This repository has been archived on 2026-08-11. You can view files and clone it, but cannot push or open issues or pull requests.
Gishen-Mob/lib/api/client.ts
kirukib d40cb22ff4 Finalize profile, prescription, and checkout with shared UI modules.
Add payment/notification prefs, assisted pharmacist codes, Rx status journey, and mock payment intents so demo flows match the storefront brief.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-10 14:53:34 +03:00

74 lines
2.0 KiB
TypeScript

/** API client — mock adapters when EXPO_PUBLIC_API_URL is unset. */
export const BASE_URLS = {
core: process.env.EXPO_PUBLIC_API_URL ?? "https://api.gishen.example/v1",
} as const;
export const USE_MOCKS = !process.env.EXPO_PUBLIC_API_URL;
export type ApiError = { message: string; code?: string };
export type PaymentIntent = {
id: string;
provider: string;
status: "requires_action" | "succeeded" | "pending";
amountEtb: number;
checkoutUrl?: string;
};
export async function initiatePayment(input: {
provider: string;
amountEtb: number;
orderId: string;
}): Promise<PaymentIntent> {
if (USE_MOCKS) {
await delay(450);
return {
id: `pay_${Date.now()}`,
provider: input.provider,
status: input.provider === "bank" || input.provider === "cod" || input.provider === "pay_at_branch"
? "pending"
: "succeeded",
amountEtb: input.amountEtb,
checkoutUrl:
input.provider === "chapa" || input.provider === "arifpay"
? `https://checkout.mock.gishen/${input.provider}`
: undefined,
};
}
return callEndpoint<PaymentIntent>("/payments/intent", {
method: "POST",
body: JSON.stringify(input),
});
}
export async function callEndpoint<T>(
path: string,
init?: RequestInit & { locale?: string }
): Promise<T> {
const headers: Record<string, string> = {
"Content-Type": "application/json",
Accept: "application/json",
...(init?.locale ? { "Accept-Language": init.locale } : {}),
...(init?.headers as Record<string, string>),
};
if (USE_MOCKS) {
throw new Error(`No mock for ${path} — pass EXPO_PUBLIC_API_URL or add an adapter`);
}
const res = await fetch(`${BASE_URLS.core}${path}`, {
...init,
headers,
});
if (!res.ok) {
const body = (await res.json().catch(() => ({}))) as ApiError;
throw new Error(body.message || res.statusText);
}
return res.json() as Promise<T>;
}
function delay(ms: number) {
return new Promise((r) => setTimeout(r, ms));
}