summaryrefslogtreecommitdiff
path: root/sw-ui-kt
diff options
context:
space:
mode:
Diffstat (limited to 'sw-ui-kt')
-rw-r--r--sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/CreateGameForm.kt49
-rw-r--r--sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameBrowser.kt2
-rw-r--r--sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameList.kt83
-rw-r--r--sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Reducers.kt13
-rw-r--r--sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Store.kt6
-rw-r--r--sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Utils.kt33
6 files changed, 173 insertions, 13 deletions
diff --git a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/CreateGameForm.kt b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/CreateGameForm.kt
new file mode 100644
index 00000000..318f49f4
--- /dev/null
+++ b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/CreateGameForm.kt
@@ -0,0 +1,49 @@
+package org.luxons.sevenwonders.ui.components.gameBrowser
+
+import kotlinx.html.InputType
+import kotlinx.html.js.onChangeFunction
+import kotlinx.html.js.onSubmitFunction
+import org.luxons.sevenwonders.ui.redux.RequestCreateGameAction
+import org.luxons.sevenwonders.ui.redux.connectDispatch
+import org.w3c.dom.HTMLInputElement
+import react.RBuilder
+import react.RClass
+import react.RComponent
+import react.RProps
+import react.RState
+import react.dom.*
+
+private interface CreateGameFormProps: RProps {
+ var createGame: (String) -> Unit
+}
+
+private data class CreateGameFormState(var gameName: String = ""): RState
+
+private class CreateGameForm(props: CreateGameFormProps): RComponent<CreateGameFormProps, CreateGameFormState>(props) {
+
+ override fun CreateGameFormState.init(props: CreateGameFormProps) {
+ gameName = ""
+ }
+
+ override fun RBuilder.render() {
+ form {
+ attrs.onSubmitFunction = { props.createGame(state.gameName) }
+
+ input(type = InputType.text) {
+ attrs {
+ value = state.gameName
+ onChangeFunction = { e ->
+ val input = e.currentTarget as HTMLInputElement
+ setState(transformState = { CreateGameFormState(input.value) })
+ }
+ }
+ }
+
+ input(type = InputType.submit) {}
+ }
+ }
+}
+
+val createGameForm: RClass<RProps> = connectDispatch(CreateGameForm::class) { dispatch, _ ->
+ createGame = { name -> dispatch(RequestCreateGameAction(name)) }
+}
diff --git a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameBrowser.kt b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameBrowser.kt
index 73c11984..fc7e12d5 100644
--- a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameBrowser.kt
+++ b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameBrowser.kt
@@ -5,4 +5,6 @@ import react.dom.*
fun RBuilder.gameBrowser() = div {
h1 { +"Games" }
+ createGameForm {}
+ gameList {}
}
diff --git a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameList.kt b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameList.kt
new file mode 100644
index 00000000..40ad826a
--- /dev/null
+++ b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameList.kt
@@ -0,0 +1,83 @@
+package org.luxons.sevenwonders.ui.components.gameBrowser
+
+import kotlinx.html.js.onClickFunction
+import org.luxons.sevenwonders.model.api.LobbyDTO
+import org.luxons.sevenwonders.model.api.State
+import org.luxons.sevenwonders.ui.redux.RequestJoinGameAction
+import org.luxons.sevenwonders.ui.redux.connect
+import react.RBuilder
+import react.RComponent
+import react.RProps
+import react.RState
+import react.dom.*
+
+interface GameListStateProps : RProps {
+ var games: List<LobbyDTO>
+}
+
+interface GameListDispatchProps: RProps {
+ var joinGame: (Long) -> Unit
+}
+
+interface GameListProps : GameListStateProps, GameListDispatchProps
+
+class GameListPresenter(props: GameListProps) : RComponent<GameListProps, RState>(props) {
+
+ override fun RBuilder.render() {
+ table {
+ thead {
+ gameListHeaderRow()
+ }
+ tbody {
+ props.games.map {
+ gameListItemRow(it, props.joinGame)
+ }
+ }
+ }
+ }
+}
+
+private fun RBuilder.gameListHeaderRow() = tr {
+ th { +"Name" }
+ th { +"Status" }
+ th { +"Nb Players" }
+ th { +"Join" }
+}
+
+private fun RBuilder.gameListItemRow(lobby: LobbyDTO, joinGame: (Long) -> Unit) = tr {
+ th { +lobby.name }
+ th { gameStatus(lobby.state) }
+ th { playerCount(lobby.players.size) }
+ th { joinButton(lobby, joinGame) }
+}
+
+private fun RBuilder.gameStatus(state: State) {
+ span {
+ +state.toString()
+ }
+}
+
+private fun RBuilder.playerCount(nPlayers: Int) {
+ span {
+ +nPlayers.toString()
+ }
+}
+
+private fun RBuilder.joinButton(lobby: LobbyDTO, joinGame: (Long) -> Unit) {
+ button {
+ attrs {
+ disabled = lobby.state != State.LOBBY
+ onClickFunction = { joinGame(lobby.id) }
+ }
+ }
+}
+
+val gameList = connect<GameListStateProps, GameListDispatchProps, GameListProps>(
+ clazz = GameListPresenter::class,
+ mapStateToProps = { state, _ ->
+ games = state.games
+ },
+ mapDispatchToProps = { dispatch, _ ->
+ joinGame = { gameId -> dispatch(RequestJoinGameAction(gameId = gameId)) }
+ }
+)
diff --git a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Reducers.kt b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Reducers.kt
index f9f5a26d..21fc7480 100644
--- a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Reducers.kt
+++ b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Reducers.kt
@@ -1,8 +1,19 @@
package org.luxons.sevenwonders.ui.redux
+import org.luxons.sevenwonders.model.api.LobbyDTO
+import org.luxons.sevenwonders.model.api.PlayerDTO
import redux.RAction
+data class SwState(
+ val player: PlayerDTO? = null,
+ val lobby: LobbyDTO? = null,
+ val games: List<LobbyDTO> = emptyList()
+)
+
fun rootReducer(state: SwState, action: RAction) = when (action) {
- is RequestChooseName -> state.copy(playerName = action.playerName)
+ is SetCurrentPlayerAction -> state.copy(player = action.player)
+ is UpdateGameListAction -> state.copy(games = action.games)
+ is UpdateLobbyAction -> state.copy(lobby = action.lobby)
+ is UpdatePlayers -> TODO()
else -> state
}
diff --git a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Store.kt b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Store.kt
index fea13f04..44237794 100644
--- a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Store.kt
+++ b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Store.kt
@@ -9,11 +9,7 @@ import redux.compose
import redux.createStore
import redux.rEnhancer
-data class SwState(
- val playerName: String
-)
-
-val INITIAL_STATE = SwState("Bob")
+val INITIAL_STATE = SwState()
fun configureStore(
sagaManager: SagaManager<SwState, RAction, WrapperAction>,
diff --git a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Utils.kt b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Utils.kt
index e40e11bc..dc85d358 100644
--- a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Utils.kt
+++ b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Utils.kt
@@ -10,12 +10,31 @@ import redux.RAction
import redux.WrapperAction
import kotlin.reflect.KClass
-inline fun <reified T : RProps> connectDispatch(
- clazz: KClass<out RComponent<T, out RState>>,
- crossinline mapDispatchToProps: T.((RAction) -> WrapperAction, RProps) -> Unit
+inline fun <reified DP : RProps> connectDispatch(
+ clazz: KClass<out RComponent<DP, out RState>>,
+ noinline mapDispatchToProps: DP.((RAction) -> WrapperAction, RProps) -> Unit
): RClass<RProps> {
- val connect = rConnect<RAction, WrapperAction, RProps, T>(mapDispatchToProps = { dispatch, ownProps ->
- mapDispatchToProps(dispatch, ownProps)
- })
- return connect.invoke(clazz.js.unsafeCast<RClass<T>>())
+ val connect = rConnect(mapDispatchToProps = mapDispatchToProps)
+ return connect.invoke(clazz.js.unsafeCast<RClass<DP>>())
+}
+
+inline fun <reified SP : RProps> connectState(
+ clazz: KClass<out RComponent<SP, out RState>>,
+ noinline mapStateToProps: SP.(SwState, RProps) -> Unit
+): RClass<RProps> {
+ val connect = rConnect(mapStateToProps = mapStateToProps)
+ return connect.invoke(clazz.js.unsafeCast<RClass<SP>>())
+}
+
+
+inline fun <reified SP : RProps, reified DP : RProps, reified P : RProps> connect(
+ clazz: KClass<out RComponent<P, out RState>>,
+ noinline mapStateToProps: SP.(SwState, RProps) -> Unit,
+ noinline mapDispatchToProps: DP.((RAction) -> WrapperAction, RProps) -> Unit
+): RClass<RProps> {
+ val connect = rConnect<SwState, RAction, WrapperAction, RProps, SP, DP, P>(
+ mapStateToProps = mapStateToProps,
+ mapDispatchToProps = mapDispatchToProps
+ )
+ return connect.invoke(clazz.js.unsafeCast<RClass<P>>())
}
bgstack15