From ef71eb02948d3f51ee78fdf3ec9c36d1b840b3e0 Mon Sep 17 00:00:00 2001 From: AfonsoMartins26 Date: Thu, 13 Mar 2025 11:41:52 +0000 Subject: [PATCH 01/12] feat: initial commit --- lib/atomic/quantum/certificate_delivery.ex | 2 +- .../certificate_live/index.ex | 58 +++++++++++++++++++ .../certificate_live/index.html.heex | 22 +++++++ .../live/organization_live/form_component.ex | 1 + .../live/organization_live/show.html.heex | 7 ++- lib/atomic_web/router.ex | 1 + 6 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 lib/atomic_web/live/organization_live/certificate_live/index.ex create mode 100644 lib/atomic_web/live/organization_live/certificate_live/index.html.heex diff --git a/lib/atomic/quantum/certificate_delivery.ex b/lib/atomic/quantum/certificate_delivery.ex index 373f7d621..6421b9535 100644 --- a/lib/atomic/quantum/certificate_delivery.ex +++ b/lib/atomic/quantum/certificate_delivery.ex @@ -65,7 +65,7 @@ defmodule Atomic.Quantum.CertificateDelivery do # It uses `wkhtmltopdf` to build it from an HTML template, which # is rendered beforehand. - defp generate_certificate( + def generate_certificate( %Enrollment{} = enrollment, %Activity{} = activity, %Organization{} = organization diff --git a/lib/atomic_web/live/organization_live/certificate_live/index.ex b/lib/atomic_web/live/organization_live/certificate_live/index.ex new file mode 100644 index 000000000..fd95c464b --- /dev/null +++ b/lib/atomic_web/live/organization_live/certificate_live/index.ex @@ -0,0 +1,58 @@ +defmodule AtomicWeb.OrganizationLive.CertificateLive.Index do + use AtomicWeb, :live_view + + alias Atomic.Activities + alias Atomic.Organizations + import Atomic.Quantum.CertificateDelivery + import AtomicWeb.Components.Forms + + + @impl true + def mount(_params, _session, socket) do + {:ok, socket} + end + + @impl true + def handle_params(%{"organization_id" => organization_id} = params, _url, socket) do + activities = list_activities(organization_id) + organization = Organizations.get_organization!(organization_id) + changeset = Organizations.change_organization(organization) + + + {:noreply, + socket + |> assign(:page_title, gettext("Certeficate")) + |> assign(:current_page, :certificate) + |> assign(:organization, organization) + |> assign(:changeset, changeset) + |> assign(:activities, activities) + |> assign(:params, params)} + end + + @impl true + def handle_event("generate",_params, socket) do + %{ + enrollment: enrollment, + activity: activity, + organization: organization + } = socket.assigns + + case generate_certificate(enrollment, activity, organization) do + {:ok, _pdf_path} -> + {:noreply, socket |> put_flash(:info, "Certificado gerado com sucesso!")} + + {:error, reason} -> + {:noreply, socket |> put_flash(:error, "Erro ao gerar certificado: #{inspect(reason)}")} + end + end + + defp list_activities(organization_id) do + case Activities.list_activities_by_organization_id(organization_id) do + {:ok, {activities, meta}} -> + %{activities: activities, meta: meta} + + {:error, flop} -> + %{activities: [], meta: flop} + end + end + end diff --git a/lib/atomic_web/live/organization_live/certificate_live/index.html.heex b/lib/atomic_web/live/organization_live/certificate_live/index.html.heex new file mode 100644 index 000000000..a2185f53d --- /dev/null +++ b/lib/atomic_web/live/organization_live/certificate_live/index.html.heex @@ -0,0 +1,22 @@ +<.page title="Certeficate" > + <:actions> +

Boas

