Ship Expo Router screens, seeded stores, and polished UX so auth, shop, checkout, prescriptions, loyalty, family, and account processes work end-to-end offline. Co-authored-by: Cursor <cursoragent@cursor.com>
35 lines
1002 B
TypeScript
35 lines
1002 B
TypeScript
/** API client stub — swap BASE_URL when shared backend is live. */
|
|
|
|
export const BASE_URLS = {
|
|
core: process.env.EXPO_PUBLIC_API_URL ?? "https://api.gishen.example/v1",
|
|
} as const;
|
|
|
|
export type ApiError = { message: string; code?: string };
|
|
|
|
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>),
|
|
};
|
|
|
|
// Mock mode until backend exists
|
|
if (!process.env.EXPO_PUBLIC_API_URL) {
|
|
throw new Error(`API not configured for ${path}`);
|
|
}
|
|
|
|
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>;
|
|
}
|