How to implement a grouped timeline?

Hi,

I want to implement something like this (grouped timeline):

I have a loop in EEX template:

<%= for event <- @events do %>
<%= today = event.date %>
<%= for event <- @events do %>
            <%= if event.date == today do %>
            <%= event.title %>
<% end %>
<% end %>

It seems to work beside duplicates…

Monday

  • event 1
  • event 2
  • event 3

Monday (duplicate)

  • event 1
  • event 2
  • event 3

Monday (duplicate)

  • event 1
  • event 2
  • event 3

Tuesday

  • event 4

Friday

  • event 5
  • event 6

Friday (duplicate)

  • event 5
  • event 6

how to check if date was already used to skip duplicates?

2 Likes

Resolved.

I added another query for distinct dates.

2 Likes

To recreate the Tailwind on the linked page, you want an inner and outer list. Take a look at Enum.chunk_by/2 in the documentation.

I’d probably do additional processing with a separate reducer function (rather than chunk it within the reducer using something like Map.get_and_update/3)

events = [
    %{date: "Monday", task: "Feed cat"},
    %{date: "Tuesday", task: "Pay bills"},
    %{date: "Monday", task: "Grocery Shopping"}
]

events
|> Enum.sort_by(& &1.date)
|> Enum.chunk_by(& &1.date)
|> Enum.reduce(%{}, fn [sample | _] = day_events, acc -> Map.put(acc, sample.date, day_events) end)
|> Map.to_list()

The result is a list of lists:

[
  {"Monday",
    [
      %{date: "Monday", task: "Feed cat"},
      %{date: "Monday", task: "Grocery Shopping"}
    ]
  },
  {"Tuesday",
    [
      %{date: "Tuesday", task: "Pay bills"}
    ]
  }
]

The you iterate over the outer list adding the div tags to display the date; within that <div> you iterate over the inner lists adding your <li> tags within <ol> tags to display the events for each date.