diff options
8 files changed, 221 insertions, 23 deletions
diff --git a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/score/Score.kt b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/score/Score.kt index 3f9dbe41..1896ecd3 100644 --- a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/score/Score.kt +++ b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/score/Score.kt @@ -17,12 +17,12 @@ data class PlayerScore( override fun compareTo(other: PlayerScore) = compareValuesBy(this, other, { it.totalPoints }, { it.boardGold }) } -enum class ScoreCategory { - CIVIL, - SCIENCE, - MILITARY, - TRADE, - GUILD, - WONDER, - GOLD +enum class ScoreCategory(val title: String) { + CIVIL("Civil"), + SCIENCE("Science"), + MILITARY("War"), + TRADE("Trade"), + GUILD("Guild"), + WONDER("Wonder"), + GOLD("Gold") } diff --git a/sw-ui/src/main/kotlin/com/palantir/blueprintjs/BpHtmlTable.kt b/sw-ui/src/main/kotlin/com/palantir/blueprintjs/BpHtmlTable.kt new file mode 100644 index 00000000..1a602882 --- /dev/null +++ b/sw-ui/src/main/kotlin/com/palantir/blueprintjs/BpHtmlTable.kt @@ -0,0 +1,26 @@ +@file:JsModule("@blueprintjs/core") +package com.palantir.blueprintjs + +import react.PureComponent +import react.RProps +import react.RState +import react.ReactElement + +external interface IHTMLTableProps : RProps { + var bordered: Boolean? + get() = definedExternally + set(value) = definedExternally + var condensed: Boolean? + get() = definedExternally + set(value) = definedExternally + var interactive: Boolean? + get() = definedExternally + set(value) = definedExternally + var striped: Boolean? + get() = definedExternally + set(value) = definedExternally +} + +open external class HTMLTable : PureComponent<IHTMLTableProps, RState> { + override fun render(): ReactElement +} diff --git a/sw-ui/src/main/kotlin/com/palantir/blueprintjs/blueprintjsHelpers.kt b/sw-ui/src/main/kotlin/com/palantir/blueprintjs/blueprintjsHelpers.kt index a366c446..1a7638dc 100644 --- a/sw-ui/src/main/kotlin/com/palantir/blueprintjs/blueprintjsHelpers.kt +++ b/sw-ui/src/main/kotlin/com/palantir/blueprintjs/blueprintjsHelpers.kt @@ -85,12 +85,20 @@ fun RBuilder.bpInputGroup( fun RBuilder.bpTag( intent: Intent? = null, minimal: Boolean? = null, + large: Boolean? = null, + round: Boolean? = null, + fill: Boolean? = null, active: Boolean? = null, + icon: String? = null, block: RHandler<ITagProps> = {} ): ReactElement = child(Tag::class) { attrs { this.intent = intent this.minimal = minimal + this.large = large + this.round = round + this.fill = fill + this.icon = icon this.active = active } block() @@ -176,3 +184,19 @@ fun RBuilder.bpCard( } block() } + +fun RBuilder.bpHtmlTable( + bordered: Boolean = false, + interactive: Boolean = false, + condensed: Boolean = false, + striped: Boolean = false, + block: RHandler<IHTMLTableProps> = {} +): ReactElement = child(HTMLTable::class) { + attrs { + this.bordered = bordered + this.interactive = interactive + this.condensed = condensed + this.striped = striped + } + block() +} diff --git a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameScene.kt b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameScene.kt index ce32e8b9..dcd80b6f 100644 --- a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameScene.kt +++ b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameScene.kt @@ -11,11 +11,7 @@ import org.luxons.sevenwonders.model.PlayerTurnInfo import org.luxons.sevenwonders.model.api.PlayerDTO import org.luxons.sevenwonders.model.cards.HandCard import org.luxons.sevenwonders.ui.components.GlobalStyles -import org.luxons.sevenwonders.ui.redux.GameState -import org.luxons.sevenwonders.ui.redux.RequestPrepareMove -import org.luxons.sevenwonders.ui.redux.RequestSayReady -import org.luxons.sevenwonders.ui.redux.RequestUnprepareMove -import org.luxons.sevenwonders.ui.redux.connectStateAndDispatch +import org.luxons.sevenwonders.ui.redux.* import react.* import react.dom.* import styled.* @@ -32,6 +28,7 @@ interface GameSceneDispatchProps : RProps { var sayReady: () -> Unit var prepareMove: (move: PlayerMove) -> Unit var unprepareMove: () -> Unit + var leaveGame: () -> Unit } interface GameSceneProps : GameSceneStateProps, GameSceneDispatchProps @@ -57,6 +54,9 @@ private class GameScene(props: GameSceneProps) : RComponent<GameSceneProps, RSta private fun RBuilder.turnInfoScene(turnInfo: PlayerTurnInfo) { val board = turnInfo.table.boards[turnInfo.playerIndex] div { + turnInfo.scoreBoard?.let { + scoreTableOverlay(it, props.players, props.leaveGame) + } actionInfo(turnInfo.message) boardComponent(board = board) val hand = turnInfo.hand @@ -206,6 +206,7 @@ private val gameScene: RClass<GameSceneProps> = prepareMove = { move -> dispatch(RequestPrepareMove(move)) } unprepareMove = { dispatch(RequestUnprepareMove()) } sayReady = { dispatch(RequestSayReady()) } + leaveGame = { dispatch(RequestLeaveGame()) } }, mapStateToProps = { state, _ -> playerIsReady = state.currentPlayer?.isReady == true diff --git a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameStyles.kt b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameStyles.kt new file mode 100644 index 00000000..dc52a83a --- /dev/null +++ b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameStyles.kt @@ -0,0 +1,11 @@ +package org.luxons.sevenwonders.ui.components.game + +import kotlinx.css.* +import styled.StyleSheet + +object GameStyles : StyleSheet("GameStyles", isStatic = true) { + + val scoreBoard by css { + backgroundColor = Color.paleGoldenrod + } +} diff --git a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/ScoreTable.kt b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/ScoreTable.kt new file mode 100644 index 00000000..149fd3c9 --- /dev/null +++ b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/ScoreTable.kt @@ -0,0 +1,142 @@ +package org.luxons.sevenwonders.ui.components.game + +import com.palantir.blueprintjs.* +import kotlinx.css.* +import kotlinx.html.TD +import kotlinx.html.TH +import org.luxons.sevenwonders.model.api.PlayerDTO +import org.luxons.sevenwonders.model.score.ScoreBoard +import org.luxons.sevenwonders.model.score.ScoreCategory +import org.luxons.sevenwonders.ui.components.GlobalStyles +import react.RBuilder +import react.dom.* +import styled.* + +fun RBuilder.scoreTableOverlay(scoreBoard: ScoreBoard, players: List<PlayerDTO>, leaveGame: () -> Unit) { + bpOverlay(isOpen = true) { + bpCard { + attrs { + val fixedCenterClass = GlobalStyles.getClassName { it::fixedCenter } + val scoreBoardClass = GameStyles.getClassName { it::scoreBoard } + className = "$fixedCenterClass $scoreBoardClass" + } + styledDiv { + css { + display = Display.flex + flexDirection = FlexDirection.column + alignItems = Align.center + } + styledH1 { + css { + marginTop = 0.px + } + +"Score Board" + } + scoreTable(scoreBoard, players) + styledDiv { + css { + marginTop = 1.rem + } + bpButton(intent = Intent.WARNING, rightIcon = "log-out", large = true, onClick = { leaveGame() }) { + +"LEAVE" + } + } + } + } + } +} + +private fun RBuilder.scoreTable(scoreBoard: ScoreBoard, players: List<PlayerDTO>) { + bpHtmlTable(bordered = false, interactive = true) { + thead { + tr { + centeredTh { +"Rank" } + centeredTh { + attrs { colSpan = "2" } + +"Player" + } + centeredTh { +"Score" } + ScoreCategory.values().forEach { + centeredTh { +it.title } + } + } + } + tbody { + scoreBoard.scores.forEachIndexed { index, score -> + val player = players[score.playerIndex] + tr { + centeredTd { +"${index + 1}" } + centeredTd { bpIcon(player.icon?.name ?: "user", size = 25) } + styledTd { + inlineStyles { + verticalAlign = VerticalAlign.middle + } + +player.displayName + } + centeredTd { + bpTag(large = true, round = true, minimal = true) { + +"${score.totalPoints}" + } + } + ScoreCategory.values().forEach { cat -> + centeredTd { + bpTag(intent = cat.intent, large = true, round = true, icon = cat.icon, fill = true) { + +"${score.pointsByCategory[cat]}" + } + } + } + } + } + } + } +} + +private fun RBuilder.centeredTh(block: RDOMBuilder<TH>.() -> Unit) { + th { + // inline styles necessary to overcome blueprintJS overrides + inlineStyles { + textAlign = TextAlign.center + verticalAlign = VerticalAlign.middle + } + block() + } +} + +private fun RBuilder.centeredTd(block: RDOMBuilder<TD>.() -> Unit) { + td { + // inline styles necessary to overcome blueprintJS overrides + inlineStyles { + textAlign = TextAlign.center + verticalAlign = VerticalAlign.middle + } + block() + } +} + +private val ScoreCategory.intent: Intent + get() = when(this) { + ScoreCategory.CIVIL -> Intent.PRIMARY + ScoreCategory.SCIENCE -> Intent.SUCCESS + ScoreCategory.MILITARY -> Intent.DANGER + ScoreCategory.TRADE -> Intent.WARNING + ScoreCategory.GUILD -> Intent.NONE + ScoreCategory.WONDER -> Intent.NONE + ScoreCategory.GOLD -> Intent.WARNING + } + +private val ScoreCategory.icon: String + get() = when(this) { + ScoreCategory.CIVIL -> "office" + ScoreCategory.SCIENCE -> "lab-test" + ScoreCategory.MILITARY -> "cut" + ScoreCategory.TRADE -> "swap-horizontal" + ScoreCategory.GUILD -> "clean" // stars + ScoreCategory.WONDER -> "symbol-triangle-up" + ScoreCategory.GOLD -> "dollar" + } + +// Potentially useful emojis: +// Greek temple: 🏛 +// Cog (science): ⚙️ +// Swords (war): ⚔️ +// Gold bag: 💰 diff --git a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameList.kt b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameList.kt index 1e591f87..4d23974f 100644 --- a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameList.kt +++ b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameList.kt @@ -1,12 +1,7 @@ package org.luxons.sevenwonders.ui.components.gameBrowser -import com.palantir.blueprintjs.Classes -import com.palantir.blueprintjs.Intent -import com.palantir.blueprintjs.bpButton -import com.palantir.blueprintjs.bpIcon -import com.palantir.blueprintjs.bpTag +import com.palantir.blueprintjs.* import kotlinx.css.* -import kotlinx.html.classes import kotlinx.html.title import org.luxons.sevenwonders.model.api.ConnectedPlayer import org.luxons.sevenwonders.model.api.LobbyDTO @@ -37,10 +32,7 @@ interface GameListProps : GameListStateProps, GameListDispatchProps class GameListPresenter(props: GameListProps) : RComponent<GameListProps, RState>(props) { override fun RBuilder.render() { - table { - attrs { - classes = setOf(Classes.HTML_TABLE) - } + bpHtmlTable { thead { gameListHeaderRow() } diff --git a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/redux/ApiActions.kt b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/redux/ApiActions.kt index 300693a3..6fbaadb9 100644 --- a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/redux/ApiActions.kt +++ b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/redux/ApiActions.kt @@ -20,6 +20,8 @@ class RequestStartGame : RAction class RequestLeaveLobby : RAction +class RequestLeaveGame : RAction + class RequestSayReady : RAction data class RequestPrepareMove(val move: PlayerMove) : RAction |