diff --git a/build.sbt b/build.sbt index f847e78..b8e9436 100644 --- a/build.sbt +++ b/build.sbt @@ -34,7 +34,8 @@ lazy val frontend = project libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "2.4.0", libraryDependencies += "com.raquo" %%% "laminar" % "15.0.1", libraryDependencies += "io.laminext" %%% "websocket-circe" % "0.15.0", - libraryDependencies += "io.laminext" %%% "fetch-circe" % "0.15.0" + libraryDependencies += "io.laminext" %%% "fetch-circe" % "0.15.0", + libraryDependencies += "io.laminext" %%% "validation-cats" % "0.15.0" ) .dependsOn(common.js) diff --git a/frontend/src/main/scala/industries/sunshine/planningpoker/JoinRoomComponent.scala b/frontend/src/main/scala/industries/sunshine/planningpoker/JoinRoomComponent.scala index b03bbf8..eaf778e 100644 --- a/frontend/src/main/scala/industries/sunshine/planningpoker/JoinRoomComponent.scala +++ b/frontend/src/main/scala/industries/sunshine/planningpoker/JoinRoomComponent.scala @@ -6,6 +6,9 @@ import com.raquo.laminar.api.L.{*, given} import io.laminext.fetch.Fetch import io.laminext.fetch.circe._ +import io.laminext.syntax.core._ +import io.laminext.syntax.validation._ + import scala.util.Failure import scala.util.Success @@ -29,7 +32,8 @@ object JoinRoomComponent { value <-- data.signal, onInput.mapToValue --> data.writer ) - ) + ).validated(V.nonBlank("name must not be blank")) + def passInput(data: Var[String], placeholderText: String) = input( tpe := "password", className := "border-2 m-1 rounded", @@ -104,16 +108,36 @@ object JoinRoomComponent { } --> responseReceived ) + val roomNameInput = nameInput(roomNameVar, "Enter room name:") + val roomPassInput = passInput(roomPassVar, "room password") + val nickNameInput = nameInput(nicknameVar, "Enter your nickname:") + val nickPassInput = passInput(nicknamePass, "nickname pass") div( className := "bg-green-50 w-full h-full flex justify-center", div( className := "w-60 flex flex-col justify-center", "Logging in:", - nameInput(roomNameVar, "Enter room name:"), - passInput(roomPassVar, "room password"), - label("Alert: no https, please don't use good passwords"), - nameInput(nicknameVar, "Enter your nickname:"), - passInput(nicknamePass, "nickname pass:"), + roomNameInput, + div( + child.maybe <-- roomNameInput.validationError.optionMap(errors => + span( + cls := "text-red-700 text-sm", + errors.map(error => div(error)) + ) + ) + ), + roomPassInput, + label("Alert: no https, please use throwaway passwords"), + nickNameInput, + div( + child.maybe <-- nickNameInput.validationError.optionMap(errors => + span( + cls := "text-red-700 text-sm", + errors.map(error => div(error)) + ) + ) + ), + nickPassInput, submitButton, newRoomButton, div(