Add medicine management functionality with UI and data handling

- Implemented MedicineManagementWindow for adding, editing, and removing medicines.
- Created MedicineManager to handle medicine configurations, including loading and saving to JSON.
- Updated UIManager to dynamically generate medicine-related UI components based on the MedicineManager.
- Enhanced test suite with mock objects for MedicineManager to ensure proper functionality in DataManager tests.
- Added validation for medicine input fields in the UI.
- Introduced default medicine configurations for initial setup.
This commit is contained in:
William Valentin
2025-07-30 16:01:02 -07:00
parent ea30cb88c9
commit d7d4b332d4
34 changed files with 1370 additions and 2576 deletions
+36 -56
View File
@@ -9,13 +9,18 @@ from typing import Any
from PIL import Image, ImageTk
from medicine_manager import MedicineManager
class UIManager:
"""Handle UI creation and management for the application."""
def __init__(self, root: tk.Tk, logger: logging.Logger) -> None:
def __init__(
self, root: tk.Tk, logger: logging.Logger, medicine_manager: MedicineManager
) -> None:
self.root: tk.Tk = root
self.logger: logging.Logger = logger
self.medicine_manager = medicine_manager
def setup_application_icon(self, img_path: str) -> bool:
"""Set up the application icon."""
@@ -157,14 +162,15 @@ class UIManager:
medicine_frame.grid(row=4, column=1, padx=0, pady=10, sticky="nsew")
medicine_frame.grid_columnconfigure(0, weight=1)
# Store medicine variables (checkboxes only)
medicine_vars: dict[str, tuple[tk.IntVar, str]] = {
"bupropion": (tk.IntVar(value=0), "Bupropion 150/300 mg"),
"hydroxyzine": (tk.IntVar(value=0), "Hydroxyzine 25mg"),
"gabapentin": (tk.IntVar(value=0), "Gabapentin 100mg"),
"propranolol": (tk.IntVar(value=0), "Propranolol 10mg"),
"quetiapine": (tk.IntVar(value=0), "Quetiapine 25mg"),
}
# Store medicine variables (checkboxes only) - dynamic based on medicine manager
medicine_vars: dict[str, tuple[tk.IntVar, str]] = {}
for medicine_key in self.medicine_manager.get_medicine_keys():
medicine = self.medicine_manager.get_medicine(medicine_key)
if medicine:
var = tk.IntVar(value=0)
text = f"{medicine.display_name} {medicine.dosage_info}"
medicine_vars[medicine_key] = (var, text)
for idx, (_med_name, (var, text)) in enumerate(medicine_vars.items()):
# Just checkbox for medicine taken
@@ -218,53 +224,34 @@ class UIManager:
table_frame.grid_rowconfigure(0, weight=1)
table_frame.grid_columnconfigure(0, weight=1)
columns: list[str] = [
"Date",
"Depression",
"Anxiety",
"Sleep",
"Appetite",
"Bupropion",
"Hydroxyzine",
"Gabapentin",
"Propranolol",
"Quetiapine",
"Note",
]
tree: ttk.Treeview = ttk.Treeview(table_frame, columns=columns, show="headings")
col_labels: list[str] = [
"Date",
"Depression",
"Anxiety",
"Sleep",
"Appetite",
"Bupropion 150/300 mg",
"Hydroxyzine 25mg",
"Gabapentin 100mg",
"Propranolol 10mg",
"Quetiapine 25mg",
"Note",
]
for col, label in zip(columns, col_labels, strict=False):
tree.heading(col, text=label)
# Build columns dynamically
columns: list[str] = ["Date", "Depression", "Anxiety", "Sleep", "Appetite"]
col_labels: list[str] = ["Date", "Depression", "Anxiety", "Sleep", "Appetite"]
col_settings: list[tuple[str, int, str]] = [
("Date", 80, "center"),
("Depression", 80, "center"),
("Anxiety", 80, "center"),
("Sleep", 80, "center"),
("Appetite", 80, "center"),
("Bupropion", 120, "center"),
("Hydroxyzine", 120, "center"),
("Gabapentin", 120, "center"),
("Propranolol", 120, "center"),
("Quetiapine", 120, "center"),
("Note", 300, "w"),
]
# Add medicine columns dynamically
for medicine_key in self.medicine_manager.get_medicine_keys():
medicine = self.medicine_manager.get_medicine(medicine_key)
if medicine:
columns.append(medicine.display_name)
col_labels.append(f"{medicine.display_name} {medicine.dosage_info}")
col_settings.append((medicine.display_name, 120, "center"))
columns.append("Note")
col_labels.append("Note")
col_settings.append(("Note", 300, "w"))
tree: ttk.Treeview = ttk.Treeview(table_frame, columns=columns, show="headings")
for col, label in zip(columns, col_labels, strict=False):
tree.heading(col, text=label)
for col, width, anchor in col_settings:
tree.column(col, width=width, anchor=anchor)
@@ -918,14 +905,7 @@ class UIManager:
def _get_quick_doses(self, medicine_key: str) -> list[str]:
"""Get common dose amounts for quick selection."""
dose_map = {
"bupropion": ["150", "300"],
"hydroxyzine": ["25", "50"],
"gabapentin": ["100", "300", "600"],
"propranolol": ["10", "20", "40"],
"quetiapine": ["25", "50", "100"],
}
return dose_map.get(medicine_key, ["25", "50"])
return self.medicine_manager.get_quick_doses(medicine_key)
def _populate_dose_history(self, text_widget: tk.Text, doses_str: str) -> None:
"""Populate dose history text widget with formatted dose data."""