Fix passkey login tracking, add email opt-out UI guards, and add Quick/Full quote mode toggle

- PasskeyController: set LastLoginDate on passkey sign-in so Company Health
  and audit pages show accurate last-login times (was always showing 'Never')
- Jobs/Index status modal: disable 'Notify customer' email toggle and show
  warning when customer has notifications turned off; CustomerNotifyByEmail
  added to JobListDto + JobProfile mapping + data-customer-notify attribute
- Quotes/Create: disable 'Send quote via email' checkbox with 'Notifications
  off' badge when selected customer has email opt-out; ViewBag.CustomerEmailOptOutIds
  added alongside existing CustomerTaxExemptIds pattern
- Quotes/Create: Quick Quote / Full Quote segmented toggle at top of form;
  hides non-essential fields (dates, notes, tags, oven, discount, photos) in
  Quick mode; selection persisted in localStorage
- InvoicesController Send action: improved error logging and user-facing
  warning when PDF generation or email dispatch fails after status is saved
- item-wizard.js: guard item restoration with try/catch; ensure writeHiddenFields
  always runs on form submit via capture-phase listener
- Help docs and AI knowledge base updated for all new features

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-27 13:32:34 -04:00
parent 0ea192d55b
commit cad728ba66
11 changed files with 194 additions and 18 deletions
@@ -184,12 +184,15 @@ public static class HelpKnowledgeBase
- *Expired* validity period passed
- *Converted* converted into a job
**Quick Quote vs Full Quote mode:** The New Quote form has a toggle at the top "Quick Quote" hides non-essential fields (dates, notes, tags, oven settings, discounts, photos) so you can get a price in seconds. "Full Quote" shows the complete form. Your selection is remembered automatically. Both modes use the same pricing engine hidden fields just use defaults.
**How to create a quote:**
1. Go to [Quotes](/Quotes) "New Quote"
2. Select existing customer OR enter prospect info (name, email, phone)
3. Add line items using the item wizard (3 item types below)
4. Review the pricing breakdown
5. Save as Draft or Send immediately
2. Choose Quick Quote (fast) or Full Quote (complete form) using the toggle at the top
3. Select existing customer OR enter prospect info (name, email, phone)
4. Add line items using the item wizard (3 item types below)
5. Review the pricing breakdown
6. Save as Draft or Send immediately
**Three item types in the quote wizard:**
1. *Calculated* you enter dimensions; system calculates surface area and price from operating costs
@@ -220,7 +223,7 @@ public static class HelpKnowledgeBase
**Prospect conversion:** If a quote was for a prospect (no existing customer), you can convert them to a customer from the Quote Details page after the quote is approved.
**Sending a quote:** Click "Send" generates a PDF and emails it to the customer with an online approval link.
**Sending a quote:** Click "Send" generates a PDF and emails it to the customer with an online approval link. If the customer has email notifications turned off, the send checkbox on the Create page and the Send button on Details are both disabled a "Notifications off" warning is shown instead.
**Customer approval portal:** Customers can approve/reject quotes via a public link (/QuoteApproval) no login required.
@@ -284,6 +287,8 @@ public static class HelpKnowledgeBase
**Assigning workers:** Select an assigned shop worker on the Create or Edit page. Worker appears on the Details and Index views.
**Quick status change:** On the Jobs list, click any status badge to open a status-change modal without leaving the page. The modal includes a "Notify customer via email" toggle. If the customer has email notifications turned off, that toggle is automatically disabled and a warning is shown no email will be sent.
**Job Notes:** Add internal notes on the Job Details page. Notes are private.
**Time Entries:** Track labor time on a job from the Details page.