Files
temetro/frontend/lib/inventory.ts
T
Khalid Abdi 321a6298a4 frontend: pharmacy inventory, lab add-result & analysis charts
- Pharmacy: the sidebar entry now expands into Pharmacy + a new Inventory page
  (searchable medication stock with derived in-stock/low/out availability,
  backed by /api/inventory). Fix the dispensing-queue "Expiring" badge so it
  only flags courses ending within the next 7 days, not ones already elapsed.
- Lab "Add analysis result": the patient picker no longer lists patients until
  you type and supports arrow-key + Enter selection; the test field offers a
  catalog of common analyses with an Advanced option (custom analysis + ref
  range); submitted results now show immediately in a Recent results feed.
- Analysis: add a Live panel (real-time line chart) and replace the flat trend
  sparklines with bklit-ui area + bar charts (installed from the @bklit shadcn
  registry; chart CSS variables wired into the theme for light and dark).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 19:22:07 +03:00

67 lines
1.8 KiB
TypeScript

import { apiFetch } from "@/lib/api-client";
// A pharmacy stock item. Mirrors the backend `src/types/inventory.ts`. Scoped to
// the active clinic. `expiresAt` is an ISO YYYY-MM-DD date (or null).
export type InventoryItem = {
id: string;
name: string;
form: string;
strength: string;
unit: string;
stockQuantity: number;
reorderThreshold: number;
location: string;
expiresAt: string | null;
notes: string | null;
createdAt: string;
updatedAt: string;
};
// The fields the inventory dialog collects.
export type InventoryInput = {
name: string;
form?: string;
strength?: string;
unit?: string;
stockQuantity?: number;
reorderThreshold?: number;
location?: string;
expiresAt?: string | null;
notes?: string | null;
};
export type Availability = "in-stock" | "low" | "out";
// Derived stock status: out at zero, low at/under the reorder threshold,
// otherwise in stock. Computed on the client (not persisted).
export function availabilityOf(item: InventoryItem): Availability {
if (item.stockQuantity <= 0) return "out";
if (item.stockQuantity <= item.reorderThreshold) return "low";
return "in-stock";
}
export function listInventory(): Promise<InventoryItem[]> {
return apiFetch<InventoryItem[]>("/api/inventory");
}
export function createInventory(input: InventoryInput): Promise<InventoryItem> {
return apiFetch<InventoryItem>("/api/inventory", {
method: "POST",
body: JSON.stringify(input),
});
}
export function updateInventory(
id: string,
input: InventoryInput,
): Promise<InventoryItem> {
return apiFetch<InventoryItem>(`/api/inventory/${id}`, {
method: "PUT",
body: JSON.stringify(input),
});
}
export function deleteInventory(id: string): Promise<void> {
return apiFetch<void>(`/api/inventory/${id}`, { method: "DELETE" });
}