)
}
/* ── Builder onboarding section ─────────────────────────────────────────── */
/**
* Replays the `/builder/onboarding` first-run flow.
*
* - Per-device flag: `builder:onboarding-complete:v1` (set by the onboarding
* page, read by the `` cold-start gate in `routes.tsx`).
* - Gated by `useProductAuthoringEnabled()` — non-builders never see it.
* - Restart only resets the gate flag and routes to the onboarding screen;
* it does NOT delete custom products the user already created (those are
* managed in **Organization → Products**).
*/
function BuilderOnboardingSection() {
const navigate = useNavigate()
const authoringEnabled = useProductAuthoringEnabled()
const [completed, setCompleted] = React.useState(false)
React.useEffect(() => {
setCompleted(getStorageItem(BUILDER_ONBOARDING_COMPLETE_KEY) === "true")
}, [])
if (!authoringEnabled) return null
function handleRestart() {
removeStorageItem(BUILDER_ONBOARDING_COMPLETE_KEY)
setCompleted(false)
navigate("/builder/onboarding")
}
return (
Builder onboarding
The first-run guided setup that picks a product name, brand color, scope, persona,
and starter primary nav. Replay it to scaffold another custom product or to walk
a teammate through it on this device.
{completed ? "Completed" : "Pending"}
)
}
/* ── Main component ─────────────────────────────────────────────────────── */
function buildFlowStatuses() {
return COACH_MARK_FLOWS.map((f) => ({
flow: f,
dismissed: isFlowDismissed(f.id),
}))
}
/** @deprecated Use `SettingsProfileClient` — kept for back-compat imports. */
export function SettingsClient() {
return
}
export function SettingsProfileClient() {
const navigate = useNavigate()
const organizationSettingsHref = useProductOrganizationSettingsHref()
const [demoPhone, setDemoPhone] = React.useState("")
const [demoZip, setDemoZip] = React.useState("")
const [demoDate, setDemoDate] = React.useState("")
/** SSR + first client paint: all undismissed so markup matches; sync from storage after mount. */
const [flowStatuses, setFlowStatuses] = React.useState(() =>
COACH_MARK_FLOWS.map((f) => ({ flow: f, dismissed: false })),
)
React.useEffect(() => {
setFlowStatuses(buildFlowStatuses())
}, [])
const completedCount = flowStatuses.filter((f) => f.dismissed).length
const totalCount = flowStatuses.length
function refreshFlowStatuses() {
setFlowStatuses(buildFlowStatuses())
}
function handleResetFlow(flowId: string) {
resetCoachMarkFlow(flowId)
refreshFlowStatuses()
}
function handleResetAll() {
resetAllCoachMarks()
refreshFlowStatuses()
}
function handlePreview(pageUrl: string, flowId: string) {
resetCoachMarkFlow(flowId)
refreshFlowStatuses()
navigate(pageUrl)
}
return (
Profile settings
Your preferences on this device. Workspace products and branding live in{" "}
organization settings
.
Account
Profile, billing, and notification shortcuts still live in the sidebar avatar menu.
Use your avatar at the bottom of the left sidebar for
account details, billing, and alerts.
Input formats
Phone, ZIP, and date masks match table filters and properties drawer fields. Values here are only a local
preview.
Guided tours
Tours start when you first open a page, highlight one control at a time, and stop after you finish or
skip. They won’t repeat until you reset them here.