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

Add transaction sidebar (#534)

* Create sidebar element and working with turbo

* Add overview fields

* Add columns to transations and tidy modal

* permit new transaction params

* Add autosubmit form controller

* remove unused show code
This commit is contained in:
Cristiano Crolla 2024-03-10 21:38:31 +00:00 committed by GitHub
parent 9c9459211f
commit 7f2633f9da
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 134 additions and 15 deletions

View file

@ -56,6 +56,6 @@ class TransactionsController < ApplicationController
# Only allow a list of trusted parameters through. # Only allow a list of trusted parameters through.
def transaction_params def transaction_params
params.require(:transaction).permit(:name, :date, :amount, :currency) params.require(:transaction).permit(:name, :date, :amount, :currency, :notes, :excluded)
end end
end end

View file

@ -31,6 +31,12 @@ module ApplicationHelper
render partial: "shared/currency_dropdown", locals: { f: f, options: options } render partial: "shared/currency_dropdown", locals: { f: f, options: options }
end end
def sidebar_modal(&block)
content = capture &block
render partial: "shared/sidebar_modal", locals: { content: content }
end
def sidebar_link_to(name, path, options = {}) def sidebar_link_to(name, path, options = {})
base_class_names = [ "block", "border", "border-transparent", "rounded-xl", "-ml-2", "p-2", "text-sm", "font-medium", "text-gray-500", "flex", "items-center" ] base_class_names = [ "block", "border", "border-transparent", "rounded-xl", "-ml-2", "p-2", "text-sm", "font-medium", "text-gray-500", "flex", "items-center" ]
hover_class_names = [ "hover:bg-white", "hover:border-alpha-black-50", "hover:text-gray-900", "hover:shadow-xs" ] hover_class_names = [ "hover:bg-white", "hover:border-alpha-black-50", "hover:text-gray-900", "hover:shadow-xs" ]

View file

@ -0,0 +1,33 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
get cssInputSelector() {
return 'input:not(.no-auto-submit), textarea:not(.no-auto-submit)';
}
get inputElements() {
return this.element.querySelectorAll(this.cssInputSelector);
}
get selectElements() {
return this.element.querySelectorAll('select:not(.no-auto-submit)');
}
connect() {
this.inputElements.forEach(el => el.addEventListener('change', this.handler.bind(this)));
this.selectElements.forEach(el => el.addEventListener('change', this.handler.bind(this)));
}
disconnect() {
this.inputElements.forEach(el => el.removeEventListener('change', this.handler.bind(this)));
this.selectElements.forEach(el => el.removeEventListener('change', this.handler.bind(this)));
}
handler(e) {
console.log(e);
this.element.requestSubmit();
}
}

View file

@ -0,0 +1,14 @@
<%= turbo_frame_tag "modal" do %>
<dialog class="bg-white border border-alpha-black-25 rounded-2xl max-h-[calc(100vh-32px)] max-w-[480px] w-full shadow-xs h-full mt-4 mr-4" data-controller="modal" data-action="click->modal#click_outside">
<div class="flex flex-col h-full p-4">
<div class="flex justify-end items-center h-9">
<div data-action="click->modal#close" class="cursor-pointer">
<%= lucide_icon("x", class: "w-5 h-5 shrink-0") %>
</div>
</div>
<div class="flex flex-col overflow-scroll">
<%= content %>
</div>
</div>
</dialog>
<% end %>

View file

@ -1,4 +1,4 @@
<div id="<%= dom_id transaction %>" class="flex items-center gap-6 py-4 text-sm font-medium"> <%= link_to transaction_path(transaction), data: { turbo_frame: "modal" }, class: "text-gray-900 flex items-center gap-6 py-4 text-sm font-medium hover:bg-gray-50 px-4", id: dom_id(transaction) do %>
<div class="w-96 flex items-center gap-2"> <div class="w-96 flex items-center gap-2">
<div class="w-8 h-8 flex items-center justify-center rounded-full bg-gray-600/5 text-gray-600"><%= transaction.name[0].upcase %></div> <div class="w-8 h-8 flex items-center justify-center rounded-full bg-gray-600/5 text-gray-600"><%= transaction.name[0].upcase %></div>
<p class="text-gray-900"><%= transaction.name %></p> <p class="text-gray-900"><%= transaction.name %></p>
@ -9,4 +9,4 @@
<div class="ml-auto"> <div class="ml-auto">
<p class="<%= transaction.amount < 0 ? "text-green-600" : "" %>"><%= number_to_currency(-transaction.amount, { precision: 2 }) %></p> <p class="<%= transaction.amount < 0 ? "text-green-600" : "" %>"><%= number_to_currency(-transaction.amount, { precision: 2 }) %></p>
</div> </div>
</div> <% end %>

View file

@ -4,7 +4,7 @@
<h4><%= date.strftime('%b %d, %Y') %> &middot; <%= transactions.size %></h4> <h4><%= date.strftime('%b %d, %Y') %> &middot; <%= transactions.size %></h4>
<span><%= number_to_currency(-transactions.sum(&:amount)) %></span> <span><%= number_to_currency(-transactions.sum(&:amount)) %></span>
</div> </div>
<div class="bg-white shadow-xs rounded-md border border-alpha-black-25 divide-y divide-alpha-black-50 px-4"> <div class="bg-white shadow-xs rounded-md border border-alpha-black-25 divide-y divide-alpha-black-50">
<%= render partial: "transactions/transaction", collection: transactions %> <%= render partial: "transactions/transaction", collection: transactions %>
</div> </div>
</div> </div>

