diff --git a/lib/atomic/organizations/partner.ex b/lib/atomic/organizations/partner.ex index 1da52391..17a96514 100644 --- a/lib/atomic/organizations/partner.ex +++ b/lib/atomic/organizations/partner.ex @@ -27,6 +27,8 @@ defmodule Atomic.Organizations.Partner do field :description, :string field :notes, :string + field :banner, Atomic.Uploaders.Banner.Type + field :benefits, :string field :archived, :boolean, default: false field :image, Uploaders.PartnerImage.Type diff --git a/lib/atomic_web/live/partner_live/components/partner_card.ex b/lib/atomic_web/live/partner_live/components/partner_card.ex new file mode 100644 index 00000000..c02d2212 --- /dev/null +++ b/lib/atomic_web/live/partner_live/components/partner_card.ex @@ -0,0 +1,49 @@ +defmodule AtomicWeb.PartnerLive.Components.PartnerCard do + @moduledoc false + use AtomicWeb, :component + + import AtomicWeb.Components.{Avatar, Gradient} + + attr :partner, :map, required: true + + def partner_card(assigns) do + ~H""" +
  • +
    +
    + <.gradient seed={@partner.id} class="rounded-t-lg" /> +
    +
    + +
    +
    +
    + <.avatar color={:light_zinc} class="" name={@partner.name} src={Uploaders.PartnerImage.url({@partner.image, @partner}, :original)} type={:company} size={:xl} /> +
    +
    +
    +

    {@partner.name}

    + + +
    + <%= if @partner.location do %> +
    + <.icon name="hero-map-pin" class="h-6 w-6 text-zinc-400" /> +

    {@partner.location.name}

    +
    + <% end %> +
    +
    + +
    +
  • + """ + end +end diff --git a/lib/atomic_web/live/partner_live/form_component.ex b/lib/atomic_web/live/partner_live/form_component.ex index b2384695..e9d2250c 100644 --- a/lib/atomic_web/live/partner_live/form_component.ex +++ b/lib/atomic_web/live/partner_live/form_component.ex @@ -4,6 +4,7 @@ defmodule AtomicWeb.PartnerLive.FormComponent do alias Atomic.Partners alias AtomicWeb.Components.ImageUploader import AtomicWeb.Components.Forms + import ImageUploader @impl true def render(assigns) do @@ -38,7 +39,7 @@ defmodule AtomicWeb.PartnerLive.FormComponent do

    {gettext("The image of the partner (960x960px for best display)")}

    - <.live_component module={ImageUploader} id="uploader" uploads={@uploads} target={@myself} /> + <.image_uploader id="uploader" upload={@uploads.image} class="h-32 w-full border border-zinc-300 shadow-sm xl:h-64" image_class="h-32 w-full object-cover xl:h-64" />

    {gettext("Internal")}

    diff --git a/lib/atomic_web/live/partner_live/index.ex b/lib/atomic_web/live/partner_live/index.ex index ec73fc5e..d5c0afb4 100644 --- a/lib/atomic_web/live/partner_live/index.ex +++ b/lib/atomic_web/live/partner_live/index.ex @@ -1,7 +1,8 @@ defmodule AtomicWeb.PartnerLive.Index do + import AtomicWeb.PartnerLive.Components.PartnerCard use AtomicWeb, :live_view - import AtomicWeb.Components.{Avatar, Button, Empty, Pagination, Tabs} + import AtomicWeb.Components.{Button, Empty, Pagination, Tabs} import AtomicWeb.LiveHelpers alias Atomic.Accounts diff --git a/lib/atomic_web/live/partner_live/index.html.heex b/lib/atomic_web/live/partner_live/index.html.heex index b7d477c6..8c87de07 100644 --- a/lib/atomic_web/live/partner_live/index.html.heex +++ b/lib/atomic_web/live/partner_live/index.html.heex @@ -1,4 +1,4 @@ -<.page title="Partners"> +<.page title={"#{@organization.name} Partners"}> <:actions> <%= if not @empty? and @has_permissions? do %> <.button navigate={~p"/organizations/#{@current_organization}/partners/new"} icon="hero-plus"> @@ -8,9 +8,9 @@
    -
    -
    - <.tabs class="px-4 sm:px-6 lg:px-8"> +
    +
    + <.tabs class="overflow-auto px-4 sm:px-6 lg:px-8"> <.link patch="?tab=all" replace={false}> <.tab active={@current_tab == "all"}> {gettext("Current Partners")} @@ -29,42 +29,18 @@
    <%= if @empty? and @has_permissions? do %> -
    +
    <.empty_state url={~p"/organizations/#{@organization}/partners/new"} placeholder="partner" />
    <% else %> -
      +
        <%= for partner <- @partners do %> - <.link navigate={~p"/organizations/#{@organization}/partners/#{partner}"} class="block hover:bg-zinc-50"> -
      • -
        -
        - <.avatar color={:light_zinc} name={partner.name} src={Uploaders.PartnerImage.url({partner.image, partner}, :original)} type={:company} size={:sm} /> -
        -
        -

        {partner.name}

        - <%= if partner.location do %> -
        - <.icon name="hero-map-pin" class="size-5 text-zinc-400" /> -

        {partner.location.name}

        -
        - <% end %> -

        - <%= Enum.map(String.split(partner.benefits, "\n"), fn phrase -> %> - <%= if String.length(phrase) < 150 do %> - {phrase}
        - <% else %> - {String.slice(phrase, 0..150) <> "..."}
        - <% end %> - <% end) %> -

        -
        -
        -
      • + <.link navigate={~p"/organizations/#{partner.organization_id}/partners/#{partner.id}"} class="block hover:bg-zinc-50"> + <.partner_card partner={partner} /> <% end %>
      - <.pagination items={@partners} meta={@meta} params={@params} class="mt-2 flex w-full items-center justify-between" /> + <.pagination items={@partners} meta={@meta} params={@params} class="mt-2 flex w-full flex-wrap items-center justify-between" /> <% end %> diff --git a/lib/atomic_web/live/partner_live/show.ex b/lib/atomic_web/live/partner_live/show.ex index 522d1feb..c3a73453 100644 --- a/lib/atomic_web/live/partner_live/show.ex +++ b/lib/atomic_web/live/partner_live/show.ex @@ -1,7 +1,7 @@ defmodule AtomicWeb.PartnerLive.Show do use AtomicWeb, :live_view - import AtomicWeb.Components.{Avatar, Socials} + import AtomicWeb.Components.{Avatar, Tabs, Gradient} import AtomicWeb.LiveHelpers alias Atomic.Accounts @@ -14,7 +14,7 @@ defmodule AtomicWeb.PartnerLive.Show do end @impl true - def handle_params(%{"organization_id" => organization_id, "id" => id}, _, socket) do + def handle_params(%{"organization_id" => organization_id, "id" => id} = params, _, socket) do organization = Organizations.get_organization!(organization_id) partner = Partners.get_partner!(id) @@ -23,6 +23,7 @@ defmodule AtomicWeb.PartnerLive.Show do |> assign(:page_title, partner.name) |> assign_page_metadata(:partner) |> assign(:current_page, :partners) + |> assign(:current_tab, current_tab(socket, params)) |> assign(:organization, organization) |> assign(:partner, partner) |> assign( @@ -32,6 +33,9 @@ defmodule AtomicWeb.PartnerLive.Show do |> assign(:has_permissions?, has_permissions?(socket, organization_id))} end + defp current_tab(_socket, params) when is_map_key(params, "tab"), do: params["tab"] + defp current_tab(_socket, _params), do: "benefits" + defp has_permissions?(socket, _organization_id) when not socket.assigns.is_authenticated?, do: false diff --git a/lib/atomic_web/live/partner_live/show.html.heex b/lib/atomic_web/live/partner_live/show.html.heex index 5833bb63..0286e3f3 100644 --- a/lib/atomic_web/live/partner_live/show.html.heex +++ b/lib/atomic_web/live/partner_live/show.html.heex @@ -1,108 +1,143 @@ -<.page title="Partners"> - <:actions> - <%= if @has_permissions? do %> -
      - <.button navigate={~p"/organizations/#{@organization}/partners/#{@partner}/edit"} icon="hero-pencil"> - {gettext("Edit Partner")} - -
      - <% end %> - -
      -
      -
      + +
      + <%= if @partner.banner do %> + + <% else %> + <.gradient seed={@partner.id} class="object-cover" /> + <% end %> +
      +<.page title=""> + +
      +
      +
      - <.avatar color={:light_zinc} name={@partner.name} src={Uploaders.PartnerImage.url({@partner.image, @partner}, :original)} type={:company} size={:xl} /> + <.avatar class="size-28" color={:light_zinc} name={@partner.name} src={Uploaders.PartnerImage.url({@partner.image, @partner}, :original)} type={:company} size={:xl} />
      -
      -
      -

      +
      +
      +

      {@partner.name} -

      -
      - <%= if @partner.location do %> - -
      - <.icon name="hero-map-pin" class="h-5 w-5 text-zinc-400" /> - <.link class="text-blue-500" href={"https://www.google.com/maps/search/?api=1&query=#{@partner.location.name}"}> - {@partner.location.name} - -
      - <% end %> +

      - <%= if @partner.socials do %> - -
      - - <%= if @partner.socials.website do %> -
      - <.icon name="hero-globe-alt" class="h-5 w-5 text-zinc-400" /> - <.link class="text-blue-500" href={@partner.socials.website}>Website + <%= if @has_permissions? do %> +
      + <.button navigate={~p"/organizations/#{@partner.organization_id}/partners/#{@partner.id}/edit"} icon="hero-pencil"> + + +
      + <% end %> +
      +
      +
      + <%= if @partner.location do %> +
      + <.icon name="hero-map-pin" class="h-5 w-5 text-zinc-400" /> + <.link class="text-sm text-blue-500" href={"https://www.google.com/maps/search/?api=1&query=#{@partner.location.name}"}>{@partner.location.name}
      <% end %> - <%= if @partner.socials do %> - <.socials entity={@partner.socials} /> +
      + <%= if @partner.socials.website do %> +
      + <.icon name="hero-globe-alt" class="h-5 w-5 text-zinc-400" /> + <.link class="text-sm text-blue-500" href={@partner.socials.website}>Website +
      + <% end %> + <%= if @partner.socials.instagram do %> +
      + Instagram + <.link class="text-sm text-blue-500" href={"https://instagram.com/" <> @partner.socials.instagram}>Instagram +
      + <% end %> + <%= if @partner.socials.facebook do %> +
      + Facebook + <.link class="text-sm text-blue-500" href={"https://facebook.com/" <> @partner.socials.facebook}>Facebook +
      + <% end %> + <%= if @partner.socials.x do %> +
      + X + <.link class="text-sm text-blue-500" href={"https://x.com/" <> @partner.socials.x}>X +
      + <% end %> +
      <% end %>
      - <% end %> -
      -
      -
      -
      -
      - <.icon name="hero-clock" class="size-5 mb-2" /> -

      Overview

      - - <%= Enum.map(String.split(@partner.description, "\n"), fn phrase -> %> - {phrase} - <% end) %> -
      -
      -
      - <.icon name="hero-signal" class="size-5 mb-2" /> -

      Benefits

      -
      - - <%= Enum.map(String.split(@partner.benefits, "\n"), fn phrase -> %> +
      + + <.tabs class="scrollbar-hide mt-2 flex overflow-auto px-4"> + <.link patch="?tab=benefits" replace={false}> + <.tab id="benefits-tab" active={@current_tab == "benefits"}> + <.icon name="hero-signal" class="size-5 mr-2" /> + {gettext("Benefits")} + + + <.link patch="?tab=about" replace={false}> + <.tab id="about-tab" active={@current_tab == "about"}> + <.icon name="hero-information-circle" class="size-5 mr-2" /> + {gettext("About")} + + + + +
      + <%= if @current_tab == "benefits" do %> +
      + <%= for phrase <- String.split(@partner.benefits, "\n") do %> <%= if String.length(phrase) < 300 do %> {phrase} <% else %> {String.slice(phrase, 0..300)} <% end %> - <% end) %> - -
      - <%= if @partners do %> -
      -
      - <.icon name="hero-star" class="size-5 mb-2" /> -

      Related Partners

      -
      -
      - <%= for partner <- @partners |> Enum.filter(fn partner -> partner.id != @partner.id end) do %> -
      - <.link href={~p"/organizations/#{@organization}/partners/#{@partner}"}> -
      - <.avatar color={:light_zinc} name={partner.name} src={Uploaders.PartnerImage.url({partner.image, partner}, :original)} type={:company} size={:xs} /> -

      {partner.name}

      -
      - <%= if partner.location do %> -
      - <.icon name="hero-map-pin" class="size-5 text-zinc-400" /> - {partner.location.name} -
      - <% end %> - {partner.description} - -
      - <% end %> -
      + <% end %> +
      + <% end %> + + <%= if @current_tab == "about" do %> +
      + <%= for phrase <- String.split(@partner.description, "\n") do %> + {phrase} + <% end %>
      <% end %>
      + <%= if @partners do %> +
      +
      + <.icon name="hero-star" class="mb-2 h-5 w-5" /> +

      Related Partners

      +
      +
      + <%= for partner <- @partners |> Enum.filter(fn partner -> partner.id != @partner.id end) do %> + <.link href={~p"/organizations/#{partner.organization_id}/partners/#{partner.id}"}> +
    • +
      + <.avatar class="size-10" color={:light_zinc} name={partner.name} src={Uploaders.PartnerImage.url({partner.image, partner}, :original)} type={:company} size={:xs} /> +
      +
      +

      {partner.name}

      + <%= if partner.location do %> +
      + <.icon name="hero-map-pin" class="my-1 h-4 w-4 text-zinc-400" /> + {partner.location.name} +
      + <% end %> +

      + {partner.description} +

      +
      +
    • + + <% end %> +
      +
      + <% end %> diff --git a/priv/repo/migrations/20221123000537_create_partners.exs b/priv/repo/migrations/20221123000537_create_partners.exs index 68470bf5..242660aa 100644 --- a/priv/repo/migrations/20221123000537_create_partners.exs +++ b/priv/repo/migrations/20221123000537_create_partners.exs @@ -16,6 +16,8 @@ defmodule Atomic.Repo.Migrations.CreatePartners do add :location, :map add :socials, :map + add :banner, :string + add :organization_id, references(:organizations, on_delete: :delete_all, type: :binary_id) timestamps()