Phase 7: Add user onboarding tour and tenant setup wizard
Feature 1 - How-To Intro Tour (react-joyride): - 8-step guided walkthrough highlighting Dashboard, Accounts, Assessments, Transactions, Budgets, Reports, and AI Investment Planning - Runs automatically on first login, tracked via has_seen_intro flag on user - Centralized step config in config/tourSteps.ts for easy text editing - data-tour attributes on Sidebar nav items and Dashboard for targeting Feature 2 - Tenant Onboarding Wizard: - 3-step modal wizard: create operating account, assessment group + units, import budget CSV - Runs after tour completes, tracked via onboardingComplete in org settings JSONB - Reuses existing API endpoints (POST /accounts, /assessment-groups, /units, /budgets/:year/import) Backend changes: - Add has_seen_intro column to shared.users + migration - Add PATCH /auth/intro-seen endpoint to mark tour complete - Add PATCH /organizations/settings endpoint for org settings updates - Include hasSeenIntro in login response, settings in switch-org response Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,7 @@ interface Organization {
|
||||
role: string;
|
||||
schemaName?: string;
|
||||
status?: string;
|
||||
settings?: Record<string, any>;
|
||||
}
|
||||
|
||||
interface User {
|
||||
@@ -16,6 +17,7 @@ interface User {
|
||||
lastName: string;
|
||||
isSuperadmin?: boolean;
|
||||
isPlatformOwner?: boolean;
|
||||
hasSeenIntro?: boolean;
|
||||
}
|
||||
|
||||
interface ImpersonationOriginal {
|
||||
@@ -33,6 +35,8 @@ interface AuthState {
|
||||
impersonationOriginal: ImpersonationOriginal | null;
|
||||
setAuth: (token: string, user: User, organizations: Organization[]) => void;
|
||||
setCurrentOrg: (org: Organization, token?: string) => void;
|
||||
setUserIntroSeen: () => void;
|
||||
setOrgSettings: (settings: Record<string, any>) => void;
|
||||
startImpersonation: (token: string, user: User, organizations: Organization[]) => void;
|
||||
stopImpersonation: () => void;
|
||||
logout: () => void;
|
||||
@@ -59,6 +63,16 @@ export const useAuthStore = create<AuthState>()(
|
||||
currentOrg: org,
|
||||
token: token || state.token,
|
||||
})),
|
||||
setUserIntroSeen: () =>
|
||||
set((state) => ({
|
||||
user: state.user ? { ...state.user, hasSeenIntro: true } : null,
|
||||
})),
|
||||
setOrgSettings: (settings) =>
|
||||
set((state) => ({
|
||||
currentOrg: state.currentOrg
|
||||
? { ...state.currentOrg, settings: { ...(state.currentOrg.settings || {}), ...settings } }
|
||||
: null,
|
||||
})),
|
||||
startImpersonation: (token, user, organizations) => {
|
||||
const state = get();
|
||||
set({
|
||||
@@ -97,7 +111,7 @@ export const useAuthStore = create<AuthState>()(
|
||||
}),
|
||||
{
|
||||
name: 'ledgeriq-auth',
|
||||
version: 4,
|
||||
version: 5,
|
||||
migrate: () => ({
|
||||
token: null,
|
||||
user: null,
|
||||
|
||||
Reference in New Issue
Block a user