diff --git a/lib/dotcom/trip_plan/leg_to_segment_helper.ex b/lib/dotcom/trip_plan/leg_to_segment_helper.ex new file mode 100644 index 0000000000..0b6c6bbc0c --- /dev/null +++ b/lib/dotcom/trip_plan/leg_to_segment_helper.ex @@ -0,0 +1,42 @@ +defmodule Dotcom.TripPlan.LegToSegmentHelper do + @moduledoc """ + A simple algorithm to convert legs as returned by Open Trip Planner + into segments to be displayed by our trip planner tool. + """ + + alias Dotcom.TripPlan.{PersonalDetail, TransitDetail} + + def legs_to_segments(legs) do + legs + |> raw_convert_to_segments() + |> prepend_start_location() + |> append_end_location() + end + + defp raw_convert_to_segments(legs) do + Enum.map(legs, &to_segment/1) + end + + defp to_segment(%{mode: %PersonalDetail{}} = leg) do + {:walking_segment, leg} + end + + defp to_segment(%{mode: %TransitDetail{}} = leg) do + {:transit_segment, leg} + end + + defp prepend_start_location([{_, leg} | _] = segments) do + [ + {:location_segment, %{time: leg.start, place: leg.from}} + | segments + ] + end + + defp append_end_location([{_, leg} = last_segment]) do + [last_segment, {:location_segment, %{time: leg.stop, place: leg.to}}] + end + + defp append_end_location([first_segment | rest_of_segments]) do + [first_segment | append_end_location(rest_of_segments)] + end +end diff --git a/lib/dotcom_web/components/trip_planner/itinerary_detail.ex b/lib/dotcom_web/components/trip_planner/itinerary_detail.ex index bacab77c1a..ff7cd75721 100644 --- a/lib/dotcom_web/components/trip_planner/itinerary_detail.ex +++ b/lib/dotcom_web/components/trip_planner/itinerary_detail.ex @@ -10,7 +10,7 @@ defmodule DotcomWeb.Components.TripPlanner.ItineraryDetail do import DotcomWeb.Components.TripPlanner.TransitLeg, only: [transit_leg: 1] import DotcomWeb.Components.TripPlanner.WalkingLeg, only: [walking_leg: 1] - alias Dotcom.TripPlan.{PersonalDetail, TransitDetail} + alias Dotcom.TripPlan.LegToSegmentHelper def itinerary_detail( %{ @@ -77,27 +77,45 @@ defmodule DotcomWeb.Components.TripPlanner.ItineraryDetail do defp specific_itinerary_detail(assigns) do assigns = - assigns - |> assign(:start_place, List.first(assigns.itinerary.legs).from) - |> assign(:start_time, List.first(assigns.itinerary.legs).start) - |> assign(:end_place, List.last(assigns.itinerary.legs).to) - |> assign(:end_time, List.last(assigns.itinerary.legs).stop) + assign( + assigns, + :segments, + LegToSegmentHelper.legs_to_segments(assigns.itinerary.legs) + ) ~H"""
- <.place place={@start_place} time={@start_time} /> -
- <%= if match?(%PersonalDetail{}, leg.mode) do %> - <.walking_leg leg={leg} /> - <% else %> - <.transit_leg leg={leg} /> - <% end %> +
+ <.segment segment={segment} />
- <.place place={@end_place} time={@end_time} />
""" end + + defp segment(%{segment: {:location_segment, %{time: time, place: place}}} = assigns) do + assigns = + assigns + |> assign(:time, time) + |> assign(:place, place) + + ~H""" + <.place place={@place} time={@time} /> + """ + end + + defp segment(%{segment: {:walking_segment, leg}} = assigns) do + assigns = assign(assigns, :leg, leg) + + ~H""" + <.walking_leg leg={@leg} /> + """ + end + + defp segment(%{segment: {:transit_segment, leg}} = assigns) do + assigns = assign(assigns, :leg, leg) + + ~H""" + <.transit_leg leg={@leg} /> + """ + end end diff --git a/lib/dotcom_web/components/trip_planner/transit_leg.ex b/lib/dotcom_web/components/trip_planner/transit_leg.ex index 044c2b2f91..4e6107288a 100644 --- a/lib/dotcom_web/components/trip_planner/transit_leg.ex +++ b/lib/dotcom_web/components/trip_planner/transit_leg.ex @@ -23,7 +23,7 @@ defmodule DotcomWeb.Components.TripPlanner.TransitLeg do def transit_leg(assigns) do ~H""" -
+
<.place place={@leg.from} time={@leg.start} diff --git a/test/dotcom/trip_plan/leg_to_segment_helper_test.exs b/test/dotcom/trip_plan/leg_to_segment_helper_test.exs new file mode 100644 index 0000000000..bef92dfd1f --- /dev/null +++ b/test/dotcom/trip_plan/leg_to_segment_helper_test.exs @@ -0,0 +1,23 @@ +defmodule Dotcom.TripPlan.LegToSegmentHelperTest do + @moduledoc false + + use ExUnit.Case, async: true + + alias Dotcom.TripPlan.LegToSegmentHelper + alias Dotcom.TripPlan.{Leg, PersonalDetail, TransitDetail} + + test "works for a typical walking-transit-walking itinerary and puts a location on either end" do + assert [ + {:location_segment, _}, + {:walking_segment, _}, + {:transit_segment, _}, + {:walking_segment, _}, + {:location_segment, _} + ] = + LegToSegmentHelper.legs_to_segments([ + %Leg{mode: %PersonalDetail{}}, + %Leg{mode: %TransitDetail{}}, + %Leg{mode: %PersonalDetail{}} + ]) + end +end