Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Bike comparison with Phoenix Live View
defmodule GoBikesWeb.CompareSelectBikeView do
use Phoenix.LiveView
alias GoBikesWeb.Router.Helpers, as: Routes
alias GoBikes.Bikes
def render(assigns) do
GoBikesWeb.CompareView.render("show.html", assigns)
end
def mount(session, socket) do
makers = GoBikes.Bikes.list_bike_makers()
{:ok,
assign(socket,
bikes: session[:bikes],
makers: makers,
available_bikes: nil,
maker: %GoBikes.Bikes.Maker{},
bike: %GoBikes.Bikes.Bike{},
compare_path: compare_path_for(socket, session[:bikes])
)}
end
def handle_event("maker_chosen", %{"maker" => %{"id" => maker_id}}, socket) do
available_bikes = Bikes.get_bikes_by_maker_id(maker_id)
maker = Bikes.get_maker!(maker_id)
{:noreply, socket |> assign(available_bikes: available_bikes, maker: maker)}
end
def handle_event("bike_chosen", %{"bike" => %{"slug" => slug}}, socket) do
bike = Bikes.get_bike_by_slug!(slug)
bikes = [bike | socket.assigns.bikes]
{:noreply,
socket
|> assign(
bikes: bikes,
bike: %GoBikes.Bikes.Bike{},
compare_path: compare_path_for(socket, bikes)
)}
end
def handle_event("remove_bike_" <> bike_id, _, socket) do
bikes = Enum.filter(socket.assigns.bikes, &(&1.id != String.to_integer(bike_id)))
{:noreply, socket |> assign(bikes: bikes, compare_path: compare_path_for(socket, bikes))}
end
def compare_path_for(socket, bikes) do
slug = Enum.join(Enum.map(bikes, & &1.slug), ",")
Routes.compare_path(socket, :show, slug)
end
end
<div class="container mx-auto">
<div class="flex my-8 -mx-2" data-compare="bikes" data-compare-url="<%= @compare_path %>">
<div class="w-1/5 shadow mx-2 bg-white rounded">
<div class="flex items-center flex-col justify-center p-4" style="min-height: 170px">
<%= icon_tag(@socket, "bike", class: "icon text-8xl text-gray-200") %>
<p class=" tet-center text-gray-400">Adicionar bike no comparativo</p>
</div>
<div class="text-center -my-6">
<%= icon_tag(@socket, "chevron-down", class: "icon text-6xl text-gray-200") %>
</div>
<div class="text-left p-4">
<%= if length(@bikes) < 4 do %>
<%= form_for GoBikes.Bikes.change_maker(@maker), "#", [phx_change: :maker_chosen, class: "mb-2"], fn f -> %>
<%= label f, :id, "Marca", class: "text-gray-600 text-sm" %>
<div class="flex items-center border rounded w-full">
<%= select f, :id, Enum.map(@makers, &{&1.name, &1.id}), prompt: "Escolha o marca", class: "appearance-none bg-white p-2 w-full outline-none" %>
<%= icon_tag(@socket, "chevron-down", class: "icon text-base text-gray-500 mr-2") %>
</div>
<% end %>
<%= if @available_bikes do %>
<%= form_for GoBikes.Bikes.change_bike(@bike), "#", [phx_change: :bike_chosen], fn f -> %>
<%= label f, :slug, "Modelo", class: "text-gray-600" %>
<div class="flex items-center border rounded w-full">
<%= select f, :slug, Enum.map(@available_bikes, &{&1.model, &1.slug}), prompt: "Escolha o modelo", class: "appearance-none bg-white p-2 w-full outline-none" %>
<%= icon_tag(@socket, "chevron-down", class: "icon text-base text-gray-500 mr-2") %>
</div>
<% end %>
<% end %>
<% end %>
</div>
</div>
<%= if length(@bikes) == 0 do %>
<div class="flex-1 flex items-center justify-center shadow mx-2 bg-white rounded">
<p class="text-3xl text-gray-300">Monte seu comparativo com até 4 bikes diferentes.</p>
</div>
<% end %>
<%= for bike <- @bikes do %>
<div class="flex-1 shadow mx-2 bg-white rounded relative">
<div class="flex items-center justify-center" style="min-height: 170px">
<%= if Enum.at(bike.images, 0) do %>
<%= link to: Routes.bike_path(@socket, :show, bike) do %>
<%= img_tag GoBikes.BikeImage.url({Enum.at(bike.images, 0).filename, bike}, :thumb), class: "", alt: "#{bike.maker.name} #{bike.model}" %>
<% end %>
<% end %>
</div>
<div class="text-center p-4">
<h2 class="text-xl font-semibold mb-4"><%= bike.maker.name %> <%= bike.model %></h2>
<%= link 'Ver esta bike', to: Routes.bike_path(@socket, :show, bike), class: 'no-underline btn btn-flat btn-sm block' %>
</div>
<button class="absolute top-0 right-0 p-2" phx-click="remove_bike_<%= bike.id %>">
<%= icon_tag(@socket, "delete", class: "icon text-2xl text-red-200 hover:text-red-300") %>
</button>
</div>
<% end %>
</div>
<!-- ... -->
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.