220 lines
7.5 KiB
TypeScript
220 lines
7.5 KiB
TypeScript
/**
|
|
* SignupFlow - Example multi-step signup with funnel tracking
|
|
*
|
|
* This demonstrates how to integrate funnel tracking into a real component.
|
|
*/
|
|
|
|
import { useState, useEffect } from 'react';
|
|
import { useSignupFunnel } from './use-signup-funnel';
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// Types
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
type Step = 'email' | 'verify' | 'profile' | 'complete';
|
|
|
|
interface FormData {
|
|
email: string;
|
|
code: string;
|
|
name: string;
|
|
company: string;
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// Component
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
export function SignupFlow() {
|
|
const [step, setStep] = useState<Step>('email');
|
|
const [formData, setFormData] = useState<FormData>({
|
|
email: '',
|
|
code: '',
|
|
name: '',
|
|
company: '',
|
|
});
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
|
|
// Initialize funnel tracking
|
|
const { startSignup, trackStep, completeSignup, cancelSignup } = useSignupFunnel({
|
|
source: 'signup-page',
|
|
});
|
|
|
|
// Start funnel on mount
|
|
useEffect(() => {
|
|
startSignup();
|
|
}, [startSignup]);
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// Step Handlers
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
const handleEmailSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
setIsLoading(true);
|
|
|
|
try {
|
|
// Send verification email (your API)
|
|
await fetch('/api/auth/send-code', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ email: formData.email }),
|
|
});
|
|
|
|
// Track funnel step
|
|
const emailDomain = formData.email.split('@')[1];
|
|
trackStep('email_entered', {
|
|
email_domain: emailDomain,
|
|
is_business_email: !['gmail.com', 'yahoo.com', 'hotmail.com'].includes(emailDomain),
|
|
});
|
|
|
|
setStep('verify');
|
|
} catch (error) {
|
|
console.error('Failed to send verification email:', error);
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
const handleVerifySubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
setIsLoading(true);
|
|
|
|
try {
|
|
// Verify code (your API)
|
|
await fetch('/api/auth/verify-code', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ email: formData.email, code: formData.code }),
|
|
});
|
|
|
|
// Track funnel step
|
|
trackStep('email_verified', { verification_method: 'code' });
|
|
|
|
setStep('profile');
|
|
} catch (error) {
|
|
console.error('Verification failed:', error);
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
const handleProfileSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
setIsLoading(true);
|
|
|
|
try {
|
|
// Create account (your API)
|
|
const response = await fetch('/api/auth/signup', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(formData),
|
|
});
|
|
|
|
const user = await response.json();
|
|
|
|
// Track profile creation
|
|
trackStep('profile_created', {
|
|
has_company: Boolean(formData.company),
|
|
});
|
|
|
|
// Complete funnel with user ID
|
|
completeSignup(user.id);
|
|
|
|
setStep('complete');
|
|
} catch (error) {
|
|
console.error('Signup failed:', error);
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
const handleCancel = () => {
|
|
cancelSignup('user_clicked_cancel');
|
|
// Navigate away
|
|
window.location.href = '/';
|
|
};
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// Render
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
return (
|
|
<div className="signup-flow">
|
|
<div className="progress">
|
|
Step {['email', 'verify', 'profile', 'complete'].indexOf(step) + 1} of 4
|
|
</div>
|
|
|
|
{step === 'email' && (
|
|
<form onSubmit={handleEmailSubmit}>
|
|
<h2>Create your account</h2>
|
|
<input
|
|
type="email"
|
|
placeholder="Enter your email"
|
|
value={formData.email}
|
|
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
|
|
required
|
|
/>
|
|
<button type="submit" disabled={isLoading}>
|
|
{isLoading ? 'Sending...' : 'Continue'}
|
|
</button>
|
|
<button type="button" onClick={handleCancel}>
|
|
Cancel
|
|
</button>
|
|
</form>
|
|
)}
|
|
|
|
{step === 'verify' && (
|
|
<form onSubmit={handleVerifySubmit}>
|
|
<h2>Verify your email</h2>
|
|
<p>We sent a code to {formData.email}</p>
|
|
<input
|
|
type="text"
|
|
placeholder="Enter verification code"
|
|
value={formData.code}
|
|
onChange={(e) => setFormData({ ...formData, code: e.target.value })}
|
|
required
|
|
/>
|
|
<button type="submit" disabled={isLoading}>
|
|
{isLoading ? 'Verifying...' : 'Verify'}
|
|
</button>
|
|
<button type="button" onClick={() => setStep('email')}>
|
|
Back
|
|
</button>
|
|
</form>
|
|
)}
|
|
|
|
{step === 'profile' && (
|
|
<form onSubmit={handleProfileSubmit}>
|
|
<h2>Tell us about yourself</h2>
|
|
<input
|
|
type="text"
|
|
placeholder="Your name"
|
|
value={formData.name}
|
|
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
|
|
required
|
|
/>
|
|
<input
|
|
type="text"
|
|
placeholder="Company (optional)"
|
|
value={formData.company}
|
|
onChange={(e) => setFormData({ ...formData, company: e.target.value })}
|
|
/>
|
|
<button type="submit" disabled={isLoading}>
|
|
{isLoading ? 'Creating account...' : 'Create Account'}
|
|
</button>
|
|
<button type="button" onClick={() => setStep('verify')}>
|
|
Back
|
|
</button>
|
|
</form>
|
|
)}
|
|
|
|
{step === 'complete' && (
|
|
<div className="success">
|
|
<h2>🎉 Welcome aboard!</h2>
|
|
<p>Your account has been created successfully.</p>
|
|
<a href="/dashboard">Go to Dashboard</a>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|