Files
PowderCoatingLogix/src/PowderCoating.Web/Views/Expenses/Edit.cshtml
T
spouliot 21b39161a3 Fix encoding corruption in Bills and Expenses views
Replace literal Unicode chars (em dash, ellipsis, angle quotes, box-drawing)
with HTML entities to prevent corruption from AI tools and Windows encoding.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 17:06:31 -04:00

153 lines
9.9 KiB
Plaintext

@model PowderCoating.Application.DTOs.Accounting.EditExpenseDto
@* Note: ReceiptFilePath is carried via hidden field to detect existing receipt *@
@{
ViewData["Title"] = "Edit Expense";
ViewData["PageIcon"] = "bi-pencil-square";
ViewData["PageHelpTitle"] = "Edit Expense";
ViewData["PageHelpContent"] = "All fields are editable. Uploading a new receipt replaces the existing one. To remove a receipt without replacing it, use the Delete Receipt button on the Details page.";
}
<div class="d-flex justify-content-start mb-4">
<a asp-action="Details" asp-route-id="@Model.Id" class="btn btn-sm btn-outline-secondary"><i class="bi bi-arrow-left"></i></a>
</div>
<div class="row justify-content-center">
<div class="col-lg-7">
<div class="card shadow-sm">
<div class="card-body">
<form asp-action="Edit" asp-route-id="@Model.Id" method="post" enctype="multipart/form-data">
@Html.AntiForgeryToken()
<input asp-for="Id" type="hidden" />
<input asp-for="ReceiptFilePath" type="hidden" />
<div asp-validation-summary="ModelOnly" class="alert alert-danger alert-permanent mb-3"></div>
<div class="row g-3">
<div class="col-sm-6">
<label asp-for="Date" class="form-label fw-medium">Date <span class="text-danger">*</span></label>
<input asp-for="Date" type="date" class="form-control" />
</div>
<div class="col-sm-6">
<label asp-for="Amount" class="form-label fw-medium">Amount <span class="text-danger">*</span></label>
<div class="input-group">
<span class="input-group-text">$</span>
<input asp-for="Amount" type="number" step="0.01" min="0.01" class="form-control" />
</div>
</div>
<div class="col-12">
<div class="d-flex align-items-center gap-1 mb-1">
<label asp-for="ExpenseAccountId" class="form-label fw-medium mb-0">Expense Account <span class="text-danger">*</span></label>
<a tabindex="0" class="help-icon" role="button"
data-bs-toggle="popover" data-bs-placement="right" data-bs-trigger="focus"
data-bs-title="Expense Account"
data-bs-content="The expense category this purchase belongs to &mdash; e.g. Supplies, Materials, Utilities, Fuel. This account is debited when the expense is saved. Choose the most specific account that fits to keep your reports accurate.">
<i class="bi bi-question-circle"></i>
</a>
</div>
<select asp-for="ExpenseAccountId" asp-items="ViewBag.ExpenseAccounts" class="form-select">
<option value="">&mdash; Select Account &mdash;</option>
</select>
</div>
<div class="col-sm-6">
<div class="d-flex align-items-center gap-1 mb-1">
<label asp-for="PaymentAccountId" class="form-label fw-medium mb-0">Paid From <span class="text-danger">*</span></label>
<a tabindex="0" class="help-icon" role="button"
data-bs-toggle="popover" data-bs-placement="right" data-bs-trigger="focus"
data-bs-title="Paid From"
data-bs-content="The bank or cash account the money came out of &mdash; e.g. Business Checking, Petty Cash, Company Credit Card. This account is credited when the expense is saved. Used for bank reconciliation.">
<i class="bi bi-question-circle"></i>
</a>
</div>
<select asp-for="PaymentAccountId" asp-items="ViewBag.PaymentAccounts" class="form-select">
<option value="">&mdash; Select Account &mdash;</option>
</select>
</div>
<div class="col-sm-6">
<label asp-for="PaymentMethod" class="form-label fw-medium">Payment Method <span class="text-danger">*</span></label>
<select asp-for="PaymentMethod" asp-items="ViewBag.PaymentMethods" class="form-select"></select>
</div>
<div class="col-sm-6">
<label asp-for="VendorId" class="form-label fw-medium">Vendor</label>
<select asp-for="VendorId" asp-items="ViewBag.Vendors" class="form-select"
data-quick-add-url="/Vendors/Create" data-quick-add-title="Add New Vendor">
<option value="">&mdash; None &mdash;</option>
<option value="__new__">+ Add New Vendor&hellip;</option>
</select>
</div>
<div class="col-sm-6">
<div class="d-flex align-items-center gap-1 mb-1">
<label asp-for="JobId" class="form-label fw-medium mb-0">Job</label>
<a tabindex="0" class="help-icon" role="button"
data-bs-toggle="popover" data-bs-placement="right" data-bs-trigger="focus"
data-bs-title="Linked Job"
data-bs-content="Attach this expense to a specific job to track its true cost. Job-linked expenses roll up in job profitability reports, helping you see whether a job was profitable after all direct costs.">
<i class="bi bi-question-circle"></i>
</a>
</div>
<select asp-for="JobId" asp-items="ViewBag.Jobs" class="form-select">
<option value="">&mdash; None &mdash;</option>
</select>
</div>
<div class="col-12">
<label asp-for="Memo" class="form-label fw-medium">Memo</label>
<textarea asp-for="Memo" class="form-control" rows="2"></textarea>
</div>
<div class="col-12">
<div class="d-flex align-items-center gap-1 mb-1">
<label class="form-label fw-medium mb-0">Receipt</label>
<a tabindex="0" class="help-icon" role="button"
data-bs-toggle="popover" data-bs-placement="right" data-bs-trigger="focus"
data-bs-title="Receipt"
data-bs-content="Uploading a new file here replaces the existing receipt. To remove a receipt without replacing it, use the Delete Receipt button on the Details page. Supports JPG, PNG, and PDF up to 10 MB.">
<i class="bi bi-question-circle"></i>
</a>
</div>
@if (!string.IsNullOrEmpty(Model.ReceiptFilePath))
{
<div class="d-flex align-items-center gap-3 mb-2 p-2 border rounded bg-light">
<i class="bi bi-paperclip text-muted fs-5"></i>
<span class="small text-muted flex-grow-1">Receipt attached</span>
<a asp-action="ViewReceipt" asp-route-id="@Model.Id"
class="btn btn-sm btn-outline-secondary" target="_blank">
<i class="bi bi-eye me-1"></i>View
</a>
</div>
<div class="form-text mb-2">Upload a new file below to replace the existing receipt.</div>
}
<input type="file" name="receiptFile" id="receiptFile" class="form-control"
accept=".jpg,.jpeg,.png,.gif,.webp,.pdf" />
<div class="form-text">Image or PDF, up to 10 MB.</div>
<div id="receiptPreview" class="mt-2 d-none">
<img id="previewImg" src="" alt="Receipt preview" class="img-thumbnail" style="max-height:200px;" />
</div>
</div>
</div>
<div class="d-flex gap-2 mt-4">
<button type="submit" class="btn btn-primary"><i class="bi bi-check-lg me-1"></i>Save Changes</button>
<a asp-action="Details" asp-route-id="@Model.Id" class="btn btn-outline-secondary">Cancel</a>
</div>
</form>
</div>
</div>
</div>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
<script>
document.getElementById('receiptFile').addEventListener('change', function () {
const file = this.files[0];
const preview = document.getElementById('receiptPreview');
const img = document.getElementById('previewImg');
if (file && file.type.startsWith('image/')) {
img.src = URL.createObjectURL(file);
preview.classList.remove('d-none');
} else {
preview.classList.add('d-none');
}
});
</script>
}