add simple rendering of other players

This commit is contained in:
efim 2023-04-21 19:51:43 +04:00
parent a25d915bb5
commit 527e12dbd8
5 changed files with 128 additions and 17 deletions

2
.scalafmt.conf Normal file
View File

@ -0,0 +1,2 @@
runner.dialect = scala3
version = 3.7.3

View File

@ -1,6 +1,7 @@
import org.scalajs.linker.interface.ModuleSplitStyle import org.scalajs.linker.interface.ModuleSplitStyle
lazy val planningPokerGrargh = project.in(file(".")) lazy val planningPokerGrargh = project
.in(file("."))
.enablePlugins(ScalaJSPlugin) // Enable the Scala.js plugin in this project .enablePlugins(ScalaJSPlugin) // Enable the Scala.js plugin in this project
.settings( .settings(
scalaVersion := "3.2.0", scalaVersion := "3.2.0",
@ -18,12 +19,13 @@ lazy val planningPokerGrargh = project.in(file("."))
scalaJSLinkerConfig ~= { scalaJSLinkerConfig ~= {
_.withModuleKind(ModuleKind.ESModule) _.withModuleKind(ModuleKind.ESModule)
.withModuleSplitStyle( .withModuleSplitStyle(
ModuleSplitStyle.SmallModulesFor(List("livechart"))) ModuleSplitStyle.SmallModulesFor(List("livechart"))
)
}, },
/* Depend on the scalajs-dom library. /* Depend on the scalajs-dom library.
* It provides static types for the browser DOM APIs. * It provides static types for the browser DOM APIs.
*/ */
libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "2.4.0", libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "2.4.0",
libraryDependencies += "com.raquo" %%% "laminar" % "15.0.1", libraryDependencies += "com.raquo" %%% "laminar" % "15.0.1"
) )

View File

@ -23,25 +23,29 @@ object Main {
className := "w-screen h-screen flex flex-col justify-center items-center bg-green-100", className := "w-screen h-screen flex flex-col justify-center items-center bg-green-100",
div( // container for row of pictures div( // container for row of pictures
className := "flex flex-row w-1/2 justify-center", className := "flex flex-row w-1/2 justify-center",
a(className := "flex-initial", a(
href := "https://vitejs.dev", target := "_blank", className := "flex-initial",
img(src := "/vite.svg", className := "", alt := "Vite logo"), href := "https://vitejs.dev",
), target := "_blank",
a(className := "flex-initial", img(src := "/vite.svg", className := "", alt := "Vite logo")
href := "https://developer.mozilla.org/en-US/docs/Web/JavaScript", target := "_blank",
img(src := javascriptLogo, className := "", alt := "JavaScript logo"),
), ),
a(
className := "flex-initial",
href := "https://developer.mozilla.org/en-US/docs/Web/JavaScript",
target := "_blank",
img(src := javascriptLogo, className := "", alt := "JavaScript logo")
)
), ),
div( div(
className := "flex-initial", className := "flex-initial",
h1("Hello Laminar and Vite and stuff and other stuff!"), h1("Hello Laminar and Vite and stuff and other stuff!")
), ),
div(className := "bg-blue-400 flex-initial rounded-lg border-2 border-slate-500 p-1 m-1", div(
counterButton(), className := "bg-blue-400 flex-initial rounded-lg border-2 border-slate-500 p-1 m-1",
), counterButton()
p(className := "flex-initial",
"Click on the Vite logo to learn more",
), ),
p(className := "flex-initial", "Click on the Vite logo to learn more"),
RoomView.renderRoom(RoomStateView.testRoom)
) )
} }
} }
@ -52,7 +56,7 @@ def counterButton(): Element = {
tpe := "button", tpe := "button",
"count is ", "count is ",
child.text <-- counter, child.text <-- counter,
onClick --> { event => counter.update(c => c + 1) }, onClick --> { event => counter.update(c => c + 1) }
) )
} }

View File

@ -0,0 +1,55 @@
package industries.sunshine.planningpoker
import java.util.UUID
/** view of the single planning poker round
* @param players
* \- people who are currently playing
* @param allowedCards
* \- the cards values that can be used by players
* @param round
* \- state of the selected cards of the players
* @param canCloseRound
* \- whether current player has access to button to finish the round
*/
final case class RoomStateView(
players: List[Player],
me: PlayerID,
allowedCards: List[String],
round: RoundState,
canCloseRound: Boolean = false
) {
def playersCount: Int = players.size
}
object RoomStateView {
val testRoom = {
val me = Player("wormy", PlayerID())
RoomStateView(
players = List(me, Player("birdy", PlayerID()), Player("pony", PlayerID())),
me = me.id,
allowedCards = List("xs", "s", "m", "l", "xl"),
round = OpenRound(myCard = Some("l"), alreadyVoted = List(me)),
canCloseRound = true
)
}
}
trait RoundState
/** view state for round before votes are open player can know their vote and
* who of the other players have voted
*/
final case class OpenRound(
myCard: Option[String],
alreadyVoted: List[Player]
) extends RoundState
/** view state for round after opening the votes
*/
final case class ClosedRound(
votes: Map[Player, String]
) extends RoundState
final class PlayerID
final case class Player(name: String, id: PlayerID)

View File

@ -0,0 +1,48 @@
package industries.sunshine.planningpoker
import scala.scalajs.js
import com.raquo.laminar.api.L.{*, given}
/** Rendering of the Room state
*/
object RoomView {
// TODO this will take in signal of the room observable
// NOTE i guess "other players" would have to be in circle with 'me' as empty space in the bottom
def renderRoom(state: RoomStateView): Element = {
val roomStateSignal = Var(state).signal
val otherPlayers = roomStateSignal.map { state =>
state.players.filterNot(_.id == state.me)
}
div(
className := "w-96 h-96 border-4 border-amber-900",
div(
className := "flex flex-row",
children <-- otherPlayers.split(_.id) { (id, initial, playerSignal) =>
renderPlayer(playerSignal, roomStateSignal.map(_.allowedCards.size))
}
)
)
}
def renderPlayer(p: Signal[Player], cardsAmount: Signal[Int]): Element = {
div(
className := "w-20 h-20 border-2 border-amber-400 m-2",
child.text <-- p.map(_.name),
renderHandCardBacks(cardsAmount)
)
}
// TODO will also be a signal, i suppose separate, yeah
def renderHandCardBacks(amountSignal: Signal[Int]): Element = {
def renderCard(index: Int): Element =
div(
className := "w-4 h-8 m-1 rounded bg-gray-600 text-yellow-400"
)
div(
className := "flex flex-row",
children <-- amountSignal.map { amount => (1 to amount).map(renderCard) }
)
}
}