mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-08-05 21:45:23 +02:00
Add new category flow (#1857)
* resolve git issue * Add new category flow * Improve contrast checker * make error message small * update ui to match figma design * realign color picker * changes * rename color picker controller to new category controller * cleanup code * cleanup code * resize and realign icon avatar * Fix js lint errors Signed-off-by: Syed Bariman Jan <syedbarimanjan@gmail.com> --------- Signed-off-by: Syed Bariman Jan <syedbarimanjan@gmail.com>
This commit is contained in:
parent
ac9703031f
commit
95989a6c9b
14 changed files with 335 additions and 40 deletions
8
app/views/categories/_color_avatar.html.erb
Normal file
8
app/views/categories/_color_avatar.html.erb
Normal file
|
@ -0,0 +1,8 @@
|
|||
<%# locals: (category:) %>
|
||||
|
||||
<span
|
||||
data-category-target="avatar"
|
||||
class="w-14 h-14 flex items-center justify-center rounded-full"
|
||||
style="background-color: color-mix(in oklab, <%= category.color %> 10%, transparent); color: <%= category.color %>">
|
||||
<%= lucide_icon(category.lucide_icon, class: "w-8 h-8") %>
|
||||
</span>
|
|
@ -1,42 +1,70 @@
|
|||
<%# locals: (category:, categories:) %>
|
||||
|
||||
<div data-controller="color-avatar">
|
||||
<div data-controller="category" data-category-preset-colors-value="<%= Category::COLORS %>">
|
||||
<%= styled_form_with model: category, class: "space-y-4" do |f| %>
|
||||
<section class="space-y-4">
|
||||
<div class="w-fit m-auto">
|
||||
<%= render partial: "shared/color_avatar", locals: { name: category.name, color: category.color } %>
|
||||
<%= render partial: "color_avatar", locals: { category: category } %>
|
||||
</div>
|
||||
<details data-category-target="details">
|
||||
<summary class="cursor-pointer absolute top-23 left-58.5 flex justify-center items-center bg-gray-50 border-2 w-7 h-7 border-white rounded-full text-gray-500">
|
||||
<%= icon("pen", size: "sm") %>
|
||||
</summary>
|
||||
|
||||
<div class="flex gap-2 items-center justify-center" data-color-avatar-target="selection">
|
||||
<% Category::COLORS.each do |color| %>
|
||||
<label class="relative">
|
||||
<%= f.radio_button :color, color, class: "sr-only peer", data: { action: "change->color-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=" absolute z-50 bg-white p-4 border border-alpha-black-25 rounded-2xl shadow-xs h-fit left-66 top-24">
|
||||
<div class="flex gap-2 flex-col mb-4" data-category-target="selection" style="<%= "display:none;" if @category.subcategory? %>">
|
||||
<div data-category-target="pickerSection"></div>
|
||||
<h4 class="text-gray-500 text-sm">Color</h4>
|
||||
<div class="flex gap-2 items-center" data-category-target="colorsSection">
|
||||
<% Category::COLORS.each do |color| %>
|
||||
<label class="relative">
|
||||
<%= f.radio_button :color, color, class: "sr-only peer", data: { action: "change->category#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 %>
|
||||
<label class="relative">
|
||||
<%= f.radio_button :color, "custom-color", class: "sr-only peer", data: { category_target: "colorPickerRadioBtn"} %>
|
||||
<div class="w-6 h-6 rounded-full cursor-pointer peer-checked:ring-2 peer-checked:ring-offset-2 peer-checked:ring-blue-500" data-category-target="pickerBtn" style="background: conic-gradient(red,orange,yellow,lime,green,teal,cyan,blue,indigo,purple,magenta,pink,red)" ></div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="flex gap-2 items-center hidden flex-col" data-category-target="paletteSection">
|
||||
<div class="flex gap-2 items-center w-full">
|
||||
<div class="w-6 h-6 p-4 rounded-full cursor-pointer" style="background-color: <%= category.color %>" data-category-target="colorPreview"></div>
|
||||
<%= f.text_field :color , data: { category_target: "colorInput"}, class: "form-field__input blah", inline: true %>
|
||||
<%= lucide_icon "palette", class: "w-8 h-8 cursor-pointer hover:bg-gray-100 p-1", data: { action: "click->category#toggleSections" } %>
|
||||
</div>
|
||||
<div data-category-target="validationMessage" class="hidden self-start flex gap-1 items-center text-xs text-destructive ">
|
||||
<span>Poor contrast, choose darker color or</span>
|
||||
<button type="button" class="underline cursor-pointer" data-action="category#autoAdjust">auto-adjust.</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap gap-2 justify-center flex-col w-87">
|
||||
<h4 class="text-gray-500 text-sm">Icon</h4>
|
||||
<div class="flex flex-wrap gap-0.5">
|
||||
<% Category.icon_codes.each do |icon| %>
|
||||
<label class="relative">
|
||||
<%= f.radio_button :lucide_icon, icon, class: "sr-only peer", data: { action: "change->category#handleIconChange change->category#handleIconColorChange", category_target:"icon" } %>
|
||||
<div class="w-7 h-7 flex m-0.5 items-center justify-center rounded-full cursor-pointer hover:bg-gray-100 peer-checked:bg-gray-100 border-1 border-transparent" >
|
||||
<%= lucide_icon icon, class: "w-6 h-6 p-1" %>
|
||||
</div>
|
||||
</label>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<% if category.errors.any? %>
|
||||
<%= render "shared/form_errors", model: category %>
|
||||
<% end %>
|
||||
|
||||
<div class="flex flex-wrap gap-2 justify-center mb-4">
|
||||
|
||||
<% Category.icon_codes.each do |icon| %>
|
||||
<label class="relative">
|
||||
<%= f.radio_button :lucide_icon, icon, class: "sr-only peer" %>
|
||||
<div class="p-1 rounded cursor-pointer hover:bg-gray-100 peer-checked:bg-gray-100 border-1 border-transparent peer-checked:border-gray-500">
|
||||
<%= lucide_icon icon, class: "w-5 h-5" %>
|
||||
</div>
|
||||
</label>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="space-y-2">
|
||||
<%= f.select :classification, [["Income", "income"], ["Expense", "expense"]], { label: "Classification" }, required: true %>
|
||||
<%= f.text_field :name, placeholder: t(".placeholder"), required: true, autofocus: true, label: "Name", data: { color_avatar_target: "name" } %>
|
||||
<% unless category.parent? %>
|
||||
<%= f.select :parent_id, categories.pluck(:name, :id), { include_blank: "(unassigned)", label: "Parent category (optional)" }, disabled: category.parent?, data: { action: "change->color-avatar#handleParentChange" } %>
|
||||
<%= f.select :parent_id, categories.pluck(:name, :id), { include_blank: "(unassigned)", label: "Parent category (optional)" }, disabled: category.parent?, data: { action: "change->category#handleParentChange" } %>
|
||||
<% end %>
|
||||
</div>
|
||||
</section>
|
||||
|
|
|
@ -8,4 +8,4 @@
|
|||
class="w-8 h-8 flex items-center justify-center rounded-full"
|
||||
style="background-color: <%= background_color %>; border-color: <%= border_color %>; color: <%= color %>">
|
||||
<%= letter.upcase %>
|
||||
</span>
|
||||
</span>
|
|
@ -1,8 +1,8 @@
|
|||
<%# locals: (content:, classes:) -%>
|
||||
<%= turbo_frame_tag "modal" do %>
|
||||
<dialog class="m-auto bg-white shadow-border-xs rounded-2xl max-w-[580px] w-min-content h-fit <%= classes %>" data-controller="modal" data-action="click->modal#clickOutside">
|
||||
<dialog class="m-auto bg-white shadow-border-xs rounded-2xl max-w-[580px] w-min-content h-fit overflow-visible <%= classes %>" data-controller="modal" data-action="click->modal#clickOutside">
|
||||
<div class="flex flex-col">
|
||||
<%= content %>
|
||||
</div>
|
||||
</dialog>
|
||||
<% end %>
|
||||
<% end %>
|
Loading…
Add table
Add a link
Reference in a new issue