summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameStyles.kt8
-rw-r--r--sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/TransactionsSelector.kt187
2 files changed, 124 insertions, 71 deletions
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
index c3fb46a1..4b9bd0d4 100644
--- 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
@@ -6,10 +6,10 @@ import styled.StyleSheet
object GameStyles : StyleSheet("GameStyles", isStatic = true) {
- private val sandColor = Color.paleGoldenrod.withAlpha(0.7)
+ private val sandBgColor = Color.paleGoldenrod
val fullBoardPreviewPopover by css {
- val bgColor = sandColor
+ val bgColor = sandBgColor.withAlpha(0.7)
backgroundColor = bgColor
borderRadius = 0.5.rem
padding(all = 0.5.rem)
@@ -38,7 +38,7 @@ object GameStyles : StyleSheet("GameStyles", isStatic = true) {
}
val transactionsSelector by css {
- backgroundColor = sandColor
+ backgroundColor = sandBgColor
width = 600.px // default is 500px, we want to fit players on the side
children(".bp3-dialog-header") {
@@ -66,6 +66,6 @@ object GameStyles : StyleSheet("GameStyles", isStatic = true) {
}
val scoreBoard by css {
- backgroundColor = Color.paleGoldenrod
+ backgroundColor = sandBgColor
}
}
diff --git a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/TransactionsSelector.kt b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/TransactionsSelector.kt
index bb6a51f5..e41c1c26 100644
--- a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/TransactionsSelector.kt
+++ b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/TransactionsSelector.kt
@@ -3,6 +3,7 @@ package org.luxons.sevenwonders.ui.components.game
import com.palantir.blueprintjs.*
import kotlinx.css.*
import kotlinx.html.DIV
+import kotlinx.html.TBODY
import kotlinx.html.TD
import kotlinx.html.classes
import kotlinx.html.js.onClickFunction
@@ -11,10 +12,8 @@ import org.luxons.sevenwonders.model.api.PlayerDTO
import org.luxons.sevenwonders.model.resources.*
import org.luxons.sevenwonders.ui.components.gameBrowser.playerInfo
import org.luxons.sevenwonders.ui.redux.TransactionSelectorState
-import react.RBuilder
-import react.dom.div
-import react.dom.p
-import react.dom.tbody
+import react.*
+import react.dom.*
import styled.*
fun RBuilder.transactionsSelectorDialog(
@@ -54,6 +53,9 @@ fun RBuilder.transactionsSelectorDialog(
css {
grow(Grow.GROW)
margin(horizontal = 0.5.rem)
+ display = Display.flex
+ flexDirection = FlexDirection.column
+ alignItems = Align.center
}
optionsTable(state, prepareMove)
}
@@ -82,75 +84,126 @@ private fun RBuilder.optionsTable(
state: TransactionSelectorState,
prepareMove: (PlayerMove) -> Unit,
) {
+ child(optionsTable) {
+ attrs {
+ this.state = state
+ this.prepareMove = prepareMove
+ }
+ }
+}
+
+private interface OptionsTableProps : RProps {
+ var state: TransactionSelectorState
+ var prepareMove: (PlayerMove) -> Unit
+}
+
+private val optionsTable = functionalComponent<OptionsTableProps> { props ->
+ val state = props.state
+ val prepareMove = props.prepareMove
+
+ var expanded by useState { false }
+
+ val bestPrice = state.transactionsOptions.bestPrice
+ val (cheapestOptions, otherOptions) = state.transactionsOptions.partition { it.totalPrice == bestPrice }
+
bpHtmlTable(interactive = true) {
tbody {
- val bestPrice = state.transactionsOptions.bestPrice
- val hasExpensiveOptions = state.transactionsOptions.any { it.totalPrice != bestPrice }
- state.transactionsOptions.forEach { transactions ->
- val isCheapest = transactions.totalPrice == bestPrice
- styledTr {
- css {
- cursor = Cursor.pointer
- alignItems = Align.center
- }
- attrs {
- onClickFunction = { prepareMove(PlayerMove(state.moveType, state.card.name, transactions)) }
- }
- // there should be at most one of each
- val leftTr = transactions.firstOrNull { it.provider == Provider.LEFT_PLAYER }
- val rightTr = transactions.firstOrNull { it.provider == Provider.RIGHT_PLAYER }
- styledTd {
- transactionCellCss()
- styledDiv {
- css {
- opacity = if (leftTr == null) 0.5 else 1
- }
- transactionCellInnerCss()
- bpIcon(name = "caret-left", size = Icon.SIZE_LARGE)
- goldIndicator(leftTr?.totalPrice ?: 0, imgSize = 2.5.rem)
- }
- }
- styledTd {
- transactionCellCss()
- if (leftTr != null) {
- resourceList(leftTr.resources)
- }
- }
- styledTd {
- transactionCellCss()
- css {
- width = 1.5.rem
- }
- if (hasExpensiveOptions && isCheapest) {
- styledDiv {
- css {
- +GameStyles.bestPrice
- }
- +"Best\nprice!"
- }
- }
- }
- styledTd {
- transactionCellCss()
- if (rightTr != null) {
- resourceList(rightTr.resources)
- }
- }
- styledTd {
- transactionCellCss()
- styledDiv {
- css {
- opacity = if (rightTr == null) 0.5 else 1
- }
- transactionCellInnerCss()
- goldIndicator(rightTr?.totalPrice ?: 0, imgSize = 2.5.rem)
- bpIcon(name = "caret-right", size = Icon.SIZE_LARGE)
- }
- }
+ cheapestOptions.forEach { transactions ->
+ transactionsOptionRow(
+ transactions = transactions,
+ showBestPriceIndicator = expanded,
+ onClick = { prepareMove(PlayerMove(state.moveType, state.card.name, transactions)) },
+ )
+ }
+ if (expanded) {
+ otherOptions.forEach { transactions ->
+ transactionsOptionRow(
+ transactions = transactions,
+ showBestPriceIndicator = false,
+ onClick = { prepareMove(PlayerMove(state.moveType, state.card.name, transactions)) },
+ )
}
}
}
}
+ if (otherOptions.isNotEmpty()) {
+ val icon = if (expanded) "chevron-up" else "chevron-down"
+ val text = if (expanded) "Hide expensive options" else "Show more expensive options"
+ bpButton(
+ minimal = true,
+ small = true,
+ icon = icon,
+ rightIcon = icon,
+ onClick = { expanded = !expanded },
+ ) {
+ +text
+ }
+ }
+}
+
+private fun RDOMBuilder<TBODY>.transactionsOptionRow(
+ transactions: PricedResourceTransactions,
+ showBestPriceIndicator: Boolean,
+ onClick: () -> Unit,
+) {
+ styledTr {
+ css {
+ cursor = Cursor.pointer
+ alignItems = Align.center
+ }
+ attrs {
+ onClickFunction = { onClick() }
+ }
+ // there should be at most one of each
+ val leftTr = transactions.firstOrNull { it.provider == Provider.LEFT_PLAYER }
+ val rightTr = transactions.firstOrNull { it.provider == Provider.RIGHT_PLAYER }
+ styledTd {
+ transactionCellCss()
+ styledDiv {
+ css { opacity = if (leftTr == null) 0.5 else 1 }
+ transactionCellInnerCss()
+ bpIcon(name = "caret-left", size = Icon.SIZE_LARGE)
+ goldIndicator(leftTr?.totalPrice ?: 0, imgSize = 2.5.rem)
+ }
+ }
+ styledTd {
+ transactionCellCss()
+ if (leftTr != null) {
+ resourceList(leftTr.resources)
+ }
+ }
+ styledTd {
+ transactionCellCss()
+ css { width = 1.5.rem }
+ if (showBestPriceIndicator) {
+ bestPriceIndicator()
+ }
+ }
+ styledTd {
+ transactionCellCss()
+ if (rightTr != null) {
+ resourceList(rightTr.resources)
+ }
+ }
+ styledTd {
+ transactionCellCss()
+ styledDiv {
+ css { opacity = if (rightTr == null) 0.5 else 1 }
+ transactionCellInnerCss()
+ goldIndicator(rightTr?.totalPrice ?: 0, imgSize = 2.5.rem)
+ bpIcon(name = "caret-right", size = Icon.SIZE_LARGE)
+ }
+ }
+ }
+}
+
+private fun StyledDOMBuilder<TD>.bestPriceIndicator() {
+ styledDiv {
+ css {
+ +GameStyles.bestPrice
+ }
+ +"Best\nprice!"
+ }
}
private fun StyledDOMBuilder<TD>.transactionCellCss() {
bgstack15