defmodule GitGudWeb.UserLive.Profile do
use GitGudWeb, :live_view
alias GitGud.Accounts
alias GitGud.Profiles
alias GitGud.Repositories
@impl true
def mount(%{"handle" => handle}, _session, socket) do
case Accounts.get_user_by_handle(handle) do
nil ->
{:ok, socket |> put_flash(:error, "User not found.") |> push_navigate(to: ~p"/")}
user ->
viewer = viewer(socket)
repos = filter_visible(Repositories.list_repositories_for(user), user, viewer)
pins = Profiles.list_pins(user)
theme = socket.assigns[:editor_theme]
readme = Repositories.get_profile_readme(user, theme: theme)
{:ok,
socket
|> assign(:user, user)
|> assign(:repos, repos)
|> assign(:pins, pins)
|> assign(:readme, readme)
|> assign(:is_self?, viewer && viewer.id == user.id)
|> assign(:display_name, GitGud.Accounts.User.display(user))
|> assign(:page_title, "@#{user.handle}")}
end
end
defp viewer(socket), do: socket.assigns.current_scope && socket.assigns.current_scope.user
defp filter_visible(repos, owner, viewer) do
Enum.filter(repos, fn r ->
cond do
r.visibility in ["public", "internal"] -> true
viewer && viewer.id == owner.id -> true
true -> false
end
end)
end
@impl true
def render(assigns) do
~H"""
<Layouts.app flash={@flash} current_scope={@current_scope}>
<div class="grid grid-cols-1 md:grid-cols-[18rem_minmax(0,1fr)] gap-6">
<aside class="space-y-4">
<div class="flex flex-col items-center text-center gap-3 md:items-start md:text-left">
<.avatar name={@user.handle} size="2xl" alt={@user.handle} />
<div class="space-y-1 min-w-0">
<h1 class="text-2xl font-semibold">{@display_name}</h1>
<p class="text-sm font-mono opacity-60">@{@user.handle}</p>
</div>
<.link
:if={@is_self?}
navigate={~p"/users/settings"}
class="btn btn-sm btn-ghost border border-base-300"
>
<.icon name="hero-pencil" class="size-4" /> Edit profile
</.link>
</div>
<GitGudWeb.ProfileComponents.details profile={@user} />
</aside>
<main class="space-y-6 min-w-0">
<section :if={@pins != []}>
<h2 class="text-lg font-semibold mb-2">Pinned</h2>
<GitGudWeb.PinnedReposGrid.grid pins={@pins} />
</section>
<section :if={@readme}>
<header class="flex items-baseline justify-between mb-2">
<h2 class="text-lg font-semibold">README</h2>
<.link
:if={@is_self?}
navigate={~p"/r/#{@user.handle}/#{@user.handle}"}
class="text-xs link link-hover opacity-60"
>
Edit in {@user.handle}/{@user.handle} →
</.link>
</header>
<article class="prose max-w-none border border-base-300 rounded p-4">
{Phoenix.HTML.raw(elem(@readme, 1))}
</article>
</section>
<section>
<h2 class="text-lg font-semibold mb-2">Repositories</h2>
<ul class="divide-y divide-base-300">
<li class="hidden only:block py-3 opacity-60 text-sm">No public repositories.</li>
<li
:for={repo <- @repos}
class={["py-2", Repositories.profile_repo?(repo, @user.handle) && "opacity-50 italic"]}
>
<.link
navigate={~p"/r/#{@user.handle}/#{repo.name}"}
class="font-mono link link-hover"
>
{repo.name}
</.link>
<span
:if={Repositories.profile_repo?(repo, @user.handle)}
class="badge badge-xs badge-ghost ml-1 not-italic"
title="Powers your profile page"
>
profile
</span>
<p :if={repo.description} class="text-sm opacity-70">{repo.description}</p>
</li>
</ul>
</section>
</main>
</div>
</Layouts.app>
"""
end
end
4.2 KiB · text
5af55d9