core/features/auth/client/src/jsMain/kotlin/dev/inmo/postssystem/features/auth/client/AuthView.kt

123 lines
4.6 KiB
Kotlin
Raw Normal View History

package dev.inmo.postssystem.features.auth.client
2021-11-24 07:52:27 +00:00
2022-01-22 14:19:50 +00:00
import androidx.compose.runtime.mutableStateOf
import dev.inmo.jsuikit.elements.*
2022-01-25 09:21:01 +00:00
import dev.inmo.jsuikit.modifiers.*
import dev.inmo.jsuikit.utils.Attrs
import dev.inmo.micro_utils.coroutines.compose.renderComposableAndLinkToContextAndRoot
2021-11-24 07:52:27 +00:00
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
2022-05-07 15:54:19 +00:00
import dev.inmo.postssystem.features.auth.client.ui.AuthUIError.AuthIncorrect
import dev.inmo.postssystem.features.common.common.*
import dev.inmo.postssystem.features.common.common.ui.JSView
import dev.inmo.postssystem.features.common.common.ui.fsm.*
2021-11-24 07:52:27 +00:00
import kotlinx.browser.document
import kotlinx.coroutines.*
2022-01-25 09:21:01 +00:00
import kotlinx.dom.*
2022-01-22 14:19:50 +00:00
import org.jetbrains.compose.web.attributes.InputType
2022-01-25 09:21:01 +00:00
import org.jetbrains.compose.web.dom.Text
2021-11-24 07:52:27 +00:00
import org.w3c.dom.*
2022-05-07 15:54:19 +00:00
@ExperimentalStdlibApi
@EagerInitialization
val loader = DefaultModuleLoader {
factory { AuthView(get(), get(DefaultQualifiers.UIScopeQualifier), getAllDistinct()) }
2022-05-07 15:54:19 +00:00
singleWithRandomQualifier {
UIFSMHandler.Registrator {
strictlyOn(get<AuthView>())
}
}
2022-05-19 18:15:49 +00:00
} + CommonAuthModuleLoader()
2021-11-24 07:52:27 +00:00
class AuthView(
private val viewModel: AuthUIViewModel,
private val uiScope: CoroutineScope,
defaultExceptionsHandlers: Iterable<UIFSMExceptionHandler>
) : JSView<AuthUIFSMState>(defaultExceptionsHandlers) {
2021-11-24 07:52:27 +00:00
override suspend fun StatesMachine<in UIFSMState>.safeHandleState(
htmlElement: HTMLElement,
state: AuthUIFSMState
): UIFSMState? {
val completion = CompletableDeferred<UIFSMState?>()
2022-01-22 14:19:50 +00:00
val usernameState = mutableStateOf("")
val passwordState = mutableStateOf("")
2022-01-25 18:55:43 +00:00
val disabled = mutableStateOf(true)
2022-01-22 14:19:50 +00:00
val errorText = mutableStateOf<String?>(null)
2022-01-25 18:55:43 +00:00
val root = htmlElement.appendElement("div") {}
val composition = renderComposableAndLinkToContextAndRoot(root) {
2022-01-25 09:21:01 +00:00
val authBtnDisabled = usernameState.value.isBlank() || passwordState.value.isBlank()
2022-01-25 18:55:43 +00:00
Flex(
UIKitFlex.Alignment.Horizontal.Center
) {
Card(
2022-03-02 08:36:17 +00:00
Attrs(UIKitText.Alignment.Horizontal.Center),
2022-01-25 18:55:43 +00:00
bodyAttrs = Attrs(UIKitWidth.Fixed.Medium),
) {
CardTitle { Text("Log in") }
if (errorText.value != null) {
CardBadge(Attrs(UIKitLabel.Error)) {
Text(errorText.value.toString())
}
}
2022-05-07 15:54:19 +00:00
StandardInput(
2022-01-25 18:55:43 +00:00
InputType.Text,
usernameState,
disabled,
"Username",
)
2022-05-07 15:54:19 +00:00
StandardInput(
2022-01-25 18:55:43 +00:00
InputType.Password,
passwordState,
disabled,
"Password"
)
DefaultButton("Authorise", UIKitButton.Type.Primary, UIKitMargin.Small, disabled = authBtnDisabled) {
2022-01-25 09:21:01 +00:00
it.nativeEvent.preventDefault()
val serverUrl = document.location ?.run { "$hostname:$port" }
if (serverUrl != null) {
uiScope.launchSafelyWithoutExceptions { viewModel.initAuth(serverUrl, usernameState.value, passwordState.value) }
}
}
}
2021-11-24 07:52:27 +00:00
}
}
val viewJob = viewModel.currentState.subscribeSafelyWithoutExceptions(uiScope) {
when (it) {
2022-05-07 15:54:19 +00:00
is AuthUIState.Init -> {
2022-01-25 18:55:43 +00:00
disabled.value = false
2022-01-22 14:19:50 +00:00
errorText.value = when (it.showError) {
AuthUIError.ServerUnavailable -> "Server unavailable"
2022-05-07 15:54:19 +00:00
AuthIncorrect -> {
2022-01-25 18:55:43 +00:00
passwordState.value = ""
"Username or password is incorrect"
}
2022-01-22 14:19:50 +00:00
null -> null
2021-11-24 07:52:27 +00:00
}
}
2022-05-07 15:54:19 +00:00
AuthUIState.Loading -> {
2022-01-25 18:55:43 +00:00
disabled.value = true
2022-01-22 14:19:50 +00:00
errorText.value = null
2021-11-24 07:52:27 +00:00
}
2022-05-07 15:54:19 +00:00
AuthUIState.Authorized -> {
2021-11-24 07:52:27 +00:00
completion.complete(state.from)
}
}
}
return completion.await().also {
2022-01-22 14:19:50 +00:00
composition.dispose()
2021-11-24 07:52:27 +00:00
viewJob.cancel()
}
}
}