Add src/app/onboarding/page.tsx

This commit is contained in:
2026-03-11 20:12:17 +00:00
parent 6279afd2b2
commit c02676d14d

332
src/app/onboarding/page.tsx Normal file
View File

@@ -0,0 +1,332 @@
"use client";
import { useState } from "react";
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
import NavbarStyleCentered from '@/components/navbar/NavbarStyleCentered/NavbarStyleCentered';
import FooterBase from '@/components/sections/footer/FooterBase';
import { ChevronRight, User, Users } from 'lucide-react';
interface UserProfile {
name: string;
gender: string;
height: string;
weight: string;
age: string;
}
type OnboardingStep = 'basic' | 'biometric' | 'complete';
export default function OnboardingPage() {
const [step, setStep] = useState<OnboardingStep>('basic');
const [profile, setProfile] = useState<UserProfile>({
name: '',
gender: '',
height: '',
weight: '',
age: ''
});
const handleBasicChange = (field: keyof Pick<UserProfile, 'name' | 'gender'>, value: string) => {
setProfile(prev => ({ ...prev, [field]: value }));
};
const handleBiometricChange = (field: keyof Pick<UserProfile, 'height' | 'weight' | 'age'>, value: string) => {
setProfile(prev => ({ ...prev, [field]: value }));
};
const handleBasicSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (profile.name && profile.gender) {
setStep('biometric');
}
};
const handleBiometricSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (profile.height && profile.weight && profile.age) {
saveProfile();
setStep('complete');
}
};
const saveProfile = () => {
localStorage.setItem('userProfile', JSON.stringify(profile));
console.log('Profile saved:', profile);
};
const handleReset = () => {
setProfile({ name: '', gender: '', height: '', weight: '', age: '' });
setStep('basic');
};
return (
<ThemeProvider
defaultButtonVariant="elastic-effect"
defaultTextAnimation="entrance-slide"
borderRadius="pill"
contentWidth="smallMedium"
sizing="mediumSizeLargeTitles"
background="blurBottom"
cardStyle="gradient-bordered"
primaryButtonStyle="flat"
secondaryButtonStyle="glass"
headingFontWeight="extrabold"
>
<div id="nav" data-section="nav">
<NavbarStyleCentered
navItems={[
{ name: "Dashboard", id: "dashboard" },
{ name: "Treino", id: "training" },
{ name: "Nutrição", id: "nutrition" },
{ name: "Comunidade", id: "community" },
{ name: "Perfil", id: "onboarding" }
]}
button={{ text: "Começar Agora", href: "contact" }}
brandName="FitFlow Pro"
/>
</div>
<div id="onboarding-flow" data-section="onboarding-flow" className="min-h-screen flex items-center justify-center py-20">
<div className="w-full max-w-2xl px-6">
{/* Progress Indicator */}
<div className="mb-12">
<div className="flex items-center justify-between mb-4">
<div className={`flex items-center gap-2 ${
step === 'basic' || step === 'biometric' || step === 'complete'
? 'text-primary-cta'
: 'text-gray-400'
}`}>
<div className="w-8 h-8 rounded-full bg-primary-cta flex items-center justify-center text-white text-sm font-bold">1</div>
<span className="font-semibold">Dados Pessoais</span>
</div>
<div className="flex-1 h-1 mx-4 bg-gray-300"></div>
<div className={`flex items-center gap-2 ${
step === 'biometric' || step === 'complete'
? 'text-primary-cta'
: 'text-gray-400'
}`}>
<div className={`w-8 h-8 rounded-full flex items-center justify-center text-sm font-bold ${
step === 'biometric' || step === 'complete'
? 'bg-primary-cta text-white'
: 'bg-gray-300 text-gray-600'
}`}>2</div>
<span className="font-semibold">Biometria</span>
</div>
</div>
</div>
{/* Step 1: Basic Information */}
{step === 'basic' && (
<div className="bg-card rounded-2xl p-8 shadow-lg">
<div className="mb-8">
<h1 className="text-4xl font-extrabold mb-2">Vamos Começar!</h1>
<p className="text-gray-600">Primeiro, precisamos conhecer você melhor.</p>
</div>
<form onSubmit={handleBasicSubmit} className="space-y-6">
{/* Name Input */}
<div>
<label className="block text-sm font-semibold mb-2">Nome Completo</label>
<input
type="text"
value={profile.name}
onChange={(e) => handleBasicChange('name', e.target.value)}
placeholder="Digite seu nome"
className="w-full px-4 py-3 rounded-lg border-2 border-gray-200 focus:border-primary-cta focus:outline-none transition"
required
/>
</div>
{/* Gender Selection */}
<div>
<label className="block text-sm font-semibold mb-2">Gênero</label>
<div className="grid grid-cols-2 gap-4">
{['Masculino', 'Feminino'].map((gender) => (
<button
key={gender}
type="button"
onClick={() => handleBasicChange('gender', gender)}
className={`py-3 px-4 rounded-lg font-semibold transition-all ${
profile.gender === gender
? 'bg-primary-cta text-white'
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
}`}
>
{gender}
</button>
))}
</div>
</div>
{/* Submit Button */}
<button
type="submit"
disabled={!profile.name || !profile.gender}
className="w-full bg-primary-cta text-white py-3 rounded-lg font-semibold hover:opacity-90 disabled:opacity-50 disabled:cursor-not-allowed transition flex items-center justify-center gap-2"
>
Próximo <ChevronRight size={18} />
</button>
</form>
</div>
)}
{/* Step 2: Biometric Information */}
{step === 'biometric' && (
<div className="bg-card rounded-2xl p-8 shadow-lg">
<div className="mb-8">
<h1 className="text-4xl font-extrabold mb-2">Dados Biométricos</h1>
<p className="text-gray-600">Agora, alguns dados de biometria para personalizar seu treino.</p>
</div>
<form onSubmit={handleBiometricSubmit} className="space-y-6">
{/* Height Input */}
<div>
<label className="block text-sm font-semibold mb-2">Altura (cm)</label>
<input
type="number"
value={profile.height}
onChange={(e) => handleBiometricChange('height', e.target.value)}
placeholder="Ex: 175"
className="w-full px-4 py-3 rounded-lg border-2 border-gray-200 focus:border-primary-cta focus:outline-none transition"
required
/>
</div>
{/* Weight Input */}
<div>
<label className="block text-sm font-semibold mb-2">Peso (kg)</label>
<input
type="number"
value={profile.weight}
onChange={(e) => handleBiometricChange('weight', e.target.value)}
placeholder="Ex: 75"
step="0.1"
className="w-full px-4 py-3 rounded-lg border-2 border-gray-200 focus:border-primary-cta focus:outline-none transition"
required
/>
</div>
{/* Age Input */}
<div>
<label className="block text-sm font-semibold mb-2">Idade</label>
<input
type="number"
value={profile.age}
onChange={(e) => handleBiometricChange('age', e.target.value)}
placeholder="Ex: 28"
className="w-full px-4 py-3 rounded-lg border-2 border-gray-200 focus:border-primary-cta focus:outline-none transition"
required
/>
</div>
{/* Buttons */}
<div className="grid grid-cols-2 gap-4">
<button
type="button"
onClick={() => setStep('basic')}
className="py-3 px-4 rounded-lg font-semibold border-2 border-gray-300 hover:bg-gray-100 transition"
>
Voltar
</button>
<button
type="submit"
disabled={!profile.height || !profile.weight || !profile.age}
className="bg-primary-cta text-white py-3 px-4 rounded-lg font-semibold hover:opacity-90 disabled:opacity-50 disabled:cursor-not-allowed transition flex items-center justify-center gap-2"
>
Concluir <ChevronRight size={18} />
</button>
</div>
</form>
</div>
)}
{/* Step 3: Completion */}
{step === 'complete' && (
<div className="bg-card rounded-2xl p-8 shadow-lg text-center">
<div className="mb-8">
<div className="w-16 h-16 bg-primary-cta rounded-full flex items-center justify-center mx-auto mb-6">
<User size={32} className="text-white" />
</div>
<h1 className="text-4xl font-extrabold mb-2">Perfil Criado com Sucesso!</h1>
<p className="text-gray-600 mb-6">Bem-vindo ao FitFlow Pro, {profile.name}!</p>
{/* Profile Summary */}
<div className="bg-gray-50 rounded-lg p-6 mb-8 text-left space-y-3">
<div className="flex justify-between">
<span className="font-semibold text-gray-700">Nome:</span>
<span className="text-gray-600">{profile.name}</span>
</div>
<div className="flex justify-between">
<span className="font-semibold text-gray-700">Gênero:</span>
<span className="text-gray-600">{profile.gender}</span>
</div>
<div className="flex justify-between">
<span className="font-semibold text-gray-700">Altura:</span>
<span className="text-gray-600">{profile.height} cm</span>
</div>
<div className="flex justify-between">
<span className="font-semibold text-gray-700">Peso:</span>
<span className="text-gray-600">{profile.weight} kg</span>
</div>
<div className="flex justify-between">
<span className="font-semibold text-gray-700">Idade:</span>
<span className="text-gray-600">{profile.age} anos</span>
</div>
</div>
</div>
{/* Action Buttons */}
<div className="grid grid-cols-2 gap-4">
<button
onClick={handleReset}
className="py-3 px-4 rounded-lg font-semibold border-2 border-gray-300 hover:bg-gray-100 transition"
>
Editar Dados
</button>
<a
href="/"
className="bg-primary-cta text-white py-3 px-4 rounded-lg font-semibold hover:opacity-90 transition flex items-center justify-center gap-2"
>
Ir para Dashboard <ChevronRight size={18} />
</a>
</div>
</div>
)}
</div>
</div>
<div id="footer" data-section="footer">
<FooterBase
columns={[
{
title: "Produto", items: [
{ label: "Dashboard", href: "dashboard" },
{ label: "Treino", href: "training" },
{ label: "Nutrição", href: "nutrition" },
{ label: "Cardio Hub", href: "cardio" }
]
},
{
title: "Comunidade", items: [
{ label: "Comunidade", href: "community" },
{ label: "Perfil", href: "onboarding" },
{ label: "Rankings", href: "rankings" },
{ label: "Blog", href: "blog" }
]
},
{
title: "Empresa", items: [
{ label: "Sobre", href: "about" },
{ label: "Contato", href: "contact" },
{ label: "Privacidade", href: "privacy" },
{ label: "Termos", href: "terms" }
]
}
]}
logoText="FitFlow Pro"
copyrightText="© 2025 FitFlow Pro. Todos os direitos reservados."
/>
</div>
</ThemeProvider>
);
}