completed the frontend dashboard component and bound it to the tenant admin pwa for the optimal onboarding experience.. Added a profile page.
This commit is contained in:
@@ -78,6 +78,13 @@ export default function WelcomePackagesPage() {
|
||||
isSubscription: Boolean(active.package_limits?.subscription),
|
||||
}
|
||||
: null,
|
||||
serverStep: active ? "package_selected" : undefined,
|
||||
meta: active
|
||||
? {
|
||||
packages: [active.package_id],
|
||||
is_active: active.active,
|
||||
}
|
||||
: undefined,
|
||||
});
|
||||
}
|
||||
}, [packagesState, markStep, currencyFormatter, t]);
|
||||
@@ -96,6 +103,8 @@ export default function WelcomePackagesPage() {
|
||||
priceText,
|
||||
isSubscription: Boolean(pkg.features?.subscription),
|
||||
},
|
||||
serverStep: "package_selected",
|
||||
meta: { packages: [pkg.id] },
|
||||
});
|
||||
|
||||
navigate(ADMIN_WELCOME_SUMMARY_PATH, { state: { packageId: pkg.id } });
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import React from 'react';
|
||||
import { fetchOnboardingStatus, trackOnboarding } from '../api';
|
||||
|
||||
export type OnboardingProgress = {
|
||||
welcomeSeen: boolean;
|
||||
packageSelected: boolean;
|
||||
eventCreated: boolean;
|
||||
lastStep?: string | null;
|
||||
adminAppOpenedAt?: string | null;
|
||||
selectedPackage?: {
|
||||
id: number;
|
||||
name: string;
|
||||
@@ -13,10 +15,15 @@ export type OnboardingProgress = {
|
||||
} | null;
|
||||
};
|
||||
|
||||
type OnboardingUpdate = Partial<OnboardingProgress> & {
|
||||
serverStep?: string;
|
||||
meta?: Record<string, unknown>;
|
||||
};
|
||||
|
||||
type OnboardingContextValue = {
|
||||
progress: OnboardingProgress;
|
||||
setProgress: (updater: (prev: OnboardingProgress) => OnboardingProgress) => void;
|
||||
markStep: (step: Partial<OnboardingProgress>) => void;
|
||||
markStep: (step: OnboardingUpdate) => void;
|
||||
reset: () => void;
|
||||
};
|
||||
|
||||
@@ -25,6 +32,7 @@ const DEFAULT_PROGRESS: OnboardingProgress = {
|
||||
packageSelected: false,
|
||||
eventCreated: false,
|
||||
lastStep: null,
|
||||
adminAppOpenedAt: null,
|
||||
selectedPackage: null,
|
||||
};
|
||||
|
||||
@@ -65,6 +73,45 @@ function writeStoredProgress(progress: OnboardingProgress) {
|
||||
|
||||
export function OnboardingProgressProvider({ children }: { children: React.ReactNode }) {
|
||||
const [progress, setProgressState] = React.useState<OnboardingProgress>(() => readStoredProgress());
|
||||
const [synced, setSynced] = React.useState(false);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (synced) {
|
||||
return;
|
||||
}
|
||||
|
||||
fetchOnboardingStatus().then((status) => {
|
||||
if (!status) {
|
||||
setSynced(true);
|
||||
return;
|
||||
}
|
||||
|
||||
setProgressState((prev) => {
|
||||
const next: OnboardingProgress = {
|
||||
...prev,
|
||||
adminAppOpenedAt: status.steps.admin_app_opened_at ?? prev.adminAppOpenedAt ?? null,
|
||||
eventCreated: Boolean(status.steps.event_created ?? prev.eventCreated),
|
||||
packageSelected: Boolean(status.steps.selected_packages ?? prev.packageSelected),
|
||||
};
|
||||
|
||||
writeStoredProgress(next);
|
||||
|
||||
return next;
|
||||
});
|
||||
|
||||
if (!status.steps.admin_app_opened_at) {
|
||||
const timestamp = new Date().toISOString();
|
||||
trackOnboarding('admin_app_opened').catch(() => {});
|
||||
setProgressState((prev) => {
|
||||
const next = { ...prev, adminAppOpenedAt: timestamp };
|
||||
writeStoredProgress(next);
|
||||
return next;
|
||||
});
|
||||
}
|
||||
|
||||
setSynced(true);
|
||||
});
|
||||
}, [synced]);
|
||||
|
||||
const setProgress = React.useCallback((updater: (prev: OnboardingProgress) => OnboardingProgress) => {
|
||||
setProgressState((prev) => {
|
||||
@@ -74,12 +121,18 @@ export function OnboardingProgressProvider({ children }: { children: React.React
|
||||
});
|
||||
}, []);
|
||||
|
||||
const markStep = React.useCallback((step: Partial<OnboardingProgress>) => {
|
||||
const markStep = React.useCallback((step: OnboardingUpdate) => {
|
||||
const { serverStep, meta, ...rest } = step;
|
||||
|
||||
setProgress((prev) => ({
|
||||
...prev,
|
||||
...step,
|
||||
lastStep: typeof step.lastStep === 'undefined' ? prev.lastStep : step.lastStep,
|
||||
...rest,
|
||||
lastStep: typeof rest.lastStep === 'undefined' ? prev.lastStep : rest.lastStep,
|
||||
}));
|
||||
|
||||
if (serverStep) {
|
||||
trackOnboarding(serverStep, meta).catch(() => {});
|
||||
}
|
||||
}, [setProgress]);
|
||||
|
||||
const reset = React.useCallback(() => {
|
||||
|
||||
Reference in New Issue
Block a user