Skip to content

Commit

Permalink
feat: sort function in the products list (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
ricksonoliveira authored Dec 11, 2023
1 parent b975227 commit d978dee
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 12 deletions.
3 changes: 3 additions & 0 deletions lib/food_order/products.ex
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ defmodule FoodOrder.Products do
{:name, name}, query ->
name = "%#{name}%"
where(query, [q], ilike(q.name, ^name))

{:sort, %{sort_by: sort_by, sort_order: sort_order}}, query ->
order_by(query, [q], [{^sort_order, ^sort_by}])
end)
|> Repo.all()
end
Expand Down
44 changes: 43 additions & 1 deletion lib/food_order_web/components/core_components.ex
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,8 @@ defmodule FoodOrderWeb.CoreComponents do

slot :col, required: true do
attr :label, :string
attr :link, :any
attr :options, :map
end

slot :action, doc: "the slot for showing user actions in the last table column"
Expand All @@ -486,7 +488,24 @@ defmodule FoodOrderWeb.CoreComponents do
<table class="mt-11 w-[40rem] sm:w-full">
<thead class="text-left text-[0.8125rem] leading-6 text-zinc-500">
<tr>
<th :for={col <- @col} class="p-0 pb-4 pr-6 font-normal"><%= col[:label] %></th>
<th :for={col <- @col} class="p-0 pb-4 pr-6 font-normal">
<%= if col[:link] do %>
<.link patch={create_sort_link(col[:link], col[:options], col[:label])} >
<div class="flex items-center">
<span class="pr-2">
<%= col[:label] %>
</span>
<%= if col[:options][:sort_order] == :asc do %>
<Heroicons.bars_arrow_up solid class={[is_active(col), "h-5 w-5 stroke-current"]} />
<% else %>
<Heroicons.bars_arrow_down solid class="text-gray-500 h-5 w-5 stroke-current" />
<% end %>
</div>
</.link>
<% else %>
<%= col[:label] %>
<% end %>
</th>
<th class="relative p-0 pb-4"><span class="sr-only"><%= gettext("Actions") %></span></th>
</tr>
</thead>
Expand Down Expand Up @@ -529,6 +548,29 @@ defmodule FoodOrderWeb.CoreComponents do
"""
end

defp is_active(col) do
if Atom.to_string(col[:options][:sort_by]) == String.downcase(col[:label]) do
"text-fuchsia-500"
else
"text-gray-500"
end
end

defp create_sort_link(link, options, label) do
sort_order = (options[:sort_order] == :desc && :asc) || :desc

params =
options
|> Map.put(:sort_by, String.downcase(label))
|> Map.put(:sort_order, sort_order)
|> Map.to_list()
|> Enum.reduce("", fn {k, v}, acc ->
acc <> "#{Atom.to_string(k)}=#{v}&"
end)

"#{link}?#{params}"
end

@doc """
Renders a data list.
Expand Down
21 changes: 16 additions & 5 deletions lib/food_order_web/live/admin/product_live/index/index.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ defmodule FoodOrderWeb.Admin.ProductLive.Index do
def handle_params(params, _uri, socket) do
live_action = socket.assigns.live_action
name = params["name"] || ""
products = Products.list_products(name: name)
assigns = [name: name, products: products, loading: false]
sort_by = (params["sort_by"] || "updated_at") |> String.to_atom()
sort_order = (params["sort_order"] || "desc") |> String.to_atom()
sort = %{sort_by: sort_by, sort_order: sort_order}
products = Products.list_products(name: name, sort: sort)
options = Map.merge(sort, %{name: name})
assigns = [options: options, products: products, loading: false]

socket =
socket
Expand Down Expand Up @@ -51,7 +55,10 @@ defmodule FoodOrderWeb.Admin.ProductLive.Index do
defp apply_filters(socket, name) do
assings = [products: [], name: name, loading: true]
send(self(), {:list_product, name})
assign(socket, assings)

socket
|> assign(assings)
|> update(:options, &Map.put(&1, :name, name))
end

defp perform_filter(socket, params) do
Expand All @@ -61,11 +68,15 @@ defmodule FoodOrderWeb.Admin.ProductLive.Index do
end

defp return_response([], socket, params) do
assigns = [loading: false, products: [], name: params[:name]]
assigns = [
loading: false,
products: []
]

socket
|> put_flash(:error, "No products found for #{params[:name]}")
|> assign(assigns)
|> update(:options, &Map.put(&1, :name, params[:name]))
|> put_flash(:error, "No products found for #{params[:name]}")
end

defp return_response(products, socket, _params) do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
List Products
<:actions>
<div class="flex items-center justify-between">
<.search_by_product name={@name} />
<.search_by_product name={@options.name} />
<.link patch={~p"/admin/products/new"} class="text-[0.8125rem] text-zinc-900 font-semibold hover:text-zinc-700">New Product</.link>
</div>
</:actions>
Expand All @@ -16,7 +16,7 @@
</div>
<% else %>
<.table id="products" rows={@products} row_click={&JS.navigate(~p"/admin/products/#{&1}")}>
<:col :let={product} label="Name" ><%= product.name %></:col>
<:col :let={product} label="Name" options={@options} link={~p"/admin/products"}><%= product.name %></:col>
<:col :let={product} label="Price" ><%= product.price %></:col>
<:col :let={product} label="Size" ><%= product.size %></:col>

Expand Down
8 changes: 4 additions & 4 deletions priv/repo/seeds.exs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ for _ <- 0..50,
})

Accounts.register_user(%{
email: "admin@elxpro.com",
password: "Admin@elxpro123",
email: "admin@food.com",
password: "Admin@food123",
role: "ADMIN"
})

Accounts.register_user(%{
email: "user@elxpro.com",
password: "User@elxpro123",
email: "user@food.com",
password: "User@food123",
role: "USER"
})

0 comments on commit d978dee

Please sign in to comment.