in same ui
All checks were successful
Build and Deploy / Build & Push Image (push) Successful in 36s

This commit is contained in:
2026-03-16 19:41:56 -06:00
parent cbd7d508a0
commit 34ee245543
3 changed files with 106 additions and 253 deletions

View File

@@ -14,6 +14,7 @@ defmodule CobblemonUiWeb.DashboardLive do
players: players,
selected_player: nil,
player_data: nil,
battle: nil,
selected_pokemon: nil,
view_mode: :party,
loading: false,
@@ -25,10 +26,13 @@ defmodule CobblemonUiWeb.DashboardLive do
def handle_params(%{"uuid" => uuid}, _uri, socket) do
case CobblemonUi.CobblemonFS.get_player(uuid) do
{:ok, data} ->
battle = find_player_battle(uuid)
{:noreply,
assign(socket,
selected_player: uuid,
player_data: data,
battle: battle,
selected_pokemon: nil,
error: nil
)}
@@ -52,7 +56,7 @@ defmodule CobblemonUiWeb.DashboardLive do
end
def handle_params(_params, _uri, socket) do
{:noreply, assign(socket, selected_player: nil, player_data: nil, selected_pokemon: nil)}
{:noreply, assign(socket, selected_player: nil, player_data: nil, battle: nil, selected_pokemon: nil)}
end
@impl true
@@ -89,9 +93,11 @@ defmodule CobblemonUiWeb.DashboardLive do
socket =
if uuid = socket.assigns.selected_player do
battle = find_player_battle(uuid)
case CobblemonUi.CobblemonFS.get_player(uuid) do
{:ok, data} -> assign(socket, player_data: data, error: nil)
_ -> socket
{:ok, data} -> assign(socket, player_data: data, battle: battle, error: nil)
_ -> assign(socket, battle: battle)
end
else
socket
@@ -118,12 +124,6 @@ defmodule CobblemonUiWeb.DashboardLive do
</div>
</div>
<div class="flex items-center gap-2">
<.link
navigate={~p"/battles"}
class="btn btn-ghost btn-sm gap-2 hover:bg-base-300/50 transition-colors"
>
<.icon name="hero-bolt" class="size-4 text-error" /> Battles
</.link>
<button
id="refresh-btn"
phx-click="refresh"
@@ -234,6 +234,9 @@ defmodule CobblemonUiWeb.DashboardLive do
</div>
</div>
<%!-- Active battle --%>
<.battle_panel :if={@battle} battle={@battle} player_id={@selected_player} />
<%!-- View mode tabs --%>
<div class="flex items-center gap-1 mb-5 p-1 rounded-lg bg-base-200/40 w-fit">
<button
@@ -545,6 +548,88 @@ defmodule CobblemonUiWeb.DashboardLive do
"""
end
# --- Battle components ---
attr :battle, :map, required: true
attr :player_id, :string, required: true
defp battle_panel(assigns) do
~H"""
<div class="rounded-xl border border-error/30 bg-error/5 overflow-hidden mb-6">
<div class="px-5 py-3 border-b border-error/20 flex items-center gap-2">
<span class="w-2 h-2 rounded-full bg-error animate-pulse inline-block"></span>
<span class="text-sm font-semibold text-error">Active Battle</span>
<span class="ml-auto text-[10px] font-mono text-base-content/30">{@battle.battle_id}</span>
</div>
<div class="p-4 grid grid-cols-1 md:grid-cols-2 gap-3 relative">
<div class="hidden md:flex absolute inset-y-0 left-1/2 -translate-x-1/2 items-center justify-center z-10 pointer-events-none">
<span class="text-base font-black text-base-content/20 bg-base-200/80 px-2 py-1 rounded-lg">
VS
</span>
</div>
<%= for actor <- @battle.actors do %>
<div class={[
"rounded-lg border p-3",
if(actor.player_id == @player_id,
do: "border-primary/25 bg-primary/5",
else: "border-warning/25 bg-warning/5"
)
]}>
<div class="flex items-center gap-2 mb-2">
<div class={[
"w-7 h-7 rounded-md flex items-center justify-center shrink-0",
if(actor.type == "player", do: "bg-primary/15", else: "bg-warning/15")
]}>
<%= if actor.type == "player" do %>
<.icon name="hero-user" class="size-3.5 text-primary" />
<% else %>
<.icon name="hero-cpu-chip" class="size-3.5 text-warning" />
<% end %>
</div>
<div>
<p class="text-sm font-semibold text-base-content">{actor.name}</p>
<p class={[
"text-[10px] uppercase font-medium tracking-wide",
if(actor.type == "player", do: "text-primary/60", else: "text-warning/60")
]}>
{actor.type}
</p>
</div>
</div>
<%= for poke <- actor.active_pokemon do %>
<div class="rounded-md bg-base-100/50 border border-base-300/30 px-3 py-2">
<div class="flex items-center justify-between mb-1">
<div class="flex items-center gap-1.5">
<span class="text-sm font-bold text-base-content">{poke.species}</span>
<span class="text-[10px] text-base-content/40 bg-base-300/40 px-1.5 py-0.5 rounded font-mono">
Lv.{poke.level}
</span>
</div>
<span class="text-xs font-mono text-base-content/50">{poke.hp}/{poke.max_hp}</span>
</div>
<div class="w-full h-1.5 rounded-full bg-base-300/50 overflow-hidden">
<div
class={[
"h-full rounded-full transition-all",
cond do
poke.max_hp == 0 -> "bg-base-content/20"
poke.hp / poke.max_hp > 0.5 -> "bg-success"
poke.hp / poke.max_hp > 0.2 -> "bg-warning"
true -> "bg-error"
end
]}
style={"width: #{if poke.max_hp > 0, do: Float.round(poke.hp / poke.max_hp * 100, 1), else: 0}%"}
/>
</div>
</div>
<% end %>
</div>
<% end %>
</div>
</div>
"""
end
# --- Helpers ---
defp party_count(%{party: party}), do: Enum.count(party, &(not is_nil(&1)))
@@ -599,4 +684,16 @@ defmodule CobblemonUiWeb.DashboardLive do
_ -> "Unknown"
end
end
defp find_player_battle(uuid) do
case CobblemonUi.BattlesApi.list_battles() do
{:ok, battles} ->
Enum.find(battles, fn battle ->
Enum.any?(battle.actors, fn actor -> actor.player_id == uuid end)
end)
_ ->
nil
end
end
end