Display provider merchants alongside family merchants (#418)

* Display provider merchants alongside family merchants

* Styling

* Rabbit suggestion
This commit is contained in:
Juan José Mata
2025-12-05 22:15:07 +01:00
committed by GitHub
parent a91a4397e9
commit a790009290
11 changed files with 210 additions and 69 deletions

View File

@@ -6,6 +6,7 @@ class FamilyMerchantsController < ApplicationController
# Show all merchants for this family
@family_merchants = Current.family.merchants.alphabetically
@provider_merchants = Current.family.assigned_merchants.where(type: "ProviderMerchant").alphabetically
render layout: "settings"
end

View File

@@ -1,20 +1,22 @@
<%# locals: (family_merchant:) %>
<div class="flex justify-between items-center p-4 bg-container">
<div class="flex w-full items-center gap-2.5">
<% if family_merchant.logo_url %>
<div class="w-8 h-8 rounded-full flex justify-center items-center">
<%= image_tag family_merchant.logo_url, class: "w-8 h-8 rounded-full" %>
</div>
<% else %>
<%= render partial: "shared/color_avatar", locals: { name: family_merchant.name, color: family_merchant.color } %>
<% end %>
<tr class="border-b border-subdued last:border-0 hover:bg-surface-hover">
<td class="py-3 px-4 text-sm text-primary">
<div class="flex w-full items-center gap-2.5">
<% if family_merchant.logo_url %>
<div class="w-8 h-8 rounded-full flex justify-center items-center">
<%= image_tag family_merchant.logo_url, class: "w-8 h-8 rounded-full" %>
</div>
<% else %>
<%= render partial: "shared/color_avatar", locals: { name: family_merchant.name, color: family_merchant.color } %>
<% end %>
<p class="text-primary text-sm truncate">
<%= family_merchant.name %>
</p>
</div>
<div class="justify-self-end">
<p class="font-medium truncate">
<%= family_merchant.name %>
</p>
</div>
</td>
<td class="py-3 px-4 text-sm text-right align-middle">
<%= render DS::Menu.new do |menu| %>
<% menu.with_item(variant: "link", text: "Edit", href: edit_family_merchant_path(family_merchant), icon: "pencil", data: { turbo_frame: "modal" }) %>
<% menu.with_item(
@@ -25,5 +27,5 @@
method: :delete,
confirm: CustomConfirm.for_resource_deletion(family_merchant.name)) %>
<% end %>
</div>
</div>
</td>
</tr>

View File

@@ -0,0 +1,24 @@
<%# locals: (provider_merchant:) %>
<tr class="border-b border-subdued last:border-0 hover:bg-surface-hover">
<td class="py-3 px-4 text-sm text-primary">
<div class="flex w-full items-center gap-2.5">
<% if provider_merchant.logo_url %>
<div class="w-8 h-8 rounded-full flex justify-center items-center">
<%= image_tag provider_merchant.logo_url, class: "w-8 h-8 rounded-full" %>
</div>
<% else %>
<div class="w-8 h-8 rounded-full flex items-center justify-center bg-container-inset text-secondary text-sm font-medium">
<%= provider_merchant.name&.first&.upcase || "?" %>
</div>
<% end %>
<p class="font-medium truncate">
<%= provider_merchant.name %>
</p>
</div>
</td>
<td class="py-3 px-4 text-sm text-secondary align-middle">
<%= provider_merchant.source&.titleize %>
</td>
</tr>

View File

@@ -9,33 +9,80 @@
) %>
</header>
<div class="bg-container rounded-xl shadow-border-xs p-4">
<% if @family_merchants.any? %>
<div class="rounded-xl bg-container-inset space-y-1 p-1">
<div class="flex items-center gap-1.5 px-4 py-2 text-xs font-medium text-secondary uppercase">
<p><%= t(".title") %></p>
<span class="text-subdued">&middot;</span>
<p><%= @family_merchants.count %></p>
</div>
<div class="bg-container rounded-xl shadow-border-xs p-4 space-y-6">
<section class="space-y-3">
<div class="flex items-center gap-1.5 px-4 py-2 text-xs font-medium text-secondary uppercase">
<p><%= t(".family_title") %></p>
<span class="text-subdued">&middot;</span>
<p><%= @family_merchants.count %></p>
</div>
<div class="bg-container rounded-lg shadow-border-xs">
<div class="overflow-hidden rounded-lg">
<%= render partial: "family_merchants/family_merchant", collection: @family_merchants, spacer_template: "shared/ruler" %>
<% if @family_merchants.any? %>
<div class="rounded-xl bg-container-inset space-y-1 p-1">
<div class="bg-container rounded-lg shadow-border-xs overflow-x-auto">
<table class="w-full">
<thead>
<tr class="text-xs uppercase font-medium text-secondary border-b border-divider">
<th scope="col" class="text-left py-3 px-4"><%= t(".table.merchant") %></th>
<th scope="col" class="text-right py-3 px-4"><%= t(".table.actions") %></th>
</tr>
</thead>
<tbody>
<%= render partial: "family_merchants/family_merchant", collection: @family_merchants %>
</tbody>
</table>
</div>
</div>
</div>
<% else %>
<div class="flex justify-center items-center py-20">
<div class="text-center flex flex-col items-center max-w-[300px]">
<p class="text-primary mb-1 font-medium text-sm"><%= t(".empty") %></p>
<% else %>
<div class="flex justify-center items-center py-12">
<div class="text-center flex flex-col items-center max-w-[300px]">
<p class="text-primary mb-1 font-medium text-sm"><%= t(".family_empty") %></p>
<%= render DS::Link.new(
text: t(".new"),
icon: "plus",
href: new_family_merchant_path,
frame: :modal
) %>
<%= render DS::Link.new(
text: t(".new"),
icon: "plus",
href: new_family_merchant_path,
frame: :modal
) %>
</div>
</div>
<% end %>
</section>
<section class="space-y-3">
<div class="flex items-center gap-1.5 px-4 py-2 text-xs font-medium text-secondary uppercase">
<p><%= t(".provider_title") %></p>
<span class="text-subdued">&middot;</span>
<p><%= @provider_merchants.count %></p>
</div>
<div class="p-4 bg-container-inset border border-secondary rounded-lg">
<div class="flex items-start gap-2">
<%= icon "info", class: "w-5 h-5 text-link mt-0.5 flex-shrink-0" %>
<p class="text-xs text-secondary leading-relaxed"><%= t(".provider_read_only") %></p>
</div>
</div>
<% end %>
<% if @provider_merchants.any? %>
<div class="rounded-xl bg-container-inset space-y-1 p-1">
<div class="bg-container rounded-lg shadow-border-xs overflow-x-auto">
<table class="w-full">
<thead>
<tr class="text-xs uppercase font-medium text-secondary border-b border-divider">
<th scope="col" class="text-left py-3 px-4"><%= t(".table.merchant") %></th>
<th scope="col" class="text-left py-3 px-4"><%= t(".table.source") %></th>
</tr>
</thead>
<tbody>
<%= render partial: "family_merchants/provider_merchant", collection: @provider_merchants %>
</tbody>
</table>
</div>
</div>
<% else %>
<div class="flex justify-center items-center py-8">
<p class="text-secondary text-sm text-center"><%= t(".provider_empty") %></p>
</div>
<% end %>
</section>
</div>