Onboarding overhaul: slim wizard, progress widget, guided activation UX
Setup Wizard: reduced from 10 steps to 5 (Company Info → QB Migration →
Pricing Defaults → Named Ovens → Notifications). Removed Doc Numbering,
Job Settings, Payment Terms, Pricing Tiers, and Team Members steps — these
all have sensible defaults and are accessible any time in Company Settings.
Wizard now completes in ~5 minutes instead of 15–20.
Dashboard progress widget (new): "Get the most out of your shop" checklist
appears for Company Admins after wizard completion. Tracks six post-setup
activation tasks with dynamic progress badge, motivating subtitle copy,
collapsed-state persistence via localStorage, and a full completion state
("Your shop is fully set up 🎉") that replaces the checklist at 100%.
The next recommended step is highlighted with a solid CTA button and a
subtle blue row tint. Completed steps show encouraging green subtext instead
of just "Done". Widget disappears from controller when AllDone would have
caused a silent vanish — now renders the completion state instead.
Guided activation (Daily Board): rewrote the BoardIntroStep callout to lead
with "This is your shop in real time" and a plain-English description of the
board's purpose. Added a separate InstructionText field to
GuidedActivationCalloutViewModel so the "Move this job to the next stage"
action prompt renders as a distinct bold line with an arrow icon rather than
being buried in the body copy. After the stage change, the confirmation
callout now reads "Nice — your workflow just updated" to reinforce what just
happened before prompting the invoice step.
All copy passes the "shop owner, not SaaS" test: no technical jargon,
benefit-driven descriptions, natural language throughout.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
@{
|
||||
ViewData["Title"] = "Setup Complete!";
|
||||
var progress = ViewBag.Progress as WizardProgressDto ?? new WizardProgressDto();
|
||||
var showGuidedActivationCta = (bool?)ViewBag.ShowGuidedActivationCta ?? false;
|
||||
}
|
||||
|
||||
@section Styles {
|
||||
@@ -79,24 +80,28 @@
|
||||
<p style="color:rgba(255,255,255,0.8);font-size:1.05rem;max-width:500px;margin:0 auto 1.5rem;">
|
||||
Your setup is complete. @progress.DoneSteps.Count of @WizardProgressDto.TotalSteps steps were configured — your shop is ready to roll.
|
||||
</p>
|
||||
<a asp-controller="Dashboard" asp-action="Index" class="btn btn-light btn-lg px-5 fw-semibold">
|
||||
<i class="bi bi-house me-2"></i>Go to Dashboard
|
||||
</a>
|
||||
@if (showGuidedActivationCta)
|
||||
{
|
||||
<a asp-controller="GuidedActivation" asp-action="Start" class="btn btn-light btn-lg px-5 fw-semibold">
|
||||
<i class="bi bi-play-circle me-2"></i>Start First Workflow
|
||||
</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<a asp-controller="Dashboard" asp-action="Index" class="btn btn-light btn-lg px-5 fw-semibold">
|
||||
<i class="bi bi-house me-2"></i>Go to Dashboard
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
|
||||
@{
|
||||
var stepLabels = new Dictionary<int, (string Label, string Icon)>
|
||||
{
|
||||
{ 1, ("Company Profile", "bi-building") },
|
||||
{ 2, ("QB Migration", "bi-arrow-left-right") },
|
||||
{ 3, ("Operating Costs", "bi-currency-dollar") },
|
||||
{ 4, ("Shop Ovens", "bi-fire") },
|
||||
{ 5, ("Doc Numbering", "bi-palette") },
|
||||
{ 6, ("Job Settings", "bi-diagram-3") },
|
||||
{ 7, ("Payment Terms", "bi-file-earmark-text") },
|
||||
{ 8, ("Pricing Tiers", "bi-percent") },
|
||||
{ 9, ("Notifications", "bi-bell") },
|
||||
{ 10, ("Team Members", "bi-people") },
|
||||
{ 1, ("Company Profile", "bi-building") },
|
||||
{ 2, ("QB Migration", "bi-arrow-left-right") },
|
||||
{ 3, ("Operating Costs", "bi-currency-dollar") },
|
||||
{ 4, ("Shop Ovens", "bi-fire") },
|
||||
{ 5, ("Notifications", "bi-bell") },
|
||||
};
|
||||
}
|
||||
|
||||
@@ -146,7 +151,16 @@
|
||||
<a asp-controller="CompanySettings" asp-action="Index" class="btn btn-outline-primary">
|
||||
<i class="bi bi-gear me-1"></i>Open Company Settings
|
||||
</a>
|
||||
<a asp-controller="Dashboard" asp-action="Index" class="btn btn-primary">
|
||||
<i class="bi bi-house me-1"></i>Go to Dashboard
|
||||
</a>
|
||||
@if (showGuidedActivationCta)
|
||||
{
|
||||
<a asp-controller="GuidedActivation" asp-action="Start" class="btn btn-primary">
|
||||
<i class="bi bi-play-circle me-1"></i>Start First Workflow
|
||||
</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<a asp-controller="Dashboard" asp-action="Index" class="btn btn-primary">
|
||||
<i class="bi bi-house me-1"></i>Go to Dashboard
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -19,8 +19,10 @@
|
||||
|
||||
<form asp-action="PostStep4" method="post" onsubmit="return validateStep4()">
|
||||
@Html.AntiForgeryToken()
|
||||
<input type="hidden" name="OvensJson" id="ovensJson" value="@Html.Raw(Model.OvensJson ?? "[]")" />
|
||||
<input type="hidden" name="BlastSetupsJson" id="blastSetupsJson" value="@Html.Raw(Model.BlastSetupsJson ?? "[]")" />
|
||||
<script type="application/json" id="ovensSeedJson">@Html.Raw(Model.OvensJson ?? "[]")</script>
|
||||
<script type="application/json" id="blastSetupsSeedJson">@Html.Raw(Model.BlastSetupsJson ?? "[]")</script>
|
||||
<input type="hidden" name="OvensJson" id="ovensJson" value="[]" />
|
||||
<input type="hidden" name="BlastSetupsJson" id="blastSetupsJson" value="[]" />
|
||||
|
||||
<!-- ── Ovens ─────────────────────────────────────────────────────── -->
|
||||
<div class="wizard-card">
|
||||
@@ -75,7 +77,7 @@
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// OVENS
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
var ovens = JSON.parse(document.getElementById('ovensJson').value || '[]');
|
||||
var ovens = JSON.parse(document.getElementById('ovensSeedJson').textContent || '[]');
|
||||
|
||||
function serializeOvens() {
|
||||
document.getElementById('ovensJson').value = JSON.stringify(
|
||||
@@ -212,7 +214,7 @@
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// BLAST SETUPS
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
var blasts = JSON.parse(document.getElementById('blastSetupsJson').value || '[]');
|
||||
var blasts = JSON.parse(document.getElementById('blastSetupsSeedJson').textContent || '[]');
|
||||
|
||||
function serializeBlasts() {
|
||||
document.getElementById('blastSetupsJson').value = JSON.stringify(
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
@{
|
||||
ViewData["Title"] = "Setup Wizard — Notifications";
|
||||
var progress = ViewBag.Progress as WizardProgressDto ?? new WizardProgressDto();
|
||||
int step = ViewBag.Step as int? ?? 9;
|
||||
int step = ViewBag.Step as int? ?? 5;
|
||||
}
|
||||
@section Styles { @await Html.PartialAsync("_WizardStyles") }
|
||||
|
||||
|
||||
@@ -4,16 +4,11 @@
|
||||
@{
|
||||
var steps = new[]
|
||||
{
|
||||
(1, "Company Profile", "bi-building"),
|
||||
(2, "QB Migration", "bi-arrow-left-right"),
|
||||
(3, "Operating Costs", "bi-currency-dollar"),
|
||||
(4, "Shop Ovens", "bi-fire"),
|
||||
(5, "Doc Numbering", "bi-palette"),
|
||||
(6, "Job Settings", "bi-diagram-3"),
|
||||
(7, "Payment Terms", "bi-file-earmark-text"),
|
||||
(8, "Pricing Tiers", "bi-percent"),
|
||||
(9, "Notifications", "bi-bell"),
|
||||
(10, "Team Members", "bi-people"),
|
||||
(1, "Company Profile", "bi-building"),
|
||||
(2, "QB Migration", "bi-arrow-left-right"),
|
||||
(3, "Operating Costs", "bi-currency-dollar"),
|
||||
(4, "Shop Ovens", "bi-fire"),
|
||||
(5, "Notifications", "bi-bell"),
|
||||
};
|
||||
int currentStep = ViewBag.Step as int? ?? 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user