Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 38 additions & 47 deletions custom_components/medication_tracker/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import voluptuous as vol
from homeassistant import config_entries
from homeassistant.core import callback
from homeassistant.helpers import selector

from .const import DOMAIN

Expand All @@ -16,8 +15,10 @@ def get_dosage_schema(defaults: Dict[str, Any] = None) -> vol.Schema:
return vol.Schema({
vol.Required("pills_per_dose", default=defaults.get("pills_per_dose", 1.0)): vol.Coerce(float),
vol.Required("doses_per_day", default=defaults.get("doses_per_day", 1.0)): vol.Coerce(float),
# Added refill_amount here so single meds have it by default
vol.Required("refill_amount", default=defaults.get("refill_amount", 30)): int,
vol.Optional(
"step_value",
default=defaults.get("step_value", 0.01)
): vol.All(vol.Coerce(float), vol.Range(min=0.01)),
})

def get_threshold_schema(defaults: Dict[str, Any] = None) -> vol.Schema:
Expand All @@ -34,20 +35,13 @@ class MedicationConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
@staticmethod
@callback
def async_get_options_flow(config_entry):
"""Get the options flow for this handler."""
return MedicationOptionsFlowHandler(config_entry)

data: Dict[str, Any] = {}

async def async_step_user(self, user_input: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
"""Show the menu: Add Medication or Create Group."""
return self.async_show_menu(
step_id="user",
menu_options=["medication", "group"]
)

# --- FLOW 1: ADD MEDICATION (Original Logic) ---
async def async_step_medication(self, user_input: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
"""Handle adding a single medication."""
"""Handle the initial step."""
if user_input is not None:
self.data.update(user_input)
return await self.async_step_dosage()
Expand All @@ -59,8 +53,9 @@ async def async_step_medication(self, user_input: Optional[Dict[str, Any]] = Non
}
)
return self.async_show_form(
step_id="medication",
step_id="user",
data_schema=DATA_SCHEMA,
errors={},
description_placeholders={
"info": "Enter the name of the medication and your starting tablet count."
}
Expand All @@ -75,72 +70,68 @@ async def async_step_dosage(self, user_input: Optional[Dict[str, Any]] = None) -
return self.async_show_form(
step_id="dosage",
data_schema=get_dosage_schema(),
description_placeholders={"info": "Enter dosage and refill pack size."}
errors={},
description_placeholders={
"info": "Enter the dosage details (decimals allowed)."
}
)

async def async_step_threshold(self, user_input: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
"""Handle the threshold step."""
if user_input is not None:
self.data.update(user_input)

# Calculate daily consumption for initial setup (informational log only, entity calculates dynamically)
daily_consumption = self.data["pills_per_dose"] * self.data["doses_per_day"]
self.data["daily_consumption"] = daily_consumption

if "low_stock_days" not in self.data:
self.data["low_stock_days"] = 7

return self.async_create_entry(title=self.data["name"], data=self.data)

return self.async_show_form(
step_id="threshold",
data_schema=get_threshold_schema(),
description_placeholders={"info": "Set the low stock alert level."}
)
_LOGGER.info(f"Medication Configured: {self.data['name']} - Daily Use: {daily_consumption} tablets.")

# --- FLOW 2: CREATE GROUP (New Feature) ---
async def async_step_group(self, user_input: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
"""Handle creating a medication group."""
if user_input is not None:
return self.async_create_entry(title=user_input["name"], data=user_input)

# Uses the Native Entity Selector to show a nice list of existing trackers
SCHEMA = vol.Schema({
vol.Required("name"): str,
vol.Required("members"): selector.EntitySelector(
selector.EntitySelectorConfig(
domain="number",
integration=DOMAIN,
multiple=True
)
return self.async_create_entry(
title=self.data["name"],
data=self.data
)
})

return self.async_show_form(
step_id="group",
data_schema=SCHEMA,
step_id="threshold",
data_schema=get_threshold_schema(),
errors={},
description_placeholders={
"info": "Select the medications to include in this group."
"info": "Set the low stock alert level (in days of supply)."
}
)

class MedicationOptionsFlowHandler(config_entries.OptionsFlow):
"""Handle options."""
"""Handle Medication Tracker options."""

def __init__(self, config_entry: config_entries.ConfigEntry) -> None:
"""Initialize options flow."""
# FIXED: Use self._config_entry to avoid conflict with property 'config_entry'
self._config_entry = config_entry

async def async_step_init(self, user_input: Dict[str, Any] = None) -> Dict[str, Any]:

# If this is a Group entry, we prevent editing for now (simplicity)
if "members" in self._config_entry.data:
return self.async_abort(reason="groups_not_editable")

"""Manage the options."""
if user_input is not None:
# Update entry options
return self.async_create_entry(title="", data=user_input)

# Combine data and options to show current values as defaults
# Use self._config_entry here
current_config = {**self._config_entry.data, **self._config_entry.options}

# Build schema with current values
schema = vol.Schema({
**get_dosage_schema(current_config).schema,
**get_threshold_schema(current_config).schema,
})

return self.async_show_form(step_id="init", data_schema=schema)
return self.async_show_form(
step_id="init",
data_schema=schema,
description_placeholders={
"info": "Update dosage and alert settings."
}
)
10 changes: 9 additions & 1 deletion custom_components/medication_tracker/number.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,15 @@ def __init__(self, unique_id: str, config: Dict[str, Any]):
self._attr_mode = NumberMode.BOX
self._attr_native_min_value = 0
self._attr_native_max_value = 10000
self._attr_native_step = 0.01 # Allow decimals
# Read step_value from config (default 0.01)
try:
step_val = float(config.get("step_value", 0.01))
if step_val <= 0:
step_val = 0.01
except (TypeError, ValueError):
step_val = 0.01

self._attr_native_step = step_val
self._attr_unit_of_measurement = "tablets"
self._attr_icon = "mdi:pill"

Expand Down