164 lines
5.0 KiB
GDScript
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
|