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

Fix account creation

This commit is contained in:
Rob Zolkos 2024-02-02 23:06:29 +00:00
parent ace7fb48ee
commit 48ade396ca
17 changed files with 204 additions and 90 deletions

View file

@ -2,34 +2,35 @@ class AccountsController < ApplicationController
before_action :authenticate_user!
def new
if params[:type].blank? || Account.accountable_types.include?("Account::#{params[:type]}")
@account = if params[:type].blank?
Account.new
else
Account.new(accountable_type: "Account::#{params[:type]}")
end
def new_bank
@account = Depository.new
else
head :not_found
end
def new_credit
@account = Credit.new
end
def show
end
def create
@account = account_type_class.new(account_params)
@account.family = current_family
@account = Account.new(account_params.merge(family: current_family))
@account.accountable = account_params[:accountable_type].constantize.new
if @account.save
redirect_to root_path
redirect_to accounts_path, notice: "New account created successfully"
else
render :new
render "new", status: :unprocessable_entity
end
end
private
def account_params
params.require(:account).permit(:name, :balance, :type, :subtype)
params.require(:account).permit(:name, :accountable_type, :balance, :subtype)
end
def account_type_class

View file

@ -1,9 +1,14 @@
class Account < ApplicationRecord
# VALID_ACCOUNT_TYPES = %w[Investment Depository Credit Loan Property Vehicle OtherAsset OtherLiability].freeze
belongs_to :family
delegated_type :accountable, types: %w[ Credit Depository Investment Loan OtherAsset OtherLiability Property Vehicle], dependent: :destroy
delegated_type :accountable, types: %w[ Account::Credit Account::Depository Account::Investment Account::Loan Account::OtherAsset Account::OtherLiability Account::Property Account::Vehicle], dependent: :destroy
scope :depository, -> { where(type: "Depository") }
delegate :icon, :type_name, :color, to: :accountable
# Class method to get a representative instance of each accountable type
def self.accountable_type_instances
accountable_types.map do |type|
type.constantize.new
end
end
end

View file

@ -1,3 +1,18 @@
class Account::Credit < ApplicationRecord
include Accountable
def icon
"icon-credit-card.svg"
end
def type_name
"Credit Card"
end
def color
{
background: "bg-[#E6F6FA]",
text: "text-[#189FC7]"
}
end
end

View file

@ -1,3 +1,18 @@
class Account::Depository < ApplicationRecord
include Accountable
def icon
"icon-bank-accounts.svg"
end
def type_name
"Bank Accounts"
end
def color
{
background: "bg-[#EAF4FF]",
text: "text-[#3492FB]"
}
end
end

View file

@ -1,3 +1,18 @@
class Account::Investment < ApplicationRecord
include Accountable
def icon
"icon-bank-accounts.svg"
end
def type_name
"Investments"
end
def color
{
background: "bg-[#EDF7F4]",
text: "text-[#1BD5A1]"
}
end
end

View file

@ -1,3 +1,18 @@
class Account::Loan < ApplicationRecord
include Accountable
def icon
"icon-bank-accounts.svg"
end
def type_name
"Loan"
end
def color
{
background: "bg-[#EDF7F4]",
text: "text-[#1BD5A1]"
}
end
end

View file

@ -1,3 +1,18 @@
class Account::OtherAsset < ApplicationRecord
include Accountable
def icon
"icon-bank-accounts.svg"
end
def type_name
"Other Asset"
end
def color
{
background: "bg-[#EDF7F4]",
text: "text-[#1BD5A1]"
}
end
end

View file

@ -1,3 +1,18 @@
class Account::OtherLiability < ApplicationRecord
include Accountable
def icon
"icon-bank-accounts.svg"
end
def type_name
"Other Liability"
end
def color
{
background: "bg-[#EDF7F4]",
text: "text-[#1BD5A1]"
}
end
end

View file

@ -1,3 +1,18 @@
class Account::Property < ApplicationRecord
include Accountable
def icon
"icon-real-estate.svg"
end
def type_name
"Real Estate"
end
def color
{
background: "bg-[#FEF0F7]",
text: "text-[#F03695]"
}
end
end

View file

@ -1,3 +1,18 @@
class Account::Vehicle < ApplicationRecord
include Accountable
def icon
"icon-bank-accounts.svg"
end
def type_name
"Vehicle"
end
def color
{
background: "bg-[#EDF7F4]",
text: "text-[#1BD5A1]"
}
end
end

View file

@ -1,2 +0,0 @@
class Depository < Account
end

View file

