Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Convert itinerary legs to segments for easier rendering #2262

Merged
merged 10 commits into from
Dec 11, 2024
1 change: 1 addition & 0 deletions lib/dotcom/trip_plan/input_form.ex
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ defmodule Dotcom.TripPlan.InputForm do
date: PlanParams.to_date_param(datetime),
time: PlanParams.to_time_param(datetime),
transportModes: __MODULE__.Modes.selected_mode_keys(modes) |> PlanParams.to_modes_param(),
numItineraries: 40,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kinda wanna let this slide, but 40 seems kinda excessive?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh oops - didn't mean to include this change. I've been using that to get more itineraries so that the one I'm looking for is more likely to actually show up.

wheelchair: wheelchair
}
|> PlanParams.new()
Expand Down
51 changes: 34 additions & 17 deletions lib/dotcom_web/components/trip_planner/itinerary_detail.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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 DotcomWeb.Components.TripPlanner.LegToSegmentHelper

def itinerary_detail(
%{
Expand Down Expand Up @@ -77,27 +77,44 @@ 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"""
<div class="mt-4">
<.place place={@start_place} time={@start_time} />
<div
:for={leg <- @itinerary.legs}
class={"#{if(match?(%TransitDetail{}, leg.mode), do: "bg-gray-bordered-background")}"}
>
<%= if match?(%PersonalDetail{}, leg.mode) do %>
<.walking_leg leg={leg} />
<% else %>
<.transit_leg leg={leg} />
<% end %>
<div :for={segment <- @segments}>
<.segment segment={segment} />
</div>
<.place place={@end_place} time={@end_time} />
</div>
"""
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
37 changes: 37 additions & 0 deletions lib/dotcom_web/components/trip_planner/leg_to_segment_helper.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
defmodule DotcomWeb.Components.TripPlanner.LegToSegmentHelper do
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sold on either this name or this location for this file, but I couldn't think of a better one off the top of my head.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since it's not technically a rendered component, you can move this to the Dotcom.TripPlan. namespace. I don't mind the current name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💥 5caf9b7 💥

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_leg]) do
[last_leg, {:location_segment, %{time: leg.stop, place: leg.to}}]
end

defp append_end_location([first_leg | rest_of_legs]) do
[first_leg | append_end_location(rest_of_legs)]
end
end
2 changes: 1 addition & 1 deletion lib/dotcom_web/components/trip_planner/transit_leg.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ defmodule DotcomWeb.Components.TripPlanner.TransitLeg do

def transit_leg(assigns) do
~H"""
<div>
<div class="bg-gray-bordered-background">
<.place
place={@leg.from}
time={@leg.start}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
defmodule DotcomWeb.Components.TripPlanner.LegToSegmentHelperTest do
@moduledoc false

use ExUnit.Case, async: true

alias Dotcom.TripPlan.{Leg, PersonalDetail, TransitDetail}
alias DotcomWeb.Components.TripPlanner.LegToSegmentHelper

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
Loading