Add KioskIntakeOutput company setting and fix kiosk submission bugs

- New CompanyPreferences.KioskIntakeOutput setting ("Quote" default / "Job"): controls
  what the kiosk creates on submission; shown as a card-style radio toggle in
  Company Settings → Kiosk tab
- KioskSession.LinkedQuoteId added so quote-first sessions link back to the draft quote
- Migration AddKioskIntakeOutputSetting applies both schema changes
- ProcessSubmissionAsync branches on setting: creates Draft quote (quote-first) or
  Pending job (job-first); save order fixed (CompleteAsync before using DB-assigned Id as FK)
- Terms.cshtml pricing paragraph is now dynamic: "subject to formal quote" for Quote mode,
  "team member will reach out about pricing" for Job mode
- Customer Intakes list: "View Quote" button appears when LinkedQuoteId is set
- Notification label fixed: Remote sessions now say "Remote Intake", not "Walk-in Intake"
- Inactivity reset shortened to 45 s on intake steps
- Signature pad: hosted locally (no CDN), canvas resize deferred via requestAnimationFrame
- AI photo upload: client-side compression to ≤1200px + AbortController 120 s timeout
- Help article and AI knowledge base updated with kiosk feature

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-13 22:35:37 -04:00
parent d134dd51e5
commit d5ad9fa073
13 changed files with 11087 additions and 43 deletions
@@ -2253,6 +2253,10 @@ namespace PowderCoating.Infrastructure.Migrations
b.Property<int>("JobRetentionYears")
.HasColumnType("int");
b.Property<string>("KioskIntakeOutput")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("LogRetentionDays")
.HasColumnType("int");
@@ -5637,6 +5641,9 @@ namespace PowderCoating.Infrastructure.Migrations
b.Property<int?>("LinkedJobId")
.HasColumnType("int");
b.Property<int?>("LinkedQuoteId")
.HasColumnType("int");
b.Property<string>("RemoteLinkEmail")
.HasColumnType("nvarchar(max)");
@@ -6692,7 +6699,7 @@ namespace PowderCoating.Infrastructure.Migrations
{
Id = 1,
CompanyId = 0,
CreatedAt = new DateTime(2026, 5, 13, 19, 28, 44, 26, DateTimeKind.Utc).AddTicks(4259),
CreatedAt = new DateTime(2026, 5, 14, 2, 27, 27, 993, DateTimeKind.Utc).AddTicks(2349),
Description = "Standard pricing for regular customers",
DiscountPercent = 0m,
IsActive = true,
@@ -6703,7 +6710,7 @@ namespace PowderCoating.Infrastructure.Migrations
{
Id = 2,
CompanyId = 0,
CreatedAt = new DateTime(2026, 5, 13, 19, 28, 44, 26, DateTimeKind.Utc).AddTicks(4264),
CreatedAt = new DateTime(2026, 5, 14, 2, 27, 27, 993, DateTimeKind.Utc).AddTicks(2366),
Description = "5% discount for preferred customers",
DiscountPercent = 5m,
IsActive = true,
@@ -6714,7 +6721,7 @@ namespace PowderCoating.Infrastructure.Migrations
{
Id = 3,
CompanyId = 0,
CreatedAt = new DateTime(2026, 5, 13, 19, 28, 44, 26, DateTimeKind.Utc).AddTicks(4266),
CreatedAt = new DateTime(2026, 5, 14, 2, 27, 27, 993, DateTimeKind.Utc).AddTicks(2367),
Description = "10% discount for premium customers",
DiscountPercent = 10m,
IsActive = true,