View file

@ -1,10 +1,68 @@
<div class="mx-auto md:w-2/3 w-full flex"> <%= sidebar_modal do %>
<div class="mx-auto"> <h3 class="font-medium mb-1">
<%= render @transaction %> <span class="text-2xl"><%=format_currency @transaction.amount %></span>
<%= link_to "Edit this transaction", edit_transaction_path(@transaction), class: "mt-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %> <span class="text-lg text-gray-500"><%= @transaction.currency %></span>
<div class="inline-block ml-2"> </h3>
<%= button_to "Destroy this transaction", transaction_path(@transaction), method: :delete, class: "mt-2 rounded-lg py-3 px-5 bg-gray-100 font-medium" %> <span class="text-sm text-gray-500"><%= @transaction.date.strftime("%A %d %B") %></span>
<%= form_with model: @transaction, html: {data: {controller: "auto-submit-form"}} do |f| %>
<details class="group" open>
<summary class="list-none bg-gray-25 rounded-xl py-1 mt-4 group-open:mb-2">
<div class="py-2 px-[11px] flex items-center justify-between font-medium text-xs text-gray-500">
Overview
<%= lucide_icon("chevron-down", class: "hidden group-open:block text-gray-500 w-5 h-5") %>
<%= lucide_icon("chevron-right", class: "group-open:hidden text-gray-500 w-5 h-5") %>
</div> </div>
<%= link_to "Back to transactions", transactions_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %> </summary>
<%= f.date_field :date, label: "Date" %>
<div class="h-2"></div>
<%= f.collection_select :account_id, Current.family.accounts, :id, :name, { prompt: "Select an Account", label: "Account", class: "text-gray-400" }, {class: "form-field__input cursor-not-allowed text-gray-400", disabled: "disabled"} %>
</details>
<details class="group" open>
<summary class="list-none bg-gray-25 rounded-xl py-1 mt-6 group-open:mb-2">
<div class="py-2 px-[11px] flex items-center justify-between font-medium text-xs text-gray-500">
Description
<%= lucide_icon("chevron-down", class: "hidden group-open:block text-gray-500 w-5 h-5") %>
<%= lucide_icon("chevron-right", class: "group-open:hidden text-gray-500 w-5 h-5") %>
</div> </div>
</div> </summary>
<%= f.text_field :name, label: "Name" %>
</details>
<details class="group" open>
<summary class="list-none bg-gray-25 rounded-xl py-1 mt-6 group-open:mb-2">
<div class="py-2 px-[11px] flex items-center justify-between font-medium text-xs text-gray-500">
<span>Settings</span>
<%= lucide_icon("chevron-down", class: "hidden group-open:block text-gray-500 w-5 h-5") %>
<%= lucide_icon("chevron-right", class: "group-open:hidden text-gray-500 w-5 h-5") %>
</div>
</summary>
<label class="flex items-center cursor-pointer justify-between mx-3">
<%= f.check_box :excluded, class: "sr-only peer" %>
<div class="flex flex-col justify-center text-sm w-[340px] py-3">
<span class="text-gray-900 mb-1">Exclude from analytics</span>
<span class="text-gray-500">This excludes the transaction from any in-app features or analytics.</span>
</div>
<div class="relative w-9 h-5 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 rounded-full peer dark:bg-gray-100 peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all dark:border-gray-600 peer-checked:bg-blue-600"></div>
</label>
</details>
<details class="group" open>
<summary class="list-none bg-gray-25 rounded-xl py-1 mt-6 mb-2">
<div class="py-2 px-[11px] flex items-center justify-between font-medium text-xs text-gray-500">
<span>Additional</span>
<%= lucide_icon("chevron-down", class: "hidden group-open:block text-gray-500 w-5 h-5") %>
<%= lucide_icon("chevron-right", class: "group-open:hidden text-gray-500 w-5 h-5") %>
</div>
</summary>
<%= f.text_area :notes, label: "Notes", placeholder: "Enter a note" %>
</details>
<% end %>
<% end %>

View file

@ -0,0 +1,6 @@
class AddNotesAndExcludedToTransaction < ActiveRecord::Migration[7.2]
def change
add_column :transactions, :excluded, :boolean, default: false
add_column :transactions, :notes, :text
end
end

4
db/schema.rb generated
View file

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.2].define(version: 2024_03_07_082827) do ActiveRecord::Schema[7.2].define(version: 2024_03_08_214956) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "pgcrypto" enable_extension "pgcrypto"
enable_extension "plpgsql" enable_extension "plpgsql"
@ -217,6 +217,8 @@ ActiveRecord::Schema[7.2].define(version: 2024_03_07_082827) do
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.uuid "category_id" t.uuid "category_id"
t.boolean "excluded", default: false
t.text "notes"
t.index ["account_id"], name: "index_transactions_on_account_id" t.index ["account_id"], name: "index_transactions_on_account_id"
t.index ["category_id"], name: "index_transactions_on_category_id" t.index ["category_id"], name: "index_transactions_on_category_id"
end end