mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-08-02 20:15:22 +02:00
Move categories to top-level namespace (#894)
This commit is contained in:
parent
a947db92b2
commit
2681dd96b1
48 changed files with 229 additions and 223 deletions
10
app/views/categories/_badge.html.erb
Normal file
10
app/views/categories/_badge.html.erb
Normal file
|
@ -0,0 +1,10 @@
|
|||
<%# locals: (category:) %>
|
||||
<% category ||= null_category %>
|
||||
|
||||
<span class="border text-sm font-medium px-2.5 py-1 rounded-full content-center"
|
||||
style="
|
||||
background-color: color-mix(in srgb, <%= category.color %> 5%, white);
|
||||
border-color: color-mix(in srgb, <%= category.color %> 10%, white);
|
||||
color: <%= category.color %>;">
|
||||
<%= category.name %>
|
||||
</span>
|
38
app/views/categories/_form.html.erb
Normal file
38
app/views/categories/_form.html.erb
Normal file
|
@ -0,0 +1,38 @@
|
|||
<%= form_with model: category, data: { turbo: false } do |form| %>
|
||||
<div class="flex flex-col space-y-4 w-96" data-controller="color-select" data-color-select-selection-value="<%= category.color %>">
|
||||
<fieldset class="relative">
|
||||
<span data-color-select-target="decoration" class="pointer-events-none absolute inset-y-3.5 left-3 flex items-center pl-1 block w-1 rounded-lg"></span>
|
||||
<%= form.text_field :name,
|
||||
value: category.name,
|
||||
autofocus: "",
|
||||
required: true,
|
||||
placeholder: "Enter Category name",
|
||||
class: "rounded-lg w-full focus:ring-black focus:border-transparent placeholder:text-gray-500 pl-6" %>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<%= form.hidden_field :color, data: { color_select_target: "input" } %>
|
||||
|
||||
<ul role="radiogroup" class="flex justify-between items-center py-2">
|
||||
<% Category::COLORS.each do |color| %>
|
||||
<li tabindex="0"
|
||||
role="radio"
|
||||
data-action="click->color-select#select keydown.enter->color-select#select keydown.space->color-select#select"
|
||||
data-value="<%= color %>"
|
||||
class="flex shrink-0 justify-center items-center w-5 h-5 cursor-pointer hover:bg-gray-200 rounded-full">
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</fieldset>
|
||||
|
||||
<section>
|
||||
<%= hidden_field_tag :transaction_id, params[:transaction_id] %>
|
||||
|
||||
<% if category.persisted? %>
|
||||
<%= form.submit t(".update") %>
|
||||
<% else %>
|
||||
<%= form.submit t(".create") %>
|
||||
<% end %>
|
||||
</section>
|
||||
</div>
|
||||
<% end %>
|
15
app/views/categories/_menu.html.erb
Normal file
15
app/views/categories/_menu.html.erb
Normal file
|
@ -0,0 +1,15 @@
|
|||
<%# locals: (transaction:) %>
|
||||
<div class="relative" data-controller="menu">
|
||||
<button data-menu-target="button" class="flex cursor-pointer">
|
||||
<%= render partial: "categories/badge", locals: { category: transaction.category } %>
|
||||
</button>
|
||||
<div data-menu-target="content" class="absolute z-10 hidden w-screen mt-2 max-w-min cursor-default">
|
||||
<div class="w-64 text-sm font-semibold leading-6 text-gray-900 bg-white shadow-lg shrink rounded-xl ring-1 ring-gray-900/5">
|
||||
<%= turbo_frame_tag "category_dropdown", src: category_dropdown_path(category_id: transaction.category_id, transaction_id: transaction.id), loading: :lazy do %>
|
||||
<div class="p-6 flex items-center justify-center">
|
||||
<p class="text-sm text-gray-500 animate-pulse"><%= t(".loading") %></p>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
23
app/views/categories/_row.html.erb
Normal file
23
app/views/categories/_row.html.erb
Normal file
|
@ -0,0 +1,23 @@
|
|||
<div class="flex justify-between mx-4 py-5 border-b last:border-b-0 border-alpha-black-50">
|
||||
<%= render partial: "categories/badge", locals: { category: row } %>
|
||||
|
||||
<%= 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">
|
||||
<%= link_to edit_category_path(row),
|
||||
class: "block w-full py-2 px-3 space-x-2 text-gray-900 hover:bg-gray-50 flex items-center rounded-lg",
|
||||
data: { turbo_frame: :modal } do %>
|
||||
<%= lucide_icon "pencil-line", class: "w-5 h-5 text-gray-500" %>
|
||||
|
||||
<span><%= t(".edit") %></span>
|
||||
<% end %>
|
||||
|
||||
<%= link_to new_category_deletion_path(row),
|
||||
class: "block w-full py-2 px-3 space-x-2 text-red-600 hover:bg-red-50 flex items-center rounded-lg",
|
||||
data: { turbo_frame: :modal } do %>
|
||||
<%= lucide_icon "trash-2", class: "w-5 h-5" %>
|
||||
|
||||
<span><%= t(".delete") %></span>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
33
app/views/categories/deletions/new.html.erb
Normal file
33
app/views/categories/deletions/new.html.erb
Normal file
|
@ -0,0 +1,33 @@
|
|||
<%= modal do %>
|
||||
<article class="mx-auto p-4 w-screen max-w-md">
|
||||
<div class="space-y-2">
|
||||
<header class="flex justify-between">
|
||||
<h2 class="font-medium text-xl"><%= t(".delete_category") %></h2>
|
||||
<%= lucide_icon "x", class: "w-5 h-5 text-gray-500", data: { action: "click->modal#close" } %>
|
||||
</header>
|
||||
|
||||
<p class="text-gray-500 font-light">
|
||||
<%= t(".explanation", category_name: @category.name) %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<%= form_with url: category_deletions_path(@category),
|
||||
data: {
|
||||
turbo: false,
|
||||
controller: "deletion",
|
||||
deletion_dangerous_action_class: "form-field__submit bg-white text-red-600 border hover:bg-red-50",
|
||||
deletion_safe_action_class: "form-field__submit border border-transparent",
|
||||
deletion_submit_text_when_not_replacing_value: t(".delete_and_leave_uncategorized", category_name: @category.name),
|
||||
deletion_submit_text_when_replacing_value: t(".delete_and_recategorize", category_name: @category.name) } do |f| %>
|
||||
<%= f.collection_select :replacement_category_id,
|
||||
Current.family.categories.alphabetically.without(@category),
|
||||
:id, :name,
|
||||
{ prompt: t(".replacement_category_prompt"), label: t(".category") },
|
||||
{ data: { deletion_target: "replacementField", action: "deletion#updateSubmitButton" } } %>
|
||||
|
||||
<%= f.submit t(".delete_and_leave_uncategorized", category_name: @category.name),
|
||||
class: "form-field__submit bg-white text-red-600 border hover:bg-red-50",
|
||||
data: { deletion_target: "submitButton" } %>
|
||||
<% end %>
|
||||
</article>
|
||||
<% end %>
|
31
app/views/categories/dropdowns/_row.html.erb
Normal file
31
app/views/categories/dropdowns/_row.html.erb
Normal file
|
@ -0,0 +1,31 @@
|
|||
<%# locals: (category:) %>
|
||||
<% is_selected = category.id === @selected_category&.id %>
|
||||
|
||||
<%= content_tag :div, class: ["filterable-item flex justify-between items-center border-none rounded-lg px-2 py-1 group w-full", { "bg-gray-25": is_selected }], data: { filter_name: category.name } do %>
|
||||
<%= button_to transaction_row_path(@transaction, transaction: { category_id: category.id }), method: :patch, data: { turbo_frame: dom_id(@transaction) }, class: "flex w-full items-center gap-1.5 cursor-pointer" do %>
|
||||
<span class="w-5 h-5">
|
||||
<%= lucide_icon("check", class: "w-5 h-5 text-gray-500") if is_selected %>
|
||||
</span>
|
||||
<%= render partial: "categories/badge", locals: { category: category } %>
|
||||
<% 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">
|
||||
<%= link_to edit_category_path(category),
|
||||
class: "block w-full py-2 px-3 space-x-2 text-gray-900 hover:bg-gray-50 flex items-center rounded-lg",
|
||||
data: { turbo_frame: :modal } do %>
|
||||
<%= lucide_icon "pencil-line", class: "w-5 h-5 text-gray-500" %>
|
||||
|
||||
<span><%= t(".edit") %></span>
|
||||
<% end %>
|
||||
|
||||
<%= link_to new_category_deletion_path(category),
|
||||
class: "block w-full py-2 px-3 space-x-2 text-red-600 hover:bg-red-50 flex items-center rounded-lg",
|
||||
data: { turbo_frame: :modal } do %>
|
||||
<%= lucide_icon "trash-2", class: "w-5 h-5" %>
|
||||
|
||||
<span><%= t(".delete") %></span>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
40
app/views/categories/dropdowns/show.html.erb
Normal file
40
app/views/categories/dropdowns/show.html.erb
Normal file
|
@ -0,0 +1,40 @@
|
|||
<%= turbo_frame_tag "category_dropdown" do %>
|
||||
<div class="flex flex-col relative" data-controller="list-filter">
|
||||
<div class="grow p-1.5">
|
||||
<div class="relative flex items-center bg-white border border-gray-200 rounded-lg">
|
||||
<input placeholder="<%= t(".search_placeholder") %>" autocomplete="nope" type="search" class="placeholder:text-sm placeholder:text-gray-500 font-normal h-10 relative pl-10 w-full border-none rounded-lg" data-list-filter-target="input" data-action="list-filter#filter">
|
||||
<%= lucide_icon("search", class: "w-5 h-5 text-gray-500 ml-2 absolute inset-0 transform top-1/2 -translate-y-1/2") %>
|
||||
</div>
|
||||
</div>
|
||||
<div data-list-filter-target="list" class="flex flex-col gap-0.5 p-1.5 mt-0.5 mr-2 max-h-64 overflow-y-scroll scrollbar">
|
||||
<div class="pb-2 pl-4 mr-2 text-gray-500 hidden" data-list-filter-target="emptyMessage">
|
||||
<%= t(".no_categories") %>
|
||||
</div>
|
||||
<% @categories.each do |category| %>
|
||||
<%= render partial: "categories/dropdowns/row", locals: { category: } %>
|
||||
<% end %>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="relative p-1.5 w-full">
|
||||
<%= link_to new_category_path(transaction_id: @transaction),
|
||||
class: "flex text-sm font-medium items-center gap-2 text-gray-500 w-full rounded-lg p-2 hover:bg-gray-100",
|
||||
data: { turbo_frame: "modal" } do %>
|
||||
<%= lucide_icon "plus", class: "w-5 h-5" %>
|
||||
|
||||
<%= t(".add_new") %>
|
||||
<% end %>
|
||||
|
||||
<% if @transaction.category %>
|
||||
<%= button_to transaction_row_path(@transaction),
|
||||
method: :patch,
|
||||
data: { turbo_frame: dom_id(@transaction) },
|
||||
params: { transaction: { category_id: nil } },
|
||||
class: "flex text-sm font-medium items-center gap-2 text-gray-500 w-full rounded-lg p-2 hover:bg-gray-100" do %>
|
||||
<%= lucide_icon "minus", class: "w-5 h-5" %>
|
||||
|
||||
<%= t(".clear") %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
10
app/views/categories/edit.html.erb
Normal file
10
app/views/categories/edit.html.erb
Normal file
|
@ -0,0 +1,10 @@
|
|||
<%= modal do %>
|
||||
<article class="mx-auto w-full p-4 space-y-4">
|
||||
<header class="flex justify-between">
|
||||
<h2 class="font-medium text-xl"><%= t(".edit") %></h2>
|
||||
<%= lucide_icon "x", class: "w-5 h-5 text-gray-500", data: { action: "click->modal#close" } %>
|
||||
</header>
|
||||
|
||||
<%= render "form", category: @category %>
|
||||
</article>
|
||||
<% end %>
|
28
app/views/categories/index.html.erb
Normal file
28
app/views/categories/index.html.erb
Normal file
|
@ -0,0 +1,28 @@
|
|||
<% content_for :sidebar do %>
|
||||
<%= render "settings/nav" %>
|
||||
<% end %>
|
||||
<section class="space-y-4">
|
||||
<header class="flex items-center justify-between">
|
||||
<h1 class="text-gray-900 text-xl font-medium"><%= t(".categories") %></h1>
|
||||
|
||||
<%= link_to new_category_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" %>
|
||||
<p><%= t(".new") %></p>
|
||||
<% end %>
|
||||
</header>
|
||||
|
||||
<div class="bg-white shadow-xs border border-alpha-black-25 rounded-xl p-4">
|
||||
<div class="rounded-xl bg-gray-25 p-1">
|
||||
<h2 class="uppercase px-4 py-2 text-gray-500 text-xs"><%= t(".categories") %> · <%= @categories.size %></h2>
|
||||
|
||||
<div class="border border-alpha-gray-100 rounded-lg bg-white shadow-xs">
|
||||
<%= render collection: @categories, partial: "categories/row" %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="flex justify-between gap-4">
|
||||
<%= previous_setting("Tags", tags_path) %>
|
||||
<%= next_setting("Merchants", transaction_merchants_path) %>
|
||||
</footer>
|
||||
</section>
|
10
app/views/categories/new.html.erb
Normal file
10
app/views/categories/new.html.erb
Normal file
|
@ -0,0 +1,10 @@
|
|||
<%= modal do %>
|
||||
<article class="mx-auto w-full p-4 space-y-4">
|
||||
<header class="flex justify-between">
|
||||
<h2 class="font-medium text-xl"><%= t(".new_category") %></h2>
|
||||
<%= lucide_icon "x", class: "w-5 h-5 text-gray-500", data: { action: "click->modal#close" } %>
|
||||
</header>
|
||||
|
||||
<%= render "form", category: @category %>
|
||||
</article>
|
||||
<% end %>
|
Loading…
Add table
Add a link
Reference in a new issue