Files
MoneyMap/MoneyMap/Pages/_ProposalTable.cshtml
T
aj 444035fd72 Refactor: AICategorizePreview with tabbed proposals and rule status
Split proposals into High Confidence / Needs Review tabs. Extract
proposal table into _ProposalTable partial view. Show rule status
(Create/Update/Exists) based on existing category mappings. Persist
proposals in hidden form field to survive app restarts. Add per-tab
select-all and improved error reporting on apply.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 19:14:19 -05:00

102 lines
4.9 KiB
Plaintext

@model List<MoneyMap.Pages.AICategorizePreviewModel.ProposalViewModel>
<div class="table-responsive">
<table class="table table-hover mb-0">
<thead class="table-light">
<tr>
<th style="width: 40px;">
<input type="checkbox" class="form-check-input select-all-tab" onchange="selectAllInTab(this)" checked>
</th>
<th>Transaction</th>
<th>Current</th>
<th>Proposed</th>
<th>Merchant</th>
<th style="width: 100px;">Confidence</th>
<th style="width: 140px;">Rule</th>
</tr>
</thead>
<tbody>
@foreach (var proposal in Model)
{
var confidenceClass = proposal.Confidence >= 0.8m ? "bg-success" :
proposal.Confidence >= 0.6m ? "bg-warning text-dark" : "bg-secondary";
<tr>
<td>
<input type="checkbox" class="form-check-input proposal-checkbox"
name="selectedIds" value="@proposal.TransactionId" checked>
</td>
<td>
<div class="fw-bold">@proposal.TransactionName</div>
@if (!string.IsNullOrWhiteSpace(proposal.TransactionMemo))
{
<small class="text-muted">@proposal.TransactionMemo</small>
}
<div class="small text-muted">
@proposal.TransactionDate.ToString("yyyy-MM-dd") | @proposal.TransactionAmount.ToString("C")
</div>
</td>
<td>
@if (!string.IsNullOrWhiteSpace(proposal.CurrentCategory))
{
<span class="badge bg-secondary">@proposal.CurrentCategory</span>
}
else
{
<span class="text-muted small">(none)</span>
}
</td>
<td>
<span class="badge bg-primary">@proposal.ProposedCategory</span>
@if (!string.IsNullOrWhiteSpace(proposal.Reasoning))
{
<div class="small text-muted mt-1">@proposal.Reasoning</div>
}
</td>
<td>
@if (!string.IsNullOrWhiteSpace(proposal.ProposedMerchant))
{
<div>@proposal.ProposedMerchant</div>
}
@if (!string.IsNullOrWhiteSpace(proposal.ProposedPattern))
{
<div class="small text-muted mt-1">Pattern: <code>@proposal.ProposedPattern</code></div>
}
</td>
<td>
<span class="badge @confidenceClass">@proposal.Confidence.ToString("P0")</span>
</td>
<td>
@if (proposal.HasExistingRule && !proposal.NeedsRuleUpdate)
{
<span class="badge bg-info text-dark" title="Rule already exists for pattern '@proposal.ProposedPattern' with same category">
Exists
</span>
}
else if (proposal.NeedsRuleUpdate)
{
<div>
<input type="checkbox" class="form-check-input create-rule-checkbox"
name="createRules" value="@proposal.TransactionId"
@(proposal.CreateRule ? "checked" : "")
title="Update existing rule from '@proposal.ExistingRuleCategory' to '@proposal.ProposedCategory'">
<span class="badge bg-warning text-dark">Update</span>
</div>
<div class="small text-muted mt-1">
Currently: <code>@proposal.ExistingRuleCategory</code>
</div>
}
else
{
<input type="checkbox" class="form-check-input create-rule-checkbox"
name="createRules" value="@proposal.TransactionId"
@(proposal.CreateRule ? "checked" : "")
title="Create a new mapping rule for this pattern">
<span class="small text-muted">Create</span>
}
</td>
</tr>
}
</tbody>
</table>
</div>