Downloads a ZIP with one CSV per report (overview, trend, pages, entry/exit pages, sources, referrers, countries, devices, funnel). Export button lives next to the period selector and picks up the current period and any active filters using a JS hook + JS.set_attribute, so the downloaded data always matches what's on screen. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -144,15 +144,30 @@ defmodule BerrypodWeb.Admin.Analytics do
|
||||
<.header>Analytics</.header>
|
||||
|
||||
<%!-- Period selector --%>
|
||||
<div class="analytics-periods" style="display: flex; gap: 0.25rem; margin-top: 1rem;">
|
||||
<div
|
||||
class="analytics-periods"
|
||||
style="display: flex; gap: 0.25rem; margin-top: 1rem; align-items: center;"
|
||||
>
|
||||
<button
|
||||
:for={period <- ["today", "7d", "30d", "12m"]}
|
||||
phx-click="change_period"
|
||||
phx-value-period={period}
|
||||
phx-click={
|
||||
JS.push("change_period", value: %{period: period})
|
||||
|> JS.set_attribute({"data-period", period}, to: "#analytics-export-link")
|
||||
}
|
||||
class={["admin-btn admin-btn-sm", @period == period && "admin-btn-primary"]}
|
||||
>
|
||||
{period_label(period)}
|
||||
</button>
|
||||
<a
|
||||
id="analytics-export-link"
|
||||
data-period={@period}
|
||||
href={export_url(@period, @filters)}
|
||||
class="admin-btn admin-btn-sm"
|
||||
style="margin-left: auto;"
|
||||
phx-hook="AnalyticsExport"
|
||||
>
|
||||
Export CSV
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<%!-- Active filters --%>
|
||||
@@ -308,7 +323,11 @@ defmodule BerrypodWeb.Admin.Analytics do
|
||||
assigns = assign(assigns, label: filter_label(assigns.dimension, assigns.value))
|
||||
|
||||
~H"""
|
||||
<span style="display: inline-flex; align-items: center; gap: 0.25rem; padding: 0.25rem 0.5rem; font-size: 0.75rem; background: var(--color-base-200, #e5e5e5); border-radius: 0.25rem;">
|
||||
<span
|
||||
data-filter-dimension={@dimension}
|
||||
data-filter-value={@value}
|
||||
style="display: inline-flex; align-items: center; gap: 0.25rem; padding: 0.25rem 0.5rem; font-size: 0.75rem; background: var(--color-base-200, #e5e5e5); border-radius: 0.25rem;"
|
||||
>
|
||||
{@label}
|
||||
<button
|
||||
phx-click="remove_filter"
|
||||
@@ -745,6 +764,15 @@ defmodule BerrypodWeb.Admin.Analytics do
|
||||
defp period_label("30d"), do: "30 days"
|
||||
defp period_label("12m"), do: "12 months"
|
||||
|
||||
defp export_url(period, filters) do
|
||||
params =
|
||||
Enum.reduce(filters, %{"period" => period}, fn {k, v}, acc ->
|
||||
Map.put(acc, "filter[#{k}]", v)
|
||||
end)
|
||||
|
||||
"/admin/analytics/export?" <> URI.encode_query(params)
|
||||
end
|
||||
|
||||
defp format_number(n) when n >= 1_000_000, do: "#{Float.round(n / 1_000_000, 1)}M"
|
||||
defp format_number(n) when n >= 1_000, do: "#{Float.round(n / 1_000, 1)}k"
|
||||
defp format_number(n), do: to_string(n)
|
||||
|
||||
Reference in New Issue
Block a user