Files
eminuxCRM/app/views/mailings/dashboard.html.erb
T
eminuxandCursor 353ace4d99
CI / scan_ruby (push) Failing after 12m32s
CI / scan_js (push) Successful in 13m28s
CI / lint (push) Failing after 13m58s
Permette di scegliere 12 ore, 24 ore o la settimana nello storico invii.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-07 13:00:09 +02:00

189 lines
9.6 KiB
ERB
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<% refresh = @active_mailings.any? %>
<%= turbo_frame_tag "mailings_dashboard_live", target: "_top", refresh: "morph" do %>
<%= tag.div class: "space-y-6", data: (refresh ? { controller: "auto-reload", auto_reload_interval_value: 10_000 } : {}) do %>
<div class="flex flex-wrap items-end justify-between gap-3">
<div>
<h1 class="text-xl font-semibold tracking-tight md:text-2xl">Invii email</h1>
<p class="mt-1 text-sm text-zinc-500">Stato delle campagne, prove e invii di massa scaglionati.</p>
</div>
<div class="flex w-full flex-wrap gap-2 sm:w-auto">
<%= link_to "Template", mail_templates_path, class: "#{btn_secondary} flex-1 sm:flex-none" %>
<% if current_user.admin? %>
<%= link_to "Account SMTP", mail_identities_path, class: "#{btn_secondary} flex-1 sm:flex-none" %>
<% end %>
<%= link_to "Nuovo invio", new_mailing_path, class: "#{btn_primary} flex-1 sm:flex-none" %>
</div>
</div>
<% if @mail_identities_count.zero? %>
<div class="rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-900 dark:border-amber-900 dark:bg-amber-950 dark:text-amber-100">
Manca un account mittente SMTP.
<% if current_user.admin? %>
<%= link_to "Configuralo qui", mail_identities_path, class: "font-medium underline" %>.
<% else %>
Chiedi a un amministratore di censirlo.
<% end %>
</div>
<% end %>
<div class="grid grid-cols-2 gap-3 md:grid-cols-3">
<div class="<%= card_class %> p-4">
<div class="text-xs uppercase tracking-wide text-zinc-500">In corso</div>
<div class="mt-1 text-2xl font-semibold tabular-nums"><%= @active_mailings.size %></div>
</div>
<div class="<%= card_class %> p-4">
<div class="text-xs uppercase tracking-wide text-zinc-500">Mail / ora</div>
<div class="mt-1 text-2xl font-semibold tabular-nums"><%= @hourly_throughput.sent %></div>
<div class="mt-1 text-xs text-zinc-500">
<%= @hourly_throughput.recent_sent %> ultimi 15 min
<% if @hourly_throughput.failed.positive? %>
· <%= @hourly_throughput.failed %> scodate in errore
<% end %>
</div>
</div>
<div class="<%= card_class %> p-4">
<div class="flex items-center justify-between gap-1">
<div class="text-xs uppercase tracking-wide text-zinc-500">Storico invio</div>
<div class="inline-flex items-center gap-1">
<% Mailings::HourlyThroughput::RANGES.each do |key, config| %>
<% if @hourly_throughput.range_key == key %>
<span class="rounded-md bg-zinc-900 px-1.5 py-0.5 text-[10px] font-medium leading-none text-white dark:bg-zinc-100 dark:text-zinc-900"><%= config[:short] %></span>
<% else %>
<%= link_to config[:short], dashboard_mailings_path(history: key), class: "rounded-md px-1.5 py-0.5 text-[10px] font-medium leading-none text-zinc-500 hover:bg-zinc-100 dark:text-zinc-400 dark:hover:bg-zinc-800" %>
<% end %>
<% end %>
</div>
</div>
<div class="mt-2 flex items-end gap-0.5" style="height: 2.5rem" role="img" aria-label="Invii confermati, <%= @hourly_throughput.range[:label] %>">
<% @hourly_throughput.history.each do |bucket| %>
<% pct = (bucket[:count].to_f / @hourly_throughput.history_max * 100).round %>
<div class="flex-1 rounded <%= bucket[:count].positive? ? "bg-emerald-500" : "bg-zinc-200 dark:bg-zinc-700" %>"
style="height: <%= bucket[:count].positive? ? [pct, 12].max : 8 %>%"
title="<%= bucket[:label] %>: <%= bucket[:count] %>"></div>
<% end %>
</div>
<div class="mt-1 text-xs text-zinc-500"><%= @hourly_throughput.history_total %> inviate · <%= @hourly_throughput.range[:label] %></div>
</div>
<div class="<%= card_class %> p-4">
<div class="text-xs uppercase tracking-wide text-zinc-500">In pausa (fascia)</div>
<div class="mt-1 text-2xl font-semibold tabular-nums"><%= @paused_mailings.size %></div>
</div>
<div class="<%= card_class %> p-4">
<div class="text-xs uppercase tracking-wide text-zinc-500">Completati oggi</div>
<div class="mt-1 text-2xl font-semibold tabular-nums"><%= @completed_today %></div>
</div>
<div class="<%= card_class %> p-4">
<div class="text-xs uppercase tracking-wide text-zinc-500">Errori aperti</div>
<div class="mt-1 text-2xl font-semibold tabular-nums"><%= @failed_open %></div>
</div>
</div>
<% if @active_mailings.any? %>
<section class="space-y-3">
<h2 class="text-lg font-semibold">Campagne in corso</h2>
<div class="grid gap-4 lg:grid-cols-2">
<% @active_mailings.each do |mailing| %>
<%= render "mailings/progress_card", mailing: mailing %>
<% end %>
</div>
<p class="text-xs text-zinc-500">Questa pagina si aggiorna da sola ogni 10 secondi mentre c’è un invio attivo.</p>
</section>
<% end %>
<div class="<%= card_class %>">
<% if @mailings.empty? %>
<p class="p-6 text-sm text-zinc-500">Nessun invio. Crea una bozza, fai una prova con dati manuali e poi autorizza linvio di massa.</p>
<% else %>
<div class="divide-y divide-zinc-100 dark:divide-zinc-800 md:hidden">
<% @mailings.each do |mailing| %>
<div class="p-4">
<%= link_to mailing, class: "block active:bg-zinc-50 dark:active:bg-zinc-800" do %>
<div class="flex items-start justify-between gap-3">
<div class="min-w-0">
<div class="font-semibold"><%= mailing.name %></div>
<div class="mt-0.5 text-xs text-zinc-500 break-anywhere"><%= mailing.mail_identity.from_email %></div>
</div>
<%= mailing_status_badge(mailing.status) %>
</div>
<div class="mt-3"><%= progress_bar(mailing.progress_percentage) %></div>
<div class="mt-2 text-xs text-zinc-500">
<%= mailing.sent_count %> inviate · <%= mailing.opened_count %> aperte · <%= mailing.pending_count %> in coda
<% if mailing.sending? && mailing.next_send_at.present? && mailing.next_send_at > Time.current %>
· Riparte <%= l(mailing.next_send_at, format: :short) %>
<% elsif mailing.paused? %>
· In pausa, si può riprendere
<% end %>
</div>
<% end %>
<% if mailing.draft? %>
<div class="mt-3">
<%= render "mailings/delete_draft_button", mailing: mailing, extra_class: "w-full" %>
</div>
<% end %>
</div>
<% end %>
</div>
<div class="hidden md:block">
<div class="<%= table_wrap_class %>">
<table class="<%= table_class %>">
<thead class="border-b border-zinc-100 bg-zinc-50 text-left text-xs font-medium uppercase tracking-wide text-zinc-500 dark:border-zinc-800 dark:bg-zinc-800 dark:text-zinc-400">
<tr>
<th class="px-4 py-3">Invio</th>
<th class="px-4 py-3">Avanzamento</th>
<th class="px-4 py-3">Stato</th>
<th class="px-4 py-3">Prossimo / creato</th>
<th class="px-4 py-3"><span class="sr-only">Azioni</span></th>
</tr>
</thead>
<tbody class="divide-y divide-zinc-100 dark:divide-zinc-800">
<% @mailings.each do |mailing| %>
<tr class="hover:bg-zinc-50 dark:hover:bg-zinc-800/80">
<td class="px-4 py-3">
<%= link_to mailing.name, mailing, class: "font-medium hover:underline" %>
<div class="text-xs text-zinc-500"><%= mailing.mail_identity.from_email %></div>
<% if mailing.ab_test? %>
<span class="mt-1 inline-flex gap-1"><%= ab_variant_badge("A") %><%= ab_variant_badge("B") %></span>
<% end %>
</td>
<td class="px-4 py-3 min-w-48">
<%= progress_bar(mailing.progress_percentage) %>
<div class="mt-1 text-xs text-zinc-500">
<%= mailing.sent_count %> inviate
· <%= mailing.opened_count %> aperte
· <%= mailing.pending_count %> in coda
<% if mailing.failed_count.positive? %>
· <span class="text-rose-700"><%= mailing.failed_count %> errori</span>
<% end %>
</div>
</td>
<td class="px-4 py-3">
<%= mailing_status_badge(mailing.status) %>
<% if mailing.draft? && mailing.tested? %>
<div class="mt-1 text-xs text-emerald-700 dark:text-emerald-300">Prova ok</div>
<% elsif mailing.draft? %>
<div class="mt-1 text-xs text-amber-700 dark:text-amber-400">Manca prova</div>
<% end %>
</td>
<td class="px-4 py-3 text-sm text-zinc-500">
<% if mailing.sending? && mailing.next_send_at.present? %>
<%= mailing.next_send_at > Time.current ? "Riparte #{l(mailing.next_send_at, format: :short)}" : "In invio" %>
<% else %>
<%= format_dt(mailing.created_at) %>
<% end %>
</td>
<td class="px-4 py-3 text-right">
<% if mailing.draft? %>
<%= render "mailings/delete_draft_button", mailing: mailing, label: "Elimina", extra_class: "text-sm", form_class: "inline" %>
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>
<% end %>
</div>
<% end %>
<% end %>