Files
step3/scripts/ui/login_screen.gd
T

164 lines
5.0 KiB
GDScript

extends VBoxContainer
const Style := preload("res://scripts/ui/ui_style.gd")
const AUTH_LOGIN_URL := "https://pauth.ranaze.com/api/Auth/login"
var main: Control
var username_input: LineEdit
var password_input: LineEdit
var login_button: Button
var error_label: Label
var login_request: HTTPRequest
func _ready() -> void:
set_anchors_preset(Control.PRESET_FULL_RECT)
add_theme_constant_override("separation", 18)
var spacer_top := Control.new()
spacer_top.size_flags_vertical = Control.SIZE_EXPAND_FILL
add_child(spacer_top)
var center := CenterContainer.new()
center.size_flags_horizontal = Control.SIZE_EXPAND_FILL
add_child(center)
var panel := PanelContainer.new()
panel.custom_minimum_size = Vector2(520, 430)
panel.add_theme_stylebox_override("panel", Style.panel_box(Color("172337"), Color("2bdbff")))
center.add_child(panel)
var content := VBoxContainer.new()
content.add_theme_constant_override("separation", 14)
panel.add_child(content)
var title := Label.new()
title.text = "STEP 3 Arcade"
title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
Style.set_label(title, 36, Style.TEXT)
content.add_child(title)
var subtitle := Label.new()
subtitle.text = "Sign in with your Promiscuity account to start studying."
subtitle.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
subtitle.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
Style.set_label(subtitle, 16, Style.MUTED)
content.add_child(subtitle)
var username_label := Label.new()
username_label.text = "Username"
Style.set_label(username_label, 15, Style.CYAN)
content.add_child(username_label)
username_input = LineEdit.new()
username_input.placeholder_text = "enter username"
username_input.custom_minimum_size = Vector2(0, 44)
username_input.text_submitted.connect(_on_input_submitted)
content.add_child(username_input)
var password_label := Label.new()
password_label.text = "Password"
Style.set_label(password_label, 15, Style.CYAN)
content.add_child(password_label)
password_input = LineEdit.new()
password_input.placeholder_text = "enter password"
password_input.secret = true
password_input.custom_minimum_size = Vector2(0, 44)
password_input.text_submitted.connect(_on_input_submitted)
content.add_child(password_input)
login_button = Button.new()
login_button.text = "Log In"
login_button.custom_minimum_size = Vector2(0, 50)
Style.style_primary_button(login_button)
login_button.pressed.connect(_on_login_pressed)
content.add_child(login_button)
error_label = Label.new()
error_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
error_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
Style.set_label(error_label, 15, Style.RED)
content.add_child(error_label)
var spacer_bottom := Control.new()
spacer_bottom.size_flags_vertical = Control.SIZE_EXPAND_FILL
add_child(spacer_bottom)
login_request = HTTPRequest.new()
login_request.name = "LoginRequest"
login_request.request_completed.connect(_on_login_request_completed)
add_child(login_request)
func on_show(_payload: Variant = null) -> void:
error_label.text = ""
login_button.disabled = false
login_button.text = "Log In"
username_input.grab_focus()
func _on_login_pressed() -> void:
var username := username_input.text.strip_edges()
var password := password_input.text
if username.is_empty() or password.is_empty():
_show_error("Username and password required.")
return
login_button.disabled = true
login_button.text = "Signing in..."
error_label.text = ""
var payload := {
"username": username,
"password": password,
}
var headers := PackedStringArray(["Content-Type: application/json"])
var err := login_request.request(AUTH_LOGIN_URL, headers, HTTPClient.METHOD_POST, JSON.stringify(payload))
if err != OK:
login_button.disabled = false
login_button.text = "Log In"
_show_error("Failed to send login request.")
func _on_login_request_completed(result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void:
login_button.disabled = false
login_button.text = "Log In"
if result != HTTPRequest.RESULT_SUCCESS:
_show_error("Network error. Please try again.")
return
if response_code < 200 or response_code >= 300:
_show_error("Login failed. Check your credentials.")
return
var response: Variant = JSON.parse_string(body.get_string_from_utf8())
if typeof(response) != TYPE_DICTIONARY:
_show_error("Login response was not valid JSON.")
return
var token := String(response.get("accessToken", ""))
var username := String(response.get("username", username_input.text.strip_edges()))
if token.is_empty():
_show_error("Login response did not include an access token.")
return
AuthState.set_session(
username,
token,
String(response.get("refreshToken", "")),
String(response.get("role", "")),
String(response.get("exp", ""))
)
QuestionBankService.load_questions_from_api()
password_input.text = ""
main.show_screen("menu")
func _on_input_submitted(_new_text: String) -> void:
_on_login_pressed()
func _show_error(message: String) -> void:
error_label.text = message