extends VBoxContainer const Brand := preload("res://scripts/ui/medmind_style.gd") var main: Control var title_label: Label var summary_label: Label var status_label: Label var another_button: Button var results_panel: PanelContainer var dashboard_button: Button var launch_pending := false var latest_remaining := 0 func _ready() -> void: set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) alignment = BoxContainer.ALIGNMENT_CENTER add_theme_constant_override("separation", 18) UIThemeService.theme_changed.connect(_apply_theme) ReviewQueueService.question_loaded.connect(_on_question_loaded) ReviewQueueService.question_failed.connect(_on_question_failed) ReviewQueueService.pass_completed.connect(_on_pass_completed) ReviewQueueService.attempt_synced.connect(_on_attempt_synced) var spacer := Control.new() spacer.size_flags_vertical = Control.SIZE_EXPAND_FILL add_child(spacer) results_panel = PanelContainer.new() results_panel.custom_minimum_size = Vector2(520, 0) results_panel.size_flags_horizontal = Control.SIZE_SHRINK_CENTER add_child(results_panel) var content := VBoxContainer.new() content.add_theme_constant_override("separation", 16) results_panel.add_child(content) title_label = _label("Review pass complete", 28, true) content.add_child(title_label) summary_label = _label("", 17) summary_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART content.add_child(summary_label) status_label = _label("", 14) status_label.visible = false content.add_child(status_label) another_button = Button.new() another_button.text = "Start Another Review" another_button.custom_minimum_size.y = 46 another_button.pressed.connect(_start_another) content.add_child(another_button) dashboard_button = Button.new() dashboard_button.text = "Back to Dashboard" dashboard_button.custom_minimum_size.y = 46 dashboard_button.pressed.connect(_back_to_dashboard) content.add_child(dashboard_button) var bottom_spacer := Control.new() bottom_spacer.size_flags_vertical = Control.SIZE_EXPAND_FILL add_child(bottom_spacer) _apply_theme() func on_show(payload: Variant = null) -> void: var summary: Dictionary = payload if typeof(payload) == TYPE_DICTIONARY else ReviewQueueService.get_summary() var reviewed := int(summary.get("reviewed", 0)) var cleared := int(summary.get("cleared", 0)) var remaining := int(summary.get("remaining", 0)) latest_remaining = remaining summary_label.text = "Reviewed %d question%s\nCleared %d from the queue\n%d still need%s review" % [ reviewed, "" if reviewed == 1 else "s", cleared, remaining, "s" if remaining == 1 else "" ] another_button.disabled = remaining <= 0 or ReviewQueueService.has_pending_submissions() status_label.text = "Saving your review result..." if ReviewQueueService.has_pending_submissions() else "" status_label.visible = not status_label.text.is_empty() launch_pending = false DashboardService.refresh() func _start_another() -> void: if launch_pending: return launch_pending = true another_button.disabled = true status_label.text = "Preparing another review pass..." status_label.visible = true if not StudySessionService.session_started.is_connected(_on_review_session_started): StudySessionService.session_started.connect(_on_review_session_started) if not StudySessionService.session_failed.is_connected(_on_review_session_failed): StudySessionService.session_failed.connect(_on_review_session_failed) StudySessionService.start("due_reviews", 20, "Tutor") func _on_review_session_started() -> void: if launch_pending and visible: ReviewQueueService.start_pass("", int(StudySessionService.progress.get("targetValue", 20))) func _on_review_session_failed(message: String) -> void: if launch_pending and visible: _on_question_failed(message) func _on_question_loaded(question: Dictionary) -> void: if not launch_pending or not visible: return launch_pending = false if BlockSessionService.start_review_question(question): main.show_screen("player") else: _on_question_failed("The review question could not be prepared.") func _on_question_failed(message: String) -> void: if not launch_pending or not visible: return launch_pending = false another_button.disabled = false status_label.text = message status_label.visible = true func _on_pass_completed(summary: Dictionary) -> void: if not launch_pending or not visible: return launch_pending = false on_show(summary) func _on_attempt_synced(_question_id: String, _is_correct: bool, server_pending_count: int) -> void: if not visible: return var summary := ReviewQueueService.get_summary() summary["remaining"] = server_pending_count on_show(summary) func _back_to_dashboard() -> void: main.show_screen("dashboard") func _apply_theme(_dark: bool = UIThemeService.is_dark_mode()) -> void: var dark := UIThemeService.is_dark_mode() if results_panel != null: results_panel.add_theme_stylebox_override("panel", Brand.panel_box(dark)) for label in [title_label, summary_label]: if label != null: label.add_theme_color_override("font_color", Brand.text_color(dark)) if status_label != null: status_label.add_theme_color_override("font_color", Brand.muted_color(dark)) if another_button != null: another_button.add_theme_stylebox_override("normal", Brand.secondary_button_box(dark)) if dashboard_button != null: dashboard_button.add_theme_stylebox_override("normal", Brand.secondary_button_box(dark)) func _label(text: String, font_size: int, bold: bool = false) -> Label: var label := Label.new() label.text = text label.add_theme_font_override("font", Brand.font) label.add_theme_font_size_override("font_size", font_size) label.add_theme_color_override("font_color", Brand.text_color(UIThemeService.is_dark_mode())) if bold: label.add_theme_constant_override("outline_size", 0) return label