defmodule LocalspotWeb.BusinessLive.New do use LocalspotWeb, :live_view alias Localspot.Businesses alias Localspot.Businesses.Business @impl true def mount(_params, _session, socket) do categories = Businesses.list_categories() changeset = Businesses.change_business(%Business{}) {:ok, socket |> assign(:page_title, "Add Your Business") |> assign(:categories, categories) |> assign(:form, to_form(changeset)) |> assign(:hours, default_hours()) |> assign(:photo_url, "")} end @impl true def handle_event("validate", %{"business" => business_params}, socket) do changeset = %Business{} |> Businesses.change_business(business_params) |> Map.put(:action, :validate) {:noreply, assign(socket, :form, to_form(changeset))} end @impl true def handle_event("update_hours", %{"day" => day, "field" => field, "value" => value}, socket) do day = String.to_integer(day) hours = update_hours(socket.assigns.hours, day, field, value) {:noreply, assign(socket, :hours, hours)} end @impl true def handle_event("update_photo_url", %{"value" => value}, socket) do {:noreply, assign(socket, :photo_url, value)} end @impl true def handle_event("save", %{"business" => business_params}, socket) do business_params = business_params |> Map.put("slug", Businesses.generate_slug(business_params["name"] || "")) |> Map.put("locally_owned", true) hours_attrs = build_hours_attrs(socket.assigns.hours) photo_attrs = build_photo_attrs(socket.assigns.photo_url) case Businesses.create_business_with_associations(business_params, hours_attrs, photo_attrs) do {:ok, business} -> {:noreply, socket |> put_flash(:info, "Business submitted successfully!") |> push_navigate(to: ~p"/businesses/#{business.slug}")} {:error, %Ecto.Changeset{} = changeset} -> {:noreply, assign(socket, :form, to_form(changeset))} end end defp default_hours do for day <- 0..6, into: %{} do {day, %{closed: day == 0, opens_at: "09:00", closes_at: "17:00"}} end end defp update_hours(hours, day, "closed", value) do put_in(hours, [day, :closed], value == "true") end defp update_hours(hours, day, field, value) do put_in(hours, [day, String.to_existing_atom(field)], value) end defp build_hours_attrs(hours) do hours |> Enum.map(fn {day, data} -> if data.closed do %{day_of_week: day, closed: true} else %{ day_of_week: day, closed: false, opens_at: parse_time(data.opens_at), closes_at: parse_time(data.closes_at) } end end) end defp parse_time(time_string) do case Time.from_iso8601(time_string <> ":00") do {:ok, time} -> time _ -> nil end end defp build_photo_attrs(""), do: [] defp build_photo_attrs(url), do: [%{url: url, primary: true}] @impl true def render(assigns) do ~H""" <.link navigate={~p"/businesses"} class="btn btn-ghost btn-sm mb-4"> <.icon name="hero-arrow-left" class="w-4 h-4" /> Back to Directory <.header> Add Your Business <:subtitle>List your locally owned business in our directory
<.icon name="hero-information-circle" class="w-5 h-5" /> This directory is exclusively for locally owned businesses - no chains or franchises.
<.form for={@form} phx-change="validate" phx-submit="save" class="space-y-6">

Basic Information

<.input field={@form[:name]} label="Business Name" required /> <.input field={@form[:description]} type="textarea" label="Description" rows="3" />

Location

<.input field={@form[:street_address]} label="Street Address" required />
<.input field={@form[:city]} label="City" required />
<.input field={@form[:state]} label="State" maxlength="2" placeholder="OH" required /> <.input field={@form[:zip_code]} label="ZIP Code" maxlength="10" required />
<.input field={@form[:latitude]} type="number" step="any" label="Latitude" placeholder="39.9612" /> <.input field={@form[:longitude]} type="number" step="any" label="Longitude" placeholder="-82.9988" />

Coordinates help customers find you on the map. You can find yours on Google Maps.

Contact Information

<.input field={@form[:phone]} label="Phone Number" placeholder="6145551234" /> <.input field={@form[:email]} type="email" label="Email Address" /> <.input field={@form[:website]} type="url" label="Website" placeholder="https://example.com" />

Business Hours

<.hours_row :for={day <- 0..6} day={day} hours={@hours[day]} />

Photo

Enter a URL to an image of your business. Direct image links work best.

Local Ownership Attestation

<.link navigate={~p"/businesses"} class="btn btn-ghost">Cancel
""" end defp hours_row(assigns) do ~H"""
{Businesses.day_name(@day)}
to
""" end end