Skip to content

Commit

Permalink
feat(trip_planner): Use <.itinerary_summary /> in the details panel (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
joshlarson authored Nov 26, 2024
1 parent ac6d8ed commit f0bee0f
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 104 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ defmodule DotcomWeb.Components.LiveComponents.TripPlannerResultsSection do

use DotcomWeb, :live_component

import DotcomWeb.Components.TripPlanner.ItineraryDetail
import DotcomWeb.Components.TripPlanner.{ItineraryDetail, ItinerarySummary}
import DotcomWeb.Components.TripPlanner.ItineraryGroup, only: [itinerary_group: 1]

@impl true
Expand Down Expand Up @@ -54,8 +54,12 @@ defmodule DotcomWeb.Components.LiveComponents.TripPlannerResultsSection do
end

defp itinerary_panel(%{results: results, details_index: details_index} = assigns) do
result = results |> Enum.at(details_index)

assigns =
assign(assigns, :itineraries, results |> Enum.at(details_index) |> Map.get(:itineraries))
assigns
|> assign(:itineraries, result |> Map.get(:itineraries))
|> assign(:summary, result |> Map.get(:summary))

~H"""
<div class="mt-30">
Expand All @@ -71,6 +75,11 @@ defmodule DotcomWeb.Components.LiveComponents.TripPlannerResultsSection do
<span class="font-medium">View All Options</span>
</p>
</button>
<div class="border-b-[1px] border-gray-lighter">
<.itinerary_summary summary={@summary} />
</div>
<.itinerary_detail :for={itinerary <- @itineraries} itinerary={itinerary} />
</div>
"""
Expand Down
105 changes: 3 additions & 102 deletions lib/dotcom_web/components/trip_planner/itinerary_group.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ defmodule DotcomWeb.Components.TripPlanner.ItineraryGroup do
"""
use DotcomWeb, :component

import DotcomWeb.Components.TripPlanner.ItinerarySummary

attr(:summary, :map, doc: "ItineraryGroups.summary()", required: true)
attr(:itineraries, :list, doc: "List of %Dotcom.TripPlan.Itinerary{}", required: true)

Expand All @@ -30,37 +32,7 @@ defmodule DotcomWeb.Components.TripPlanner.ItineraryGroup do
>
<%= @summary.tag %>
</div>
<div class="flex flex-row mb-3 font-bold text-lg justify-between">
<div>
<%= format_datetime_full(@summary.first_start) %> - <%= format_datetime_full(
@summary.first_stop
) %>
</div>
<div>
<%= @summary.duration %> min
</div>
</div>
<div class="flex flex-wrap gap-1 items-center content-center mb-3">
<%= for {summary_leg, index} <- Enum.with_index(@summary.summarized_legs) do %>
<.icon :if={index > 0} name="angle-right" class="font-black w-2" />
<.leg_icon {summary_leg} />
<% end %>
</div>
<div class="flex flex-wrap gap-1 items-center mb-3 text-sm text-grey-dark">
<div :if={@summary.accessible?} class="inline-flex items-center gap-0.5">
<.icon type="icon-svg" name="icon-accessible-small" class="h-3 w-3 mr-0.5" /> Accessible
<.icon name="circle" class="h-0.5 w-0.5 mx-1" />
</div>
<div class="inline-flex items-center gap-0.5">
<.icon name="person-walking" class="h-3 w-3" />
<%= @summary.walk_distance %> mi
</div>
<div :if={@summary.total_cost > 0} class="inline-flex items-center gap-0.5">
<.icon name="circle" class="h-0.5 w-0.5 mx-1" />
<.icon name="wallet" class="h-3 w-3" />
<%= Fares.Format.price(@summary.total_cost) %>
</div>
</div>
<.itinerary_summary summary={@summary} />
<div class="flex justify-end items-center">
<div :if={Enum.count(@summary.next_starts) > 0} class="grow text-sm text-grey-dark">
Similar trips depart at <%= Enum.map(@summary.next_starts, &format_datetime_short/1)
Expand All @@ -83,77 +55,6 @@ defmodule DotcomWeb.Components.TripPlanner.ItineraryGroup do
attr(:routes, :list, required: true, doc: "List of %Routes.Route{}")
attr(:walk_minutes, :integer, required: true)

# No routes
defp leg_icon(%{routes: [], walk_minutes: _} = assigns) do
~H"""
<span class={[
"flex items-center gap-1 text-sm font-semibold leading-none whitespace-nowrap py-1 px-2 rounded-full border border-solid border-gray-light",
@class
]}>
<.icon name="person-walking" class="h-4 w-4" />
<span><%= @walk_minutes %> min</span>
</span>
"""
end

# Group of commuter rail routes are summarized to one symbol.
defp leg_icon(%{routes: [%Routes.Route{type: 2} | _]} = assigns) do
~H"""
<.route_symbol route={List.first(@routes)} class={@class} />
"""
end

# No grouping when there's only one route!
defp leg_icon(%{routes: [%Routes.Route{}]} = assigns) do
~H"""
<.route_symbol route={List.first(@routes)} {assigns} />
"""
end

defp leg_icon(
%{routes: [%Routes.Route{type: type, external_agency_name: agency} | _]} = assigns
) do
slashed? = type == 3 && is_nil(agency)

assigns =
assigns
|> assign(:slashed?, slashed?)
|> assign(
:grouped_classes,
if(slashed?,
do: "[&:not(:first-child)]:rounded-l-none [&:not(:last-child)]:rounded-r-none",
else: "rounded-full ring-white ring-2"
)
)

~H"""
<div class="flex items-center -space-x-0.5">
<%= for {route, index} <- Enum.with_index(@routes) do %>
<.route_symbol route={route} class={"#{@grouped_classes} #{zindex(index)} #{@class}"} />
<%= if @slashed? and index < Kernel.length(@routes) - 1 do %>
<div class={"bg-white -mt-0.5 w-1 h-7 #{zindex(index)} transform rotate-[17deg]"}></div>
<% end %>
<% end %>
</div>
"""
end

defp leg_icon(assigns) do
inspect(assigns) |> Sentry.capture_message(tags: %{feature: "Trip Planner"})

~H"""
<span></span>
"""
end

defp zindex(index) do
"z-#{50 - index * 10}"
end

defp format_datetime_full(datetime) do
Timex.format!(datetime, "%-I:%M %p", :strftime)
end

defp format_datetime_short(datetime) do
Timex.format!(datetime, "%-I:%M", :strftime)
end
Expand Down
121 changes: 121 additions & 0 deletions lib/dotcom_web/components/trip_planner/itinerary_summary.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
defmodule DotcomWeb.Components.TripPlanner.ItinerarySummary do
@moduledoc """
A component that renders the summary for a given itinerary
"""
use DotcomWeb, :component

attr :summary, :map, doc: "ItineraryGroups.summary()", required: true

def itinerary_summary(assigns) do
~H"""
<div>
<div class="flex flex-row mb-3 font-bold text-lg justify-between">
<div>
<%= format_datetime_full(@summary.first_start) %> - <%= format_datetime_full(
@summary.first_stop
) %>
</div>
<div>
<%= @summary.duration %> min
</div>
</div>
<div class="flex flex-wrap gap-1 items-center content-center mb-3">
<%= for {summary_leg, index} <- Enum.with_index(@summary.summarized_legs) do %>
<.icon :if={index > 0} name="angle-right" class="font-black w-2" />
<.leg_icon {summary_leg} />
<% end %>
</div>
<div class="flex flex-wrap gap-1 items-center mb-3 text-sm text-grey-dark">
<div :if={@summary.accessible?} class="inline-flex items-center gap-0.5">
<.icon type="icon-svg" name="icon-accessible-small" class="h-3 w-3 mr-0.5" /> Accessible
<.icon name="circle" class="h-0.5 w-0.5 mx-1" />
</div>
<div class="inline-flex items-center gap-0.5">
<.icon name="person-walking" class="h-3 w-3" />
<%= @summary.walk_distance %> mi
</div>
<div :if={@summary.total_cost > 0} class="inline-flex items-center gap-0.5">
<.icon name="circle" class="h-0.5 w-0.5 mx-1" />
<.icon name="wallet" class="h-3 w-3" />
<%= Fares.Format.price(@summary.total_cost) %>
</div>
</div>
</div>
"""
end

attr(:class, :string, default: "")
attr(:routes, :list, required: true, doc: "List of %Routes.Route{}")
attr(:walk_minutes, :integer, required: true)

# No routes
defp leg_icon(%{routes: [], walk_minutes: _} = assigns) do
~H"""
<span class={[
"flex items-center gap-1 text-sm font-semibold leading-none whitespace-nowrap py-1 px-2 rounded-full border border-solid border-gray-light",
@class
]}>
<.icon name="person-walking" class="h-4 w-4" />
<span><%= @walk_minutes %> min</span>
</span>
"""
end

# Group of commuter rail routes are summarized to one symbol.
defp leg_icon(%{routes: [%Routes.Route{type: 2} | _]} = assigns) do
~H"""
<.route_symbol route={List.first(@routes)} class={@class} />
"""
end

# No grouping when there's only one route!
defp leg_icon(%{routes: [%Routes.Route{}]} = assigns) do
~H"""
<.route_symbol route={List.first(@routes)} {assigns} />
"""
end

defp leg_icon(
%{routes: [%Routes.Route{type: type, external_agency_name: agency} | _]} = assigns
) do
slashed? = type == 3 && is_nil(agency)

assigns =
assigns
|> assign(:slashed?, slashed?)
|> assign(
:grouped_classes,
if(slashed?,
do: "[&:not(:first-child)]:rounded-l-none [&:not(:last-child)]:rounded-r-none",
else: "rounded-full ring-white ring-2"
)
)

~H"""
<div class="flex items-center -space-x-0.5">
<%= for {route, index} <- Enum.with_index(@routes) do %>
<.route_symbol route={route} class={"#{@grouped_classes} #{zindex(index)} #{@class}"} />
<%= if @slashed? and index < Kernel.length(@routes) - 1 do %>
<div class={"bg-white -mt-0.5 w-1 h-7 #{zindex(index)} transform rotate-[17deg]"}></div>
<% end %>
<% end %>
</div>
"""
end

defp leg_icon(assigns) do
inspect(assigns) |> Sentry.capture_message(tags: %{feature: "Trip Planner"})

~H"""
<span></span>
"""
end

defp zindex(index) do
"z-#{50 - index * 10}"
end

defp format_datetime_full(datetime) do
Timex.format!(datetime, "%-I:%M %p", :strftime)
end
end

0 comments on commit f0bee0f

Please sign in to comment.