-
Notifications
You must be signed in to change notification settings - Fork 18
/
crypto_dashboard_live.ex
133 lines (112 loc) · 3.88 KB
/
crypto_dashboard_live.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
defmodule PoeticoinsWeb.CryptoDashboardLive do
use PoeticoinsWeb, :live_view
alias Poeticoins.Product
import PoeticoinsWeb.ProductHelpers
def mount(_params, _session, socket) do
socket = assign(socket, trades: %{}, products: [])
{:ok, socket}
end
def render(assigns) do
~L"""
<div class="poeticoins-toolbar">
<div class="title">Poeticoins</div>
<form action="#" phx-submit="add-product">
<select name="product_id" class="select-product">
<option selected disabled>Add a Crypto Product</option>
<%= for {exchange_name, products} <- grouped_products_by_exchange_name() do %>
<optgroup label="<%= exchange_name %>">
<%= for product <- products do %>
<option value="<%= to_string(product) %>">
<%= crypto_name(product)%>
-
<%= fiat_character(product) %>
</option>
<% end %>
</optgroup>
<% end %>
</select>
<button type="submit" phx-disable-with="Loading...">+</button>
</form>
</div>
<div class="product-components">
<%= for product <- @products, trade = @trades[product] do%>
<div class="product-component">
<div class="currency-container">
<img class="icon" src="<%= crypto_icon(@socket, product) %>" />
<div class="crypto-name">
<%= crypto_name(product) %>
</div>
</div>
<div class="price-container">
<ul class="fiat-symbols">
<%= for fiat <- fiat_symbols() do %>
<li class="
<%= if fiat_symbol(product) == fiat, do: "active" %>
"><%= fiat %></li>
<% end %>
</ul>
<div class="price">
<%= trade.price %>
<%= fiat_character(product) %>
</div>
</div>
<div class="exchange-name">
<%= product.exchange_name %>
</div>
<div class="trade-time">
<%= human_datetime(trade.traded_at) %>
</div>
</div>
<% end %>
</div>
"""
end
def handle_info({:new_trade, trade}, socket) do
socket = update(socket, :trades, &Map.put(&1, trade.product, trade))
{:noreply, socket}
end
def handle_event("add-product", %{"product_id" => product_id} = _params, socket) do
[exchange_name, currency_pair] = String.split(product_id, ":")
product = Product.new(exchange_name, currency_pair)
socket = maybe_add_product(socket, product)
{:noreply, socket}
end
def handle_event("add-product", _, socket) do
{:noreply, socket}
end
def handle_event("filter-products", %{"search" => search}, socket) do
products =
Poeticoins.available_products()
|> Enum.filter(fn product ->
String.downcase(product.exchange_name) =~ String.downcase(search) or
String.downcase(product.currency_pair) =~ String.downcase(search)
end)
{:noreply, assign(socket, :products, products)}
end
def add_product(socket, product) do
Poeticoins.subscribe_to_trades(product)
socket
|> update(:products, &(&1 ++ [product]))
|> update(:trades, fn trades ->
trade = Poeticoins.get_last_trade(product)
Map.put(trades, product, trade)
end)
end
@spec maybe_add_product(Phoenix.LiveView.Socket.t(), Product.t()) :: Phoenix.LiveView.Socket.t()
defp maybe_add_product(socket, product) do
if product not in socket.assigns.products do
socket
|> add_product(product)
|> put_flash(
:info,
"#{product.exchange_name} - #{product.currency_pair} added successfully"
)
else
put_flash(socket, :error, "The product was already added")
end
end
defp grouped_products_by_exchange_name do
Poeticoins.available_products()
|> Enum.group_by(& &1.exchange_name)
end
end