der tenant admin hat eine neue, mobil unterstützende UI, login redirect funktioniert, typescript fehler wurden bereinigt. Neue Blog Posts von ChatGPT eingebaut, übersetzt von Gemini 2.5
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import { fetchOnboardingStatus, trackOnboarding } from '../api';
|
||||
import { useAuth } from '../auth/context';
|
||||
|
||||
export type OnboardingProgress = {
|
||||
welcomeSeen: boolean;
|
||||
@@ -13,6 +14,8 @@ export type OnboardingProgress = {
|
||||
priceText?: string | null;
|
||||
isSubscription?: boolean;
|
||||
} | null;
|
||||
inviteCreated: boolean;
|
||||
brandingConfigured: boolean;
|
||||
};
|
||||
|
||||
type OnboardingUpdate = Partial<OnboardingProgress> & {
|
||||
@@ -34,6 +37,8 @@ const DEFAULT_PROGRESS: OnboardingProgress = {
|
||||
lastStep: null,
|
||||
adminAppOpenedAt: null,
|
||||
selectedPackage: null,
|
||||
inviteCreated: false,
|
||||
brandingConfigured: false,
|
||||
};
|
||||
|
||||
const STORAGE_KEY = 'tenant-admin:onboarding-progress';
|
||||
@@ -74,13 +79,27 @@ function writeStoredProgress(progress: OnboardingProgress) {
|
||||
export function OnboardingProgressProvider({ children }: { children: React.ReactNode }) {
|
||||
const [progress, setProgressState] = React.useState<OnboardingProgress>(() => readStoredProgress());
|
||||
const [synced, setSynced] = React.useState(false);
|
||||
const { status } = useAuth();
|
||||
|
||||
React.useEffect(() => {
|
||||
if (status !== 'authenticated') {
|
||||
if (synced) {
|
||||
setSynced(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (synced) {
|
||||
return;
|
||||
}
|
||||
|
||||
let cancelled = false;
|
||||
|
||||
fetchOnboardingStatus().then((status) => {
|
||||
if (cancelled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!status) {
|
||||
setSynced(true);
|
||||
return;
|
||||
@@ -92,6 +111,8 @@ export function OnboardingProgressProvider({ children }: { children: React.React
|
||||
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),
|
||||
inviteCreated: Boolean(status.steps.invite_created ?? prev.inviteCreated),
|
||||
brandingConfigured: Boolean(status.steps.branding_completed ?? prev.brandingConfigured),
|
||||
};
|
||||
|
||||
writeStoredProgress(next);
|
||||
@@ -110,8 +131,16 @@ export function OnboardingProgressProvider({ children }: { children: React.React
|
||||
}
|
||||
|
||||
setSynced(true);
|
||||
}).catch(() => {
|
||||
if (!cancelled) {
|
||||
setSynced(true);
|
||||
}
|
||||
});
|
||||
}, [synced]);
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [status, synced]);
|
||||
|
||||
const setProgress = React.useCallback((updater: (prev: OnboardingProgress) => OnboardingProgress) => {
|
||||
setProgressState((prev) => {
|
||||
@@ -124,11 +153,39 @@ export function OnboardingProgressProvider({ children }: { children: React.React
|
||||
const markStep = React.useCallback((step: OnboardingUpdate) => {
|
||||
const { serverStep, meta, ...rest } = step;
|
||||
|
||||
setProgress((prev) => ({
|
||||
...prev,
|
||||
...rest,
|
||||
lastStep: typeof rest.lastStep === 'undefined' ? prev.lastStep : rest.lastStep,
|
||||
}));
|
||||
setProgress((prev) => {
|
||||
const derived: Partial<OnboardingProgress> = {};
|
||||
|
||||
switch (serverStep) {
|
||||
case 'package_selected':
|
||||
derived.packageSelected = true;
|
||||
break;
|
||||
case 'event_created':
|
||||
derived.eventCreated = true;
|
||||
break;
|
||||
case 'invite_created':
|
||||
derived.inviteCreated = true;
|
||||
break;
|
||||
case 'branding_configured':
|
||||
derived.brandingConfigured = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const next: OnboardingProgress = {
|
||||
...prev,
|
||||
...rest,
|
||||
...derived,
|
||||
lastStep: typeof rest.lastStep === 'undefined' ? prev.lastStep : rest.lastStep,
|
||||
};
|
||||
|
||||
if (serverStep === 'admin_app_opened' && !next.adminAppOpenedAt) {
|
||||
next.adminAppOpenedAt = new Date().toISOString();
|
||||
}
|
||||
|
||||
return next;
|
||||
});
|
||||
|
||||
if (serverStep) {
|
||||
trackOnboarding(serverStep, meta).catch(() => {});
|
||||
|
||||
Reference in New Issue
Block a user