diff --git a/scripts/ui/ccs_cases_2/doctor_office.gd b/scripts/ui/ccs_cases_2/doctor_office.gd index c206e60..57f3cce 100644 --- a/scripts/ui/ccs_cases_2/doctor_office.gd +++ b/scripts/ui/ccs_cases_2/doctor_office.gd @@ -85,10 +85,12 @@ var orders_advance_button: Button var orders_advance_option: OptionButton var orders_submit_final_button: Button var orders_status: Label +var order_search_timer: Timer var staged_order_codes: Array[String] = [] var order_names := {} var final_orders_mode := false var active_order_codes: Array = [] +var current_order_location := "" var known_order_result_count := -1 var experience_mode := "management" var pending_choices: Array = [] @@ -500,7 +502,13 @@ func _build_order_search_tab() -> void: orders_search.placeholder_text = "Search tests, medications, treatments, and procedures" orders_search.size_flags_horizontal = Control.SIZE_EXPAND_FILL orders_search.text_submitted.connect(func(_value): _request_order_search()) + orders_search.text_changed.connect(_queue_live_order_search) row.add_child(orders_search) + order_search_timer = Timer.new() + order_search_timer.one_shot = true + order_search_timer.wait_time = 0.35 + order_search_timer.timeout.connect(_request_order_search) + add_child(order_search_timer) var search_button := Button.new() search_button.text = "Search" search_button.pressed.connect(_request_order_search) @@ -572,11 +580,24 @@ func _request_order_search() -> void: order_search_requested.emit(query) +func _queue_live_order_search(query: String) -> void: + order_search_timer.stop() + if query.strip_edges().length() < 2: + _clear_dynamic_children(orders_search_results) + orders_status.text = "" + return + order_search_timer.start() + + func render_order_search(rows: Array) -> void: _clear_dynamic_children(orders_search_results) - orders_status.text = "" if not rows.is_empty() else "No matching orders found." + var available_count := 0 for raw_order in rows: var order: Dictionary = raw_order + var locations: Array = order.get("availableLocations", []) + if not locations.is_empty() and current_order_location not in locations: + continue + available_count += 1 var code := str(order.get("code", "")) order_names[code] = str(order.get("canonicalName", code.capitalize())) var button := Button.new() @@ -585,6 +606,7 @@ func render_order_search(rows: Array) -> void: button.disabled = code in staged_order_codes or code in active_order_codes button.pressed.connect(_stage_order.bind(code)) orders_search_results.add_child(button) + orders_status.text = "" if available_count > 0 else "No matching orders are available at this location." func _stage_order(code: String) -> void: @@ -624,6 +646,7 @@ func _confirm_staged_orders() -> void: func configure_orders(attempt: Dictionary) -> void: if orders_window == null: return + current_order_location = str(attempt.get("location", "")) active_order_codes = attempt.get("activeOrderCodes", []).duplicate() for code in attempt.get("activeOrderCodes", []): staged_order_codes.erase(str(code)) @@ -644,6 +667,22 @@ func configure_orders(attempt: Dictionary) -> void: " Deadline: %s" % deadline if not deadline.is_empty() else ""] open_computer() open_orders() + elif orders_status.text.begins_with("Submitting") or orders_status.text.begins_with("Cancelling") \ + or orders_status.text.begins_with("Obtaining"): + orders_status.text = "" + + +func show_order_action_complete(action: String) -> void: + match action: + "orders": + orders_tabs.current_tab = 1 + orders_status.text = "Orders confirmed. Use Obtain Results for pending tests." + "cancel_order": + orders_tabs.current_tab = 1 + orders_status.text = "Order cancelled." + "advance": + orders_tabs.current_tab = 2 + orders_status.text = "The chart has been updated with all results now available." func _render_active_orders(rows: Array) -> void: diff --git a/scripts/ui/ccs_cases_2_screen.gd b/scripts/ui/ccs_cases_2_screen.gd index 438a757..cf1a02d 100644 --- a/scripts/ui/ccs_cases_2_screen.gd +++ b/scripts/ui/ccs_cases_2_screen.gd @@ -102,6 +102,8 @@ func _on_attempt_changed() -> void: if completed_action in ["orders", "cancel_order", "advance", "enter_final_orders"] \ and active_scene != null and current_view == "doctor_office": _refresh_case_workspace(CCSService.attempt) + if completed_action != "enter_final_orders": + active_scene.show_order_action_complete(completed_action) return _render_state() diff --git a/tests/ccs_cases_2_ui_test.gd b/tests/ccs_cases_2_ui_test.gd index e0e2677..e681b88 100644 --- a/tests/ccs_cases_2_ui_test.gd +++ b/tests/ccs_cases_2_ui_test.gd @@ -99,7 +99,15 @@ func _run() -> void: _assert(screen.active_scene.vitals_launcher.icon.get_width() >= 58 and screen.active_scene.medical_history_launcher.icon.get_width() >= 58, "desktop shortcuts should use high-resolution vector imports") screen.active_scene.orders_launcher.pressed.emit() _assert(screen.active_scene.orders_window.visible and screen.active_scene.orders_tabs.get_tab_count() == 3, "Orders should open a three-tab clinical workspace") - screen.active_scene.render_order_search([{"code": "cbc", "canonicalName": "Complete blood count", "category": "laboratory"}]) + screen.active_scene._queue_live_order_search("bl") + _assert(not screen.active_scene.order_search_timer.is_stopped(), "order typing should schedule a debounced live search") + screen.active_scene.order_search_timer.stop() + screen.active_scene.current_order_location = "office" + screen.active_scene.render_order_search([ + {"code": "cbc", "canonicalName": "Complete blood count", "category": "laboratory", "availableLocations": []}, + {"code": "venous_blood_gas", "canonicalName": "Venous blood gas", "category": "laboratory", "availableLocations": ["emergency_department", "icu"]} + ]) + _assert(screen.active_scene.orders_search_results.get_child_count() == 1, "order search should hide catalog entries unavailable at the current location") (screen.active_scene.orders_search_results.get_child(0) as Button).pressed.emit() _assert(screen.active_scene.staged_order_codes == ["cbc"] and not screen.active_scene.orders_confirm_button.disabled, "catalog results should stage for confirmation") screen.active_scene.configure_orders({ @@ -109,6 +117,10 @@ func _run() -> void: }) _assert(screen.active_scene.staged_order_codes.is_empty(), "confirmed active orders should leave the staged list") _assert(screen.active_scene.orders_results.text.contains("Hemoglobin 10.4"), "returned results should render in the Orders results tab") + screen.active_scene.show_order_action_complete("orders") + _assert(screen.active_scene.orders_tabs.current_tab == 1 and screen.active_scene.orders_status.text.begins_with("Orders confirmed"), "successful submission should explain completion and open Active Orders") + screen.active_scene.show_order_action_complete("advance") + _assert(screen.active_scene.orders_tabs.current_tab == 2, "obtaining results should open the Results tab") screen.active_scene.close_orders() screen.active_scene.configure_orders({"state": "final_orders", "activeOrderCodes": [], "activeOrders": [], "chart": [], "finalOrdersDeadlineUtc": "2026-08-14T12:00:00Z"}) _assert(screen.active_scene.is_computer_open() and screen.active_scene.orders_window.visible, "final orders should automatically open the Orders app")