Files
eminuxCRM/app/views/organizations/show.html.erb
T
eminuxandCursor ab57309f5c
CI / scan_ruby (push) Failing after 11m50s
CI / scan_js (push) Successful in 11m31s
CI / lint (push) Failing after 12m1s
Aggiunge pulsante Modifica ai task nella scheda organizzazione.
Disponibile nel banner prossima azione, nella lista pendenti e nei task completati.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-19 11:23:21 +02:00

201 lines
15 KiB
ERB

<div class="space-y-6">
<div class="rounded-2xl border border-zinc-200 bg-white text-zinc-900 dark:border-zinc-800 dark:bg-zinc-900 dark:text-zinc-100 p-5">
<div class="flex flex-wrap items-start justify-between gap-4">
<div>
<h1 class="break-anywhere text-xl font-semibold tracking-tight md:text-2xl"><%= @organization.name %></h1>
<div class="mt-2 flex flex-wrap items-center gap-2">
<%= status_badge(@organization.status) %>
<% stage = @organization.primary_pipeline_stage(current_project) %>
<% if stage %><%= stage_badge(stage) %><% end %>
<span class="text-sm text-slate-500">Owner: <%= @organization.assigned_user&.full_name || "—" %></span>
<span class="text-sm text-slate-500">Fonte: <%= @organization.lead_source_label %></span>
<span class="text-sm text-slate-500">Progetti: <%= @organization.projects.ordered.map(&:name).join(", ").presence || "—" %></span>
</div>
</div>
<div class="flex w-full flex-wrap gap-2 sm:w-auto">
<%= link_to "Modifica", edit_organization_path(@organization), class: btn_secondary %>
<%= button_to "Elimina", @organization, method: :delete, form: { data: { turbo_confirm: "Eliminare?" } }, class: btn_danger %>
</div>
</div>
<div class="mt-4 flex flex-wrap gap-2" data-controller="dropdown">
<% [
["Aggiungi nota", "note", "Nota"],
["Registra email", "email_sent", "Email inviata"],
["Registra telefonata", "call", "Telefonata"],
["Registra demo", "demo", "Demo"],
["Segna primo utilizzo", "first_use", "Primo utilizzo"],
["Crea proposta", "proposal_sent", "Proposta inviata"]
].each do |label, type, subject| %>
<%= form_with url: organization_activities_path(@organization), class: "inline" do %>
<%= hidden_field_tag "activity[activity_type]", type %>
<%= hidden_field_tag "activity[subject]", subject %>
<%= hidden_field_tag "activity[happened_at]", Time.current %>
<%= submit_tag label, class: chip_action_class %>
<% end %>
<% end %>
<%= link_to "Crea follow-up", new_task_path(organization_id: @organization.id, task_type: "follow_up"), class: chip_action_class %>
<% opp = @opportunities.open_stage.first || @opportunities.first %>
<% if opp %>
<%= button_to "Segna come vinto", update_stage_opportunity_path(opp), method: :patch, params: { pipeline_stage: "won" }, class: "rounded-md bg-emerald-600 px-3 py-2 text-xs font-medium text-white" %>
<%= form_with url: update_stage_opportunity_path(opp), method: :patch, class: "inline-flex items-center gap-1" do %>
<%= hidden_field_tag :pipeline_stage, "lost" %>
<%= select_tag :lost_reason, options_for_catalog(Catalog::LOST_REASONS), class: "rounded-md border border-zinc-300 bg-white px-2 py-1 text-xs dark:border-zinc-600 dark:bg-zinc-950 dark:text-zinc-100" %>
<%= submit_tag "Segna come perso", class: "rounded-md bg-rose-600 px-3 py-2 text-xs font-medium text-white" %>
<% end %>
<% end %>
</div>
</div>
<% if @next_task %>
<section class="rounded-xl border-2 border-amber-300 bg-amber-50 p-5 text-zinc-900 dark:border-amber-800 dark:bg-amber-950 dark:text-amber-50">
<div class="text-xs font-semibold uppercase tracking-wide text-amber-800 dark:text-amber-200">Prossima azione</div>
<div class="mt-1 flex flex-wrap items-center justify-between gap-3">
<div>
<div class="text-lg font-semibold"><%= @next_task.title %></div>
<div class="text-sm text-zinc-600 dark:text-amber-100/80"><%= format_dt(@next_task.due_at) %> · <%= @next_task.task_type_label %> · <%= priority_badge(@next_task.priority) %></div>
</div>
<div class="flex flex-wrap gap-2">
<%= button_to "Completa", complete_task_path(@next_task), method: :patch, class: "rounded-lg bg-emerald-600 px-4 py-2 text-sm font-medium text-white" %>
<%= link_to "Modifica", edit_task_path(@next_task), class: "rounded-lg border border-amber-400 bg-white px-4 py-2 text-sm font-medium text-amber-900 hover:bg-amber-50 dark:bg-transparent dark:text-amber-100 dark:hover:bg-amber-900/30" %>
</div>
</div>
</section>
<% end %>
<div class="grid gap-6 xl:grid-cols-3">
<div class="space-y-6 xl:col-span-2">
<section class="rounded-xl border border-zinc-200 bg-white text-zinc-900 dark:border-zinc-800 dark:bg-zinc-900 dark:text-zinc-100 p-5">
<div class="flex items-center justify-between">
<h2 class="text-lg font-semibold">Informazioni</h2>
</div>
<dl class="mt-3 grid gap-3 sm:grid-cols-2 text-sm">
<div><dt class="text-slate-500">Tipologia</dt><dd class="font-medium"><%= @organization.organization_type_label %></dd></div>
<div><dt class="text-slate-500">Sport</dt><dd class="font-medium"><%= [@organization.sport.presence, @organization.team_gender_label.presence].compact.join(" · ").presence || "—" %></dd></div>
<div><dt class="text-slate-500">Località</dt><dd class="font-medium"><%= [@organization.city, @organization.province, @organization.region, @organization.country].compact_blank.join(", ").presence || "—" %></dd></div>
<div><dt class="text-slate-500">Lista campagna</dt><dd class="font-medium"><%= @organization.list_position || "—" %></dd></div>
<div><dt class="text-slate-500">Email</dt><dd class="font-medium break-anywhere"><%= mailto_link(@organization.email, class: "text-sky-700 hover:underline dark:text-sky-400") %></dd></div>
<div><dt class="text-slate-500">Telefono</dt><dd class="font-medium"><%= tel_link(@organization.phone, class: "text-sky-700 hover:underline dark:text-sky-400") %></dd></div>
<div><dt class="text-slate-500">Sito / profilo</dt><dd class="font-medium"><%= external_link(@organization.website, class: "text-sky-700 hover:underline dark:text-sky-400") %></dd></div>
<div><dt class="text-slate-500">Fonte ricerca</dt><dd class="font-medium"><%= external_link(@organization.source_url, class: "text-sky-700 hover:underline dark:text-sky-400") %></dd></div>
<div><dt class="text-slate-500">Streaming rilevato</dt><dd class="font-medium"><%= streaming_badge(@organization.streaming_status) || "—" %></dd></div>
<div><dt class="text-slate-500">Data verifica</dt><dd class="font-medium"><%= format_date(@organization.verified_at) %></dd></div>
<div class="sm:col-span-2"><dt class="text-slate-500">Evidenza / fit commerciale</dt><dd class="mt-1 whitespace-pre-wrap text-zinc-700 dark:text-zinc-200"><%= @organization.commercial_fit.presence || "—" %></dd></div>
<div class="sm:col-span-2"><dt class="text-slate-500">Note follow-up</dt><dd class="mt-1 whitespace-pre-wrap text-zinc-700 dark:text-zinc-200"><%= @organization.notes.presence || "—" %></dd></div>
</dl>
</section>
<section class="rounded-xl border border-zinc-200 bg-white text-zinc-900 dark:border-zinc-800 dark:bg-zinc-900 dark:text-zinc-100 p-5">
<div class="flex items-center justify-between">
<h2 class="text-lg font-semibold">Contatti</h2>
<%= link_to "+ Contatto", new_contact_path(organization_id: @organization.id), class: "text-sm font-medium text-emerald-700 hover:underline dark:text-emerald-400" %>
</div>
<div class="mt-3 divide-y divide-zinc-100 dark:divide-zinc-800">
<% @contacts.each do |contact| %>
<div class="flex flex-wrap items-center justify-between gap-2 py-3">
<div>
<div class="font-medium">
<%= contact.full_name %>
<% if contact.primary_contact? %><span class="ml-1 rounded bg-emerald-100 px-1.5 py-0.5 text-[10px] font-semibold uppercase text-emerald-800">Principale</span><% end %>
</div>
<div class="break-anywhere text-sm text-slate-500"><%= [contact.role, contact.email, contact.phone.presence || contact.mobile].compact_blank.join(" · ") %></div>
</div>
<%= link_to "Modifica", edit_contact_path(contact), class: "text-sm text-zinc-600 hover:underline dark:text-zinc-300" %>
</div>
<% end %>
<% if @contacts.blank? %><p class="text-sm text-slate-500">Nessun contatto.</p><% end %>
</div>
</section>
<section class="rounded-xl border border-zinc-200 bg-white text-zinc-900 dark:border-zinc-800 dark:bg-zinc-900 dark:text-zinc-100 p-5">
<div class="flex items-center justify-between">
<h2 class="text-lg font-semibold">Opportunità</h2>
<%= link_to "+ Opportunità", new_opportunity_path(organization_id: @organization.id), class: "text-sm font-medium text-emerald-700 hover:underline dark:text-emerald-400" %>
</div>
<div class="mt-3 space-y-3">
<% @opportunities.each do |opp| %>
<div class="rounded-lg border border-zinc-100 bg-zinc-50 p-3 dark:border-zinc-700 dark:bg-zinc-800">
<div class="flex flex-wrap items-center justify-between gap-2">
<div class="font-medium"><%= opp.name %></div>
<%= stage_badge(opp.pipeline_stage) %>
</div>
<div class="mt-1 text-sm text-zinc-600 dark:text-zinc-300">
<%= format_money(opp.estimated_value) %> · <%= opp.product.presence || "—" %> · <%= opp.probability || 0 %>% · <%= opp.assigned_user&.full_name || "—" %>
</div>
<div class="mt-1 text-xs text-zinc-500">
Test <%= opp.ab_variant.presence || "—" %>
· <%= opp.send_status_label.presence || "Invio n/d" %>
· Demo/Trial <%= yes_no(opp.demo_trial) %>
· Conversione <%= yes_no(opp.converted) %>
<% if opp.sent_on %> · Inviato il <%= format_date(opp.sent_on) %><% end %>
<% if opp.outcome.present? %> · Esito: <%= opp.outcome %><% end %>
</div>
<%= form_with url: update_stage_opportunity_path(opp), method: :patch, class: "mt-2 flex flex-wrap items-center gap-2" do %>
<%= select_tag :pipeline_stage, options_for_catalog(Catalog::PIPELINE_STAGES, opp.pipeline_stage), class: "#{input_class} text-xs py-1" %>
<%= select_tag :lost_reason, options_for_catalog(Catalog::LOST_REASONS, opp.lost_reason), include_blank: "Motivo perdita", class: "#{input_class} text-xs py-1" %>
<%= submit_tag "Aggiorna stage", class: "#{btn_primary} px-2 py-1 text-xs" %>
<%= link_to "Modifica", edit_opportunity_path(opp), class: "text-xs text-zinc-600 hover:underline dark:text-zinc-300" %>
<% end %>
</div>
<% end %>
<% if @opportunities.blank? %><p class="text-sm text-slate-500">Nessuna opportunità.</p><% end %>
</div>
</section>
<section class="rounded-xl border border-zinc-200 bg-white text-zinc-900 dark:border-zinc-800 dark:bg-zinc-900 dark:text-zinc-100 p-5">
<div class="flex items-center justify-between">
<h2 class="text-lg font-semibold">Task</h2>
<%= link_to "+ Task", new_task_path(organization_id: @organization.id), class: "text-sm font-medium text-emerald-700 hover:underline dark:text-emerald-400" %>
</div>
<h3 class="mt-3 text-sm font-semibold text-zinc-600 dark:text-zinc-400">Pendenti</h3>
<%= render "shared/task_list", tasks: @pending_tasks %>
<h3 class="mt-4 text-sm font-semibold text-zinc-600 dark:text-zinc-400">Completati</h3>
<ul class="mt-2 divide-y divide-zinc-100 text-sm text-zinc-600 dark:divide-zinc-800 dark:text-zinc-300">
<% @completed_tasks.each do |task| %>
<li class="flex items-center justify-between gap-2 py-1.5">
<span><%= task.title %> · <%= format_dt(task.completed_at) %></span>
<%= link_to "Modifica", edit_task_path(task), class: "shrink-0 text-xs text-zinc-500 hover:underline dark:text-zinc-400" %>
</li>
<% end %>
<% if @completed_tasks.blank? %><li class="py-1.5 text-slate-400">Nessuno</li><% end %>
</ul>
</section>
</div>
<div class="space-y-6">
<section class="rounded-xl border border-zinc-200 bg-white text-zinc-900 dark:border-zinc-800 dark:bg-zinc-900 dark:text-zinc-100 p-5">
<h2 class="text-lg font-semibold">Aggiungi nota</h2>
<%= form_with url: organization_activities_path(@organization), class: "mt-3 space-y-3" do %>
<%= hidden_field_tag "activity[activity_type]", "note" %>
<%= text_field_tag "activity[subject]", nil, placeholder: "Oggetto", required: true, class: input_class %>
<%= text_area_tag "activity[description]", nil, rows: 3, placeholder: "Descrizione", class: input_class %>
<%= datetime_local_field_tag "activity[happened_at]", Time.current.strftime("%Y-%m-%dT%H:%M"), class: input_class %>
<%= submit_tag "Salva nota", class: btn_primary %>
<% end %>
</section>
<section class="rounded-xl border border-zinc-200 bg-white text-zinc-900 dark:border-zinc-800 dark:bg-zinc-900 dark:text-zinc-100 p-5">
<h2 class="text-lg font-semibold">Timeline</h2>
<div class="mt-4 space-y-4">
<% @activities.each do |activity| %>
<div class="relative border-l-2 border-slate-200 pl-4">
<div class="absolute -left-1.5 top-1.5 h-3 w-3 rounded-full bg-slate-400"></div>
<div class="text-xs font-medium text-slate-500"><%= format_dt(activity.happened_at) %></div>
<div class="font-medium text-zinc-900 dark:text-zinc-100"><%= activity.activity_type_label %>: <%= activity.subject %></div>
<% if activity.description.present? %>
<div class="mt-0.5 whitespace-pre-wrap text-sm text-slate-600 dark:text-zinc-300"><%= activity.description %></div>
<% end %>
<div class="mt-0.5 text-xs text-slate-400"><%= activity.user&.full_name || "Utente rimosso" %><% if activity.contact %> · <%= activity.contact.full_name %><% end %></div>
<div class="mt-1 flex flex-wrap items-center gap-3 text-xs">
<%= link_to "Modifica", edit_organization_activity_path(@organization, activity), class: "font-medium text-zinc-600 hover:underline dark:text-zinc-300" %>
<%= button_to "Elimina", organization_activity_path(@organization, activity), method: :delete, form: { data: { turbo_confirm: "Eliminare questa voce dalla timeline?" }, class: "inline" }, class: "font-medium text-rose-600 hover:underline dark:text-rose-400" %>
</div>
</div>
<% end %>
<% if @activities.blank? %><p class="text-sm text-slate-500">Nessuna attività.</p><% end %>
</div>
</section>
</div>
</div>
</div>