WIP
This commit is contained in:
1 parent
2cf6128a85
commit
45a5e3fc5e
11 files changed
+428
-40
No files matched your search
@@ -137,8 +137,8 @@ else
|
||||
}
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<ul class="nav nav-tabs card-header-tabs">
|
||||
<div class="card-header d-flex justify-content-between align-items-center flex-wrap gap-2">
|
||||
<ul class="nav nav-tabs card-header-tabs" style="flex-grow: 0;">
|
||||
<li class="nav-item">
|
||||
<button class="nav-link @(activeTab == "recent" ? "active" : "")" @onclick='() => { activeTab = "recent"; recentPage = 1; }'>
|
||||
Recent <span class="badge bg-secondary ms-1">@filteredRecent.Count</span>
|
||||
@@ -150,7 +150,11 @@ else
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
<button class="btn btn-sm btn-primary" @onclick="OpenAddModal">+ Add</button>
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<input type="search" class="form-control form-control-sm" style="max-width: 180px;"
|
||||
placeholder="Search..." @bind="dashboardSearchQuery" @bind:event="oninput" @bind:after="OnDashboardSearchChanged" />
|
||||
<button class="btn btn-sm btn-primary" @onclick="OpenAddModal">+ Add</button>
|
||||
</div>
|
||||
</div>
|
||||
@if (data.Accounts.Count > 1)
|
||||
{
|
||||
@@ -303,19 +307,31 @@ else
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Delete Recurring Transaction</h5>
|
||||
<h5 class="modal-title">@(pendingDeleteIsRecurring ? "Delete Recurring Transaction" : "Delete Transaction")</h5>
|
||||
<button type="button" class="btn-close" @onclick="CancelDelete"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>
|
||||
<strong>@pendingDeleteTransaction.Description</strong> is part of a recurring series.
|
||||
</p>
|
||||
<p>Would you like to delete just this transaction, or all future transactions in the series?</p>
|
||||
<p>Are you sure you want to delete <strong>@pendingDeleteTransaction.Description</strong>?</p>
|
||||
@if (pendingDeleteIsRecurring)
|
||||
{
|
||||
<p>This transaction is part of a recurring series. Would you like to delete just this one, or all future transactions in the series?</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<p class="text-danger mb-0">This action cannot be undone.</p>
|
||||
}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" @onclick="CancelDelete">Cancel</button>
|
||||
<button type="button" class="btn btn-outline-danger" @onclick="DeleteSingle">This One Only</button>
|
||||
<button type="button" class="btn btn-danger" @onclick="DeleteSeries">All Future in Series</button>
|
||||
@if (pendingDeleteIsRecurring)
|
||||
{
|
||||
<button type="button" class="btn btn-outline-danger" @onclick="DeleteSingle">This One Only</button>
|
||||
<button type="button" class="btn btn-danger" @onclick="DeleteSeries">All Future in Series</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button type="button" class="btn btn-danger" @onclick="DeleteSingle">Delete</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -347,12 +363,29 @@ else
|
||||
|
||||
// Account filter
|
||||
private HashSet<int> hiddenAccountIds = [];
|
||||
private string dashboardSearchQuery = string.Empty;
|
||||
|
||||
private List<Transaction> filteredRecent => data is null ? []
|
||||
: data.RecentTransactions.Where(t => !hiddenAccountIds.Contains(t.AccountId)).ToList();
|
||||
: data.RecentTransactions
|
||||
.Where(t => !hiddenAccountIds.Contains(t.AccountId))
|
||||
.Where(t => MatchesSearch(t))
|
||||
.ToList();
|
||||
|
||||
private List<Transaction> filteredUpcoming => data is null ? []
|
||||
: data.UpcomingTransactions.Where(t => !hiddenAccountIds.Contains(t.AccountId)).ToList();
|
||||
: data.UpcomingTransactions
|
||||
.Where(t => !hiddenAccountIds.Contains(t.AccountId))
|
||||
.Where(t => MatchesSearch(t))
|
||||
.ToList();
|
||||
|
||||
private bool MatchesSearch(Transaction t)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(dashboardSearchQuery)) return true;
|
||||
var q = dashboardSearchQuery.Trim();
|
||||
return t.Description.Contains(q, StringComparison.OrdinalIgnoreCase)
|
||||
|| t.Account.Name.Contains(q, StringComparison.OrdinalIgnoreCase)
|
||||
|| (t.Category?.Name?.Contains(q, StringComparison.OrdinalIgnoreCase) ?? false)
|
||||
|| t.Amount.ToString("F2").Contains(q, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private void ToggleAccountFilter(int accountId)
|
||||
{
|
||||
@@ -362,6 +395,12 @@ else
|
||||
upcomingPage = 1;
|
||||
}
|
||||
|
||||
private void OnDashboardSearchChanged()
|
||||
{
|
||||
recentPage = 1;
|
||||
upcomingPage = 1;
|
||||
}
|
||||
|
||||
// Pagination
|
||||
private int recentPage = 1;
|
||||
private int upcomingPage = 1;
|
||||
@@ -509,18 +548,13 @@ else
|
||||
// Delete confirmation state
|
||||
private bool showDeleteModal;
|
||||
private Transaction? pendingDeleteTransaction;
|
||||
private bool pendingDeleteIsRecurring;
|
||||
|
||||
private void ConfirmDelete(Transaction t)
|
||||
{
|
||||
pendingDeleteTransaction = t;
|
||||
if (t.RecurrenceType != RecurrenceType.None || t.ParentTransactionId is not null)
|
||||
{
|
||||
showDeleteModal = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_ = DeleteSingle();
|
||||
}
|
||||
pendingDeleteIsRecurring = t.RecurrenceType != RecurrenceType.None || t.ParentTransactionId is not null;
|
||||
showDeleteModal = true;
|
||||
}
|
||||
|
||||
private async Task DeleteSingle()
|
||||
|
||||
Reference in new issue
Block a user