shockmap-api / frontend /src /api /client.js
Dhruva P Gowda
Deploy ShockMap MVP: High-fidelity UI overhaul, animated graph particles, live GDELT ingestion, and production scaffolding
f59a149
Raw History Blame Contribute Delete
4.22 kB
// In dev the Vite proxy forwards /api and /healthz to localhost:8000.
// Set VITE_BACKEND_URL in .env only when deploying with a separate origin.
const BASE_URL = import.meta.env.VITE_BACKEND_URL || '';
async function request(path, options = {}) {
const res = await fetch(`${BASE_URL}${path}`, {
headers: { 'Content-Type': 'application/json', ...options.headers },
...options,
});
if (!res.ok) {
const err = await res.json().catch(() => ({ message: res.statusText }));
throw new Error(err.detail || err.message || `HTTP ${res.status}`);
}
return res.json();
}
export const api = {
health: () => request('/healthz'),
getDrugs: (params = {}) => {
const q = new URLSearchParams();
if (params.tier) q.set('tier', params.tier);
if (params.severity) q.set('severity', params.severity);
if (params.limit) q.set('limit', params.limit);
if (params.offset) q.set('offset', params.offset);
return request(`/api/v1/drugs?${q}`);
},
getDrug: (id) => request(`/api/v1/drug/${id}`),
getAlerts: (params = {}) => {
const q = new URLSearchParams();
if (params.severity) q.set('severity', params.severity);
if (params.drug_id) q.set('drug_id', params.drug_id);
if (params.source) q.set('source', params.source);
if (params.limit) q.set('limit', params.limit);
if (params.offset) q.set('offset', params.offset);
return request(`/api/v1/alerts?${q}`);
},
getAlert: (id) => request(`/api/v1/alert/${id}`),
getGraph: () => request('/api/v1/graph'),
getStateRisks: () => request('/api/v1/graph/states'),
query: (question, context_filters = {}) =>
request('/api/v1/query', {
method: 'POST',
body: JSON.stringify({ question, context_filters }),
}),
simulate: (province, duration_days, severity) =>
request('/api/v1/simulate', {
method: 'POST',
body: JSON.stringify({ province, duration_days, severity }),
}),
getSectors: () => request('/api/v1/sectors'),
getShocks: (params = {}) => {
const q = new URLSearchParams();
if (params.sector) q.set('sector', params.sector);
if (params.severity) q.set('severity', params.severity);
if (params.limit) q.set('limit', params.limit);
return request(`/api/v1/shocks?${q}`);
},
getShock: (id) => request(`/api/v1/shocks/${id}`),
getShockWarRoom: (id) => request(`/api/v1/shocks/${id}/war-room`),
simulateShockAction: (id, actionId) =>
request(`/api/v1/shocks/${id}/simulate-action`, {
method: 'POST',
body: JSON.stringify({ action_id: actionId }),
}),
// Engine 2: Propagation + Communities
getPropagation: (province, sector = 'pharma') =>
request(`/api/v1/propagation/${encodeURIComponent(province)}?sector=${sector}`),
getCommunities: () => request('/api/v1/communities'),
getNodeCommunity: (nodeId) =>
request(`/api/v1/communities/${encodeURIComponent(nodeId)}`),
getCriticality: (nodeId) =>
request(`/api/v1/criticality/${encodeURIComponent(nodeId)}`),
// Engine 3: Action Intelligence
getActionPlan: (region, shockType = 'factory_shutdown', sector = 'pharma') =>
request('/api/v1/action-plan', {
method: 'POST',
body: JSON.stringify({ region, shock_type: shockType, sector }),
}),
// Engine Status
getEngineStatus: () => request('/api/v1/engines'),
// ─── Map Intelligence ────────────────────────────────────────────────
getMapHeatmap: (params = {}) => {
const q = new URLSearchParams();
if (params.sector) q.set('sector', params.sector);
if (params.risk_min) q.set('risk_min', params.risk_min);
if (params.shock_type) q.set('shock_type', params.shock_type);
if (params.region) q.set('region', params.region);
return request(`/api/v1/map/heatmap?${q}`);
},
getMapProvince: (id, sector = 'both') =>
request(`/api/v1/map/provinces/${encodeURIComponent(id)}?sector=${sector}`),
getMapCorridors: (sector = 'both') =>
request(`/api/v1/map/supply-corridors?sector=${sector}`),
getMapFacets: () => request('/api/v1/map/filter-facets'),
getMapStats: () => request('/api/v1/map/stats'),
};