Hide email controls when no email on file; show SMS hint for quote/job events

- Quotes Create/Edit: hide 'Send via email' checkbox when customer has no
  email; show badge 'send via SMS from details' or 'SMS consent required'
  when customer has a mobile number. JS responds to customer dropdown change.
- Quotes Details: hide 'Send Quote via Email' button and approval email
  checkbox; hide SMS button when no mobile; show consent-required note.
- Jobs Details (Mark Complete modal): hide email checkbox; show
  'SMS notification will be sent' badge or consent-required note.
- Jobs Index (status modal): hide email row when customer has no email.
- Jobs Edit: hide 'Notify customer if status changes' when no email.
- Invoices Details: hide Send/Re-send buttons when no email (vs. disabled).

DTOs: added CustomerEmail + CustomerNotifyByEmail to JobDto/JobListDto;
added CustomerNotifyByEmail/CustomerMobilePhone/CustomerNotifyBySms to
QuoteDto. Mapped in JobProfile and QuotesController customer blocks.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-06 17:32:08 -04:00
parent d3863c713b
commit acbd9f60be
1190 changed files with 338016 additions and 88 deletions
@@ -1524,29 +1524,53 @@
<a asp-action="Edit" asp-route-id="@Model.Id" class="btn btn-outline-secondary">
<i class="bi bi-pencil me-1"></i>Edit Quote
</a>
@{
var detHasEmail = !string.IsNullOrWhiteSpace(Model.CustomerEmail);
var detHasMobile = !string.IsNullOrWhiteSpace(Model.CustomerMobilePhone);
var detHasSmsConsent = Model.CustomerNotifyBySms && detHasMobile;
}
@if (Model.StatusCode != "APPROVED" && Model.StatusCode != "CONVERTED")
{
<form asp-action="ApproveQuote" asp-route-id="@Model.Id" method="post" id="approveQuoteForm">
@Html.AntiForgeryToken()
<div class="form-check form-switch mb-2">
<input class="form-check-input" type="checkbox" role="switch"
id="approveQuoteSendEmail" name="sendEmail" value="true"
@(ViewBag.EmailDefaultOnApprove == true ? "checked" : "") />
<label class="form-check-label small" for="approveQuoteSendEmail">
<i class="bi bi-envelope me-1"></i>Notify customer via email
</label>
</div>
@if (detHasEmail)
{
<div class="form-check form-switch mb-2">
<input class="form-check-input" type="checkbox" role="switch"
id="approveQuoteSendEmail" name="sendEmail" value="true"
@(ViewBag.EmailDefaultOnApprove == true ? "checked" : "") />
<label class="form-check-label small" for="approveQuoteSendEmail">
<i class="bi bi-envelope me-1"></i>Notify customer via email
</label>
</div>
}
<button type="button" class="btn btn-outline-success w-100" data-bs-toggle="modal" data-bs-target="#approveQuoteModal">
<i class="bi bi-check-circle me-1"></i>Approve Quote
</button>
</form>
}
<button type="button" class="btn btn-outline-primary" onclick="resendQuote(@Model.Id)">
<i class="bi bi-envelope-arrow-up me-1"></i>Send Quote via Email
</button>
<button type="button" class="btn btn-outline-info" onclick="sendQuoteSms(@Model.Id)">
<i class="bi bi-chat-dots me-1"></i>Send Quote via SMS
</button>
@if (detHasEmail)
{
<button type="button" class="btn btn-outline-primary" onclick="resendQuote(@Model.Id)">
<i class="bi bi-envelope-arrow-up me-1"></i>Send Quote via Email
</button>
}
@if (detHasMobile)
{
<button type="button" class="btn btn-outline-info" onclick="sendQuoteSms(@Model.Id)">
<i class="bi bi-chat-dots me-1"></i>Send Quote via SMS
</button>
}
@if (!detHasMobile && !detHasEmail)
{
<div class="alert alert-warning alert-permanent py-1 px-2 small">
<i class="bi bi-exclamation-triangle me-1"></i>No email or phone — update the customer record to send this quote.
</div>
}
@if (detHasMobile && !detHasSmsConsent)
{
<div class="text-muted small"><i class="bi bi-phone-slash me-1"></i>SMS consent required to send via text.</div>
}
@if (!Model.ConvertedToJobId.HasValue)
{
<form asp-action="ConvertToJob" asp-route-id="@Model.Id" method="post" class="d-inline" id="createJobForm">