mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-08-07 22:45:20 +02:00
New Design System + Codebase Refresh (#1823)
Since the very first 0.1.0-alpha.1 release, we've been moving quickly to add new features to the Maybe app. In doing so, some parts of the codebase have become outdated, unnecessary, or overly-complex as a natural result of this feature prioritization. Now that "core" Maybe is complete, we're moving into a second phase of development where we'll be working hard to improve the accuracy of existing features and build additional features on top of "core". This PR is a quick overhaul of the existing codebase aimed to: - Establish the brand new and simplified dashboard view (pictured above) - Establish and move towards the conventions introduced in Cursor rules and project design overview #1788 - Consolidate layouts and improve the performance of layout queries - Organize the core models of the Maybe domain (i.e. Account::Entry, Account::Transaction, etc.) and break out specific traits of each model into dedicated concerns for better readability - Remove stale / dead code from codebase - Remove overly complex code paths in favor of simpler ones
This commit is contained in:
parent
8539ac7dec
commit
d75be2282b
278 changed files with 3428 additions and 4354 deletions
|
@ -4,26 +4,24 @@
|
|||
<div class="p-4 border-b border-gray-100">
|
||||
<h3 class="text-sm text-secondary mb-2">Income</h3>
|
||||
|
||||
<% income_totals = budget.income_categories_with_totals %>
|
||||
<% income_categories = income_totals.category_totals.reject { |ct| ct.amount_money.zero? }.sort_by { |ct| ct.percentage }.reverse %>
|
||||
<span class="inline-block mb-2 text-xl font-medium text-primary">
|
||||
<%= format_money(income_totals.total_money) %>
|
||||
<%= budget.actual_income_money.format %>
|
||||
</span>
|
||||
|
||||
<% if income_categories.any? %>
|
||||
<% if budget.income_category_totals.any? %>
|
||||
<div>
|
||||
<div class="flex h-1.5 mb-3 gap-1">
|
||||
<% income_categories.each do |item| %>
|
||||
<div class="h-full rounded-xs" style="background-color: <%= item.category.color %>; width: <%= item.percentage %>%"></div>
|
||||
<% budget.income_category_totals.each do |category_total| %>
|
||||
<div class="h-full rounded-xs" style="background-color: <%= category_total.category.color %>; width: <%= category_total.weight %>%"></div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap gap-x-2.5 gap-y-1 text-xs">
|
||||
<% income_categories.each do |item| %>
|
||||
<% budget.income_category_totals.each do |category_total| %>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<div class="w-2.5 h-2.5 rounded-full shrink-0" style="background-color: <%= item.category.color %>"></div>
|
||||
<span class="text-secondary"><%= item.category.name %></span>
|
||||
<span class="text-primary"><%= number_to_percentage(item.percentage, precision: 0) %></span>
|
||||
<div class="w-2.5 h-2.5 rounded-full shrink-0" style="background-color: <%= category_total.category.color %>"></div>
|
||||
<span class="text-secondary"><%= category_total.category.name %></span>
|
||||
<span class="text-primary"><%= number_to_percentage(category_total.weight, precision: 0) %></span>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
@ -34,25 +32,22 @@
|
|||
<div class="p-4">
|
||||
<h3 class="text-sm text-secondary mb-2">Expenses</h3>
|
||||
|
||||
<% expense_totals = budget.expense_categories_with_totals %>
|
||||
<% expense_categories = expense_totals.category_totals.reject { |ct| ct.amount_money.zero? || ct.category.subcategory? }.sort_by { |ct| ct.percentage }.reverse %>
|
||||
<span class="inline-block mb-2 text-xl font-medium text-primary"><%= budget.actual_spending_money.format %></span>
|
||||
|
||||
<span class="inline-block mb-2 text-xl font-medium text-primary"><%= format_money(expense_totals.total_money) %></span>
|
||||
|
||||
<% if expense_categories.any? %>
|
||||
<% if budget.expense_category_totals.any? %>
|
||||
<div>
|
||||
<div class="flex h-1.5 mb-3 gap-1">
|
||||
<% expense_categories.each do |item| %>
|
||||
<div class="h-full rounded-xs" style="background-color: <%= item.category.color %>; width: <%= item.percentage %>%"></div>
|
||||
<% budget.expense_category_totals.each do |category_total| %>
|
||||
<div class="h-full rounded-xs" style="background-color: <%= category_total.category.color %>; width: <%= category_total.weight %>%"></div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap gap-x-2.5 gap-y-1 text-xs">
|
||||
<% expense_categories.each do |item| %>
|
||||
<% budget.expense_category_totals.each do |category_total| %>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<div class="w-2.5 h-2.5 rounded-full shrink-0" style="background-color: <%= item.category.color %>"></div>
|
||||
<span class="text-secondary"><%= item.category.name %></span>
|
||||
<span class="text-primary"><%= number_to_percentage(item.percentage, precision: 0) %></span>
|
||||
<div class="w-2.5 h-2.5 rounded-full shrink-0" style="background-color: <%= category_total.category.color %>"></div>
|
||||
<span class="text-secondary"><%= category_total.category.name %></span>
|
||||
<span class="text-primary"><%= number_to_percentage(category_total.weight, precision: 0) %></span>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<p class="ml-auto">Amount</p>
|
||||
</div>
|
||||
|
||||
<div class="bg-white py-1 shadow-xs border border-gray-100 rounded-md">
|
||||
<div class="bg-white py-1 shadow-border-xs rounded-md">
|
||||
<% if budget.family.categories.expenses.empty? %>
|
||||
<div class="py-8">
|
||||
<%= render "budget_categories/no_categories" %>
|
||||
|
|
|
@ -2,16 +2,16 @@
|
|||
|
||||
<div class="flex items-center gap-1 mb-4">
|
||||
<div class="flex items-center gap-2">
|
||||
<% if @previous_budget %>
|
||||
<%= link_to budget_path(@previous_budget) do %>
|
||||
<% if budget.previous_budget_param %>
|
||||
<%= link_to budget_path(budget.previous_budget_param) do %>
|
||||
<%= lucide_icon "chevron-left" %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= lucide_icon "chevron-left", class: "text-subdued" %>
|
||||
<% end %>
|
||||
|
||||
<% if @next_budget %>
|
||||
<%= link_to budget_path(@next_budget) do %>
|
||||
<% if budget.next_budget_param %>
|
||||
<%= link_to budget_path(budget.next_budget_param) do %>
|
||||
<%= lucide_icon "chevron-right" %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
|
@ -20,13 +20,13 @@
|
|||
</div>
|
||||
|
||||
<div data-controller="menu" data-menu-placement-value="bottom-start">
|
||||
<%= tag.button data: { menu_target: "button" }, class: "flex items-center gap-1 hover:bg-gray-50 rounded-md p-2" do %>
|
||||
<%= tag.button data: { menu_target: "button" }, class: "flex items-center gap-1 hover:bg-alpha-black-25 cursor-pointer rounded-md p-2" do %>
|
||||
<span class="text-primary font-medium"><%= @budget.name %></span>
|
||||
<%= lucide_icon "chevron-down", class: "w-5 h-5 shrink-0 text-secondary" %>
|
||||
<% end %>
|
||||
|
||||
<div data-menu-target="content" class="hidden z-10">
|
||||
<%= render "budgets/picker", family: Current.family, year: Date.current.year %>
|
||||
<%= render "budgets/picker", family: Current.family, year: budget.start_date.year %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
|||
<% if @budget.current? %>
|
||||
<span class="border border-secondary text-primary text-sm font-medium px-3 py-2 rounded-lg">Today</span>
|
||||
<% else %>
|
||||
<%= link_to "Today", budget_path(@latest_budget), class: "btn btn--outline" %>
|
||||
<%= link_to "Today", budget_path(Budget.date_to_param(Date.current)), class: "btn btn--outline" %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
<%# locals: (family:, year:) %>
|
||||
|
||||
<%= turbo_frame_tag "budget_picker" do %>
|
||||
<div class="bg-white shadow-md border border-alpha-black-25 p-3 rounded-xl space-y-4">
|
||||
<div class="bg-white shadow-border-xs p-3 rounded-xl space-y-4">
|
||||
<div class="flex items-center gap-2 justify-between">
|
||||
<% if year > family.oldest_entry_date.year %>
|
||||
<% last_month_of_previous_year = Date.new(year - 1, 12, 1) %>
|
||||
|
||||
<% if Budget.budget_date_valid?(last_month_of_previous_year, family: family) %>
|
||||
<%= link_to picker_budgets_path(year: year - 1), data: { turbo_frame: "budget_picker" }, class: "p-2 flex items-center justify-center hover:bg-alpha-black-25 rounded-md" do %>
|
||||
<%= lucide_icon "chevron-left", class: "w-5 h-5 shrink-0 text-secondary" %>
|
||||
<% end %>
|
||||
|
@ -17,7 +19,9 @@
|
|||
<%= year %>
|
||||
</span>
|
||||
|
||||
<% if year < Date.current.year %>
|
||||
<% first_month_of_next_year = Date.new(year + 1, 1, 1) %>
|
||||
|
||||
<% if Budget.budget_date_valid?(first_month_of_next_year, family: family) %>
|
||||
<%= link_to picker_budgets_path(year: year + 1), data: { turbo_frame: "budget_picker" }, class: "p-2 flex items-center justify-center hover:bg-alpha-black-25 rounded-md" do %>
|
||||
<%= lucide_icon "chevron-right", class: "w-5 h-5 shrink-0 text-secondary" %>
|
||||
<% end %>
|
||||
|
@ -29,17 +33,12 @@
|
|||
</div>
|
||||
|
||||
<div class="grid grid-cols-3 gap-2 text-sm text-center font-medium">
|
||||
<% Date::ABBR_MONTHNAMES.compact.each_with_index do |month_name, index| %>
|
||||
<% month_number = index + 1 %>
|
||||
<% start_date = Date.new(year, month_number) %>
|
||||
<% budget = family.budgets.for_date(start_date) %>
|
||||
<% Date::ABBR_MONTHNAMES.compact.each do |month_name| %>
|
||||
<% date = Date.strptime("#{month_name}-#{year}", "%b-%Y") %>
|
||||
<% param_key = Budget.date_to_param(date) %>
|
||||
|
||||
<% if budget %>
|
||||
<%= link_to month_name, budget_path(budget), data: { turbo_frame: "_top" }, class: "block px-3 py-2 text-sm text-primary hover:bg-gray-100 rounded-md" %>
|
||||
<% elsif start_date >= family.oldest_entry_date.beginning_of_month && start_date <= Date.current %>
|
||||
<%= button_to budgets_path(budget: { start_date: start_date }), data: { turbo_frame: "_top" }, class: "block w-full px-3 py-2 text-primary hover:bg-gray-100 rounded-md" do %>
|
||||
<%= month_name %>
|
||||
<% end %>
|
||||
<% if Budget.budget_date_valid?(date, family: family) %>
|
||||
<%= link_to month_name, budget_path(param_key), data: { turbo_frame: "_top" }, class: "block px-3 py-2 text-sm text-primary hover:bg-gray-100 rounded-md" %>
|
||||
<% else %>
|
||||
<span class="px-3 py-2 text-subdued rounded-md"><%= month_name %></span>
|
||||
<% end %>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
<div class="flex items-start gap-4">
|
||||
<div class="w-[300px] space-y-4">
|
||||
<div class="h-[300px] bg-white rounded-xl shadow-xs p-8 border border-gray-100">
|
||||
<div class="h-[300px] bg-white rounded-xl shadow-border-xs p-8">
|
||||
<% if @budget.available_to_allocate.negative? %>
|
||||
<%= render "budgets/over_allocation_warning", budget: @budget %>
|
||||
<% else %>
|
||||
|
@ -38,18 +38,18 @@
|
|||
) %>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-xl shadow-xs border border-gray-100">
|
||||
<div class="bg-white rounded-xl shadow-border-xs">
|
||||
<%= render selected_tab == "budgeted" ? "budgets/budgeted_summary" : "budgets/actuals_summary", budget: @budget %>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="bg-white rounded-xl shadow-xs border border-gray-100">
|
||||
<div class="bg-white rounded-xl shadow-border-xs">
|
||||
<%= render "budgets/actuals_summary", budget: @budget %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grow bg-white rounded-xl shadow-xs p-4 border border-gray-100">
|
||||
<div class="grow bg-white rounded-xl shadow-border-xs p-4">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h2 class="text-lg font-medium">Categories</h2>
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue