core/client/src/jsMain/kotlin/dev/inmo/postssystem/client/fsm/ui/AuthView.kt
2022-01-25 15:21:01 +06:00

106 lines
4.0 KiB
Kotlin

package dev.inmo.postssystem.client.fsm.ui
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import dev.inmo.jsuikit.elements.*
import dev.inmo.jsuikit.modifiers.*
import dev.inmo.jsuikit.utils.Attrs
import dev.inmo.postssystem.client.ui.fsm.*
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 dev.inmo.postssystem.client.utils.renderComposableAndLinkToContext
import kotlinx.browser.document
import kotlinx.coroutines.*
import kotlinx.dom.*
import org.jetbrains.compose.web.attributes.InputType
import org.jetbrains.compose.web.dom.Form
import org.jetbrains.compose.web.dom.Text
import org.w3c.dom.*
class AuthView(
private val viewModel: AuthUIViewModel,
private val uiScope: CoroutineScope
) : JSView<AuthUIFSMState>() {
override suspend fun StatesMachine<in UIFSMState>.safeHandleState(
htmlElement: HTMLElement,
state: AuthUIFSMState
): UIFSMState? {
val completion = CompletableDeferred<UIFSMState?>()
val usernameState = mutableStateOf("")
val passwordState = mutableStateOf("")
val usernameDisabled = mutableStateOf(true)
val passwordDisabled = mutableStateOf(true)
val errorText = mutableStateOf<String?>(null)
val root = htmlElement.appendElement("div") {
addClass(*UIKitWidth.Fixed.Medium.classes, *UIKitText.Alignment.Center.classes)
}
val composition = renderComposableAndLinkToContext(root) {
val authBtnDisabled = usernameState.value.isBlank() || passwordState.value.isBlank()
console.log(authBtnDisabled)
Card(
Attrs(UIKitWidth.Fixed.Medium),
footerAttrs = Attrs(UIKitText.Alignment.Center),
footer = {
DefaultButton("Authorise", UIKitButton.Type.Primary, disabled = authBtnDisabled) {
it.nativeEvent.preventDefault()
val serverUrl = document.location ?.run { "$hostname:$port" }
if (serverUrl != null) {
uiScope.launchSafelyWithoutExceptions { viewModel.initAuth(serverUrl, usernameState.value, passwordState.value) }
}
}
}
) {
CardTitle { Text("Log in") }
TextField(
InputType.Text,
usernameState,
disabledState = usernameDisabled
)
TextField(
InputType.Password,
passwordState,
disabledState = passwordDisabled
)
if (errorText.value != null) {
Label(errorText.value.toString(), Attrs(UIKitLabel.Error, UIKitMargin.Small.Bottom))
}
}
}
val viewJob = viewModel.currentState.subscribeSafelyWithoutExceptions(uiScope) {
when (it) {
is InitAuthUIState -> {
usernameDisabled.value = false
passwordDisabled.value = false
errorText.value = when (it.showError) {
ServerUnavailableAuthUIError -> "Сервер недоступен"
AuthIncorrectAuthUIError -> "Данные некорректны"
null -> null
}
}
LoadingAuthUIState -> {
usernameDisabled.value = true
passwordDisabled.value = true
errorText.value = null
}
AuthorizedAuthUIState -> {
completion.complete(state.from)
}
}
}
return completion.await().also {
composition.dispose()
viewJob.cancel()
}
}
}