package dev.inmo.postssystem.client.fsm.ui import dev.inmo.postssystem.client.ui.fsm.* import dev.inmo.postssystem.client.utils.HTMLViewContainer import dev.inmo.postssystem.features.auth.client.ui.* import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions import dev.inmo.micro_utils.fsm.common.StatesMachine import kotlinx.browser.document import kotlinx.coroutines.* import kotlinx.dom.clear import kotlinx.html.* import kotlinx.html.dom.append import kotlinx.html.js.form import kotlinx.html.js.onClickFunction import org.w3c.dom.* class AuthView( private val viewModel: AuthUIViewModel, private val uiScope: CoroutineScope ) : JSView() { private val usernameInput get() = document.getElementById("authUsername") as? HTMLInputElement private val passwordInput get() = document.getElementById("authPassword") as? HTMLInputElement private val authButton get() = document.getElementById("authButton") private val errorBadge get() = document.getElementById("errorBadge") as? HTMLElement private val progressBarDiv get() = document.getElementById("progressBar") as? HTMLDivElement override suspend fun StatesMachine.safeHandleState( htmlElement: HTMLElement, container: HTMLViewContainer, state: AuthUIFSMState ): UIFSMState? { val completion = CompletableDeferred() htmlElement.clear() htmlElement.append { form(classes = "vertical_container") { div(classes = "mdl-textfield mdl-js-textfield mdl-textfield--floating-label") { input(type = InputType.text, classes = "mdl-textfield__input") { id = "authUsername" } label(classes = "mdl-textfield__label") { +"Имя пользователя" } } div(classes = "mdl-textfield mdl-js-textfield mdl-textfield--floating-label") { input(type = InputType.password, classes = "mdl-textfield__input") { id = "authPassword" } label(classes = "mdl-textfield__label") { +"Пароль" } } div(classes = "mdl-progress mdl-js-progress") { id = "progressBar" } span(classes = "material-icons mdl-badge mdl-badge--overlap gone") { id = "errorBadge" attributes["data-badge"] = "!" } button(classes = "mdl-button mdl-js-button mdl-button--raised") { +"Авторизоваться" id = "authButton" onClickFunction = { it.preventDefault() val serverUrl = document.location ?.run { "$hostname:$port" } val username = usernameInput ?.value val password = passwordInput ?.value if (serverUrl != null && username != null && password != null) { uiScope.launchSafelyWithoutExceptions { viewModel.initAuth(serverUrl, username, password) } } } } } } val viewJob = viewModel.currentState.subscribeSafelyWithoutExceptions(uiScope) { when (it) { is InitAuthUIState -> { usernameInput ?.removeAttribute("disabled") passwordInput ?.removeAttribute("disabled") authButton ?.removeAttribute("disabled") errorBadge ?.apply { when (it.showError) { ServerUnavailableAuthUIError -> { classList.remove("gone") innerText = "Сервер недоступен" } AuthIncorrectAuthUIError -> { classList.remove("gone") innerText = "Данные некорректны" } null -> classList.add("gone") } } progressBarDiv ?.classList ?.add("gone") } LoadingAuthUIState -> { usernameInput ?.setAttribute("disabled", "") passwordInput ?.setAttribute("disabled", "") authButton ?.setAttribute("disabled", "") errorBadge ?.classList ?.add("gone") progressBarDiv ?.classList ?.remove("gone") } AuthorizedAuthUIState -> { htmlElement.clear() completion.complete(state.from) } } } return completion.await().also { viewJob.cancel() } } }