feat: delete users - not tested

This commit is contained in:
Eric Gullickson
2025-12-22 18:20:25 -06:00
parent 91b4534e76
commit 4897f0a52c
73 changed files with 4923 additions and 62 deletions

View File

@@ -0,0 +1,150 @@
/**
* @ai-summary Mobile onboarding screen with multi-step wizard
*/
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { MobileContainer } from '../../../shared-minimal/components/mobile/MobileContainer';
import { GlassCard } from '../../../shared-minimal/components/mobile/GlassCard';
import { useSavePreferences, useCompleteOnboarding } from '../hooks/useOnboarding';
import { PreferencesStep } from '../components/PreferencesStep';
import { AddVehicleStep } from '../components/AddVehicleStep';
import { CompleteStep } from '../components/CompleteStep';
import { OnboardingStep, OnboardingPreferences } from '../types/onboarding.types';
import { CreateVehicleRequest } from '../../vehicles/types/vehicles.types';
import { vehiclesApi } from '../../vehicles/api/vehicles.api';
import toast from 'react-hot-toast';
export const OnboardingMobileScreen: React.FC = () => {
const navigate = useNavigate();
const [currentStep, setCurrentStep] = useState<OnboardingStep>('preferences');
const savePreferences = useSavePreferences();
const completeOnboarding = useCompleteOnboarding();
const [isAddingVehicle, setIsAddingVehicle] = useState(false);
const stepNumbers: Record<OnboardingStep, number> = {
preferences: 1,
vehicle: 2,
complete: 3,
};
const handleSavePreferences = async (data: OnboardingPreferences) => {
try {
await savePreferences.mutateAsync(data);
setCurrentStep('vehicle');
} catch (error) {
// Error is handled by the mutation hook
}
};
const handleAddVehicle = async (data: CreateVehicleRequest) => {
setIsAddingVehicle(true);
try {
await vehiclesApi.create(data);
toast.success('Vehicle added successfully');
setCurrentStep('complete');
} catch (error: any) {
toast.error(error.response?.data?.error || 'Failed to add vehicle');
} finally {
setIsAddingVehicle(false);
}
};
const handleSkipVehicle = () => {
setCurrentStep('complete');
};
const handleComplete = async () => {
try {
await completeOnboarding.mutateAsync();
navigate('/vehicles');
} catch (error) {
// Error is handled by the mutation hook
}
};
const handleBack = () => {
if (currentStep === 'vehicle') {
setCurrentStep('preferences');
}
};
return (
<MobileContainer>
<div className="flex-1 overflow-y-auto p-4 space-y-6">
{/* Header */}
<div className="text-center pt-4">
<h1 className="text-2xl font-bold text-slate-800 mb-2">Welcome to MotoVault Pro</h1>
<p className="text-slate-600 text-sm">Let's set up your account</p>
</div>
{/* Progress Indicator */}
<div className="flex items-center justify-between px-4">
{(['preferences', 'vehicle', 'complete'] as OnboardingStep[]).map((step, index) => (
<React.Fragment key={step}>
<div className="flex flex-col items-center">
<div
className={`w-10 h-10 rounded-full flex items-center justify-center font-semibold text-sm transition-all ${
stepNumbers[currentStep] >= stepNumbers[step]
? 'bg-primary-600 text-white'
: 'bg-gray-200 text-gray-500'
}`}
>
{stepNumbers[step]}
</div>
<span
className={`text-xs mt-1 font-medium ${
stepNumbers[currentStep] >= stepNumbers[step]
? 'text-primary-600'
: 'text-gray-500'
}`}
>
{step === 'preferences' && 'Setup'}
{step === 'vehicle' && 'Vehicle'}
{step === 'complete' && 'Done'}
</span>
</div>
{index < 2 && (
<div
className={`flex-1 h-1 mx-2 rounded transition-all ${
stepNumbers[currentStep] > stepNumbers[step]
? 'bg-primary-600'
: 'bg-gray-200'
}`}
/>
)}
</React.Fragment>
))}
</div>
{/* Step Content */}
<GlassCard padding="md">
{currentStep === 'preferences' && (
<PreferencesStep
onNext={handleSavePreferences}
loading={savePreferences.isPending}
/>
)}
{currentStep === 'vehicle' && (
<AddVehicleStep
onNext={handleSkipVehicle}
onAddVehicle={handleAddVehicle}
onBack={handleBack}
loading={isAddingVehicle}
/>
)}
{currentStep === 'complete' && (
<CompleteStep
onComplete={handleComplete}
loading={completeOnboarding.isPending}
/>
)}
</GlassCard>
</div>
</MobileContainer>
);
};
export default OnboardingMobileScreen;