mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-07-20 13:49:39 +02:00
Fix budget allocation forms from resetting and clearing data on slow networks (#1804)
* First pass * Fix null constraint bug for budget category assignment * Fix autofocus reset when allocating budget * Lint fix
This commit is contained in:
parent
f498212b2d
commit
5b083c9e33
7 changed files with 56 additions and 53 deletions
|
@ -1,12 +1,12 @@
|
||||||
class BudgetCategoriesController < ApplicationController
|
class BudgetCategoriesController < ApplicationController
|
||||||
|
before_action :set_budget
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@budget = Current.family.budgets.find(params[:budget_id])
|
@budget_categories = @budget.budget_categories.includes(:category)
|
||||||
render layout: "wizard"
|
render layout: "wizard"
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@budget = Current.family.budgets.find(params[:budget_id])
|
|
||||||
|
|
||||||
@recent_transactions = @budget.entries
|
@recent_transactions = @budget.entries
|
||||||
|
|
||||||
if params[:id] == BudgetCategory.uncategorized.id
|
if params[:id] == BudgetCategory.uncategorized.id
|
||||||
|
@ -23,13 +23,25 @@ class BudgetCategoriesController < ApplicationController
|
||||||
|
|
||||||
def update
|
def update
|
||||||
@budget_category = Current.family.budget_categories.find(params[:id])
|
@budget_category = Current.family.budget_categories.find(params[:id])
|
||||||
@budget_category.update!(budget_category_params)
|
|
||||||
|
|
||||||
redirect_to budget_budget_categories_path(@budget_category.budget)
|
if @budget_category.update(budget_category_params)
|
||||||
|
respond_to do |format|
|
||||||
|
format.turbo_stream
|
||||||
|
format.html { redirect_to budget_budget_categories_path(@budget) }
|
||||||
|
end
|
||||||
|
else
|
||||||
|
render :index, status: :unprocessable_entity
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def budget_category_params
|
def budget_category_params
|
||||||
params.require(:budget_category).permit(:budgeted_spending)
|
params.require(:budget_category).permit(:budgeted_spending).tap do |params|
|
||||||
|
params[:budgeted_spending] = params[:budgeted_spending].presence || 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_budget
|
||||||
|
@budget = Current.family.budgets.find(params[:budget_id])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -25,7 +25,7 @@ export default class extends Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleInput = (event) => {
|
handleInput = (event) => {
|
||||||
const target = event.target
|
const target = event.target;
|
||||||
|
|
||||||
clearTimeout(this.timeout);
|
clearTimeout(this.timeout);
|
||||||
this.timeout = setTimeout(() => {
|
this.timeout = setTimeout(() => {
|
||||||
|
@ -34,18 +34,18 @@ export default class extends Controller {
|
||||||
};
|
};
|
||||||
|
|
||||||
#debounceTimeout(element) {
|
#debounceTimeout(element) {
|
||||||
if(element.dataset.autosubmitDebounceTimeout) {
|
if (element.dataset.autosubmitDebounceTimeout) {
|
||||||
return Number.parseInt(element.dataset.autosubmitDebounceTimeout);
|
return Number.parseInt(element.dataset.autosubmitDebounceTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
const type = element.type || element.tagName;
|
const type = element.type || element.tagName;
|
||||||
|
|
||||||
switch (type.toLowerCase()) {
|
switch (type.toLowerCase()) {
|
||||||
case 'input':
|
case "input":
|
||||||
case 'textarea':
|
case "textarea":
|
||||||
return 500;
|
return 500;
|
||||||
case 'select-one':
|
case "select-one":
|
||||||
case 'select-multiple':
|
case "select-multiple":
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
return 500;
|
return 500;
|
||||||
|
|
|
@ -1,26 +1,44 @@
|
||||||
<%# locals: (budget:) %>
|
<%# locals: (budget:) %>
|
||||||
|
|
||||||
<div class="space-y-2 mb-6">
|
<div id="<%= dom_id(budget, :allocation_progress) %>" class="space-y-2 mb-6">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<div class="rounded-full w-1.5 h-1.5 <%= budget.allocated_spending > 0 ? "bg-gray-900" : "bg-gray-100" %>"></div>
|
<% if budget.available_to_allocate.negative? %>
|
||||||
|
<div class="rounded-full w-1.5 h-1.5 bg-red-500"></div>
|
||||||
|
<% else %>
|
||||||
|
<div class="rounded-full w-1.5 h-1.5 <%= budget.allocated_spending > 0 ? "bg-gray-900" : "bg-gray-100" %>"></div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
<p class="text-gray-500 text-sm">
|
<% if budget.available_to_allocate.negative? %>
|
||||||
<%= number_to_percentage(budget.allocated_percent, precision: 0) %> set
|
<p class="text-gray-900 text-sm">> 100% set</p>
|
||||||
</p>
|
<% else %>
|
||||||
|
<p class="text-gray-500 text-sm">
|
||||||
|
<%= number_to_percentage(budget.allocated_percent, precision: 0) %> set
|
||||||
|
</p>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
<p class="ml-auto text-sm space-x-1">
|
<p class="ml-auto text-sm space-x-1">
|
||||||
<span class="text-gray-900"><%= format_money(budget.allocated_spending_money) %></span>
|
<span class="<%= budget.available_to_allocate.negative? ? "text-red-500" : "text-gray-900" %>"><%= format_money(budget.allocated_spending_money) %></span>
|
||||||
<span class="text-gray-500"> / </span>
|
<span class="text-gray-500"> / </span>
|
||||||
<span class="text-gray-500"><%= format_money(budget.budgeted_spending_money) %></span>
|
<span class="text-gray-500"><%= format_money(budget.budgeted_spending_money) %></span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="relative h-1.5 rounded-2xl bg-gray-100">
|
<div class="relative h-1.5 rounded-2xl bg-gray-100">
|
||||||
<div class="absolute inset-0 bg-gray-900 rounded-2xl" style="width: <%= budget.allocated_percent %>%;"></div>
|
<% if budget.available_to_allocate.negative? %>
|
||||||
|
<div class="absolute inset-0 bg-red-500 rounded-2xl" style="width: 100%;"></div>
|
||||||
|
<% else %>
|
||||||
|
<div class="absolute inset-0 bg-gray-900 rounded-2xl" style="width: <%= budget.allocated_percent %>%;"></div>
|
||||||
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="text-sm">
|
<div class="text-sm">
|
||||||
<span class="text-gray-900"><%= format_money(budget.available_to_allocate_money) %></span>
|
<% if budget.available_to_allocate.negative? %>
|
||||||
<span class="text-gray-500">left to allocate</span>
|
<p class="text-gray-500">
|
||||||
|
Budget exceeded by <span class="text-red-500"><%= format_money(budget.available_to_allocate_money.abs) %></span>
|
||||||
|
</p>
|
||||||
|
<% else %>
|
||||||
|
<span class="text-gray-900"><%= format_money(budget.available_to_allocate_money) %></span>
|
||||||
|
<span class="text-gray-500">left to allocate</span>
|
||||||
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
<%# locals: (budget:) %>
|
|
||||||
|
|
||||||
<div class="space-y-2 mb-6">
|
|
||||||
<div class="flex items-center gap-2">
|
|
||||||
<div class="rounded-full w-1.5 h-1.5 bg-red-500"></div>
|
|
||||||
|
|
||||||
<p class="text-gray-900 text-sm">> 100% set</p>
|
|
||||||
|
|
||||||
<p class="ml-auto text-sm space-x-1">
|
|
||||||
<span class="text-red-500"><%= format_money(budget.allocated_spending_money) %></span>
|
|
||||||
<span class="text-gray-500"> / </span>
|
|
||||||
<span class="text-gray-500"><%= format_money(budget.budgeted_spending_money) %></span>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="relative h-1.5 rounded-2xl bg-gray-100">
|
|
||||||
<div class="absolute inset-0 bg-red-500 rounded-2xl" style="width: 100%;"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="text-sm">
|
|
||||||
<p class="text-gray-500">
|
|
||||||
Budget exceeded by <span class="text-red-500"><%= format_money(budget.available_to_allocate_money.abs) %></span>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
|
@ -12,7 +12,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="ml-auto">
|
<div class="ml-auto">
|
||||||
<%= form_with model: [budget_category.budget, budget_category], data: { controller: "auto-submit-form", auto_submit_form_trigger_event_value: "blur", turbo_frame: :_top } do |f| %>
|
<%= form_with model: [budget_category.budget, budget_category], data: { controller: "auto-submit-form preserve-focus" } do |f| %>
|
||||||
<div class="form-field w-[120px]">
|
<div class="form-field w-[120px]">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<span class="text-gray-500 text-sm mr-2"><%= currency.symbol %></span>
|
<span class="text-gray-500 text-sm mr-2"><%= currency.symbol %></span>
|
||||||
|
@ -20,6 +20,7 @@
|
||||||
class: "form-field__input text-right [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
|
class: "form-field__input text-right [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
|
||||||
placeholder: "0",
|
placeholder: "0",
|
||||||
step: currency.step,
|
step: currency.step,
|
||||||
|
id: dom_id(budget_category, :budgeted_spending),
|
||||||
min: 0,
|
min: 0,
|
||||||
data: { auto_submit_form_target: "auto" } %>
|
data: { auto_submit_form_target: "auto" } %>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -21,14 +21,10 @@
|
||||||
</div>
|
</div>
|
||||||
<% else %>
|
<% else %>
|
||||||
<div class="max-w-md mx-auto">
|
<div class="max-w-md mx-auto">
|
||||||
<% if @budget.available_to_allocate.negative? %>
|
<%= render "budget_categories/allocation_progress", budget: @budget %>
|
||||||
<%= render "budget_categories/allocation_progress_overage", budget: @budget %>
|
|
||||||
<% else %>
|
|
||||||
<%= render "budget_categories/allocation_progress", budget: @budget %>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<div class="space-y-4 mb-4">
|
<div class="space-y-4 mb-4">
|
||||||
<% BudgetCategory::Group.for(@budget.budget_categories).sort_by(&:name).each do |group| %>
|
<% BudgetCategory::Group.for(@budget_categories).sort_by(&:name).each do |group| %>
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<%= render "budget_categories/budget_category_form", budget_category: group.budget_category %>
|
<%= render "budget_categories/budget_category_form", budget_category: group.budget_category %>
|
||||||
|
|
||||||
|
|
1
app/views/budget_categories/update.turbo_stream.erb
Normal file
1
app/views/budget_categories/update.turbo_stream.erb
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<%= turbo_stream.replace dom_id(@budget, :allocation_progress), partial: "budget_categories/allocation_progress", locals: { budget: @budget } %>
|
Loading…
Add table
Add a link
Reference in a new issue