({
id: b.id, label: b.label, desc: b.desc,
icon: {b.icon},
}))}
value={value}
onChange={onChange}
columns={2}
/>
onNameChange(e.target.value)}
/>
>
);
}
const STACK_TOOLS = [
"Square / POS",
"Stripe",
"Calendly",
"Acuity",
"Shopify",
"QuickBooks",
"Mailchimp",
"Instagram",
"Google Sheets",
"Notion / Airtable",
"Wix / Squarespace",
"WhatsApp / Slack",
"A printed binder",
"Head + notepad",
];
function OwnerStack({ tools, spend, onToolsChange, onSpendChange }) {
return (
<>
v === 0 ? "$0" : v === 1500 ? "$1.5k+" : `$${v}`}
/>
{(tools || []).length > 0 && (
{tools.length} tool{tools.length === 1 ? "" : "s"}
{spend ? <> Β· ~${spend}/mo> : null}.
Replaced by one workspace, owned by you.
)}
>
);
}
const OWNER_FIRST_THINGS = [
{ id: "booking", icon: "π
", label: "Bookings & scheduling", desc: "Customers book themselves." },
{ id: "invoicing", icon: "π§Ύ", label: "Quotes, invoices, payments", desc: "Send a quote, get paid, no chasing." },
{ id: "customers", icon: "π₯", label: "Customer history & portal", desc: "One place per customer." },
{ id: "inventory", icon: "π¦", label: "Inventory & orders", desc: "Track stock, sales, suppliers." },
{ id: "team", icon: "πͺͺ", label: "Team & job dispatch", desc: "Assign jobs, log hours." },
{ id: "marketing", icon: "π£", label: "Website + email + reviews", desc: "A site that converts, list that follows up." },
];
function OwnerFirstThing({ value, onChange }) {
return (
<>
({
id: f.id, label: f.label, desc: f.desc,
icon: {f.icon},
}))}
value={value}
onChange={onChange}
columns={2}
/>
>
);
}
const OWNER_HOW_LONG = [
{ id: "starting", label: "Just starting" },
{ id: "1_3", label: "1β3 years" },
{ id: "3_10", label: "3β10 years" },
{ id: "10_plus", label: "10+ years" },
];
function OwnerScale({ customers, team, howLong, onCustomers, onTeam, onHowLong }) {
return (
<>
v === 0 ? "0" : v >= 2000 ? "2k+" : v.toLocaleString()}
/>
v >= 50 ? "50+" : `${v}`}
/>
{OWNER_HOW_LONG.map((h) => (
))}
>
);
}
// ββ Path wrapper βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
function OwnerPath({ data, onUpdate, onBack, onClose, onComplete, onJumpToStep, step }) {
const next = () => {
if (step < OWNER_TOTAL - 1) onJumpToStep(step + 1);
else onComplete();
};
const back = () => {
if (step === 0) onBack();
else onJumpToStep(step - 1);
};
let body, canNext;
if (step === 0) {
body = (
onUpdate({ biz: v })}
onNameChange={(v) => onUpdate({ bizName: v })}
/>
);
canNext = !!data.biz && (data.bizName || "").trim().length >= 2;
} else if (step === 1) {
body = (
onUpdate({ tools: v })}
onSpendChange={(v) => onUpdate({ spend: v })}
/>
);
canNext = (data.tools || []).length >= 1;
} else if (step === 2) {
body = onUpdate({ firstThing: v })} />;
canNext = !!data.firstThing;
} else {
body = (
onUpdate({ customers: v })}
onTeam={(v) => onUpdate({ team: v })}
onHowLong={(v) => onUpdate({ howLong: v })}
/>
);
canNext = !!data.howLong;
}
return (
<>
{body}
>
);
}
Object.assign(window, { OwnerPath, OWNER_TOTAL });