Packages

Social posts module for PhoenixKit — user posts, threaded comments, tags, boards, likes/dislikes, media, mentions, and scheduling

Current section

Files

Jump to
phoenix_kit_posts lib phoenix_kit_posts web details.html.heex
Raw

lib/phoenix_kit_posts/web/details.html.heex

<div class="container flex flex-col mx-auto px-4 py-6">
<%!-- Header Section --%>
<.admin_page_header back={Routes.path("/admin/posts")}>
<:actions>
<%= if can_edit_post?(@current_user, @post) do %>
<.link
href={Routes.path("/admin/posts/#{@post.uuid}/edit")}
class="btn btn-outline btn-sm"
>
<.icon name="hero-pencil" class="w-4 h-4" /> Edit
</.link>
<button
phx-click="change_status"
phx-value-status="draft"
class="btn btn-ghost btn-sm"
title="Move to Draft"
>
<.icon name="hero-pause" class="w-4 h-4" />
</button>
<button
phx-click="change_status"
phx-value-status="public"
class="btn btn-ghost btn-sm"
title="Publish"
>
<.icon name="hero-play" class="w-4 h-4" />
</button>
<button
phx-click="change_status"
phx-value-status="unlisted"
class="btn btn-ghost btn-sm"
title="Make Unlisted"
>
<.icon name="hero-eye-slash" class="w-4 h-4" />
</button>
<button
phx-click="delete_post"
data-confirm="Are you sure you want to delete this post?"
class="btn btn-ghost btn-sm text-error"
title="Delete Post"
>
<.icon name="hero-trash" class="w-4 h-4" />
</button>
<% end %>
</:actions>
</.admin_page_header>
<%!-- Main Content --%>
<div class="max-w-4xl mx-auto space-y-6">
<%!-- Post Card --%>
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<%!-- Post Header --%>
<div class="flex items-start justify-between mb-4">
<div class="flex-1">
<%!-- Post Type Badge --%>
<div class="mb-2">
<span class={format_type_badge_class(@post.type)}>
{format_post_type(@post.type)}
</span>
<span class={format_status_badge_class(@post.status)}>
{format_status(@post.status)}
</span>
</div>
<%!-- Title --%>
<h1 class="text-2xl sm:text-4xl font-bold text-base-content mb-2">
{@post.title}
</h1>
<%!-- Subtitle --%>
<%= if @post.sub_title do %>
<p class="text-xl text-base-content/70 mb-4">
{@post.sub_title}
</p>
<% end %>
<%!-- Author & Date --%>
<div class="flex items-center gap-4 text-sm text-base-content/60">
<div class="flex items-center gap-2">
<.icon name="hero-user-circle" class="w-5 h-5" />
<span>
<%= if @post.user do %>
{@post.user.email}
<% else %>
Unknown
<% end %>
</span>
</div>
<div class="flex items-center gap-2">
<.icon name="hero-clock" class="w-5 h-5" />
<span>
{Calendar.strftime(@post.inserted_at, "%B %d, %Y at %I:%M %p")}
</span>
</div>
</div>
</div>
</div>
<%!-- Stats --%>
<div class="flex gap-6 my-4 text-sm">
<%= if @show_view_count do %>
<div class="flex items-center gap-2">
<.icon name="hero-eye" class="w-5 h-5 text-base-content/60" />
<span class="font-semibold">{@post.view_count}</span>
<span class="text-base-content/60">views</span>
</div>
<% end %>
<%= if @likes_enabled do %>
<div class="flex items-center gap-2">
<.icon name="hero-heart" class="w-5 h-5 text-base-content/60" />
<span class="font-semibold">{@post.like_count}</span>
<span class="text-base-content/60">likes</span>
</div>
<% end %>
<%= if @comments_enabled do %>
<div class="flex items-center gap-2">
<.icon name="hero-chat-bubble-left" class="w-5 h-5 text-base-content/60" />
<span class="font-semibold">{@post.comment_count}</span>
<span class="text-base-content/60">comments</span>
</div>
<% end %>
</div>
<div class="divider"></div>
<%!-- Featured Image (if any) --%>
<% featured_image = Enum.find(@post.media || [], fn m -> m.position == 1 end) %>
<%= if featured_image do %>
<div class="mb-6">
<img
src={
PhoenixKit.Modules.Storage.URLSigner.signed_url(
featured_image.file_uuid,
"original"
)
}
alt={featured_image.file && featured_image.file.original_file_name}
class="w-full rounded-lg object-cover max-h-96"
/>
</div>
<% end %>
<%!-- Content (Markdown Rendered) --%>
<.markdown_content content={@rendered_content} />
<%!-- Media Gallery (if any) --%>
<% gallery_media = Enum.filter(@post.media || [], fn m -> m.position != 1 end) %>
<%= if length(gallery_media) > 0 do %>
<div class="divider"></div>
<div class="grid grid-cols-2 md:grid-cols-3 gap-4">
<%= for media <- gallery_media do %>
<div class="aspect-square rounded-lg overflow-hidden">
<img
src={
PhoenixKit.Modules.Storage.URLSigner.signed_url(media.file_uuid, "original")
}
alt={media.file && media.file.original_file_name}
class="w-full h-full object-cover"
/>
</div>
<% end %>
</div>
<% end %>
<%!-- Tags --%>
<%= if @post.tags && length(@post.tags) > 0 do %>
<div class="divider"></div>
<div class="flex flex-wrap gap-2">
<%= for tag <- @post.tags do %>
<div class="badge badge-outline badge-lg h-auto">
#{tag.name}
</div>
<% end %>
</div>
<% end %>
<%!-- Groups --%>
<%= if @post.groups && length(@post.groups) > 0 do %>
<div class="divider"></div>
<div class="space-y-2">
<h3 class="font-semibold text-base-content/70">Collections:</h3>
<div class="flex flex-wrap gap-2">
<%= for group <- @post.groups do %>
<div class="badge badge-secondary badge-lg h-auto">
<.icon name="hero-folder" class="w-4 h-4 mr-1" />
{group.name}
</div>
<% end %>
</div>
</div>
<% end %>
<%!-- Like Button --%>
<%= if @likes_enabled do %>
<div class="divider"></div>
<div class="flex justify-center">
<button
phx-click="like_post"
class={[
"btn gap-2",
if(@liked_by_user, do: "btn-error", else: "btn-outline")
]}
>
<.icon
name={if @liked_by_user, do: "hero-heart-solid", else: "hero-heart"}
class="w-5 h-5"
/>
{if @liked_by_user, do: "Unlike", else: "Like"}
</button>
</div>
<% end %>
</div>
</div>
<%!-- Comments Section (via standalone CommentsComponent) --%>
<%= if @comments_enabled do %>
<.live_component
module={PhoenixKitComments.Web.CommentsComponent}
id={"post-comments-#{@post.uuid}"}
resource_type="post"
resource_uuid={@post.uuid}
current_user={@current_user}
/>
<% end %>
</div>
</div>