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
+40 -52
View File
@@ -4,40 +4,37 @@ import os
import pandas as pd
from medicine_manager import MedicineManager
class DataManager:
"""Handle all data operations for the application."""
def __init__(self, filename: str, logger: logging.Logger) -> None:
def __init__(
self, filename: str, logger: logging.Logger, medicine_manager: MedicineManager
) -> None:
self.filename: str = filename
self.logger: logging.Logger = logger
self.medicine_manager = medicine_manager
self._initialize_csv_file()
def _get_csv_headers(self) -> list[str]:
"""Get CSV headers based on current medicine configuration."""
base_headers = ["date", "depression", "anxiety", "sleep", "appetite"]
# Add medicine headers
medicine_headers = []
for medicine_key in self.medicine_manager.get_medicine_keys():
medicine_headers.extend([medicine_key, f"{medicine_key}_doses"])
return base_headers + medicine_headers + ["note"]
def _initialize_csv_file(self) -> None:
"""Create CSV file with headers if it doesn't exist."""
if not os.path.exists(self.filename):
with open(self.filename, mode="w", newline="") as file:
writer = csv.writer(file)
writer.writerow(
[
"date",
"depression",
"anxiety",
"sleep",
"appetite",
"bupropion",
"bupropion_doses",
"hydroxyzine",
"hydroxyzine_doses",
"gabapentin",
"gabapentin_doses",
"propranolol",
"propranolol_doses",
"quetiapine",
"quetiapine_doses",
"note",
]
)
writer.writerow(self._get_csv_headers())
def load_data(self) -> pd.DataFrame:
"""Load data from CSV file."""
@@ -46,27 +43,22 @@ class DataManager:
return pd.DataFrame()
try:
df: pd.DataFrame = pd.read_csv(
self.filename,
dtype={
"depression": int,
"anxiety": int,
"sleep": int,
"appetite": int,
"bupropion": int,
"bupropion_doses": str,
"hydroxyzine": int,
"hydroxyzine_doses": str,
"gabapentin": int,
"gabapentin_doses": str,
"propranolol": int,
"propranolol_doses": str,
"quetiapine": int,
"quetiapine_doses": str,
"note": str,
"date": str,
},
).fillna("")
# Build dtype dictionary dynamically
dtype_dict = {
"depression": int,
"anxiety": int,
"sleep": int,
"appetite": int,
"date": str,
"note": str,
}
# Add medicine types
for medicine_key in self.medicine_manager.get_medicine_keys():
dtype_dict[medicine_key] = int
dtype_dict[f"{medicine_key}_doses"] = str
df: pd.DataFrame = pd.read_csv(self.filename, dtype=dtype_dict).fillna("")
return df.sort_values(by="date").reset_index(drop=True)
except pd.errors.EmptyDataError:
self.logger.warning("CSV file is empty. No data to load.")
@@ -207,18 +199,14 @@ class DataManager:
"anxiety": 0,
"sleep": 0,
"appetite": 0,
"bupropion": 0,
"bupropion_doses": "",
"hydroxyzine": 0,
"hydroxyzine_doses": "",
"gabapentin": 0,
"gabapentin_doses": "",
"propranolol": 0,
"propranolol_doses": "",
"quetiapine": 0,
"quetiapine_doses": "",
"note": "",
}
# Add medicine columns dynamically
for medicine_key in self.medicine_manager.get_medicine_keys():
new_entry[medicine_key] = 0
new_entry[f"{medicine_key}_doses"] = ""
df = pd.concat([df, pd.DataFrame([new_entry])], ignore_index=True)
# Add dose to the appropriate medicine