Files
step3/scripts/ui/review_queue_results.gd

170 lines
5.9 KiB
GDScript

extends VBoxContainer
const Brand := preload("res://scripts/ui/medmind_style.gd")
const FeatureFlags := preload("res://scripts/config/feature_flags.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 FeatureFlags.progression_enabled():
ReviewQueueService.start_pass("", 20)
return
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