defmodule LocalspotWeb.BusinessLive.Index do use LocalspotWeb, :live_view alias Localspot.Businesses @impl true def mount(_params, _session, socket) do categories = Businesses.list_categories() {:ok, socket |> assign(:page_title, "Local Businesses") |> assign(:categories, categories) |> assign(:filters, %{}) |> stream(:businesses, [])} end @impl true def handle_params(params, _uri, socket) do businesses = Businesses.list_businesses(params) {:noreply, socket |> assign(:filters, params) |> stream(:businesses, businesses, reset: true)} end @impl true def handle_event("search", %{"search" => search_params}, socket) do params = build_url_params(socket.assigns.filters, search_params) {:noreply, push_patch(socket, to: ~p"/businesses?#{params}")} end @impl true def handle_event("clear_filters", _params, socket) do {:noreply, push_patch(socket, to: ~p"/businesses")} end @impl true def handle_event("set_location", %{"latitude" => lat, "longitude" => lng}, socket) do params = socket.assigns.filters |> Map.put("latitude", lat) |> Map.put("longitude", lng) {:noreply, push_patch(socket, to: ~p"/businesses?#{params}")} end defp build_url_params(existing, new) do Map.merge(existing, new) |> Enum.reject(fn {_k, v} -> v == "" or is_nil(v) end) |> Map.new() end @impl true def render(assigns) do ~H"""
<.header> Local Business Directory <:subtitle>Discover locally owned businesses in your area <.link navigate={~p"/businesses/map"} class="btn btn-ghost btn-sm"> <.icon name="hero-map" class="w-4 h-4" /> Map View
<%!-- Search and filters form --%> <.form for={%{}} as={:search} id="search-form" phx-submit="search" class="flex flex-col md:flex-row gap-4" >
<%!-- Location status --%>
<.icon name="hero-map-pin" class="w-5 h-5" /> Enable location to find businesses near you
<.icon name="hero-map-pin" class="w-5 h-5" /> Showing businesses within {@filters["radius"] || "10"} miles of your location
<%!-- Locally owned filter --%> <%!-- Business listing --%>
<.business_card :for={{dom_id, business} <- @streams.businesses} id={dom_id} business={business} />
<.link navigate={~p"/businesses/new"} class="btn btn-secondary"> <.icon name="hero-plus" class="w-5 h-5" /> Add Your Business
""" end defp business_card(assigns) do ~H"""
{primary_photo(@business.photos).alt_text

<.link navigate={~p"/businesses/#{@business.slug}"} class="hover:underline"> {@business.name}

Local

{@business.description}

<.icon name="hero-map-pin" class="w-4 h-4" /> {@business.city}, {@business.state}
<.icon name="hero-arrow-right" class="w-4 h-4 inline" /> {@business.distance_miles} miles away
{if @business.category, do: @business.category.name, else: "Uncategorized"}
<.link navigate={~p"/businesses/#{@business.slug}"} class="btn btn-sm btn-primary"> View Details
""" end defp primary_photo([]), do: nil defp primary_photo(photos), do: Enum.find(photos, & &1.primary) || List.first(photos) end