51 lines
1.4 KiB
Elixir
51 lines
1.4 KiB
Elixir
|
|
defmodule BerrypodWeb.Components.SeoChecklist do
|
||
|
|
@moduledoc """
|
||
|
|
SEO checklist component showing focus keyword analysis results.
|
||
|
|
|
||
|
|
Displays a score and list of checks with pass/fail/warning status.
|
||
|
|
"""
|
||
|
|
|
||
|
|
use Phoenix.Component
|
||
|
|
|
||
|
|
import BerrypodWeb.CoreComponents, only: [icon: 1]
|
||
|
|
|
||
|
|
alias Berrypod.SEO.Analyser
|
||
|
|
|
||
|
|
@doc """
|
||
|
|
Renders the SEO checklist with score and checks.
|
||
|
|
"""
|
||
|
|
attr :page, :map, required: true
|
||
|
|
|
||
|
|
def seo_checklist(assigns) do
|
||
|
|
checks = Analyser.analyse(assigns.page)
|
||
|
|
score = Analyser.score(checks)
|
||
|
|
level = Analyser.score_level(score)
|
||
|
|
|
||
|
|
assigns =
|
||
|
|
assigns
|
||
|
|
|> assign(:checks, checks)
|
||
|
|
|> assign(:score, score)
|
||
|
|
|> assign(:level, level)
|
||
|
|
|
||
|
|
~H"""
|
||
|
|
<div class="seo-checklist">
|
||
|
|
<div class="seo-score" data-level={@level}>
|
||
|
|
<span class="seo-score-value">{@score}%</span>
|
||
|
|
<span class="seo-score-label">SEO score</span>
|
||
|
|
</div>
|
||
|
|
<ul class="seo-checks">
|
||
|
|
<li :for={check <- @checks} class="seo-check" data-status={check.status}>
|
||
|
|
<.icon name={status_icon(check.status)} class="size-4 seo-check-icon" />
|
||
|
|
<span class="seo-check-label">{check.label}</span>
|
||
|
|
<span class="seo-check-hint">{check.message}</span>
|
||
|
|
</li>
|
||
|
|
</ul>
|
||
|
|
</div>
|
||
|
|
"""
|
||
|
|
end
|
||
|
|
|
||
|
|
defp status_icon(:pass), do: "hero-check-circle"
|
||
|
|
defp status_icon(:fail), do: "hero-x-circle"
|
||
|
|
defp status_icon(:warning), do: "hero-exclamation-triangle"
|
||
|
|
end
|