From 67928837564fa16049ae0f75387a50d85d53b371 Mon Sep 17 00:00:00 2001 From: daveminer Date: Fri, 24 Nov 2023 11:20:39 -0500 Subject: [PATCH] refactor ticker add --- lib/basket_web/components/core_components.ex | 32 ++++------ lib/basket_web/components/dark_mode_toggle.ex | 26 --------- lib/basket_web/components/nav_row.ex | 2 - lib/basket_web/live/overview.ex | 50 ++++++---------- lib/basket_web/live/overview/ticker_add.ex | 58 +++++++++++++++++++ 5 files changed, 89 insertions(+), 79 deletions(-) delete mode 100644 lib/basket_web/components/dark_mode_toggle.ex create mode 100644 lib/basket_web/live/overview/ticker_add.ex diff --git a/lib/basket_web/components/core_components.ex b/lib/basket_web/components/core_components.ex index 91f05dc..8b7cd21 100644 --- a/lib/basket_web/components/core_components.ex +++ b/lib/basket_web/components/core_components.ex @@ -330,8 +330,6 @@ defmodule BasketWeb.CoreComponents do slot :inner_block def input(%{field: %Phoenix.HTML.FormField{} = field} = assigns) do - IO.inspect("ASS: #{assigns}") - assigns |> assign(field: nil, id: assigns.id || field.id) |> assign(:errors, Enum.map(field.errors, &translate_error(&1))) @@ -407,8 +405,6 @@ defmodule BasketWeb.CoreComponents do # All other inputs text, datetime-local, url, password, etc. are handled here... def input(assigns) do - IO.inspect("DEF: #{inspect(assigns)}") - ~H"""
<.label for={@id}><%= @label %> @@ -541,7 +537,7 @@ defmodule BasketWeb.CoreComponents do "relative p-0", "text-center", @row_click && "hover:cursor-pointer", - diff_color(col, row) + diff_cell_color(col, row) ]} >
@@ -722,23 +718,19 @@ defmodule BasketWeb.CoreComponents do for {^field, {msg, opts}} <- errors, do: translate_error({msg, opts}) end - defp diff_color(col, row) do - key = Map.get(col, :key) + defp diff_cell_color(%{key: nil}, _row), do: "" - if is_nil(key) do - "" - else - field = row[key] - - if field != nil && is_number(field.value) && is_number(field.prev_value) do - case field.value - field.prev_value do - x when x > 0 -> "bg-emerald-300 text-emerald-900" - x when x < 0 -> "bg-rose-300 text-rose-900" - _ -> "" - end - else - "" + defp diff_cell_color(%{key: key} = _col, row) do + field = row[key] + + if field != nil && is_number(field.value) && is_number(field.prev_value) do + case field.value - field.prev_value do + x when x > 0 -> "bg-emerald-300 text-emerald-900" + x when x < 0 -> "bg-rose-300 text-rose-900" + _ -> "" end + else + "" end end end diff --git a/lib/basket_web/components/dark_mode_toggle.ex b/lib/basket_web/components/dark_mode_toggle.ex deleted file mode 100644 index c772b7c..0000000 --- a/lib/basket_web/components/dark_mode_toggle.ex +++ /dev/null @@ -1,26 +0,0 @@ -defmodule BasketWeb.Components.DarkModeToggle do - @moduledoc """ - A sample component generated by `mix surface.init`. - """ - use Surface.Component - - import BasketWeb.CoreComponents - - alias Phoenix.LiveView.JS - - def render(assigns) do - ~F""" - """ - - # ~F""" - #
- # - # - #
- # """ - end -end diff --git a/lib/basket_web/components/nav_row.ex b/lib/basket_web/components/nav_row.ex index 6bdfbc0..9862a30 100644 --- a/lib/basket_web/components/nav_row.ex +++ b/lib/basket_web/components/nav_row.ex @@ -2,14 +2,12 @@ defmodule BasketWeb.Components.NavRow do @moduledoc """ The header for the home page. """ - alias BasketWeb.Components.DarkModeToggle use Surface.Component def render(assigns) do ~F"""
- <.link href="/session" method="delete">Sign out
""" diff --git a/lib/basket_web/live/overview.ex b/lib/basket_web/live/overview.ex index ba1832b..74b12e5 100644 --- a/lib/basket_web/live/overview.ex +++ b/lib/basket_web/live/overview.ex @@ -6,10 +6,9 @@ defmodule BasketWeb.OverviewLive do require Logger - alias Basket.{Http, Websocket} + alias Basket.Websocket alias BasketWeb.Components.{NavRow, TickerBarTable} - alias BasketWeb.Live.Overview.Search - alias BasketWeb.Live.Overview.TickerBar + alias BasketWeb.Live.Overview.{Search, TickerAdd, TickerBar} def mount(_, _, socket) do BasketWeb.Endpoint.subscribe(Websocket.Alpaca.bars_topic()) @@ -24,25 +23,18 @@ defmodule BasketWeb.OverviewLive do {:noreply, socket} else socket = - case Http.Alpaca.latest_quote(ticker) do - {:ok, response} -> - %{"bars" => ticker_bars} = response - new_ticker_bars = Map.to_list(ticker_bars) |> List.first() - # TODO: nil not a tuple - AKUMQ - initial_bars = build_ticker_bars(elem(new_ticker_bars, 1)) - - assign( - socket, - :basket, - socket.assigns.basket ++ - [Map.merge(initial_bars, %{"S" => %TickerBar{value: ticker}})] - ) - - {:error, error} -> - Logger.error("Could not subscribe to ticker: #{error}") - end + case TickerAdd.call(ticker) do + row when is_map(row) -> + :ok = Websocket.Alpaca.subscribe(%{bars: [ticker], quotes: [], trades: []}) + assign(socket, :basket, (socket.assigns.basket ++ [row]) |> sort_by_ticker()) + + :market_closed -> + # TODO: add market closed row + socket - :ok = Websocket.Alpaca.subscribe(%{bars: [ticker], quotes: [], trades: []}) + _ -> + socket + end {:noreply, socket} end @@ -98,16 +90,6 @@ defmodule BasketWeb.OverviewLive do """ end - defp build_ticker_bars(ticker_bars) do - if ticker_bars == %{} do - %{"t" => "Market Closed"} - else - Enum.reduce(ticker_bars, %{}, fn {k, v}, acc -> - Map.put(acc, k, %TickerBar{value: v}) - end) - end - end - defp new_ticker_row(row, bars) do Enum.reduce(row, %{}, fn {k, v}, acc -> new_value = Map.get(bars, k) @@ -115,5 +97,11 @@ defmodule BasketWeb.OverviewLive do end) end + defp sort_by_ticker(bars), + do: + Enum.sort(bars, fn a, b -> + a["S"].value < b["S"].value + end) + defp tickers(socket), do: Enum.map(socket.assigns.basket, &Map.get(&1, "S").value) end diff --git a/lib/basket_web/live/overview/ticker_add.ex b/lib/basket_web/live/overview/ticker_add.ex new file mode 100644 index 0000000..f3bce66 --- /dev/null +++ b/lib/basket_web/live/overview/ticker_add.ex @@ -0,0 +1,58 @@ +defmodule BasketWeb.Live.Overview.TickerAdd do + @moduledoc """ + Creates a new ticker in the table. + """ + + alias Basket.Http + alias BasketWeb.Live.Overview.TickerBar + + require Logger + + @doc """ + Creates a row to be added to the ticker bar table. + """ + def call(ticker) do + case Http.Alpaca.latest_quote(ticker) do + {:ok, response} -> + case build_ticker_bars(response) do + :no_data -> + # TODO: info flash + :no_data + + :market_closed -> + :market_closed + + bars -> + bars + end + + {:error, error} -> + # TODO: error flash + Logger.error("Could not subscribe to ticker: #{error}") + end + end + + defp build_ticker_bars(%{"bars" => nil}) do + end + + defp build_ticker_bars(%{"bars" => ticker_bars}) do + # TODO: check first + new_ticker_bars = Map.to_list(ticker_bars) |> List.first() + + case new_ticker_bars do + nil -> + :no_data + + %{} -> + :market_closed + + bars -> + Enum.reduce(bars, %{}, fn {k, v}, acc -> + Map.put(acc, k, %TickerBar{value: v}) + end) + + # TODO: check + # Map.merge(new_bars, %{"S" => %TickerBar{value: ticker}}) + end + end +end