Imporve onboarding UI

This commit is contained in:
Urtzi Alfaro
2025-12-19 13:10:24 +01:00
parent 71ee2976a2
commit bfa5ff0637
39 changed files with 1016 additions and 483 deletions

View File

@@ -124,38 +124,63 @@ class OnboardingService:
async def get_user_progress(self, user_id: str) -> UserProgress:
"""Get current onboarding progress for user"""
# Get user's onboarding data from user preferences or separate table
user_progress_data = await self._get_user_onboarding_data(user_id)
# Calculate current status for each step
steps = []
completed_steps = []
for step_name in ONBOARDING_STEPS:
step_data = user_progress_data.get(step_name, {})
is_completed = step_data.get("completed", False)
if is_completed:
completed_steps.append(step_name)
steps.append(OnboardingStepStatus(
step_name=step_name,
completed=is_completed,
completed_at=step_data.get("completed_at"),
data=step_data.get("data", {})
))
# Determine current and next step
current_step = self._get_current_step(completed_steps)
next_step = self._get_next_step(completed_steps)
# Calculate completion percentage
completion_percentage = (len(completed_steps) / len(ONBOARDING_STEPS)) * 100
# Check if fully completed
fully_completed = len(completed_steps) == len(ONBOARDING_STEPS)
# Check if fully completed - based on REQUIRED steps only
# Define required steps
REQUIRED_STEPS = [
"user_registered",
"setup",
"suppliers-setup",
"ml-training",
"completion"
]
# Get user's subscription tier to determine if bakery-type-selection is required
user_registered_data = user_progress_data.get("user_registered", {}).get("data", {})
subscription_tier = user_registered_data.get("subscription_tier", "professional")
# Add bakery-type-selection to required steps for non-enterprise users
if subscription_tier != "enterprise":
required_steps_for_user = REQUIRED_STEPS + ["bakery-type-selection"]
else:
required_steps_for_user = REQUIRED_STEPS
# Check if all required steps are completed
required_completed = all(
user_progress_data.get(step, {}).get("completed", False)
for step in required_steps_for_user
)
fully_completed = required_completed
return UserProgress(
user_id=user_id,
steps=steps,
@@ -234,27 +259,77 @@ class OnboardingService:
async def complete_onboarding(self, user_id: str) -> Dict[str, Any]:
"""Mark entire onboarding as complete"""
# Ensure all steps are completed
# Get user's progress
progress = await self.get_user_progress(user_id)
if not progress.fully_completed:
incomplete_steps = [
step.step_name for step in progress.steps if not step.completed
]
user_progress_data = await self._get_user_onboarding_data(user_id)
# Define REQUIRED steps (excluding optional/conditional steps)
# These are the minimum steps needed to complete onboarding
REQUIRED_STEPS = [
"user_registered",
"setup", # bakery-type-selection is conditional for enterprise
"suppliers-setup",
"ml-training",
"completion"
]
# Define CONDITIONAL steps that are only required for certain tiers/flows
CONDITIONAL_STEPS = {
"child-tenants-setup": "enterprise", # Only for enterprise tier
"product-categorization": None, # Optional for all
"bakery-type-selection": "non-enterprise", # Only for non-enterprise
"upload-sales-data": None, # Optional (manual inventory setup is alternative)
"inventory-review": None, # Optional (manual inventory setup is alternative)
"initial-stock-entry": None, # Optional
"recipes-setup": None, # Optional
"quality-setup": None, # Optional
"team-setup": None, # Optional
}
# Get user's subscription tier
user_registered_data = user_progress_data.get("user_registered", {}).get("data", {})
subscription_tier = user_registered_data.get("subscription_tier", "professional")
# Check if all REQUIRED steps are completed
incomplete_required_steps = []
for step_name in REQUIRED_STEPS:
if not user_progress_data.get(step_name, {}).get("completed", False):
# Special case: bakery-type-selection is not required for enterprise
if step_name == "bakery-type-selection" and subscription_tier == "enterprise":
continue
incomplete_required_steps.append(step_name)
# If there are incomplete required steps, reject completion
if incomplete_required_steps:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Cannot complete onboarding: incomplete steps: {incomplete_steps}"
detail=f"Cannot complete onboarding: incomplete required steps: {incomplete_required_steps}"
)
# Log conditional steps that are incomplete (warning only, not blocking)
incomplete_conditional_steps = [
step.step_name for step in progress.steps
if not step.completed and step.step_name in CONDITIONAL_STEPS
]
if incomplete_conditional_steps:
logger.info(
f"User {user_id} completing onboarding with incomplete optional steps: {incomplete_conditional_steps}",
extra={"user_id": user_id, "subscription_tier": subscription_tier}
)
# Update user's isOnboardingComplete flag
await self.user_service.update_user_field(
user_id,
"is_onboarding_complete",
user_id,
"is_onboarding_complete",
True
)
return {"success": True, "message": "Onboarding completed successfully"}
return {
"success": True,
"message": "Onboarding completed successfully",
"optional_steps_skipped": incomplete_conditional_steps
}
def _get_current_step(self, completed_steps: List[str]) -> str:
"""Determine current step based on completed steps"""