feat: add totalPills to medication and planner rows for improved stock tracking

This commit is contained in:
Daniel Volz
2025-12-21 00:12:47 +01:00
parent 522223cb01
commit 4ffbcef877
3 changed files with 20 additions and 6 deletions
+2
View File
@@ -261,6 +261,7 @@ export async function medicationRoutes(app: FastifyInstance) {
const packCount = row.packCount ?? 1;
const stripsPerPack = row.stripsPerPack ?? row.strips ?? 1;
const looseTablets = row.looseTablets ?? 0;
const totalPills = row.count;
const stripsNeeded = tabsPerStrip > 0 ? Math.ceil(usageTotal / tabsPerStrip) : 0;
const stripsAvailable = packCount * stripsPerPack + (tabsPerStrip > 0 ? looseTablets / tabsPerStrip : 0);
@@ -268,6 +269,7 @@ export async function medicationRoutes(app: FastifyInstance) {
return {
medicationId: row.id,
medicationName: row.name,
totalPills,
plannerUsage: usageTotal,
stripSize: tabsPerStrip,
stripsNeeded,
+7 -4
View File
@@ -5,6 +5,7 @@ import { updateReminderSentTime } from "../services/reminder-scheduler.js";
type PlannerRow = {
medicationId: number;
medicationName: string;
totalPills: number;
plannerUsage: number;
stripSize: number;
stripsNeeded: number;
@@ -68,7 +69,8 @@ export async function plannerRoutes(app: FastifyInstance) {
(row) => `
<tr>
<td style="padding: 10px 12px; border-bottom: 1px solid #e5e7eb; white-space: nowrap;">${row.medicationName}</td>
<td style="padding: 10px 12px; border-bottom: 1px solid #e5e7eb; text-align: center; white-space: nowrap;"><strong>${row.plannerUsage}</strong> pills</td>
<td style="padding: 10px 12px; border-bottom: 1px solid #e5e7eb; text-align: center; white-space: nowrap;"><strong>${row.totalPills}</strong></td>
<td style="padding: 10px 12px; border-bottom: 1px solid #e5e7eb; text-align: center; white-space: nowrap;"><strong>${row.plannerUsage}</strong></td>
<td style="padding: 10px 12px; border-bottom: 1px solid #e5e7eb; text-align: center; white-space: nowrap;">${row.stripsNeeded} × ${row.stripSize}</td>
<td style="padding: 10px 12px; border-bottom: 1px solid #e5e7eb; text-align: center; white-space: nowrap;">${row.stripsAvailable}</td>
<td style="padding: 10px 12px; border-bottom: 1px solid #e5e7eb; text-align: center; white-space: nowrap;">
@@ -77,7 +79,7 @@ export async function plannerRoutes(app: FastifyInstance) {
? "background: #d1fae5; color: #065f46;"
: "background: #fee2e2; color: #991b1b;"
}">
${row.enough ? "✓ OK" : "⚠ Low"}
${row.enough ? "✓ OK" : "✗ Out of Stock"}
</span>
</td>
</tr>
@@ -108,10 +110,11 @@ export async function plannerRoutes(app: FastifyInstance) {
</div>
<div style="overflow-x: auto; -webkit-overflow-scrolling: touch;">
<table style="width: 100%; border-collapse: collapse; background: white; min-width: 500px;">
<table style="width: 100%; border-collapse: collapse; background: white; min-width: 550px;">
<thead>
<tr style="background: #f3f4f6;">
<th style="padding: 10px 12px; text-align: left; font-size: 11px; text-transform: uppercase; color: #6b7280; letter-spacing: 0.05em; white-space: nowrap;">Medication</th>
<th style="padding: 10px 12px; text-align: center; font-size: 11px; text-transform: uppercase; color: #6b7280; letter-spacing: 0.05em; white-space: nowrap;">Stock</th>
<th style="padding: 10px 12px; text-align: center; font-size: 11px; text-transform: uppercase; color: #6b7280; letter-spacing: 0.05em; white-space: nowrap;">Usage</th>
<th style="padding: 10px 12px; text-align: center; font-size: 11px; text-transform: uppercase; color: #6b7280; letter-spacing: 0.05em; white-space: nowrap;">Needed</th>
<th style="padding: 10px 12px; text-align: center; font-size: 11px; text-transform: uppercase; color: #6b7280; letter-spacing: 0.05em; white-space: nowrap;">Available</th>
@@ -135,7 +138,7 @@ Supply overview from ${fromDate} to ${untilDate}
${summaryText}
${rows.map((r) => `${r.medicationName}: ${r.plannerUsage} pills needed, ${r.stripsAvailable} blisters available (${r.stripsNeeded} needed) - ${r.enough ? "Enough" : "OUT OF STOCK"}`).join("\n")}
${rows.map((r) => `${r.medicationName}: ${r.totalPills} pills in stock, ${r.plannerUsage} pills needed, ${r.stripsAvailable} blisters available (${r.stripsNeeded} needed) - ${r.enough ? "Enough" : "OUT OF STOCK"}`).join("\n")}
---
Sent from MedAssist Medication Planner`;
+11 -2
View File
@@ -28,6 +28,7 @@ type Medication = {
type PlannerRow = {
medicationId: number;
medicationName: string;
totalPills: number;
plannerUsage: number;
stripSize: number;
stripsNeeded: number;
@@ -495,12 +496,20 @@ export default function App() {
setTheme((prev) => (prev === "dark" ? "light" : "dark"));
}
// Page titles based on current route
const pageInfo = {
"/dashboard": { eyebrow: "MedAssist · Overview", title: "Dashboard" },
"/medications": { eyebrow: "MedAssist · Inventory", title: "Manage Medications" },
"/planner": { eyebrow: "MedAssist · Planner", title: "Demand Calculator" },
"/settings": { eyebrow: "MedAssist · Configuration", title: "Settings" },
}[currentPath] || { eyebrow: "MedAssist · Overview", title: "Dashboard" };
return (
<main className="page">
<header className="hero">
<div>
<p className="eyebrow">Medassist · Planner</p>
<h1>Manage medication plans</h1>
<p className="eyebrow">{pageInfo.eyebrow}</p>
<h1>{pageInfo.title}</h1>
</div>
<div className="header-actions">
<div className="tabs">