diff --git a/assets/css/app.scss b/assets/css/app.scss index 3e81b98493..f769548ac0 100644 --- a/assets/css/app.scss +++ b/assets/css/app.scss @@ -1,4 +1,15 @@ -// MBTA METRO +// MbtaMetro, including Tailwind. +// Since Dotcom doesn't use Tailwind's Preflight, but some components require +// it, we can include some of Preflight's styles here. +*, +::before, +::after { + border-color: theme('borderColor.DEFAULT', currentColor); /* 2 */ + border-style: solid; /* 2 */ + border-width: 0; /* 2 */ + box-sizing: border-box; /* 1 */ +} + @import '../../deps/mbta_metro/priv/static/assets/default.css'; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/lib/dotcom_web/components/live_components/trip_planner_form.ex b/lib/dotcom_web/components/live_components/trip_planner_form.ex index d92c5d1ac9..c47d6e8e74 100644 --- a/lib/dotcom_web/components/live_components/trip_planner_form.ex +++ b/lib/dotcom_web/components/live_components/trip_planner_form.ex @@ -9,7 +9,7 @@ defmodule DotcomWeb.Components.LiveComponents.TripPlannerForm do import MbtaMetro.Components.InputGroup import Phoenix.HTML.Form, only: [input_name: 2, input_value: 2, input_id: 2] - alias Dotcom.TripPlan.{InputForm, InputForm.Modes, OpenTripPlanner} + alias Dotcom.TripPlan.{InputForm, InputForm.Modes} @form_defaults %{ "datetime_type" => :now, @@ -186,8 +186,8 @@ defmodule DotcomWeb.Components.LiveComponents.TripPlannerForm do |> Ecto.Changeset.apply_action(:update) |> case do {:ok, data} -> - %{on_submit: on_submit} = socket.assigns - {:noreply, assign(socket, :plan, plan(data, on_submit))} + send(self(), {:updated_form, data}) + {:noreply, socket} {:error, changeset} -> form = @@ -197,11 +197,4 @@ defmodule DotcomWeb.Components.LiveComponents.TripPlannerForm do {:noreply, assign(socket, %{form: form})} end end - - defp plan(data, on_submit) do - _ = on_submit.(data) - result = OpenTripPlanner.plan(data) - _ = on_submit.(result) - result - end end diff --git a/lib/dotcom_web/live/trip_planner.ex b/lib/dotcom_web/live/trip_planner.ex index 5ce4f3ca36..53fad9473b 100644 --- a/lib/dotcom_web/live/trip_planner.ex +++ b/lib/dotcom_web/live/trip_planner.ex @@ -11,6 +11,7 @@ defmodule DotcomWeb.Live.TripPlanner do alias Dotcom.TripPlan.{InputForm.Modes, ItineraryGroups} import DotcomWeb.Components.TripPlanner.ItineraryGroup, only: [itinerary_group: 1] + import MbtaMetro.Components.{Feedback, Spinner} @form_id "trip-planner-form" @@ -20,8 +21,10 @@ defmodule DotcomWeb.Live.TripPlanner do socket |> assign(:form_name, @form_id) |> assign(:submitted_values, nil) - |> assign(:groups, nil) |> assign(:error, nil) + |> assign_async(:groups, fn -> + {:ok, %{groups: nil}} + end) {:ok, socket} end @@ -31,39 +34,39 @@ defmodule DotcomWeb.Live.TripPlanner do ~H"""

Trip Planner Preview

- <.live_component - module={TripPlannerForm} - id={@form_name} - form_name={@form_name} - on_submit={fn data -> send(self(), {:updated_form, data}) end} - /> -
-

- Planning trips from <%= @submitted_values.from.name %> - to <%= @submitted_values.to.name %> -
using <%= Modes.selected_modes(@submitted_values.modes) %>, - - <%= if @submitted_values.datetime_type == :arrive_by, do: "Arriving by", else: "Leaving" %> <%= @submitted_values.datetime - |> Timex.format!("{Mfull} {D}, {h12}:{m} {AM}") %> - -

-

- Found - - <%= Enum.count(@groups) %> <%= Inflex.inflect("way", Enum.count(@groups)) %> - - to go. -

+ <.live_component module={TripPlannerForm} id={@form_name} form_name={@form_name} /> +
+

<%= submission_summary(@submitted_values) %>

+

<%= time_summary(@submitted_values) %>

+ <.async_result :let={groups} assign={@groups}> + <:failed :let={{:error, reason}}> + <.feedback kind={:error}> + <%= Phoenix.Naming.humanize(reason) %> + + + <:loading> + <.spinner aria_label="Waiting for results" /> Waiting for results... + + <%= if groups do %> + <%= if Enum.count(groups) == 0 do %> + <.feedback kind={:warning}>No trips found. + <% else %> + <.feedback kind={:success}> + Found <%= Enum.count(groups) %> <%= Inflex.inflect("way", Enum.count(groups)) %> to go. + + <% end %> + <% end %> +
<%= inspect(@error) %>
-
- <%= for group <- @groups do %> - <.itinerary_group group={group} /> - <% end %> -
+ <.async_result :let={groups} assign={@groups}> +
+ <.itinerary_group :for={group <- groups} group={group} /> +
+
@@ -84,16 +87,22 @@ defmodule DotcomWeb.Live.TripPlanner do @impl true def handle_info({:updated_form, %Dotcom.TripPlan.InputForm{} = data}, socket) do - {:noreply, assign(socket, %{submitted_values: data, groups: nil})} - end + socket = + socket + |> assign(:submitted_values, data) + |> assign(:groups, nil) + |> assign_async(:groups, fn -> + case Dotcom.TripPlan.OpenTripPlanner.plan(data) do + {:ok, itineraries} -> + Process.sleep(1200) + {:ok, %{groups: ItineraryGroups.from_itineraries(itineraries)}} - def handle_info({:updated_form, {:ok, itineraries}}, socket) do - groups = ItineraryGroups.from_itineraries(itineraries) - {:noreply, assign(socket, %{error: nil, groups: groups})} - end + error -> + error + end + end) - def handle_info({:updated_form, {:error, error}}, socket) do - {:noreply, assign(socket, :error, error)} + {:noreply, socket} end def handle_info(_info, socket) do @@ -121,4 +130,15 @@ defmodule DotcomWeb.Live.TripPlanner do defp location_props(props) do Map.take(props, ["name", "latitude", "longitude"]) end + + defp submission_summary(%{from: %{name: from_name}, to: %{name: to_name}, modes: modes}) do + "Planning trips from #{from_name} to #{to_name} using #{Modes.selected_modes(modes)}" + end + + defp time_summary(%{datetime_type: datetime_type, datetime: datetime}) do + preamble = if datetime_type == :arrive_by, do: "Arriving by ", else: "Leaving at " + time_description = Timex.format!(datetime, "{h12}:{m}{am}") + date_description = Timex.format!(datetime, "{WDfull}, {Mfull} {D}") + preamble <> time_description <> " on " <> date_description + end end