defmodule MtgWheelWeb.WheelLive do use MtgWheelWeb, :live_view alias MtgWheel.DeckGenerator @spin_duration_ms 3700 @item_height_px 112 @impl true def mount(_params, _session, socket) do {:ok, assign(socket, page_title: "MTG Deck Wheel", spinning: false, result: nil, budgets: DeckGenerator.budgets(), archetypes: DeckGenerator.archetypes(), subthemes: DeckGenerator.subthemes(), color_combos: DeckGenerator.color_combos() )} end @impl true def handle_event("spin", _params, socket) do result = DeckGenerator.generate() Process.send_after(self(), :stop_spin, @spin_duration_ms) {:noreply, assign(socket, spinning: true, result: result)} end @impl true def handle_info(:stop_spin, socket) do {:noreply, assign(socket, spinning: false)} end @impl true def render(assigns) do ~H"""

MTG Deck Wheel

<.wheel label="Budget" items={Enum.map(@budgets, &"$#{&1}")} result={@result && @result.budget} spinning={@spinning} duration={2500} /> <.wheel label="Archetype" items={@archetypes} result={@result && @result.archetype} spinning={@spinning} duration={2900} /> <.wheel label="Subtheme" items={@subthemes} result={@result && @result.subtheme} spinning={@spinning} duration={3300} /> <.wheel label="Colors" items={@color_combos} result={@result && @result.colors} spinning={@spinning} color?={true} duration={3600} />

Your Deck

<.stat label="Budget" value={(@result && @result.budget) || ""} /> <.stat label="Archetype" value={(@result && @result.archetype) || ""} /> <.stat label="Subtheme" value={(@result && @result.subtheme) || ""} /> <.stat label="Colors"> <.color_icons colors={(@result && @result.colors) || ""} size="lg" />
""" end defp wheel(assigns) do assigns = assigns |> assign_new(:color?, fn -> false end) |> assign_new(:duration, fn -> 3000 end) ~H"""
<%= @label %>
<%= for _ <- 1..5 do %> <%= for item <- @items do %>
<%= if @color? do %> <.color_icons colors={item} /> <% else %> <%= item %> <% end %>
<% end %> <% end %>
<%= if @color? do %> <.color_icons colors={@result || ""} size="lg" /> <% else %> <%= @result %> <% end %>
""" end defp wheel_style(items, result, duration_ms) do n = length(items) idx = if result, do: Enum.find_index(items, &(&1 == result)) || 0, else: 0 end_px = -(3 * n + idx) * @item_height_px "--wheel-end: #{end_px}px; --wheel-duration: #{duration_ms}ms" end defp color_icons(assigns) do assigns = assign_new(assigns, :size, fn -> "md" end) ~H""" <%= for letter <- String.graphemes(@colors) do %> <% end %> """ end defp stat(assigns) do assigns = assign_new(assigns, :value, fn -> nil end) ~H"""
<%= @label %>
<%= if Map.has_key?(assigns, :inner_block) do %> <%= render_slot(@inner_block) %> <% else %> <%= @value %> <% end %>
""" end end