Home Posts Post Search Tag Search

Game Site Journal - 05
Published on: 2025-04-13 Tags: elixir, Blog, Side Project, LiveView, Game Site, Html/CSS, Buttons

So for this post I wanted to go over something that I wanted to add to my games. A Wager button.

So for this to work I wanted to be able to send the info for the amount wagered as well as the answer. In the case for the Guessing Game I have hard coded a few buttons (10 that is) that are the number that a player would submit.

<div class="grid grid-cols-5 gap-x-3 gap-y-1 max-w-md mx-auto mt-4">
  <%= for guess <- 1..10 do %>
    <.simple_form for={@form} phx-submit="answer" class="text-center">
      <.input type="hidden" field={@form[:guess]} value={guess} />

      <.button type="submit" class="w-full" phx-hook="CopyBonus">
        {guess}
      </.button>
    </.simple_form>
  <% end %>
</div>

This will create 10 buttons for the user to submit. When I wanted to add a cell for a player to increase their bet simply adding a new .input added it to every cell. Adding it to a single button made it so only the button in question had the wager param sent. This is where adding a hidden field from another section comes in handy. First create your new cell:

<div class="max-w-md mx-auto mt-4">
  <label for="bonus_input" class="block text-sm font-medium text-gray-700 mb-1">
    Wager
  </label>
  <input
    type="number"
    id="wager_input"
    name="wager_visible"
    min="1"
    value="1"
    max={@score}
    step="1"
    class="w-full rounded-md border-gray-300 shadow-sm"
  />
</div>

Then add this to the .simple_form as another input:

<div class="grid grid-cols-5 gap-x-3 gap-y-1 max-w-md mx-auto mt-4">
  <%= for guess <- 1..10 do %>
    <.simple_form for={@form} phx-submit="answer" class="text-center">
      <.input type="hidden" field={@form[:guess]} value={guess} />
      <input type="hidden" name="wager" id={"wager_hidden_#{guess}"} />

      <.button type="submit" class="w-full" phx-hook="CopyBonus">
        {guess}
      </.button>
    </.simple_form>
  <% end %>
</div>

You can see that the id is a string interpolation, so that we can add in the guess id as well as call the input that is outside the current loop for the buttons.

Now that that is in place we need to add in a Hook in the app.js code:

Hooks.CopyBonus = {
  mounted() {
    this.el.addEventListener("click", (e) => {
      const visible = document.getElementById("wager_input")
      const guess = this.el.getAttribute("data-guess")
      const hidden = document.getElementById(`wager_hidden_${guess}`)
      if (visible && hidden) {
        hidden.value = visible.value || "1"
      }
    })
  }
}

let liveSocket = new LiveSocket("/live", Socket, {
  hooks: Hooks,
  longPollFallbackMs: 2500,
  params: { _csrf_token: csrfToken }
})

The last bit after this was to be sure that the different params were being used correctly. So I made a check for a win or a loss and changed all the score changes to:

parsed_wager =
  parse_wager(wager)
  |> add_subtract_wager(guess, to_string(socket.assigns.answer))

socket.assigns.score + parsed_wager

defp parse_wager(nil), do: 1
defp parse_wager(""), do: 1
defp parse_wager(wager) do
  case Integer.parse(wager) do
    {int, _} -> int
    :error -> 1
  end
end

defp add_subtract_wager(wager, guess, answer) do
  if guess == answer do
    wager
  else
    wager * -1
  end
end

This was all the new functions needed.