feat(14): manual request of house choice

hodgepodge of 2 fragments which are put into house choice depending on
the state.

the alignment is done in a very not nice way.
This commit is contained in:
efim 2023-07-01 20:00:19 +00:00
parent 66013ae1c6
commit de3d4781f0
5 changed files with 176 additions and 68 deletions

View File

@ -2,6 +2,6 @@
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;
/* div, section, span, p { */ div, section, span, p {
/* outline: 1px solid red; */ outline: 1px solid red;
/* } */ }

View File

@ -522,6 +522,10 @@ video {
--tw-backdrop-sepia: ; --tw-backdrop-sepia: ;
} }
.invisible {
visibility: hidden;
}
.static { .static {
position: static; position: static;
} }
@ -559,6 +563,10 @@ video {
top: 50%; top: 50%;
} }
.top-2\/3 {
top: 66.666667%;
}
.top-\[var\(--top-offset\)\] { .top-\[var\(--top-offset\)\] {
top: var(--top-offset); top: var(--top-offset);
} }
@ -567,14 +575,22 @@ video {
margin-right: 0.75rem; margin-right: 0.75rem;
} }
.mt-14 {
margin-top: 3.5rem;
}
.mt-6 { .mt-6 {
margin-top: 1.5rem; margin-top: 1.5rem;
} }
.mt-\[4\.5rem\] {
margin-top: 4.5rem;
}
.mt-\[0\.5rem\] {
margin-top: 0.5rem;
}
.mt-\[1rem\] {
margin-top: 1rem;
}
.block { .block {
display: block; display: block;
} }
@ -587,6 +603,10 @@ video {
display: grid; display: grid;
} }
.hidden {
display: none;
}
.h-10 { .h-10 {
height: 2.5rem; height: 2.5rem;
} }
@ -603,6 +623,10 @@ video {
height: 100px; height: 100px;
} }
.h-\[300px\] {
height: 300px;
}
.h-\[375px\] { .h-\[375px\] {
height: 375px; height: 375px;
} }
@ -619,6 +643,14 @@ video {
height: 100vh; height: 100vh;
} }
.h-full {
height: 100%;
}
.h-0 {
height: 0px;
}
.w-1\/3 { .w-1\/3 {
width: 33.333333%; width: 33.333333%;
} }
@ -635,6 +667,10 @@ video {
width: 8rem; width: 8rem;
} }
.w-9\/12 {
width: 75%;
}
.w-\[100px\] { .w-\[100px\] {
width: 100px; width: 100px;
} }
@ -651,12 +687,16 @@ video {
width: var(--diameter); width: var(--diameter);
} }
.w-screen {
width: 100vw;
}
.w-full { .w-full {
width: 100%; width: 100%;
} }
.w-screen { .w-0 {
width: 100vw; width: 0px;
} }
.grow { .grow {
@ -815,8 +855,8 @@ video {
padding-left: 1rem; padding-left: 1rem;
} }
.pt-10 { .pt-14 {
padding-top: 2.5rem; padding-top: 3.5rem;
} }
.pt-8 { .pt-8 {
@ -896,8 +936,6 @@ video {
color: rgb(255 255 255 / var(--tw-text-opacity)); color: rgb(255 255 255 / var(--tw-text-opacity));
} }
/* div, section, span, p { */ div, section, span, p {
outline: 1px solid red;
/* outline: 1px solid red; */ }
/* } */

View File

@ -56,64 +56,95 @@
</h2> </h2>
</section> </section>
<section id="showdown-table" class="grid grid-cols-2 w-[375px] h-[375px]" <div id="showdown-table" th:fragment="showdown-table (showdownState)">
th:fragment="showdown-table" <section class="grid grid-cols-2 w-[375px] h-[300px]">
>
<div id="players-choice"
class="flex relative flex-col items-center pt-10"
>
<!-- This will be imported fragment -->
<!-- <p th:text="${playersChoiceData.c.toString}">Hello</p> -->
<div th:replace="index::choiceBadge (${playersChoiceData})"> </div>
<div <div
th:remove="all" id="players-choice"
id="rock" class="flex relative flex-col items-center pt-14"
class="top-[var(--top-offset)] left-[var(--left-offset)] w-[var(--diameter)] h-[var(--diameter)] bg-gradient-to-b rounded-full -translate-x-[var(--translation)] -translate-y-[var(--translation)] from-[var(--bg-bright)] to-[var(--bg-dark)]"
style="
--diameter: 8rem;
--bg-dark: hsl(349, 71%, 52%);
--bg-bright: hsl(349, 70%, 56%);
--top-offset: 0rem;
--left-offset: 0rem;
--translation: 0%;
position: relative;
"
> >
<!-- This will be imported fragment -->
<!-- <p th:text="${showdownState}">Hello</p> -->
<div <div
class="absolute top-1/2 left-1/2 w-3/4 h-3/4 bg-gradient-to-b from-gray-300 to-gray-100 rounded-full -translate-x-1/2 -translate-y-1/2" th:replace="index::choiceBadge (${showdownState.playersChoice})"
></div> ></div>
<img <div
src="../public/images/icon-rock.svg" th:remove="all"
class="absolute top-1/2 left-1/2 w-1/3 -translate-x-1/2 -translate-y-1/2" id="rock"
/> class="top-[var(--top-offset)] left-[var(--left-offset)] w-[var(--diameter)] h-[var(--diameter)] bg-gradient-to-b rounded-full -translate-x-[var(--translation)] -translate-y-[var(--translation)] from-[var(--bg-bright)] to-[var(--bg-dark)]"
style="
--diameter: 8rem;
--bg-dark: hsl(349, 71%, 52%);
--bg-bright: hsl(349, 70%, 56%);
--top-offset: 0rem;
--left-offset: 0rem;
--translation: 0%;
position: relative;
"
>
<div
class="absolute top-1/2 left-1/2 w-3/4 h-3/4 bg-gradient-to-b from-gray-300 to-gray-100 rounded-full -translate-x-1/2 -translate-y-1/2"
></div>
<img
src="../public/images/icon-rock.svg"
class="absolute top-1/2 left-1/2 w-1/3 -translate-x-1/2 -translate-y-1/2"
/>
</div>
<p
class="absolute top-2/3 tracking-widest text-center text-white uppercase text-md"
>
You picked
</p>
</div> </div>
<p class="absolute top-1/2 tracking-widest text-center text-white uppercase text-md">You picked</p>
</div>
<div id="house-choice" <div id="house-choice"
class="flex relative flex-col items-center" class="flex relative flex-col items-center pt-14"
>
<!-- This will be imported fragment -->
<div
class="mt-14 rounded-full bg-radial-gradient-top h-[100px] w-[100px]"
> >
<!-- Here will be imported fragment -->
<!-- conditionally either house choice or request for house choice -->
<!-- <div th:text="${showdownState.houseChoice.nonEmpty} ? 'nonEmpty' : 'empty'">...</div> -->
<div
th:replace="${showdownState.houseChoice.nonEmpty} ? ~{index::choiceBadge (${showdownState.houseChoice.get})} : ~{::house-choice-placeholder}"
class="w-0 h-0"
th:class=""
>
...
</div>
<!-- This will be shown before the house made the choice, this will trigger timed request for house choice -->
<div class="w-full h-full" th:remove="all">
<div
class="flex relative flex-col items-center h-full"
th:fragment="house-choice-placeholder"
th:hx-get="'/house-choice/' + ${showdownState.playersChoice.c.name}"
hx-get="/house-choice/paper"
hx-target="#showdown-table"
hx-swap="outerHTML"
>
<div
class="rounded-full mt-[1rem] bg-radial-gradient-top h-[100px] w-[100px]"
></div>
</div>
</div>
<p
class="absolute top-2/3 tracking-widest text-center text-white uppercase text-md"
>
The house picked
</p>
</div> </div>
<p class="absolute top-1/2 tracking-widest text-center text-white uppercase text-md">The house picked</p> </section>
</div>
</section>
<section <section
id="message" id="message"
class="text-white" class="flex flex-col items-center text-white"
> th:classappend="${gameFinished} ? '' : 'invisible'"
<p >
class="text-6xl tracking-wide uppercase" <p class="text-6xl tracking-wide text-center uppercase">You lose</p>
>You lose</p> <button
<button class="mt-6 w-9/12 h-12 tracking-widest uppercase bg-white rounded-xl text-radial-gradient-bottom"
class="mt-6 w-full h-12 tracking-widest uppercase bg-white rounded-xl text-radial-gradient-bottom" >
>Play again</button> Play again
</button>
</section> </section>
</div>
<div class="py-12"> <div class="py-12">
<button <button

View File

@ -11,6 +11,7 @@ import scala.jdk.CollectionConverters._
import javax.swing.text.Position import javax.swing.text.Position
import rockpaperscissors.Models.Positioning import rockpaperscissors.Models.Positioning
import scala.util.Random import scala.util.Random
import rockpaperscissors.Models.ShowdownState
object Main { object Main {
@main def run( @main def run(
@ -70,8 +71,13 @@ object Main {
case Some(playersChoiceBadge) => case Some(playersChoiceBadge) =>
val badge = playersChoiceBadge.copy() val badge = playersChoiceBadge.copy()
badge.p = Positioning.Relative badge.p = Positioning.Relative
context.setVariable("playersChoiceData", badge) val showdownState = ShowdownState(badge, None, false)
val result = templateEngine.process("showdown", Set("showdown-table").asJava, context) context.setVariable("showdownState", showdownState)
val result = templateEngine.process(
"showdown",
Set("showdown-table").asJava,
context
)
cask.Response( cask.Response(
result, result,
headers = Seq("Content-Type" -> "text/html;charset=UTF-8") headers = Seq("Content-Type" -> "text/html;charset=UTF-8")
@ -82,9 +88,37 @@ object Main {
response response
} }
@cask.get("/house-choice/:playersChoice")
def requestHouseChoice(playersChoice: String) = {
val context = new Context()
val badge = Models.choiceSelectionItems.find(_.c.name == playersChoice)
val response = badge match {
case Some(playersChoiceBadge) =>
val badge = playersChoiceBadge.copy()
badge.p =
Positioning.Relative // this probably should be set in enclosing html tag
val houseChoice = Models.choiceSelectionItems(Random.nextInt(3)).copy()
houseChoice.p = Positioning.Relative
println(s"getting house choice $houseChoice")
val showdownState = ShowdownState(badge, Some(houseChoice), false)
context.setVariable("showdownState", showdownState)
val result = templateEngine.process(
"showdown",
Set("showdown-table").asJava,
context
)
cask.Response(
result,
headers = Seq("Content-Type" -> "text/html;charset=UTF-8")
)
case None =>
cask.Response(s"Unknown choice: '${playersChoice}'", 400)
}
response
}
@cask.staticResources("/public") @cask.staticResources("/public")
def publicFiles(req: cask.Request) = { def publicFiles(req: cask.Request) = {
println(s"getting request for ${req.remainingPathSegments}")
"public" "public"
} }

View File

@ -83,4 +83,9 @@ position: absolute;
) )
} }
final case class ShowdownState(
var playersChoice: ChoiceBadge,
var houseChoice: Option[ChoiceBadge],
var gameEnded: Boolean
)
} }