@ -0,0 +1,9 @@
<div class="relative flex-col items-center px-5 py-4 space-x-3 text-center bg-white border border-gray-100 shadow-sm rounded-xl hover:border-gray-200">
<%= link_to new_account_path(type: account_type.class.name.demodulize), class: "flex flex-col items-center justify-center w-full text-center focus:outline-none" do %>
<span class="absolute inset-0" aria-hidden="true"></span>
<span class="flex w-10 h-10 shrink-0 grow-0 items-center justify-center rounded-xl <%= account_type.color[:background] %> mb-2">
<%= inline_svg_tag(account_type.icon, class: "#{account_type.color[:text]} stroke-current") %>
</span>
<%= account_type.type_name %>
<% end %>
</div>

View file

@ -0,0 +1,17 @@
<h2 class="text-2xl font-semibold font-display">Cash</h2>
<h3 class="mt-1 mb-4 text-sm text-gray-500"><%#= number_to_currency current_family.cash_balance %></h3>
<% current_family.accounts.each do |account| %>
<div class="flex items-center justify-between px-3 py-3 mb-2 bg-white shadow-sm rounded-xl">
<div class="flex items-center text-sm">
<%= account.name %>
</div>
<div class="flex items-center text-sm">
<%= account.accountable %>
</div>
<p class="text-sm text-right">
<span class="block mb-1"><%= number_to_currency account.balance %></span>
</p>
</div>
<% end %>

View file

@ -1,43 +1,37 @@
<h1 class="text-3xl font-semibold font-display">Add an account</h1>
<% if params[:type].blank? || Account.accountable_types.include?("Account::#{params[:type]}") == false %>
<div class="grid grid-cols-2 gap-4 mt-8 text-sm sm:grid-cols-3 md:grid-cols-4">
<div class="relative flex-col items-center px-5 py-4 space-x-3 text-center bg-white border border-gray-100 shadow-sm rounded-xl hover:border-gray-200">
<%= link_to new_bank_path, class: "flex flex-col items-center justify-center w-full text-center focus:outline-none" do %>
<span class="absolute inset-0" aria-hidden="true"></span>
<span class="flex w-10 h-10 shrink-0 grow-0 items-center justify-center rounded-xl bg-[#EAF4FF] mb-2">
<%= inline_svg_tag('icon-bank-accounts.svg', class: 'text-[#3492FB] stroke-current') %>
</span>
Bank accounts
<%= render partial: "account_type", collection: Account.accountable_type_instances %>
</div>
<% else %>
<div class="relative flex items-center mb-5 space-x-2">
<%= link_to new_account_path, class: "" do %>
<%= inline_svg_tag('icon-arrow-left.svg', class: 'text-gray-500 fill-current') %>
<% end %>
<h2 class="text-2xl font-semibold font-display">Enter <%= params[:type] %> account</h2>
</div>
<div class="relative flex-col items-center px-5 py-4 space-x-3 text-center bg-white border border-gray-100 shadow-sm rounded-xl hover:border-gray-200">
<%= link_to new_credit_path, class: "flex flex-col items-center justify-center w-full text-center focus:outline-none" do %>
<span class="absolute inset-0" aria-hidden="true"></span>
<span class="flex w-10 h-10 shrink-0 grow-0 items-center justify-center rounded-xl bg-[#E6F6FA] mb-2">
<%= inline_svg_tag('icon-credit-card.svg', class: 'text-[#189FC7] stroke-current') %>
</span>
Credit cards
<% end %>
<%= form_with model: @account, url: accounts_path, scope: :account, html: { class: "space-y-4" } do |f| %>
<%= f.hidden_field :accountable_type %>
<div class="relative p-4 border border-gray-100 bg-offwhite rounded-xl focus-within:bg-white focus-within:shadow focus-within:opacity-100">
<%# <span class="absolute px-2 py-1 text-xs font-medium text-gray-400 uppercase bg-gray-200 rounded-full opacity-50 right-3">Optional</span> %>
<label for="account_name" class="block text-sm font-medium opacity-50 focus-within:opacity-100">Name</label>
<%= f.text_field :name, placeholder: "Account name", required: 'required', class: "p-0 mt-1 bg-transparent border-none opacity-50 focus:outline-none focus:ring-0 focus-within:opacity-100" %>
</div>
<div class="relative flex-col items-center px-5 py-4 space-x-3 text-center bg-white border border-gray-100 shadow-sm rounded-xl hover:border-gray-200">
<%= link_to "new_investment_path", class: "flex flex-col items-center justify-center w-full text-center focus:outline-none" do %>
<span class="absolute inset-0" aria-hidden="true"></span>
<span class="flex w-10 h-10 shrink-0 grow-0 items-center justify-center rounded-xl bg-[#EDF7F4] mb-2">
<%= inline_svg_tag('icon-investments.svg', class: 'text-[#1BD5A1] stroke-current') %>
</span>
Investments
<% end %>
<div class="relative p-4 border border-gray-100 bg-offwhite rounded-xl focus-within:bg-white focus-within:shadow focus-within:opacity-100">
<label for="account_name" class="block text-sm font-medium opacity-50 focus-within:opacity-100">Balance</label>
<div class="flex">
<%= f.number_field :balance, placeholder: "$0.00", in: 0.00..100000000.00, required: 'required', class: "p-0 mt-1 bg-transparent border-none opacity-50 focus:outline-none focus:ring-0 focus-within:opacity-100" %>
</div>
</div>
<div class="relative flex-col items-center px-5 py-4 space-x-3 text-center bg-white border border-gray-100 shadow-sm rounded-xl hover:border-gray-200">
<%= link_to "new_real_estate_path", class: "flex flex-col items-center justify-center w-full text-center focus:outline-none" do %>
<span class="absolute inset-0" aria-hidden="true"></span>
<span class="flex w-10 h-10 shrink-0 grow-0 items-center justify-center rounded-xl bg-[#FEF0F7] mb-2">
<%= inline_svg_tag('icon-real-estate.svg', class: 'text-[#F03695] stroke-current') %>
</span>
Real estate
<div class="absolute right-5 bottom-5">
<button type="submit" class="flex items-center justify-center w-12 h-12 mb-2 bg-black rounded-full shrink-0 grow-0 hover:bg-gray-600">
<i class="text-xl text-white fa-regular fa-check"></i>
</button>
</div>
<% end %>
<% end %>
</div>
</div>

