Packages
phoenix_kit
1.4.9
1.7.210
1.7.209
1.7.208
1.7.207
1.7.206
1.7.205
1.7.204
1.7.203
1.7.202
1.7.201
1.7.200
1.7.199
1.7.198
1.7.197
1.7.196
1.7.194
1.7.193
1.7.192
1.7.191
1.7.190
1.7.189
1.7.187
1.7.186
1.7.185
1.7.184
1.7.183
1.7.182
1.7.181
1.7.180
1.7.179
1.7.178
1.7.177
1.7.176
1.7.175
1.7.174
1.7.173
1.7.172
1.7.171
1.7.170
1.7.169
1.7.168
1.7.167
1.7.166
1.7.165
1.7.164
1.7.162
1.7.161
1.7.160
1.7.159
1.7.157
1.7.156
1.7.155
1.7.154
1.7.153
1.7.152
1.7.151
1.7.150
1.7.149
1.7.146
1.7.145
1.7.144
1.7.143
1.7.138
1.7.133
1.7.132
1.7.131
1.7.130
1.7.128
1.7.126
1.7.125
1.7.121
1.7.120
1.7.119
1.7.118
1.7.117
1.7.116
1.7.115
1.7.114
1.7.113
1.7.112
1.7.111
1.7.110
1.7.109
1.7.108
1.7.107
1.7.106
1.7.105
1.7.104
1.7.103
1.7.102
1.7.101
1.7.100
1.7.99
1.7.98
1.7.97
1.7.96
1.7.95
1.7.94
1.7.93
1.7.92
1.7.91
1.7.90
1.7.89
1.7.88
1.7.87
1.7.86
1.7.85
1.7.84
1.7.83
1.7.82
1.7.81
1.7.80
1.7.79
1.7.78
1.7.77
1.7.76
1.7.75
1.7.74
1.7.71
1.7.70
1.7.69
1.7.66
1.7.65
1.7.64
1.7.63
1.7.62
1.7.61
1.7.59
1.7.58
1.7.57
1.7.56
1.7.55
1.7.54
1.7.53
1.7.52
1.7.51
1.7.49
1.7.44
1.7.43
1.7.42
1.7.41
1.7.39
1.7.38
1.7.37
1.7.36
1.7.34
1.7.33
1.7.31
1.7.30
1.7.29
1.7.28
1.7.27
1.7.26
1.7.25
1.7.24
1.7.23
1.7.22
1.7.21
1.7.20
1.7.19
1.7.18
1.7.17
1.7.16
1.7.15
1.7.14
1.7.13
1.7.12
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.6.20
1.6.19
1.6.18
1.6.17
1.6.16
1.6.15
1.6.14
1.6.13
1.6.12
1.6.11
1.6.10
1.6.9
1.6.8
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.5.2
1.5.1
1.5.0
1.4.9
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.2
1.3.1
1.3.0
1.2.10
1.2.9
1.2.8
1.2.7
1.2.5
1.2.4
1.2.2
1.2.1
1.2.0
1.1.0
1.0.0
A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more
Current section
Files
Jump to
Current section
Files
lib/phoenix_kit_web/live/modules/blogging/index.html.heex
<PhoenixKitWeb.Components.LayoutWrapper.app_layout
flash={@flash}
phoenix_kit_current_scope={assigns[:phoenix_kit_current_scope]}
page_title={@page_title}
current_path={@current_path}
project_title={@project_title}
current_locale={@current_locale}
>
<div class="container mx-auto px-4 py-6 space-y-8">
<div class="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<div class="space-y-2">
<p class="text-sm uppercase tracking-wide text-base-content/60">
{gettext("Blogging Module")}
</p>
<h1 class="text-3xl font-bold text-base-content">{gettext("Content Overview")}</h1>
<p class="text-base text-base-content/60 max-w-2xl">
{gettext(
"Monitor publishing activity, jump into blog workspaces, and guide your team toward new content opportunities."
)}
</p>
</div>
<div class="flex flex-wrap gap-3">
<.link
navigate={Routes.path("/admin/settings/blogging/new", locale: @current_locale)}
class="btn btn-primary btn-sm"
>
<.icon name="hero-plus-circle" class="w-4 h-4 mr-1" /> {gettext("Create Blog")}
</.link>
<.link
navigate={Routes.path("/admin/settings/blogging", locale: @current_locale)}
class="btn btn-outline btn-sm"
>
<.icon name="hero-cog-6-tooth" class="w-4 h-4 mr-1" /> {gettext("Manage Blogs")}
</.link>
</div>
</div>
<%= if @empty_state? do %>
<div class="card bg-base-100 border border-dashed border-base-300 shadow-sm">
<div class="card-body items-center text-center space-y-4">
<div class="rounded-full bg-base-200 p-3 text-primary">
<.icon name="hero-document-text" class="w-8 h-8" />
</div>
<h2 class="text-2xl font-semibold text-base-content">{gettext("No blogs yet")}</h2>
<p class="text-base text-base-content/70 max-w-xl">
{gettext(
"Blogs let you organize content into themed workspaces with their own publishing flows. Set up your first blog to start drafting posts."
)}
</p>
<div class="flex flex-wrap justify-center gap-3">
<.link
navigate={Routes.path("/admin/settings/blogging/new", locale: @current_locale)}
class="btn btn-primary btn-sm"
>
<.icon name="hero-plus-circle" class="w-4 h-4 mr-1" /> {gettext("Create Blog")}
</.link>
<.link
navigate={Routes.path("/admin/settings/blogging", locale: @current_locale)}
class="btn btn-outline btn-sm"
>
<.icon name="hero-information-circle" class="w-4 h-4 mr-1" /> {gettext("Learn More")}
</.link>
</div>
</div>
</div>
<% else %>
<div class="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
<div class="stat bg-base-100 shadow-sm rounded-lg border border-base-200">
<div class="stat-title text-sm text-base-content/70">{gettext("Total Blogs")}</div>
<div class="stat-value text-3xl text-base-content">
{@dashboard_summary.total_blogs}
</div>
</div>
<div class="stat bg-base-100 shadow-sm rounded-lg border border-base-200">
<div class="stat-title text-sm text-base-content/70">{gettext("Total Posts")}</div>
<div class="stat-value text-3xl text-base-content">
{@dashboard_summary.total_posts}
</div>
</div>
<div class="stat bg-base-100 shadow-sm rounded-lg border border-base-200">
<div class="stat-title text-sm text-base-content/70">{gettext("Published")}</div>
<div class="stat-value text-3xl text-base-content">
{@dashboard_summary.published_posts}
</div>
<div class="stat-desc text-xs text-base-content/60">
{gettext("Drafts: %{count}", count: @dashboard_summary.draft_posts)}
</div>
</div>
<div class="stat bg-base-100 shadow-sm rounded-lg border border-base-200">
<div class="stat-title text-sm text-base-content/70">{gettext("Archived Posts")}</div>
<div class="stat-value text-3xl text-base-content">
{@dashboard_summary.archived_posts}
</div>
</div>
</div>
<div class="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
<%= for insight <- @dashboard_insights do %>
<div class="card bg-base-100 shadow-sm border border-base-200 hover:border-primary/60 transition">
<div class="card-body space-y-4">
<div class="flex items-start justify-between gap-3">
<div class="space-y-2">
<h3 class="text-xl font-semibold text-base-content">{insight.name}</h3>
<p class="text-xs text-base-content/60">
{gettext("Slug")}: <code class="font-mono">{insight.slug}</code>
</p>
<%= if insight.last_published_at_text do %>
<p class="text-xs text-base-content/60">
{gettext("Last published")} {insight.last_published_at_text}
</p>
<% end %>
</div>
<span class={[
"badge badge-sm uppercase",
if(insight.mode == "slug", do: "badge-primary", else: "badge-ghost")
]}>
{insight.mode}
</span>
</div>
<div class="grid grid-cols-3 gap-3">
<div class="rounded-lg bg-base-200/60 px-3 py-2 text-center">
<p class="text-xs uppercase tracking-wide text-base-content/60">
{gettext("Posts")}
</p>
<p class="font-semibold text-base-content">{insight.posts_count}</p>
</div>
<div class="rounded-lg bg-success/10 px-3 py-2 text-center">
<p class="text-xs uppercase tracking-wide text-success">
{gettext("Published")}
</p>
<p class="font-semibold text-success">{insight.published_count}</p>
</div>
<div class="rounded-lg bg-warning/10 px-3 py-2 text-center">
<p class="text-xs uppercase tracking-wide text-warning">{gettext("Drafts")}</p>
<p class="font-semibold text-warning">{insight.draft_count}</p>
</div>
</div>
<%= if insight.languages != [] do %>
<div class="flex flex-wrap gap-2">
<span class="text-xs font-medium uppercase text-base-content/60">
{gettext("Languages")}:
</span>
<%= for language <- insight.languages do %>
<span class="badge badge-ghost badge-sm px-2 py-1">
{String.upcase(language)}
</span>
<% end %>
</div>
<% end %>
<div class="flex flex-wrap gap-3">
<.link
navigate={
Routes.path("/admin/blogging/#{insight.slug}", locale: @current_locale)
}
class="btn btn-outline btn-sm"
>
<.icon name="hero-arrow-top-right-on-square" class="w-4 h-4 mr-1" />
{gettext("Open Admin")}
</.link>
<.link
navigate={Routes.path("/admin/settings/blogging", locale: @current_locale)}
class="btn btn-ghost btn-sm"
>
<.icon name="hero-cog-6-tooth" class="w-4 h-4 mr-1" />
{gettext("Settings")}
</.link>
</div>
</div>
</div>
<% end %>
</div>
<% end %>
</div>
</PhoenixKitWeb.Components.LayoutWrapper.app_layout>