From ae240e0cf828f6f20f4621515ac6135b8e95eac9 Mon Sep 17 00:00:00 2001 From: Anthony Shull Date: Wed, 13 Nov 2024 10:19:48 -0600 Subject: [PATCH] Take trip planner query params into account in the new trip planner (#2218) * run query params through an anti corruption layer * dont account for time selections * add handle change back in * docs * mix format * function doc * format * alias * submit the form if form values are present * rename function and add tests * rearrange assert * test a given false mode --- lib/dotcom/trip_plan/anti_corruption_layer.ex | 48 ++++++++++++ .../live_components/trip_planner_form.ex | 76 +++++++++++++------ lib/dotcom_web/live/trip_planner.ex | 16 ++-- .../trip_plan/anti_corruption_layer_test.exs | 50 ++++++++++++ 4 files changed, 162 insertions(+), 28 deletions(-) create mode 100644 lib/dotcom/trip_plan/anti_corruption_layer.ex create mode 100644 test/dotcom/trip_plan/anti_corruption_layer_test.exs diff --git a/lib/dotcom/trip_plan/anti_corruption_layer.ex b/lib/dotcom/trip_plan/anti_corruption_layer.ex new file mode 100644 index 0000000000..24fa84ebdc --- /dev/null +++ b/lib/dotcom/trip_plan/anti_corruption_layer.ex @@ -0,0 +1,48 @@ +defmodule Dotcom.TripPlan.AntiCorruptionLayer do + @moduledoc """ + This anti-corruption layer is responsible for converting the data from the old trip planner query params to the new trip planner form values. + + Currently, not all modes are sent. So, we default to setting them to 'false' if they aren't set. + Likewise with wheelchair, we default to 'false' if it isn't set because the old trip planner worked by just not setting it rather than setting it to 'false'. + + We ignore datetime_type and datetime and allow those to be set to 'now' and the current time respectively. + """ + + @doc """ + Given the params from the old trip planner, convert them to the new trip planner form values. + + If no plan is given, then we default to empty form values. + """ + def convert_old_params(%{"plan" => params}) do + %{ + "from" => %{ + "latitude" => Map.get(params, "from_latitude"), + "longitude" => Map.get(params, "from_longitude"), + "name" => Map.get(params, "from"), + "stop_id" => Map.get(params, "from_stop_id", "") + }, + "modes" => Map.get(params, "modes") |> convert_modes(), + "to" => %{ + "latitude" => Map.get(params, "to_latitude"), + "longitude" => Map.get(params, "to_longitude"), + "name" => Map.get(params, "to"), + "stop_id" => Map.get(params, "to_stop_id", "") + }, + "wheelchair" => Map.get(params, "wheelchair") || "false" + } + end + + def convert_old_params(_), do: convert_old_params(%{"plan" => %{}}) + + defp convert_modes(modes) when is_map(modes) do + default_modes = + for {k, _} <- Dotcom.TripPlan.InputForm.initial_modes(), into: %{}, do: {k, "false"} + + modes + |> Enum.reduce(default_modes, fn {key, value}, acc -> + Map.put(acc, String.upcase(key), value) + end) + end + + defp convert_modes(_), do: Dotcom.TripPlan.InputForm.initial_modes() +end 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 adcdf99f98..a02ef1b97b 100644 --- a/lib/dotcom_web/components/live_components/trip_planner_form.ex +++ b/lib/dotcom_web/components/live_components/trip_planner_form.ex @@ -13,12 +13,17 @@ defmodule DotcomWeb.Components.LiveComponents.TripPlannerForm do @impl true def mount(socket) do - form_defaults = %{ - "datetime_type" => "now", - "datetime" => Timex.now("America/New_York"), - "modes" => InputForm.initial_modes(), - "wheelchair" => true - } + {:ok, socket} + end + + @impl true + @doc """ + If form values are passed in, we merge them with the defaults and submit the form. + + Otherwise, we just render the form. + """ + def update(assigns, socket) do + form_defaults = get_form_defaults(assigns) defaults = %{ form: %InputForm{} |> InputForm.changeset(form_defaults) |> to_form(), @@ -26,7 +31,16 @@ defmodule DotcomWeb.Components.LiveComponents.TripPlannerForm do show_datepicker: false } - {:ok, assign(socket, defaults)} + new_socket = + socket + |> assign(assigns) + |> assign(defaults) + + if assigns[:form_values] do + save_form(form_defaults, new_socket) + end + + {:ok, new_socket} end @impl true @@ -177,22 +191,7 @@ defmodule DotcomWeb.Components.LiveComponents.TripPlannerForm do end def handle_event("save_form", %{"input_form" => params}, socket) do - params - |> InputForm.validate_params() - |> Ecto.Changeset.apply_action(:update) - |> case do - {:ok, data} -> - send(self(), {:updated_form, data}) - - {:noreply, socket} - - {:error, changeset} -> - form = - changeset - |> Phoenix.Component.to_form() - - {:noreply, assign(socket, %{form: form})} - end + {:noreply, save_form(params, socket)} end defp datepicker_config do @@ -204,6 +203,18 @@ defmodule DotcomWeb.Components.LiveComponents.TripPlannerForm do } end + defp get_form_defaults(assigns) do + assigns + |> Map.get(:form_values, %{ + "modes" => InputForm.initial_modes(), + "wheelchair" => true + }) + |> Map.merge(%{ + "datetime_type" => "now", + "datetime" => Timex.now("America/New_York") + }) + end + defp nearest_5_minutes do datetime = Timex.now("America/New_York") minutes = datetime.minute @@ -212,4 +223,23 @@ defmodule DotcomWeb.Components.LiveComponents.TripPlannerForm do Timex.shift(datetime, minutes: added_minutes) end + + defp save_form(params, socket) do + params + |> InputForm.validate_params() + |> Ecto.Changeset.apply_action(:update) + |> case do + {:ok, data} -> + send(self(), {:updated_form, data}) + + socket + + {:error, changeset} -> + form = + changeset + |> Phoenix.Component.to_form() + + assign(socket, %{form: form}) + end + end end diff --git a/lib/dotcom_web/live/trip_planner.ex b/lib/dotcom_web/live/trip_planner.ex index 98d525610d..3fbf53abcd 100644 --- a/lib/dotcom_web/live/trip_planner.ex +++ b/lib/dotcom_web/live/trip_planner.ex @@ -7,22 +7,23 @@ defmodule DotcomWeb.Live.TripPlanner do use DotcomWeb, :live_view - alias DotcomWeb.Components.LiveComponents.TripPlannerForm - alias Dotcom.TripPlan.{InputForm.Modes, ItineraryGroups} - import DotcomWeb.Components.TripPlanner.ItineraryGroup, only: [itinerary_group: 1] import MbtaMetro.Components.{Feedback, Spinner} + alias DotcomWeb.Components.LiveComponents.TripPlannerForm + alias Dotcom.TripPlan.{AntiCorruptionLayer, InputForm.Modes, ItineraryGroups} + @form_id "trip-planner-form" @map_config Application.compile_env!(:mbta_metro, :map) @impl true - def mount(_params, _session, socket) do + def mount(params, _session, socket) do socket = socket |> assign(:error, nil) |> assign(:form_name, @form_id) + |> assign(:form_values, AntiCorruptionLayer.convert_old_params(params)) |> assign(:map_config, @map_config) |> assign(:from, []) |> assign(:to, []) @@ -39,7 +40,12 @@ defmodule DotcomWeb.Live.TripPlanner do ~H"""

Trip Planner Preview

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

<%= submission_summary(@submitted_values) %>

<%= time_summary(@submitted_values) %>

diff --git a/test/dotcom/trip_plan/anti_corruption_layer_test.exs b/test/dotcom/trip_plan/anti_corruption_layer_test.exs new file mode 100644 index 0000000000..665620b910 --- /dev/null +++ b/test/dotcom/trip_plan/anti_corruption_layer_test.exs @@ -0,0 +1,50 @@ +defmodule Dotcom.TripPlan.AntiCorruptionLayerTest do + use ExUnit.Case + + import Dotcom.TripPlan.AntiCorruptionLayer, only: [convert_old_params: 1] + + describe "convert_old_params/1" do + test "returns all defaults when no params are given" do + assert convert_old_params(%{}) == convert_old_params(%{"plan" => %{}}) + end + + test "sets all modes to true when no modes are given" do + old_params = %{ + "plan" => %{} + } + + new_params = convert_old_params(old_params) + + assert new_params["modes"] == Dotcom.TripPlan.InputForm.initial_modes() + end + + test "sets given modes as given and all non-given as false" do + old_params = %{ + "plan" => %{ + "modes" => %{ + "bus" => "true", + "ferry" => "false", + "subway" => "true" + } + } + } + + new_params = convert_old_params(old_params) + + assert new_params["modes"]["BUS"] == "true" + assert new_params["modes"]["FERRY"] == "false" + assert new_params["modes"]["RAIL"] == "false" + assert new_params["modes"]["SUBWAY"] == "true" + end + + test "defaults to wheelchair false when no wheelchair is given" do + old_params = %{ + "plan" => %{} + } + + new_params = convert_old_params(old_params) + + assert new_params["wheelchair"] == "false" + end + end +end