+ + + <.form :let={f} for={@changeset} id="announcement-form" phx-target={@organization} phx-change="validate" phx-submit="generate" class="space-y-6"> +
+
+
+ <.field field={f[:title]} type="text" placeholder="Title" required class="w-full" /> + + <.field field={f[:description]} type="textarea" placeholder="Description" required class="h-44 w-full resize-none overflow-auto xl:h-64" /> +
+
+
+ <.button size={:md} color={:white} icon="hero-cube" type="submit">{gettext("Save Changes")} +
+
+
+
+ + \ No newline at end of file diff --git a/lib/atomic_web/live/organization_live/form_component.ex b/lib/atomic_web/live/organization_live/form_component.ex index 50b492388..28e4634e2 100644 --- a/lib/atomic_web/live/organization_live/form_component.ex +++ b/lib/atomic_web/live/organization_live/form_component.ex @@ -11,6 +11,7 @@ defmodule AtomicWeb.OrganizationLive.FormComponent do @impl true def update(%{organization: organization} = assigns, socket) do changeset = Organizations.change_organization(organization) + {:ok, socket diff --git a/lib/atomic_web/live/organization_live/show.html.heex b/lib/atomic_web/live/organization_live/show.html.heex index 328614eed..e89fd6bb3 100644 --- a/lib/atomic_web/live/organization_live/show.html.heex +++ b/lib/atomic_web/live/organization_live/show.html.heex @@ -53,7 +53,7 @@ phx-click="unfollow" @click.away="open = false" @click="open = false" - class="absolute left-0 z-10 mt-2 -mr-1 w-72 origin-top-left divide-y divide-zinc-200 overflow-hidden rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:left-0 sm:left-auto" + class="absolute left-0 z-10 mt-2 -mr-1 w-72 origin-top-left divide-y divide-zinc-200 overflow-hidden rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:left-auto" tabindex="-1" role="listbox" aria-labelledby="listbox-label" @@ -81,6 +81,11 @@ <.icon name="hero-trash-solid" class="mr-3 h-5 w-5 text-zinc-400" /> Delete <% end %> + <.link patch={~p"/organizations/#{@organization}/certificate"} class="button"> + + <% end %> diff --git a/lib/atomic_web/router.ex b/lib/atomic_web/router.ex index ee7abf568..3186088de 100644 --- a/lib/atomic_web/router.ex +++ b/lib/atomic_web/router.ex @@ -58,6 +58,7 @@ defmodule AtomicWeb.Router do scope "/organizations/:organization_id" do live "/edit", OrganizationLive.Edit, :edit + live "/certificate", OrganizationLive.CertificateLive.Index, :index scope "/activities" do pipe_through :confirm_activity_association From ab4623a5c556ded1355b16ac570b8076648b0732 Mon Sep 17 00:00:00 2001 From: AfonsoMartins26 Date: Fri, 14 Mar 2025 23:19:30 +0000 Subject: [PATCH 02/12] feat: add form --- .../organization_live/certificate_live/index.ex | 10 +++++----- .../certificate_live/index.html.heex | 13 ++++--------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/lib/atomic_web/live/organization_live/certificate_live/index.ex b/lib/atomic_web/live/organization_live/certificate_live/index.ex index fd95c464b..3e1a5d7d3 100644 --- a/lib/atomic_web/live/organization_live/certificate_live/index.ex +++ b/lib/atomic_web/live/organization_live/certificate_live/index.ex @@ -42,17 +42,17 @@ defmodule AtomicWeb.OrganizationLive.CertificateLive.Index do {:noreply, socket |> put_flash(:info, "Certificado gerado com sucesso!")} {:error, reason} -> - {:noreply, socket |> put_flash(:error, "Erro ao gerar certificado: #{inspect(reason)}")} + {:noreply, socket |> put_flash(:error, "Erro ao gerar certificado: #{reason}")} end end defp list_activities(organization_id) do case Activities.list_activities_by_organization_id(organization_id) do - {:ok, {activities, meta}} -> - %{activities: activities, meta: meta} + {:ok, {activities, _meta}} -> + activities - {:error, flop} -> - %{activities: [], meta: flop} + {:error, _flop} -> + [] end end end diff --git a/lib/atomic_web/live/organization_live/certificate_live/index.html.heex b/lib/atomic_web/live/organization_live/certificate_live/index.html.heex index a2185f53d..0eab0f224 100644 --- a/lib/atomic_web/live/organization_live/certificate_live/index.html.heex +++ b/lib/atomic_web/live/organization_live/certificate_live/index.html.heex @@ -1,15 +1,10 @@ <.page title="Certeficate" > - <:actions> -

Boas

- - - <.form :let={f} for={@changeset} id="announcement-form" phx-target={@organization} phx-change="validate" phx-submit="generate" class="space-y-6"> + <.form :let={f} for={@changeset} id="announcement-form" phx-change="validate" phx-submit="generate" class="space-y-6">
- <.field field={f[:title]} type="text" placeholder="Title" required class="w-full" /> - - <.field field={f[:description]} type="textarea" placeholder="Description" required class="h-44 w-full resize-none overflow-auto xl:h-64" /> + <.field field={f[:enrollment]} type="text" placeholder="Enrollment" required class="w-full" /> + <.field field={f[:activity]} type="textarea" placeholder="Activity" required class="h-44 w-full resize-none overflow-auto xl:h-64" />
@@ -18,5 +13,5 @@
- + \ No newline at end of file From f1d8d3474da9526cd8e10c15d22a9aa8e4701748 Mon Sep 17 00:00:00 2001 From: AfonsoMartins26 Date: Fri, 14 Mar 2025 23:36:54 +0000 Subject: [PATCH 03/12] feat: add activities as options --- .../certificate_live/index.ex | 33 +++++++++---------- .../certificate_live/index.html.heex | 2 +- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/lib/atomic_web/live/organization_live/certificate_live/index.ex b/lib/atomic_web/live/organization_live/certificate_live/index.ex index 3e1a5d7d3..009bcdc11 100644 --- a/lib/atomic_web/live/organization_live/certificate_live/index.ex +++ b/lib/atomic_web/live/organization_live/certificate_live/index.ex @@ -6,7 +6,6 @@ defmodule AtomicWeb.OrganizationLive.CertificateLive.Index do import Atomic.Quantum.CertificateDelivery import AtomicWeb.Components.Forms - @impl true def mount(_params, _session, socket) do {:ok, socket} @@ -18,10 +17,9 @@ defmodule AtomicWeb.OrganizationLive.CertificateLive.Index do organization = Organizations.get_organization!(organization_id) changeset = Organizations.change_organization(organization) - {:noreply, socket - |> assign(:page_title, gettext("Certeficate")) + |> assign(:page_title, gettext("Certificate")) |> assign(:current_page, :certificate) |> assign(:organization, organization) |> assign(:changeset, changeset) @@ -30,17 +28,13 @@ defmodule AtomicWeb.OrganizationLive.CertificateLive.Index do end @impl true - def handle_event("generate",_params, socket) do - %{ - enrollment: enrollment, - activity: activity, - organization: organization - } = socket.assigns - - case generate_certificate(enrollment, activity, organization) do - {:ok, _pdf_path} -> - {:noreply, socket |> put_flash(:info, "Certificado gerado com sucesso!")} + def handle_event("generate", _params, socket) do + with %{activity: activity, organization: organization} <- socket.assigns, + enrollment <- Activities.get_enrollment!(activity.id, user_id), + {:ok, _pdf_path} <- generate_certificate(enrollment, activity, organization) do + {:noreply, socket |> put_flash(:info, "Certificado gerado com sucesso!")} + else {:error, reason} -> {:noreply, socket |> put_flash(:error, "Erro ao gerar certificado: #{reason}")} end @@ -48,11 +42,14 @@ defmodule AtomicWeb.OrganizationLive.CertificateLive.Index do defp list_activities(organization_id) do case Activities.list_activities_by_organization_id(organization_id) do - {:ok, {activities, _meta}} -> - activities - - {:error, _flop} -> - [] + {:ok, {activities, _meta}} -> activities + {:error, _flop} -> [] end end + + defp options(activities) do + activities + |> Enum.map(&{&1.title, &1.id}) end + +end diff --git a/lib/atomic_web/live/organization_live/certificate_live/index.html.heex b/lib/atomic_web/live/organization_live/certificate_live/index.html.heex index 0eab0f224..6c4e26dc2 100644 --- a/lib/atomic_web/live/organization_live/certificate_live/index.html.heex +++ b/lib/atomic_web/live/organization_live/certificate_live/index.html.heex @@ -4,7 +4,7 @@
<.field field={f[:enrollment]} type="text" placeholder="Enrollment" required class="w-full" /> - <.field field={f[:activity]} type="textarea" placeholder="Activity" required class="h-44 w-full resize-none overflow-auto xl:h-64" /> + <.field field={f[:activity]} type="select" options={options(@activities)} placeholder="Activity" required class="h-10 w-full resize-none overflow-auto" />
From 5ac89eb7979a9ca7d6d6fae7cf465035a74594a7 Mon Sep 17 00:00:00 2001 From: AfonsoMartins26 Date: Tue, 18 Mar 2025 01:14:34 +0000 Subject: [PATCH 04/12] feat: reder certificate --- lib/atomic/activities.ex | 6 ++ lib/atomic/quantum/certificate_delivery.ex | 8 +- .../certificate_live/index.ex | 6 +- .../certificate_live/index.html.heex | 35 +++++---- .../live/organization_live/form_component.ex | 1 - .../templates/certificate/main.html.eex | 73 +++++++++++++++++++ lib/atomic_web/views/certificate_view.ex | 3 + 7 files changed, 107 insertions(+), 25 deletions(-) create mode 100644 lib/atomic_web/templates/certificate/main.html.eex create mode 100644 lib/atomic_web/views/certificate_view.ex diff --git a/lib/atomic/activities.ex b/lib/atomic/activities.ex index f6e5704c6..77c8af685 100644 --- a/lib/atomic/activities.ex +++ b/lib/atomic/activities.ex @@ -300,6 +300,12 @@ defmodule Atomic.Activities do Repo.all(Enrollment) end + def list_enrollments(opts) when is_list(opts) do + Enrollment + |> apply_filters(opts) + |> Repo.all() + end + @doc """ Gets a single enrollment. diff --git a/lib/atomic/quantum/certificate_delivery.ex b/lib/atomic/quantum/certificate_delivery.ex index 6421b9535..a37aa5b4c 100644 --- a/lib/atomic/quantum/certificate_delivery.ex +++ b/lib/atomic/quantum/certificate_delivery.ex @@ -66,10 +66,10 @@ defmodule Atomic.Quantum.CertificateDelivery do # It uses `wkhtmltopdf` to build it from an HTML template, which # is rendered beforehand. def generate_certificate( - %Enrollment{} = enrollment, - %Activity{} = activity, - %Organization{} = organization - ) do + %Enrollment{} = enrollment, + %Activity{} = activity, + %Organization{} = organization + ) do # Create the string corresponding to the HTML to convert # to a PDF Phoenix.View.render_to_string(AtomicWeb.PDFView, "activity_certificate.html", diff --git a/lib/atomic_web/live/organization_live/certificate_live/index.ex b/lib/atomic_web/live/organization_live/certificate_live/index.ex index 009bcdc11..8b1d2efed 100644 --- a/lib/atomic_web/live/organization_live/certificate_live/index.ex +++ b/lib/atomic_web/live/organization_live/certificate_live/index.ex @@ -29,9 +29,8 @@ defmodule AtomicWeb.OrganizationLive.CertificateLive.Index do @impl true def handle_event("generate", _params, socket) do - with %{activity: activity, organization: organization} <- socket.assigns, - enrollment <- Activities.get_enrollment!(activity.id, user_id), - + with %{activity: activity, organization: organization, enrollment: enrollment} <- + socket.assigns, {:ok, _pdf_path} <- generate_certificate(enrollment, activity, organization) do {:noreply, socket |> put_flash(:info, "Certificado gerado com sucesso!")} else @@ -51,5 +50,4 @@ defmodule AtomicWeb.OrganizationLive.CertificateLive.Index do activities |> Enum.map(&{&1.title, &1.id}) end - end diff --git a/lib/atomic_web/live/organization_live/certificate_live/index.html.heex b/lib/atomic_web/live/organization_live/certificate_live/index.html.heex index 6c4e26dc2..e016d8192 100644 --- a/lib/atomic_web/live/organization_live/certificate_live/index.html.heex +++ b/lib/atomic_web/live/organization_live/certificate_live/index.html.heex @@ -1,17 +1,20 @@ -<.page title="Certeficate" > - <.form :let={f} for={@changeset} id="announcement-form" phx-change="validate" phx-submit="generate" class="space-y-6"> -
-
-
- <.field field={f[:enrollment]} type="text" placeholder="Enrollment" required class="w-full" /> - <.field field={f[:activity]} type="select" options={options(@activities)} placeholder="Activity" required class="h-10 w-full resize-none overflow-auto" /> -
-
-
- <.button size={:md} color={:white} icon="hero-cube" type="submit">{gettext("Save Changes")} -
-
-
+<.page title="Certificate"> + <:actions> + <.button size={:md} color={:white} icon="hero-cube" type="submit">{gettext("Save Changes")} + + <.form :let={f} for={@changeset} id="announcement-form" phx-change="validate" phx-submit="generate" class="space-y-6"> +
+
+
+ <.field field={f[:Background_color]} type="switch" placeholder="Background color" required class="w-full" /> + <.field field={f[:enrollment]} type="switch" placeholder="Background color" required class="w-full" /> + <.field field={f[:enrollment]} type="switch" placeholder="Background color" required class="w-full" /> + <.field field={f[:enrollment]} type="switch" placeholder="Background color" required class="w-full" />
- - \ No newline at end of file +
+
+ {Phoenix.View.render(AtomicWeb.CertificateView, "main.html", assigns)} +
+
+ + diff --git a/lib/atomic_web/live/organization_live/form_component.ex b/lib/atomic_web/live/organization_live/form_component.ex index 28e4634e2..50b492388 100644 --- a/lib/atomic_web/live/organization_live/form_component.ex +++ b/lib/atomic_web/live/organization_live/form_component.ex @@ -11,7 +11,6 @@ defmodule AtomicWeb.OrganizationLive.FormComponent do @impl true def update(%{organization: organization} = assigns, socket) do changeset = Organizations.change_organization(organization) - {:ok, socket diff --git a/lib/atomic_web/templates/certificate/main.html.eex b/lib/atomic_web/templates/certificate/main.html.eex new file mode 100644 index 000000000..ed56a6ec5 --- /dev/null +++ b/lib/atomic_web/templates/certificate/main.html.eex @@ -0,0 +1,73 @@ + + + + Certificado da Atividade + + + + + +
+
Certificado de Participação
+

+ Para os devidos efeitos, certifica-se que +

+ Enrollment +

+ participou na atividade Certificado da Atividade, organizada pelo(a) <%= @organization.name %>. +

+

+ Este certificado foi gerado automaticamente pela plataforma open-source de gestão de núcleos Atomic, sendo da exclusiva responsabilidade do Centro de Estudantes de Engenharia de Informática da Universidade do Minho, com a devida autorização da organização dinamizadora da atividade. +

+
+ + diff --git a/lib/atomic_web/views/certificate_view.ex b/lib/atomic_web/views/certificate_view.ex new file mode 100644 index 000000000..9fe271bfe --- /dev/null +++ b/lib/atomic_web/views/certificate_view.ex @@ -0,0 +1,3 @@ +defmodule AtomicWeb.CertificateView do + use AtomicWeb, :view +end From 726530f62411a557ca47db370a99a9ed74eb1742 Mon Sep 17 00:00:00 2001 From: AfonsoMartins26 Date: Wed, 19 Mar 2025 19:47:08 +0000 Subject: [PATCH 05/12] feat: scale --- .../certificate_live/index.ex | 5 ----- .../certificate_live/index.html.heex | 20 +++++++++---------- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/lib/atomic_web/live/organization_live/certificate_live/index.ex b/lib/atomic_web/live/organization_live/certificate_live/index.ex index 8b1d2efed..606ad95fc 100644 --- a/lib/atomic_web/live/organization_live/certificate_live/index.ex +++ b/lib/atomic_web/live/organization_live/certificate_live/index.ex @@ -45,9 +45,4 @@ defmodule AtomicWeb.OrganizationLive.CertificateLive.Index do {:error, _flop} -> [] end end - - defp options(activities) do - activities - |> Enum.map(&{&1.title, &1.id}) - end end diff --git a/lib/atomic_web/live/organization_live/certificate_live/index.html.heex b/lib/atomic_web/live/organization_live/certificate_live/index.html.heex index e016d8192..3ca78e190 100644 --- a/lib/atomic_web/live/organization_live/certificate_live/index.html.heex +++ b/lib/atomic_web/live/organization_live/certificate_live/index.html.heex @@ -2,19 +2,17 @@ <:actions> <.button size={:md} color={:white} icon="hero-cube" type="submit">{gettext("Save Changes")} - <.form :let={f} for={@changeset} id="announcement-form" phx-change="validate" phx-submit="generate" class="space-y-6"> -
-
-
- <.field field={f[:Background_color]} type="switch" placeholder="Background color" required class="w-full" /> - <.field field={f[:enrollment]} type="switch" placeholder="Background color" required class="w-full" /> - <.field field={f[:enrollment]} type="switch" placeholder="Background color" required class="w-full" /> - <.field field={f[:enrollment]} type="switch" placeholder="Background color" required class="w-full" /> -
+ <.form :let={f} for={@changeset} id="announcement-form" phx-change="validate" phx-submit="generate"> +
+
+ <.field field={f[:Background_color]} type="switch" placeholder="Background color" required class="w-full mb-4" /> + <.field field={f[:enrollment]} type="switch" placeholder="Enrollment" required class="w-full mb-4" /> + <.field field={f[:enrollment]} type="switch" placeholder="Enrollment" required class="w-full mb-4" /> + <.field field={f[:enrollment]} type="switch" placeholder="Enrollment" required class="w-full mb-4" />
-
+
{Phoenix.View.render(AtomicWeb.CertificateView, "main.html", assigns)}
- + \ No newline at end of file From e6f18e882d4aaf66a326440018b9800be863473a Mon Sep 17 00:00:00 2001 From: AfonsoMartins26 Date: Wed, 19 Mar 2025 21:37:32 +0000 Subject: [PATCH 06/12] format --- .../certificate_live/index.html.heex | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/atomic_web/live/organization_live/certificate_live/index.html.heex b/lib/atomic_web/live/organization_live/certificate_live/index.html.heex index 3ca78e190..b97c14c1d 100644 --- a/lib/atomic_web/live/organization_live/certificate_live/index.html.heex +++ b/lib/atomic_web/live/organization_live/certificate_live/index.html.heex @@ -3,16 +3,16 @@ <.button size={:md} color={:white} icon="hero-cube" type="submit">{gettext("Save Changes")} <.form :let={f} for={@changeset} id="announcement-form" phx-change="validate" phx-submit="generate"> -
+
- <.field field={f[:Background_color]} type="switch" placeholder="Background color" required class="w-full mb-4" /> - <.field field={f[:enrollment]} type="switch" placeholder="Enrollment" required class="w-full mb-4" /> - <.field field={f[:enrollment]} type="switch" placeholder="Enrollment" required class="w-full mb-4" /> - <.field field={f[:enrollment]} type="switch" placeholder="Enrollment" required class="w-full mb-4" /> + <.field field={f[:Background_color]} type="switch" placeholder="Background color" required class="mb-4 w-full" /> + <.field field={f[:enrollment]} type="switch" placeholder="Enrollment" required class="mb-4 w-full" /> + <.field field={f[:enrollment]} type="switch" placeholder="Enrollment" required class="mb-4 w-full" /> + <.field field={f[:enrollment]} type="switch" placeholder="Enrollment" required class="mb-4 w-full" />
{Phoenix.View.render(AtomicWeb.CertificateView, "main.html", assigns)}
- \ No newline at end of file + From bcafffebd46caf717511be454f03a46449f8fb67 Mon Sep 17 00:00:00 2001 From: AfonsoMartins26 Date: Thu, 24 Apr 2025 11:23:54 +0100 Subject: [PATCH 07/12] feat: edit certificate --- lib/atomic/quantum/certificate_delivery.ex | 33 ++++++++++++ .../certificate_live/index.ex | 50 ++++++++++++++++++- .../certificate_live/index.html.heex | 33 ++++++++---- .../templates/certificate/main.html.eex | 29 ++++++++--- 4 files changed, 126 insertions(+), 19 deletions(-) diff --git a/lib/atomic/quantum/certificate_delivery.ex b/lib/atomic/quantum/certificate_delivery.ex index a37aa5b4c..a04b116e5 100644 --- a/lib/atomic/quantum/certificate_delivery.ex +++ b/lib/atomic/quantum/certificate_delivery.ex @@ -96,6 +96,39 @@ defmodule Atomic.Quantum.CertificateDelivery do ) end + def generate_certificate( + %Enrollment{} = enrollment, + %Activity{} = activity, + %Organization{} = organization, + certificate_options \\ %{} + ) do + # Create the string corresponding to the HTML to convert + # to a PDF + Phoenix.View.render_to_string(AtomicWeb.PDFView, "activity_certificate.html", + enrollment: enrollment, + activity: activity, + organization: organization, + certificate_options: certificate_options + ) + |> PdfGenerator.generate( + delete_temporary: true, + page_size: "A4", + filename: "certificate_#{enrollment.id}", + shell_params: [ + "--margin-top", + "0", + "--margin-left", + "0", + "--margin-right", + "0", + "--margin-bottom", + "0", + "-O", + "landscape" + ] + ) + end + # Builds the query to determine the activities to consider for certificate # delivery. diff --git a/lib/atomic_web/live/organization_live/certificate_live/index.ex b/lib/atomic_web/live/organization_live/certificate_live/index.ex index 606ad95fc..c442c8f12 100644 --- a/lib/atomic_web/live/organization_live/certificate_live/index.ex +++ b/lib/atomic_web/live/organization_live/certificate_live/index.ex @@ -8,7 +8,18 @@ defmodule AtomicWeb.OrganizationLive.CertificateLive.Index do @impl true def mount(_params, _session, socket) do - {:ok, socket} + certificate_options = %{ + background: true, + title: true, + content: true, + organization: true, + background_color: "#ffffff", + title_color: "#fb923c", + content_color: "#000000", + organization_color: "#000000" + } + + {:ok, assign(socket, certificate_options: certificate_options)} end @impl true @@ -27,11 +38,33 @@ defmodule AtomicWeb.OrganizationLive.CertificateLive.Index do |> assign(:params, params)} end + @impl true + def handle_event("validate", %{"organization" => organization_params}, socket) do + # Extract certificate options from the form params + certificate_options = extract_certificate_options(organization_params) + + changeset = + socket.assigns.organization + |> Organizations.change_organization(organization_params) + |> Map.put(:action, :validate) + + {:noreply, + socket + |> assign(:changeset, changeset) + |> assign(:certificate_options, certificate_options)} + end + @impl true def handle_event("generate", _params, socket) do with %{activity: activity, organization: organization, enrollment: enrollment} <- socket.assigns, - {:ok, _pdf_path} <- generate_certificate(enrollment, activity, organization) do + {:ok, _pdf_path} <- + generate_certificate( + enrollment, + activity, + organization, + socket.assigns.certificate_options + ) do {:noreply, socket |> put_flash(:info, "Certificado gerado com sucesso!")} else {:error, reason} -> @@ -45,4 +78,17 @@ defmodule AtomicWeb.OrganizationLive.CertificateLive.Index do {:error, _flop} -> [] end end + + defp extract_certificate_options(params) do + %{ + background: Map.get(params, "Background") == "true", + title: Map.get(params, "title") == "true", + content: Map.get(params, "content") == "true", + organization: Map.get(params, "organization") == "true", + background_color: Map.get(params, "Background_color") || "#ffffff", + title_color: Map.get(params, "title_color") || "#fb923c", + content_color: Map.get(params, "content_color") || "#000000", + organization_color: Map.get(params, "organization_color") || "#000000" + } + end end diff --git a/lib/atomic_web/live/organization_live/certificate_live/index.html.heex b/lib/atomic_web/live/organization_live/certificate_live/index.html.heex index b97c14c1d..4fed4cb4f 100644 --- a/lib/atomic_web/live/organization_live/certificate_live/index.html.heex +++ b/lib/atomic_web/live/organization_live/certificate_live/index.html.heex @@ -1,17 +1,28 @@ <.page title="Certificate"> <:actions> - <.button size={:md} color={:white} icon="hero-cube" type="submit">{gettext("Save Changes")} + <.button size={:md} color={:white} icon="hero-cube" type="button" phx-click="generate"> + {gettext("Generate Certificate")} + - <.form :let={f} for={@changeset} id="announcement-form" phx-change="validate" phx-submit="generate"> -
-
- <.field field={f[:Background_color]} type="switch" placeholder="Background color" required class="mb-4 w-full" /> - <.field field={f[:enrollment]} type="switch" placeholder="Enrollment" required class="mb-4 w-full" /> - <.field field={f[:enrollment]} type="switch" placeholder="Enrollment" required class="mb-4 w-full" /> - <.field field={f[:enrollment]} type="switch" placeholder="Enrollment" required class="mb-4 w-full" /> -
-
- {Phoenix.View.render(AtomicWeb.CertificateView, "main.html", assigns)} + + <.form :let={f} for={@changeset} id="certificate-form" phx-change="validate" class="flex flex-row items-start gap-8"> +
+

Display Elements

+ <.field field={f[:Background]} type="switch" label="Show Background" required class="mb-4 w-full" value={@certificate_options.background} /> + <.field field={f[:title]} type="switch" label="Show Title" required class="mb-4 w-full" value={@certificate_options.title} /> + <.field field={f[:content]} type="switch" label="Show Content" required class="mb-4 w-full" value={@certificate_options.content} /> + <.field field={f[:organization]} type="switch" label="Highlight Organization" required class="mb-4 w-full" value={@certificate_options.organization} /> + +

Color Options

+ <.field field={f[:Background_color]} type="color" label="Background Color" required class="mb-4 w-full" value={@certificate_options.background_color} /> + <.field field={f[:title_color]} type="color" label="Title Color" required class="mb-4 w-full" value={@certificate_options.title_color} /> + <.field field={f[:content_color]} type="color" label="Content Color" required class="mb-4 w-full" value={@certificate_options.content_color} /> + <.field field={f[:organization_color]} type="color" label="Organization Color" required class="mb-4 w-full" value={@certificate_options.organization_color} /> +
+ +
+
+ {Phoenix.View.render(AtomicWeb.CertificateView, "main.html", Map.put(assigns, :certificate_options, @certificate_options))}
diff --git a/lib/atomic_web/templates/certificate/main.html.eex b/lib/atomic_web/templates/certificate/main.html.eex index ed56a6ec5..353b02842 100644 --- a/lib/atomic_web/templates/certificate/main.html.eex +++ b/lib/atomic_web/templates/certificate/main.html.eex @@ -7,16 +7,18 @@