Handling grouped_by LiveView Streams

Is there a way I can implement a live view stream for things that have been grouped_by? I was thinking no, and that I’d have to sort it during render but then I’m not sure how I would make sure I get the right?

I know this is wrong because the stream won’t update but what I’m doing is putting the stream in a component

<div phx-update="stream" id="event-streamer" >
  <.live_component
    module={ClimateCollectiveWeb.EventLive.EventListComponent}
    id="event-list"
    events={@streams.events}
    current_admin={@current_admin}
  />
</div>

The component is here:

def render(assigns) do
    assigns = assign_new(assigns, :current_admin, fn -> nil end)

    assigns =
      assign(assigns, :separated_events, Event.separate_event_stream_by_date(assigns.events))

    ~H"""
    <div>
      <div
        :for={{date, events} <- @separated_events}
        id={"events-wrapper-#{Date.to_string(date)}"}
        class="space-y-1"
      >
        <% multiple_months = @separated_events |> has_different_months?() %>
        <h2 :if={multiple_months} class="pl-2 text-lg font-bold bg-orange-50">
          <%= Calendar.strftime(date, "%b %d, %Y") %>
        </h2>
        <h2 :if={!multiple_months} class="pl-2 text-lg font-bold bg-orange-50">
          <%= Calendar.strftime(date, "%a, %d ") %>
        </h2>
        <% last_event = List.last(events) %>
        <div
          :for={{id, event} <- events}
          id={id}
          class="pb-4 pl-1 space-y-2"

        >
          <.live_component
            module={ClimateCollectiveWeb.EventLive.EventComponent}
            id={event.id}
            event={event}
            current_admin={@current_admin}
          />

          <hr :if={event != last_event} />
        </div>
      </div>
    </div>
    """
  end

How I group_by events is like this:

 def separate_event_stream_by_date(events) do
    Enum.group_by(events, fn {_id, event} -> DateTime.to_date(event.starts_at) end)
    |> Enum.sort_by(fn {date, _} -> date end, {:desc, Date})
    |> Enum.to_list()
  end

then when someone saves an event, the component send “saved” event to parent and receives it like this

  def handle_info({_, {:saved, event}}, socket) do
    {:noreply, stream_insert(socket, :events, event)}
  end

in the end, it just clears the stream and leaves this the one inserted. I’m sure it’s because of things being temporarily assigned, but I don’t know how to code my way around this using streams

Any ideas on how to make this work?

1 Like