defmodule SlaxWeb.ChatRoomLive do @moduledoc false use SlaxWeb, :live_view alias Slax.Chat alias Slax.Chat.Message alias Slax.Chat.Room @impl Phoenix.LiveView def render(assigns) do ~H"""

Slax

Rooms
<.room_link :for={room <- @rooms} room={room} active={room.id == @room.id} />

#<%= @room.name %> <.link class="font-normal text-xs text-blue-600 hover:text-blue-700" navigate={~p"/rooms/#{@room}/edit"} > Edit

<%= if @hide_topic? do %> [Topic hidden] <% else %> <%= @room.topic %> <% end %>
<.message :for={{dom_id, message} <- @streams.messages} dom_id={dom_id} message={message} timezone={@timezone} />
<.form id="new-message-form" for={@new_message_form} phx-change="validate-message" phx-submit="submit-message" class="flex items-center border-2 border-slate-300 rounded-sm p-1" >
""" end @impl Phoenix.LiveView def mount(_params, _session, socket) do rooms = Chat.list_rooms() timezone = get_connect_params(socket)["timezone"] {:ok, assign(socket, hide_topic?: false, rooms: rooms, timezone: timezone)} end @impl Phoenix.LiveView def handle_params(params, _session, socket) do room = case Map.fetch(params, "id") do {:ok, id} -> Chat.get_room!(id) :error -> Chat.get_first_room!() end messages = Chat.list_messages_in_room(room) {:noreply, socket |> assign(hide_topic?: false, page_title: "# #{room.name}", room: room) |> stream(:messages, messages, reset: true) |> assign_message_form(Chat.change_message(%Message{}))} end @impl Phoenix.LiveView def handle_event("toggle-topic", _params, socket) do {:noreply, update(socket, :hide_topic?, &(!&1))} end @impl Phoenix.LiveView def handle_event("validate-message", %{"message" => message_params}, socket) do changeset = Chat.change_message(%Message{}, message_params) {:noreply, assign_message_form(socket, changeset)} end @impl Phoenix.LiveView def handle_event("submit-message", %{"message" => message_params}, socket) do %{current_user: user, room: room} = socket.assigns socket = case Chat.create_message(room, user, message_params) do {:ok, message} -> socket |> stream_insert(:messages, message) |> assign_message_form(Chat.change_message(%Message{})) {:error, changeset} -> assign_message_form(socket, changeset) end {:noreply, socket} end attr :active, :boolean, required: true attr :room, Room, required: true @spec room_link(Phoenix.LiveView.Socket.assigns()) :: Phoenix.LiveView.Rendered.t() defp room_link(assigns) do ~H""" <.link class={[ "flex items-center h-8 text-sm pl-8 pr-3", (@active && "bg-slate-300") || "hover:bg-slate-300" ]} patch={~p"/rooms/#{@room}"} > <.icon name="hero-hashtag" class="h-4 w-4" /> <%= @room.name %> """ end attr :dom_id, :string, required: true attr :message, Message, required: true attr :timezone, :string, required: true defp message(assigns) do ~H"""
<.link class="text-sm font-semibold hover:underline"> <%= username(@message.user) %> <%= message_timestamp(@message, @timezone) %>

<%= @message.body %>

""" end defp username(user) do user.email |> String.split("@") |> List.first() |> String.capitalize() end defp message_timestamp(message, timezone) do message.inserted_at |> Timex.Timezone.convert(timezone) |> Timex.format!("%-l:%M %p", :strftime) end defp assign_message_form(socket, changeset) do assign(socket, :new_message_form, to_form(changeset)) end end