Add onboardin steps improvements
This commit is contained in:
@@ -9,6 +9,16 @@ export { useData } from './useData';
|
||||
export { useTraining } from './useTraining';
|
||||
export { useForecast } from './useForecast';
|
||||
export { useNotification } from './useNotification';
|
||||
export { useOnboarding, useOnboardingStep } from './useOnboarding';
|
||||
|
||||
// Import hooks for combined usage
|
||||
import { useAuth } from './useAuth';
|
||||
import { useTenant } from './useTenant';
|
||||
import { useData } from './useData';
|
||||
import { useTraining } from './useTraining';
|
||||
import { useForecast } from './useForecast';
|
||||
import { useNotification } from './useNotification';
|
||||
import { useOnboarding } from './useOnboarding';
|
||||
|
||||
// Combined hook for common operations
|
||||
export const useApiHooks = () => {
|
||||
@@ -18,6 +28,7 @@ export const useApiHooks = () => {
|
||||
const training = useTraining();
|
||||
const forecast = useForecast();
|
||||
const notification = useNotification();
|
||||
const onboarding = useOnboarding();
|
||||
|
||||
return {
|
||||
auth,
|
||||
@@ -26,5 +37,6 @@ export const useApiHooks = () => {
|
||||
training,
|
||||
forecast,
|
||||
notification,
|
||||
onboarding,
|
||||
};
|
||||
};
|
||||
194
frontend/src/api/hooks/useOnboarding.ts
Normal file
194
frontend/src/api/hooks/useOnboarding.ts
Normal file
@@ -0,0 +1,194 @@
|
||||
// frontend/src/api/hooks/useOnboarding.ts
|
||||
/**
|
||||
* Onboarding Hook
|
||||
* React hook for managing user onboarding flow and progress
|
||||
*/
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import { onboardingService } from '../services/onboarding.service';
|
||||
import type { UserProgress, UpdateStepRequest } from '../services/onboarding.service';
|
||||
|
||||
export interface UseOnboardingReturn {
|
||||
progress: UserProgress | null;
|
||||
isLoading: boolean;
|
||||
error: string | null;
|
||||
currentStep: string | null;
|
||||
nextStep: string | null;
|
||||
completionPercentage: number;
|
||||
isFullyComplete: boolean;
|
||||
|
||||
// Actions
|
||||
updateStep: (data: UpdateStepRequest) => Promise<void>;
|
||||
completeStep: (stepName: string, data?: Record<string, any>) => Promise<void>;
|
||||
resetStep: (stepName: string) => Promise<void>;
|
||||
getNextStep: () => Promise<string>;
|
||||
completeOnboarding: () => Promise<void>;
|
||||
canAccessStep: (stepName: string) => Promise<boolean>;
|
||||
refreshProgress: () => Promise<void>;
|
||||
}
|
||||
|
||||
export const useOnboarding = (): UseOnboardingReturn => {
|
||||
const [progress, setProgress] = useState<UserProgress | null>(null);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
// Derived state
|
||||
const currentStep = progress?.current_step || null;
|
||||
const nextStep = progress?.next_step || null;
|
||||
const completionPercentage = progress?.completion_percentage || 0;
|
||||
const isFullyComplete = progress?.fully_completed || false;
|
||||
|
||||
// Load initial progress
|
||||
const loadProgress = async () => {
|
||||
setIsLoading(true);
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
const userProgress = await onboardingService.getUserProgress();
|
||||
setProgress(userProgress);
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : 'Failed to load onboarding progress';
|
||||
setError(message);
|
||||
console.error('Onboarding progress load error:', err);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// Update step
|
||||
const updateStep = async (data: UpdateStepRequest) => {
|
||||
setIsLoading(true);
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
const updatedProgress = await onboardingService.updateStep(data);
|
||||
setProgress(updatedProgress);
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : 'Failed to update step';
|
||||
setError(message);
|
||||
throw err; // Re-throw so calling component can handle it
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// Complete step with data
|
||||
const completeStep = async (stepName: string, data?: Record<string, any>) => {
|
||||
await updateStep({
|
||||
step_name: stepName,
|
||||
completed: true,
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
// Reset step
|
||||
const resetStep = async (stepName: string) => {
|
||||
await updateStep({
|
||||
step_name: stepName,
|
||||
completed: false
|
||||
});
|
||||
};
|
||||
|
||||
// Get next step
|
||||
const getNextStep = async (): Promise<string> => {
|
||||
try {
|
||||
const result = await onboardingService.getNextStep();
|
||||
return result.step;
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : 'Failed to get next step';
|
||||
setError(message);
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
// Complete entire onboarding
|
||||
const completeOnboarding = async () => {
|
||||
setIsLoading(true);
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
await onboardingService.completeOnboarding();
|
||||
await loadProgress(); // Refresh progress after completion
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : 'Failed to complete onboarding';
|
||||
setError(message);
|
||||
throw err;
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// Check if user can access step
|
||||
const canAccessStep = async (stepName: string): Promise<boolean> => {
|
||||
try {
|
||||
const result = await onboardingService.canAccessStep(stepName);
|
||||
return result.can_access;
|
||||
} catch (err) {
|
||||
console.error('Can access step check failed:', err);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// Refresh progress
|
||||
const refreshProgress = async () => {
|
||||
await loadProgress();
|
||||
};
|
||||
|
||||
// Load progress on mount
|
||||
useEffect(() => {
|
||||
loadProgress();
|
||||
}, []);
|
||||
|
||||
return {
|
||||
progress,
|
||||
isLoading,
|
||||
error,
|
||||
currentStep,
|
||||
nextStep,
|
||||
completionPercentage,
|
||||
isFullyComplete,
|
||||
updateStep,
|
||||
completeStep,
|
||||
resetStep,
|
||||
getNextStep,
|
||||
completeOnboarding,
|
||||
canAccessStep,
|
||||
refreshProgress,
|
||||
};
|
||||
};
|
||||
|
||||
// Helper hook for specific steps
|
||||
export const useOnboardingStep = (stepName: string) => {
|
||||
const onboarding = useOnboarding();
|
||||
|
||||
const stepStatus = onboarding.progress?.steps.find(
|
||||
step => step.step_name === stepName
|
||||
);
|
||||
|
||||
const isCompleted = stepStatus?.completed || false;
|
||||
const stepData = stepStatus?.data || {};
|
||||
const completedAt = stepStatus?.completed_at;
|
||||
|
||||
const completeThisStep = async (data?: Record<string, any>) => {
|
||||
await onboarding.completeStep(stepName, data);
|
||||
};
|
||||
|
||||
const resetThisStep = async () => {
|
||||
await onboarding.resetStep(stepName);
|
||||
};
|
||||
|
||||
const canAccessThisStep = async (): Promise<boolean> => {
|
||||
return await onboarding.canAccessStep(stepName);
|
||||
};
|
||||
|
||||
return {
|
||||
...onboarding,
|
||||
stepName,
|
||||
isCompleted,
|
||||
stepData,
|
||||
completedAt,
|
||||
completeThisStep,
|
||||
resetThisStep,
|
||||
canAccessThisStep,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user