diff --git a/src/animaltrack/web/routes/actions.py b/src/animaltrack/web/routes/actions.py index 16025f6..153f908 100644 --- a/src/animaltrack/web/routes/actions.py +++ b/src/animaltrack/web/routes/actions.py @@ -426,10 +426,13 @@ async def animal_promote(request: Request): form = await request.form() # Extract form data + # Note: "-" is used as sentinel for "no change" because FastHTML omits empty value attributes animal_id = form.get("animal_id", "") nickname = form.get("nickname", "") or None - sex = form.get("sex", "") or None - repro_status = form.get("repro_status", "") or None + sex_raw = form.get("sex", "") + sex = None if sex_raw in ("", "-") else sex_raw + repro_raw = form.get("repro_status", "") + repro_status = None if repro_raw in ("", "-") else repro_raw distinguishing_traits = form.get("distinguishing_traits", "") or None notes = form.get("notes", "") or None nonce = form.get("nonce") @@ -1034,10 +1037,14 @@ async def animal_attrs(request: Request, session): form = await request.form() # Extract form data + # Note: "-" is used as sentinel for "no change" because FastHTML omits empty value attributes filter_str = form.get("filter", "") - sex = form.get("sex", "").strip() or None - life_stage = form.get("life_stage", "").strip() or None - repro_status = form.get("repro_status", "").strip() or None + sex_raw = form.get("sex", "").strip() + sex = None if sex_raw in ("", "-") else sex_raw + life_stage_raw = form.get("life_stage", "").strip() + life_stage = None if life_stage_raw in ("", "-") else life_stage_raw + repro_raw = form.get("repro_status", "").strip() + repro_status = None if repro_raw in ("", "-") else repro_raw roster_hash = form.get("roster_hash", "") confirmed = form.get("confirmed", "") == "true" nonce = form.get("nonce") @@ -1277,7 +1284,9 @@ async def animal_outcome(request: Request, session): nonce = form.get("nonce") # Yield item fields - yield_product_code = form.get("yield_product_code", "").strip() or None + # Note: "-" is used as sentinel for "no selection" because FastHTML omits empty value attributes + yield_product_raw = form.get("yield_product_code", "").strip() + yield_product_code = None if yield_product_raw in ("", "-") else yield_product_raw yield_unit = form.get("yield_unit", "").strip() or None yield_quantity_str = form.get("yield_quantity", "").strip() yield_weight_str = form.get("yield_weight_kg", "").strip() diff --git a/src/animaltrack/web/templates/actions.py b/src/animaltrack/web/templates/actions.py index c3c63ab..69dd138 100644 --- a/src/animaltrack/web/templates/actions.py +++ b/src/animaltrack/web/templates/actions.py @@ -443,8 +443,9 @@ def promote_form( action_text = "Renaming" if is_rename else "Promoting" # Build sex options (optional - can refine current value) + # Note: Use "-" sentinel instead of "" because FastHTML omits empty value attributes sexes = [ - ("", "Keep current"), + ("-", "Keep current"), ("female", "Female"), ("male", "Male"), ] @@ -453,8 +454,9 @@ def promote_form( sex_options.append(Option(label, value=code, selected=code == selected_sex)) # Build repro status options (optional) - must match ReproStatus enum + # Note: Use "-" sentinel instead of "" because FastHTML omits empty value attributes repro_statuses = [ - ("", "Keep current"), + ("-", "Keep current"), ("intact", "Intact"), ("wether", "Wether (castrated male)"), ("spayed", "Spayed (female)"), @@ -1032,24 +1034,27 @@ def attrs_form( ) # Build sex options + # Note: Use "-" sentinel instead of "" because FastHTML omits empty value attributes sex_options = [ - Option("No change", value="", selected=True), + Option("No change", value="-", selected=True), Option("Female", value="female"), Option("Male", value="male"), Option("Unknown", value="unknown"), ] # Build life stage options + # Note: Use "-" sentinel instead of "" because FastHTML omits empty value attributes life_stage_options = [ - Option("No change", value="", selected=True), + Option("No change", value="-", selected=True), Option("Hatchling", value="hatchling"), Option("Juvenile", value="juvenile"), Option("Adult", value="adult"), ] # Build repro status options (intact, wether, spayed, unknown) + # Note: Use "-" sentinel instead of "" because FastHTML omits empty value attributes repro_status_options = [ - Option("No change", value="", selected=True), + Option("No change", value="-", selected=True), Option("Intact", value="intact"), Option("Wether (castrated male)", value="wether"), Option("Spayed (female)", value="spayed"), @@ -1293,7 +1298,8 @@ def outcome_form( ] # Build product options for yield items - product_options = [Option("Select product...", value="", selected=True)] + # Note: Use "-" sentinel instead of "" because FastHTML omits empty value attributes + product_options = [Option("Select product...", value="-", selected=True)] for code, name in products: product_options.append(Option(f"{name} ({code})", value=code))