View file

@ -1,34 +0,0 @@
<div class="relative flex items-center mb-5 space-x-2">
<%= link_to new_account_path, class: "" do %>
<%= inline_svg_tag('icon-arrow-left.svg', class: 'text-gray-500 fill-current') %>
<% end %>
<h2 class="text-2xl font-semibold font-display">Enter bank account</h2>
</div>
<%= form_with model: @account, url: accounts_path, scope: :account, html: { class: "space-y-4" } do |f| %>
<%= f.hidden_field :type, value: "Depository" %>
<div class="relative p-4 border border-gray-100 bg-offwhite rounded-xl focus-within:bg-white focus-within:shadow focus-within:opacity-100">
<%# <span class="absolute px-2 py-1 text-xs font-medium text-gray-400 uppercase bg-gray-200 rounded-full opacity-50 right-3">Optional</span> %>
<label for="account_name" class="block text-sm font-medium opacity-50 focus-within:opacity-100">Name</label>
<%= f.text_field :name, placeholder: "Account name", required: 'required', class: "p-0 mt-1 bg-transparent border-none opacity-50 focus:outline-none focus:ring-0 focus-within:opacity-100" %>
</div>
<div class="relative p-4 border border-gray-100 bg-offwhite rounded-xl focus-within:bg-white focus-within:shadow focus-within:opacity-100">
<label for="account_name" class="block text-sm font-medium opacity-50 focus-within:opacity-100">Type</label>
<%= f.select :subtype, options_for_select([["Checking", "checking"], ["Savings", "savings"]], selected: ""), {}, class: "block w-full p-0 mt-1 bg-transparent border-none focus:outline-none focus:ring-0" %>
</div>
<div class="relative p-4 border border-gray-100 bg-offwhite rounded-xl focus-within:bg-white focus-within:shadow focus-within:opacity-100">
<label for="account_name" class="block text-sm font-medium opacity-50 focus-within:opacity-100">Balance</label>
<div class="flex">
<%= f.number_field :balance, placeholder: "$0.00", in: 0.00..100000000.00, required: 'required', class: "p-0 mt-1 bg-transparent border-none opacity-50 focus:outline-none focus:ring-0 focus-within:opacity-100" %>
</div>
</div>
<div class="absolute right-5 bottom-5">
<button type="submit" class="flex items-center justify-center w-12 h-12 mb-2 bg-black rounded-full shrink-0 grow-0 hover:bg-gray-600">
<i class="text-xl text-white fa-regular fa-check"></i>
</button>
</div>
<% end %>

View file

@ -79,4 +79,7 @@ Rails.application.configure do
# Apply autocorrection by RuboCop to files generated by `bin/rails generate`.
config.generators.apply_rubocop_autocorrect_after_generate!
# Allow connection from any host in development
config.hosts = nil
end

View file

@ -4,6 +4,7 @@ module.exports = {
content: [
'./public/*.html',
'./app/helpers/**/*.rb',
'./app/models/**/*.rb',
'./app/javascript/**/*.js',
'./app/views/**/*.{erb,haml,html,slim}'
],