defmodule Sayfa.Blocks.RecentPosts do
@moduledoc """
Recent posts block.
Renders a chronological list of the most recent posts with date and title.
## Assigns
- `:contents` — list of all site contents (injected by block helper)
- `:limit` — number of posts to show (default: 5)
- `:show_view_all` — whether to show "View all" link (default: false)
## Examples
<%= @block.(:recent_posts, limit: 3) %>
<%= @block.(:recent_posts, limit: 5, show_view_all: true) %>
"""
@behaviour Sayfa.Behaviours.Block
alias Sayfa.Block
alias Sayfa.Content
alias Sayfa.I18n
@impl true
def name, do: :recent_posts
@impl true
def render(assigns) do
contents = Map.get(assigns, :contents, [])
limit = Map.get(assigns, :limit, 5)
show_view_all = Map.get(assigns, :show_view_all, false)
t = Map.get(assigns, :t, I18n.default_translate_function())
lang = Map.get(assigns, :lang)
site = Map.get(assigns, :site, %{})
contents = filter_by_lang(contents, lang)
lang_prefix = lang_prefix_path(lang, site)
posts =
contents
|> Content.all_of_type("posts")
|> Content.recent(limit)
if posts == [] do
""
else
items = Enum.map_join(posts, "\n", &render_post_item(&1, lang, site))
view_all_html =
if show_view_all do
"#{Block.escape_html(t.("view_all"))} "
else
""
end
"""
\
\
#{Block.escape_html(t.("recent_posts"))}
\
#{view_all_html}\
\
\
#{items}\
\
\
"""
end
end
defp render_post_item(post, lang, site) do
url = Content.url(post)
title = Block.escape_html(post.title)
date_html =
if post.date do
""
else
""
end
"""
\
#{date_html}\
#{title}\
\
"""
end
defp filter_by_lang(contents, nil), do: contents
defp filter_by_lang(contents, lang) do
Enum.filter(contents, &(&1.lang == lang))
end
defp lang_prefix_path(nil, _site), do: ""
defp lang_prefix_path(lang, site) do
case I18n.language_prefix(lang, site) do
"" -> ""
prefix -> "/#{prefix}"
end
end
end