defmodule BerrypodWeb.Shop.Collection do use BerrypodWeb, :live_view alias Berrypod.Products @sort_options [ {"featured", "Featured"}, {"newest", "Newest"}, {"price_asc", "Price: Low to High"}, {"price_desc", "Price: High to Low"}, {"name_asc", "Name: A-Z"}, {"name_desc", "Name: Z-A"} ] @impl true def mount(_params, _session, socket) do socket = socket |> assign(:sort_options, @sort_options) |> assign(:current_sort, "featured") {:ok, socket} end @impl true def handle_params(%{"slug" => slug} = params, _uri, socket) do sort = params["sort"] || "featured" case load_collection(slug, sort) do {:ok, title, category, products} -> {:noreply, socket |> assign(:page_title, title) |> assign(:page_description, collection_description(title)) |> assign(:og_url, BerrypodWeb.Endpoint.url() <> "/collections/#{slug}") |> assign(:collection_title, title) |> assign(:current_category, category) |> assign(:current_sort, sort) |> assign(:products, products)} :not_found -> {:noreply, socket |> put_flash(:error, "Collection not found") |> push_navigate(to: ~p"/collections/all")} end end defp load_collection("all", sort) do {:ok, "All Products", nil, Products.list_visible_products(sort: sort)} end defp load_collection("sale", sort) do {:ok, "Sale", :sale, Products.list_visible_products(on_sale: true, sort: sort)} end defp load_collection(slug, sort) do case Enum.find(Products.list_categories(), &(&1.slug == slug)) do nil -> :not_found category -> products = Products.list_visible_products(category: category.name, sort: sort) {:ok, category.name, category, products} end end @impl true def handle_event("sort_changed", %{"sort" => sort}, socket) do slug = case socket.assigns.current_category do nil -> "all" :sale -> "sale" category -> category.slug end {:noreply, push_patch(socket, to: ~p"/collections/#{slug}?sort=#{sort}")} end defp collection_description("All Products"), do: "Browse our full range of products." defp collection_description("Sale"), do: "Browse our current sale items." defp collection_description(title), do: "Browse our #{String.downcase(title)} collection." defp collection_path(slug, "featured"), do: ~p"/collections/#{slug}" defp collection_path(slug, sort), do: ~p"/collections/#{slug}?sort=#{sort}" @impl true def render(assigns) do ~H""" <.shop_layout {layout_assigns(assigns)} active_page="collection">
<.collection_header title={@collection_title} product_count={length(@products)} />
<.collection_filter_bar categories={@categories} current_slug={ case @current_category do :sale -> "sale" nil -> nil cat -> cat.slug end } sort_options={@sort_options} current_sort={@current_sort} /> <.product_grid theme_settings={@theme_settings}> <%= for product <- @products do %> <.product_card product={product} theme_settings={@theme_settings} mode={@mode} variant={:default} show_category={@current_category in [nil, :sale]} /> <% end %> <%= if @products == [] do %>

No products found in this collection.

<.link navigate={~p"/collections/all"} class="collection-empty-link"> View all products
<% end %>
""" end defp collection_filter_bar(assigns) do ~H"""
<.shop_select name="sort" options={@sort_options} selected={@current_sort} aria-label="Sort products" />
""" end end