1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-07-22 06:39:39 +02:00

Fix merchants color picker (#1134)

* Fix merchants color picker

* Lint fixes
This commit is contained in:
Zach Gollwitzer 2024-08-26 19:18:27 -04:00 committed by GitHub
parent 166ed4b1ea
commit f82ce59dad
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 52 additions and 71 deletions

View file

@ -6,7 +6,7 @@ module MenusHelper
end
end
def contextual_menu_modal_action_item(label, url, icon: "pencil-line", turbo_frame: nil)
def contextual_menu_modal_action_item(label, url, icon: "pencil-line", turbo_frame: :modal)
link_to url, class: "flex items-center rounded-lg text-gray-900 hover:bg-gray-50 py-2 px-3 gap-2", data: { turbo_frame: } do
concat(lucide_icon(icon, class: "shrink-0 w-5 h-5 text-gray-500"))
concat(tag.span(label, class: "text-sm"))

View file

@ -1,32 +1,29 @@
import {Controller} from "@hotwired/stimulus";
import { Controller } from "@hotwired/stimulus";
// Connects to data-controller="merchant-avatar"
// Used by the transaction merchant form to show a preview of what the avatar will look like
export default class extends Controller {
static targets = [
"name",
"color",
"avatar"
];
connect() {
this.nameTarget.addEventListener("input", this.handleNameChange);
this.colorTarget.addEventListener("input", this.handleColorChange);
}
disconnect() {
this.nameTarget.removeEventListener("input", this.handleNameChange);
this.colorTarget.removeEventListener("input", this.handleColorChange);
}
handleNameChange = (e) => {
this.avatarTarget.textContent = (e.currentTarget.value?.[0] || "?").toUpperCase();
}
handleColorChange = (e) => {
handleColorChange(e) {
const color = e.currentTarget.value;
this.avatarTarget.style.backgroundColor = `color-mix(in srgb, ${color} 5%, white)`;
this.avatarTarget.style.borderColor = `color-mix(in srgb, ${color} 10%, white)`;
this.avatarTarget.style.color = color;
}
}
}

View file

@ -1,19 +1,16 @@
<% is_editing = @merchant.id.present? %>
<div data-controller="merchant-avatar">
<%= styled_form_with model: @merchant, url: is_editing ? merchant_path(@merchant) : merchants_path, method: is_editing ? :patch : :post, scope: :merchant, class: "space-y-4", data: { turbo: false } do |f| %>
<%= styled_form_with model: @merchant, class: "space-y-4", data: { turbo: false } do |f| %>
<section class="space-y-4">
<div class="w-fit m-auto">
<%= render partial: "merchants/avatar", locals: { merchant: } %>
<%= render partial: "merchants/avatar", locals: { merchant: @merchant } %>
</div>
<div data-controller="select" data-select-active-class="bg-gray-200" data-select-selected-value="<%= @merchant&.color || Merchant::COLORS[0] %>">
<%= f.hidden_field :color, data: { select_target: "input", merchant_avatar_target: "color" } %>
<ul data-select-target="list" class="flex gap-2 items-center">
<% Merchant::COLORS.each do |color| %>
<li tabindex="0" data-select-target="option" data-action="click->select#selectOption" data-value="<%= color %>" class="flex shrink-0 justify-center items-center w-6 h-6 cursor-pointer hover:bg-gray-200 rounded-full">
<div style="background-color: <%= color %>" class="shrink-0 w-4 h-4 rounded-full"></div>
</li>
<% end %>
</ul>
<div class="flex gap-2 items-center justify-center">
<% Merchant::COLORS.each do |color| %>
<label class="relative">
<%= f.radio_button :color, color, class: "sr-only peer", data: { action: "change->merchant-avatar#handleColorChange" } %>
<div class="w-6 h-6 rounded-full cursor-pointer peer-checked:ring-2 peer-checked:ring-offset-2 peer-checked:ring-blue-500" style="background-color: <%= color %>"></div>
</label>
<% end %>
</div>
<div class="relative flex items-center border border-gray-200 rounded-lg">
<%= f.text_field :name, placeholder: t(".name_placeholder"), class: "text-sm font-normal placeholder:text-gray-500 h-10 relative pl-3 w-full border-none rounded-lg", required: true, data: { merchant_avatar_target: "name" } %>
@ -21,7 +18,7 @@
</section>
<section>
<%= f.submit(is_editing ? t(".submit_edit") : t(".submit_create")) %>
<%= f.submit %>
</section>
<% end %>
</div>

View file

@ -1,41 +0,0 @@
<%# locals: (merchants:) %>
<% merchants.each.with_index do |merchant, index| %>
<div class="flex justify-between items-center p-4 bg-white">
<div class="flex w-full items-center gap-2.5">
<%= render partial: "merchants/avatar", locals: { merchant: } %>
<p class="text-gray-900 text-sm truncate">
<%= merchant.name %>
</p>
</div>
<div class="relative cursor-pointer" data-controller="menu">
<button data-menu-target="button" class="flex hover:bg-gray-100 p-2 rounded">
<%= lucide_icon("more-horizontal", class: "w-5 h-5 text-gray-500") %>
</button>
<div data-menu-target="content" class="absolute z-10 top-10 right-0 border border-alpha-black-25 bg-white rounded-lg shadow-xs w-48 hidden">
<div class="border-t border-b border-alpha-black-100 p-1">
<%= button_to edit_merchant_path(merchant),
method: :get,
class: "flex w-full gap-1 items-center text-sm hover:bg-gray-50 rounded-lg px-3 py-2",
data: { turbo_frame: "modal" } do %>
<%= lucide_icon("pencil-line", class: "w-5 h-5 mr-2") %> <%= t(".edit") %>
<% end %>
<%= button_to merchant_path(merchant),
method: :delete,
class: "flex w-full gap-1 items-center text-sm text-red-600 hover:text-red-800 hover:bg-gray-50 rounded-lg px-3 py-2",
data: {
turbo_confirm: {
title: t(".confirm_title"),
body: t(".confirm_body"),
accept: t(".confirm_accept")
}
} do %>
<%= lucide_icon("trash-2", class: "w-5 h-5 mr-1") %> <%= t(".delete") %>
<% end %>
</div>
</div>
</div>
</div>
<% unless index == merchants.size - 1 %>
<div class="h-px bg-alpha-black-50 ml-14 mr-6"></div>
<% end %>
<% end %>

View file

@ -0,0 +1,26 @@
<%# locals: (merchant:) %>
<div class="flex justify-between items-center p-4 bg-white">
<div class="flex w-full items-center gap-2.5">
<%= render partial: "merchants/avatar", locals: { merchant: } %>
<p class="text-gray-900 text-sm truncate">
<%= merchant.name %>
</p>
</div>
<div class="justify-self-end">
<%= contextual_menu do %>
<div class="w-48 p-1 text-sm leading-6 text-gray-900 bg-white shadow-lg shrink rounded-xl ring-1 ring-gray-900/5">
<%= contextual_menu_modal_action_item t(".edit"), edit_merchant_path(merchant) %>
<%= contextual_menu_destructive_item t(".delete"),
merchant_path(merchant),
turbo_frame: "_top",
turbo_confirm: {
title: t(".confirm_title"),
body: t(".confirm_body"),
accept: t(".confirm_accept")
} %>
</div>
<% end %>
</div>
</div>

View file

@ -0,0 +1,3 @@
<div class="bg-white">
<div class="h-px bg-alpha-black-50 ml-14 mr-6"></div>
</div>

View file

@ -8,7 +8,7 @@
<%= link_to new_merchant_path, class: "rounded-lg bg-gray-900 text-white flex items-center gap-1 justify-center hover:bg-gray-700 px-3 py-2", data: { turbo_frame: :modal } do %>
<%= lucide_icon("plus", class: "w-5 h-5") %>
<span><%= t(".new_short") %></span>
<span><%= t(".new") %></span>
<% end %>
</div>
<div class="bg-white shadow-xs border border-alpha-black-25 rounded-xl p-4">
@ -18,18 +18,20 @@
<p class="text-gray-900 mb-1 font-medium text-sm"><%= t(".empty") %></p>
<%= link_to new_merchant_path, class: "w-fit flex text-white text-sm font-medium items-center gap-1 bg-gray-900 rounded-lg p-2 pr-3", data: { turbo_frame: "modal" } do %>
<%= lucide_icon("plus", class: "w-5 h-5") %>
<span><%= t(".new_long") %></span>
<span><%= t(".new") %></span>
<% end %>
</div>
</div>
<% else %>
<div class="bg-gray-25 p-1 rounded-xl">
<div class="flex items-center px-4 py-2 text-xs font-medium text-gray-500">
<div class="flex items-center gap-1.5 px-4 py-2 text-xs font-medium text-gray-500">
<p><%= t(".title") %></p>
<span class="text-gray-400 mx-2">&middot;</span>
<span class="text-gray-400">&middot;</span>
<p><%= @merchants.count %></p>
</div>
<%= render partial: "merchants/list", locals: { merchants: @merchants } %>
<div class="overflow-hidden rounded-lg">
<%= render partial: @merchants, spacer_template: "merchants/ruler" %>
</div>
</div>
<% end %>
</div>

View file

@ -9,14 +9,11 @@ en:
title: Edit merchant
form:
name_placeholder: Merchant name
submit_create: Add merchant
submit_edit: Update
index:
empty: No merchants yet
new_long: New merchant
new_short: New
new: New merchant
title: Merchants
list:
merchant:
confirm_accept: Delete merchant
confirm_body: Are you sure you want to delete this merchant? Removing this merchant
will unlink all associated transactions and may effect your reporting.