Allow medications with only a generic name (no commercial name required) (#311)
* Initial plan * feat: allow generic name only for medications (frontend changes) - Add getMedDisplayName() helper for consistent name display - Update validation to require either commercial or generic name - Update all display locations to use display name fallback - Add i18n keys for nameOrGenericRequired in en.json and de.json - Remove required attribute from commercial name field - Update FIELD_LIMITS.name.min from 1 to 0 Co-authored-by: DanielVolz <3275994+DanielVolz@users.noreply.github.com> * feat: allow generic name only for medications (backend changes) - Update Zod schema to allow empty name with cross-field refinement - Update reminder scheduler to use name || genericName for display - Update planner routes to match medications by display name - Update existing tests to match new validation behavior Co-authored-by: DanielVolz <3275994+DanielVolz@users.noreply.github.com> * fix: update placeholder text and fix FIELD_LIMITS test - Remove "(optional)" from generic name placeholder in en/de - Update types.test.ts to expect FIELD_LIMITS.name.min = 0 Co-authored-by: DanielVolz <3275994+DanielVolz@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: DanielVolz <3275994+DanielVolz@users.noreply.github.com>
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
// =============================================================================
|
||||
|
||||
import type { Medication } from "../types";
|
||||
import { getMedDisplayName } from "../types";
|
||||
|
||||
/**
|
||||
* Format a Date for ICS format (YYYYMMDDTHHMMSSZ)
|
||||
@@ -18,6 +19,7 @@ function formatICSDate(date: Date): string {
|
||||
* Generate and download an ICS calendar file for a medication's schedule
|
||||
*/
|
||||
export function generateICS(med: Medication): void {
|
||||
const displayName = getMedDisplayName(med);
|
||||
const events = med.blisters
|
||||
.map((blister, idx) => {
|
||||
const start = new Date(blister.start);
|
||||
@@ -25,9 +27,9 @@ export function generateICS(med: Medication): void {
|
||||
const interval = blister.every;
|
||||
|
||||
const pillInfo = `${blister.usage} pill${blister.usage !== 1 ? "s" : ""}${med.pillWeightMg ? ` (${blister.usage * med.pillWeightMg} mg)` : ""}`;
|
||||
const summary = `💊 ${med.name} - ${pillInfo}`;
|
||||
const summary = `💊 ${displayName} - ${pillInfo}`;
|
||||
const description = [
|
||||
`Medication: ${med.name}`,
|
||||
`Medication: ${displayName}`,
|
||||
med.genericName ? `Generic: ${med.genericName}` : "",
|
||||
med.takenBy && med.takenBy.length > 0 ? `For: ${med.takenBy.join(", ")}` : "",
|
||||
`Dosage: ${pillInfo}`,
|
||||
@@ -48,7 +50,7 @@ DESCRIPTION:${description}
|
||||
BEGIN:VALARM
|
||||
TRIGGER:-PT5M
|
||||
ACTION:DISPLAY
|
||||
DESCRIPTION:Time to take ${med.name}
|
||||
DESCRIPTION:Time to take ${displayName}
|
||||
END:VALARM
|
||||
END:VEVENT`;
|
||||
})
|
||||
@@ -59,7 +61,7 @@ VERSION:2.0
|
||||
PRODID:-//MedAssist-ng//Medication Schedule//EN
|
||||
CALSCALE:GREGORIAN
|
||||
METHOD:PUBLISH
|
||||
X-WR-CALNAME:${med.name} Schedule
|
||||
X-WR-CALNAME:${displayName} Schedule
|
||||
${events}
|
||||
END:VCALENDAR`;
|
||||
|
||||
@@ -67,7 +69,7 @@ END:VCALENDAR`;
|
||||
const url = URL.createObjectURL(blob);
|
||||
const link = document.createElement("a");
|
||||
link.href = url;
|
||||
link.download = `${med.name.replace(/[^a-zA-Z0-9]/g, "_")}_schedule.ics`;
|
||||
link.download = `${displayName.replace(/[^a-zA-Z0-9]/g, "_")}_schedule.ics`;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
|
||||
Reference in New Issue
Block a user