Files
Budgeteer/BudgetApp/Components/Pages/Accounts.razor
T
2026-03-06 11:05:01 +00:00

166 lines
8.0 KiB
Plaintext

@page "/accounts"
@using BudgetApp.Data.Entities
@attribute [Authorize]
@inject IAccountRepository AccountService
@inject AuthenticationStateProvider AuthStateProvider
@inject AppState AppState
@rendermode InteractiveServer
<PageTitle>Accounts</PageTitle>
<h3 class="mb-2">Accounts</h3>
<p class="text-muted mb-4">Manage your financial accounts, balances and currencies.</p>
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">Add Account</h5>
</div>
<div class="card-body">
<EditForm Model="_formModel" OnValidSubmit="AddAccount" FormName="addAccount">
<ToastValidator />
<div class="row g-3 align-items-end">
<div class="col-md-3">
<label class="form-label">Account Name</label>
<InputText @bind-Value="_formModel.Name" class="form-control" placeholder="e.g. Current Account" title="A friendly name for this account" />
</div>
<div class="col-md-2">
<label class="form-label">Current Balance</label>
<InputNumber @bind-Value="_formModel.CurrentBalance" class="form-control numeric-input" title="The opening balance for this account" />
</div>
<div class="col-md-2">
<label class="form-label">Currency</label>
<InputSelect @bind-Value="_formModel.CurrencyCode" class="form-select" title="Currency used for this account">
@foreach (var kvp in Account.CurrencySymbols)
{
<option value="@kvp.Key">@kvp.Key (@kvp.Value)</option>
}
</InputSelect>
</div>
<div class="col-md-2">
<label class="form-label">Colour</label>
<InputText @bind-Value="_formModel.Color" type="color" class="form-control form-control-color" title="Colour used to identify this account in charts and lists" />
</div>
<div class="col-md-2">
<button type="submit" class="btn btn-primary w-100">Add</button>
</div>
</div>
</EditForm>
</div>
</div>
@if (_accounts is null)
{
<p><em>Loading...</em></p>
}
else if (_accounts.Count == 0)
{
<div class="alert alert-info">No accounts yet. Add one above to get started.</div>
}
else
{
<div class="row">
@foreach (var account in _accounts)
{
<div class="col-md-4 col-sm-6 mb-3">
<div class="card h-100" style="border-left: 4px solid @account.Color;">
<div class="card-body">
@if (_editingAccountId == account.Id)
{
<div class="mb-2">
<label class="form-label form-label-sm mb-1">Name</label>
<input type="text" class="form-control form-control-sm" @bind="_editName" />
</div>
<div class="mb-2">
<label class="form-label form-label-sm mb-1">Currency</label>
<select class="form-select form-select-sm" @bind="_editCurrencyCode">
@foreach (var kvp in Account.CurrencySymbols)
{
<option value="@kvp.Key">@kvp.Key (@kvp.Value)</option>
}
</select>
</div>
<div class="mb-2">
<label class="form-label form-label-sm mb-1">Colour</label>
<input type="color" class="form-control form-control-color form-control-sm" @bind="_editColor" />
</div>
<div class="d-flex gap-1">
<button class="btn btn-success btn-sm" @onclick="() => SaveAccountDetails(account.Id)">Save</button>
<button class="btn btn-secondary btn-sm" @onclick="CancelAccountEdit">Cancel</button>
</div>
}
else
{
<div class="d-flex justify-content-between align-items-start">
<div>
<h5 class="card-title mb-1">@account.Name</h5>
<small class="text-muted">@account.CurrencyCode</small>
</div>
<div class="d-flex gap-1">
<button class="btn btn-outline-primary btn-sm" title="Edit account name, currency or colour" @onclick="() => StartAccountEdit(account)">Edit</button>
<button class="btn btn-outline-danger btn-sm" title="Delete this account and all its transactions" @onclick="() => ConfirmDeleteAccount(account)">Delete</button>
</div>
</div>
@if (_editingBalanceAccountId == account.Id)
{
<div class="mt-2">
<div class="input-group input-group-sm">
<span class="input-group-text">@account.GetSymbol()</span>
<input type="number" class="form-control numeric-input" step="0.01"
@bind="_editingBalanceValue" />
</div>
<div class="d-flex gap-1 mt-2">
<button class="btn btn-success btn-sm flex-fill" @onclick="() => SaveBalance(account.Id)">Save</button>
<button class="btn btn-outline-secondary btn-sm flex-fill" @onclick="CancelBalanceEdit">Cancel</button>
</div>
</div>
}
else
{
<h4 class="@(account.CurrentBalance >= 0 ? "text-success" : "text-danger") mb-1"
style="cursor: pointer;" title="Click to edit balance"
@onclick="() => StartBalanceEdit(account)">
@account.FormatAmount(account.CurrentBalance)
</h4>
<small class="text-muted">Click balance to adjust</small>
}
}
</div>
</div>
</div>
}
</div>
}
@if (_showDeleteModal && _pendingDeleteAccount is not null)
{
<div class="modal d-block" tabindex="-1" style="background: rgba(0,0,0,.5);">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Delete Account</h5>
<button type="button" class="btn-close" @onclick="CancelDeleteAccount"></button>
</div>
<div class="modal-body">
<p>Are you sure you want to delete <strong>@_pendingDeleteAccount.Name</strong>?</p>
<p class="text-danger mb-0">This will permanently remove the account and all its transactions.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" @onclick="CancelDeleteAccount">Cancel</button>
<button type="button" class="btn btn-danger" @onclick="DeleteAccountConfirmed">Delete</button>
</div>
</div>
</div>
</div>
}
@code {
// Balance editing state
// Account details editing state
// Delete confirmation state
}