mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-08-05 21:45:23 +02:00
Scaffold out basic transactions model and UI (#478)
* Transaction scaffold * Rough in transaction views * Fix sort order * Fix mass assignment issue * Fix test * Simplify CI workflow * Don't seed db before test
This commit is contained in:
parent
e767aca37f
commit
87b97b3c41
26 changed files with 430 additions and 44 deletions
7
app/views/transactions/_form.html.erb
Normal file
7
app/views/transactions/_form.html.erb
Normal file
|
@ -0,0 +1,7 @@
|
|||
<%= form_with model: @transaction do |f| %>
|
||||
<%= f.collection_select :account_id, Current.family.accounts, :id, :name, { prompt: "Select an Account", label: "Account" } %>
|
||||
<%= f.date_field :date, label: "Date" %>
|
||||
<%= f.text_field :name, label: "Name" %>
|
||||
<%= f.number_field :amount, label: "Amount", step: :any, placeholder: number_to_currency(0), in: 0.00..100000000.00 %>
|
||||
<%= f.submit %>
|
||||
<% end %>
|
12
app/views/transactions/_transaction.html.erb
Normal file
12
app/views/transactions/_transaction.html.erb
Normal file
|
@ -0,0 +1,12 @@
|
|||
<div id="<%= dom_id transaction %>" class="flex items-center gap-6 py-4 text-sm font-medium">
|
||||
<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>
|
||||
<p class="text-gray-900"><%= transaction.name %></p>
|
||||
</div>
|
||||
<div>
|
||||
<p><%= transaction.account.name %></p>
|
||||
</div>
|
||||
<div class="ml-auto">
|
||||
<p class="<%= transaction.amount < 0 ? "text-green-600" : "" %>"><%= number_to_currency(-transaction.amount, { precision: 2 }) %></p>
|
||||
</div>
|
||||
</div>
|
10
app/views/transactions/_transaction_group.html.erb
Normal file
10
app/views/transactions/_transaction_group.html.erb
Normal file
|
@ -0,0 +1,10 @@
|
|||
<%# locals: (date:, transactions:) %>
|
||||
<div class="bg-gray-25 rounded-xl p-1">
|
||||
<div class="py-2 px-4 flex items-center justify-between font-medium text-xs text-gray-500">
|
||||
<h4><%= date.strftime('%b %d, %Y') %> · <%= transactions.size %></h4>
|
||||
<span><%= number_to_currency(-transactions.sum(&:amount)) %></span>
|
||||
</div>
|
||||
<div class="bg-white shadow-xs rounded-md border border-alpha-black-25 divide-y divide-alpha-black-50 px-4">
|
||||
<%= render partial: "transactions/transaction", collection: transactions %>
|
||||
</div>
|
||||
</div>
|
8
app/views/transactions/edit.html.erb
Normal file
8
app/views/transactions/edit.html.erb
Normal file
|
@ -0,0 +1,8 @@
|
|||
<div class="mx-auto md:w-2/3 w-full">
|
||||
<h1 class="font-bold text-4xl">Editing transaction</h1>
|
||||
|
||||
<%= render "form", transaction: @transaction %>
|
||||
|
||||
<%= link_to "Show this transaction", @transaction, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
|
||||
<%= link_to "Back to transactions", transactions_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
|
||||
</div>
|
75
app/views/transactions/index.html.erb
Normal file
75
app/views/transactions/index.html.erb
Normal file
|
@ -0,0 +1,75 @@
|
|||
<div class="space-y-4">
|
||||
<div class="flex justify-between items-center text-gray-900 font-medium">
|
||||
<h1 class="text-xl">Transactions</h1>
|
||||
<div class="flex items-center gap-5">
|
||||
<div class="flex items-center gap-1 cursor-not-allowed">
|
||||
<span class="text-sm">USD $</span>
|
||||
<%= lucide_icon("chevron-down", class: "w-5 h-5 text-gray-500") %>
|
||||
</div>
|
||||
<div class="border-r border-alpha-black-200 h-5"></div>
|
||||
<div class="flex items-center gap-2">
|
||||
<%= lucide_icon("settings-2", class: "cursor-not-allowed w-5 h-5 text-gray-500") %>
|
||||
<%= link_to new_transaction_path, class: "rounded-full w-9 h-9 bg-gray-900 text-white flex items-center justify-center hover:bg-gray-700" do %>
|
||||
<%= lucide_icon("plus", class: "w-5 h-5") %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-3 bg-white rounded-xl border border-alpha-black-25 shadow-xs px-4 divide-x divide-alpha-black-100">
|
||||
<div class="p-4 space-y-2">
|
||||
<p class="text-sm text-gray-500">Total transactions</p>
|
||||
<p class="text-gray-900 font-medium text-xl"><%= @transactions.size %></p>
|
||||
</div>
|
||||
<div class="p-4 space-y-2">
|
||||
<p class="text-sm text-gray-500">Income</p>
|
||||
<p class="text-gray-900 font-medium text-xl">
|
||||
<%= number_to_currency(@transactions.select { |t| t.amount < 0 }.sum(&:amount).abs, precision: 2) %>
|
||||
</p>
|
||||
</div>
|
||||
<div class="p-4 space-y-2">
|
||||
<p class="text-sm text-gray-500">Expenses</p>
|
||||
<p class="text-gray-900 font-medium text-xl">
|
||||
<%= number_to_currency(@transactions.select { |t| t.amount >= 0 }.sum(&:amount), precision: 2) %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div id="transactions" class="bg-white rounded-xl border border-alpha-black-25 shadow-xs p-4 space-y-4">
|
||||
<div class="flex gap-2">
|
||||
<div class="grow cursor-not-allowed">
|
||||
<%= form_with url: transactions_path, method: :get, local: true, html: { role: 'search' } do |form| %>
|
||||
<div class="relative flex items-center bg-white border border-gray-200 rounded-lg">
|
||||
<%= form.text_field :search, placeholder: "Search transaction by merchant, category or amount", class: "placeholder:text-sm placeholder:text-gray-500 relative pl-10 w-full border-none rounded-lg cursor-not-allowed", 'data-action': "input->search#perform", disabled: true %>
|
||||
<%= 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>
|
||||
<% end %>
|
||||
</div>
|
||||
<div>
|
||||
<button class="cursor-not-allowed border border-gray-200 block h-full rounded-lg flex items-center gap-2 px-4">
|
||||
<%= lucide_icon("list-filter", class: "w-5 h-5 text-gray-500") %>
|
||||
<p class="text-sm font-medium text-gray-900">Filter</p>
|
||||
</button>
|
||||
</div>
|
||||
<%= form_with url: "#", method: :get, class: "flex items-center gap-4", html: { class: "" } do |f| %>
|
||||
<%= f.select :period, options_for_select([['7D', 'last_7_days'], ['1M', 'last_30_days'], ["1Y", "last_365_days"], ['All', 'all']], selected: params[:period]), {}, { class: "block h-full w-full border border-gray-200 rounded-lg text-sm py-2 pr-8 pl-2 cursor-not-allowed", onchange: "this.form.submit();", disabled: true } %>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="bg-gray-25 rounded-xl px-5 py-3 text-xs font-medium text-gray-500 flex items-center gap-6">
|
||||
<div class="w-96">
|
||||
<p class="uppercase">transaction</p>
|
||||
</div>
|
||||
<div class="grow uppercase flex justify-between items-center gap-5 text-xs font-medium text-gray-500">
|
||||
<p>account</p>
|
||||
<p>amount</p>
|
||||
</div>
|
||||
</div>
|
||||
<% if @transactions.empty? %>
|
||||
<p class="text-gray-500 py-4">No transactions for this account yet.</p>
|
||||
<% else %>
|
||||
<div class="space-y-6">
|
||||
<% @transactions.group_by { |transaction| transaction.date }.each do |date, grouped_transactions| %>
|
||||
<%= render partial: "transactions/transaction_group", locals: { date: date, transactions: grouped_transactions } %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
7
app/views/transactions/new.html.erb
Normal file
7
app/views/transactions/new.html.erb
Normal file
|
@ -0,0 +1,7 @@
|
|||
<div class="mx-auto md:w-2/3 w-full">
|
||||
<h1 class="font-bold text-4xl mb-4">New transaction</h1>
|
||||
<%= render "form", transaction: @transaction %>
|
||||
</div>
|
||||
<div class="flex justify-center">
|
||||
<%= link_to "Back to transactions", transactions_path, class: "mt-8 underline text-lg font-bold" %>
|
||||
</div>
|
10
app/views/transactions/show.html.erb
Normal file
10
app/views/transactions/show.html.erb
Normal file
|
@ -0,0 +1,10 @@
|
|||
<div class="mx-auto md:w-2/3 w-full flex">
|
||||
<div class="mx-auto">
|
||||
<%= render @transaction %>
|
||||
<%= 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" %>
|
||||
<div class="inline-block ml-2">
|
||||
<%= button_to "Destroy this transaction", transaction_path(@transaction), method: :delete, class: "mt-2 rounded-lg py-3 px-5 bg-gray-100 font-medium" %>
|
||||
</div>
|
||||
<%= link_to "Back to transactions", transactions_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
|
||||
</div>
|
||||
</div>
|
Loading…
Add table
Add a link
Reference in a new issue