From a48de5fed2260bd868575d01a516e7976acc39ae Mon Sep 17 00:00:00 2001 From: bender Date: Wed, 11 Mar 2026 19:54:53 +0000 Subject: [PATCH 1/9] Update src/app/login/page.tsx --- src/app/login/page.tsx | 289 +++++++++++++++++++++++++++-------------- 1 file changed, 194 insertions(+), 95 deletions(-) diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index 7a1bd0a..a63a45b 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -2,46 +2,69 @@ import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider"; import NavbarStyleCentered from '@/components/navbar/NavbarStyleCentered/NavbarStyleCentered'; -import { useState } from "react"; -import { Eye, EyeOff, Mail, Lock } from 'lucide-react'; -import Input from '@/components/form/Input'; +import ContactCTA from '@/components/sections/contact/ContactCTA'; +import FooterLogoEmphasis from '@/components/sections/footer/FooterLogoEmphasis'; +import { Mail, Lock, ArrowRight, AlertCircle } from 'lucide-react'; +import { useState } from 'react'; export default function LoginPage() { - const [email, setEmail] = useState(""); - const [password, setPassword] = useState(""); - const [showPassword, setShowPassword] = useState(false); - const [errors, setErrors] = useState<{ email?: string; password?: string }>({}); - const [isSubmitted, setIsSubmitted] = useState(false); + const [formData, setFormData] = useState({ + email: '', + password: '' + }); + const [errors, setErrors] = useState<{ [key: string]: string }>({}); + const [isSubmitting, setIsSubmitting] = useState(false); const validateForm = () => { - const newErrors: { email?: string; password?: string } = {}; + const newErrors: { [key: string]: string } = {}; - if (!email) { - newErrors.email = "Email é obrigatório"; - } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) { - newErrors.email = "Email inválido"; + if (!formData.email) { + newErrors.email = 'Email é obrigatório'; + } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) { + newErrors.email = 'Email inválido'; } - if (!password) { - newErrors.password = "Senha é obrigatória"; - } else if (password.length < 6) { - newErrors.password = "Senha deve ter no mínimo 6 caracteres"; + if (!formData.password) { + newErrors.password = 'Senha é obrigatória'; + } else if (formData.password.length < 6) { + newErrors.password = 'Senha deve ter pelo menos 6 caracteres'; } - return newErrors; + setErrors(newErrors); + return Object.keys(newErrors).length === 0; }; - const handleSubmit = (e: React.FormEvent) => { + const handleChange = (e: React.ChangeEvent) => { + const { name, value } = e.target; + setFormData(prev => ({ + ...prev, + [name]: value + })); + if (errors[name]) { + setErrors(prev => ({ + ...prev, + [name]: '' + })); + } + }; + + const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); - const newErrors = validateForm(); - setErrors(newErrors); - if (Object.keys(newErrors).length === 0) { - setIsSubmitted(true); - console.log("Login attempt:", { email, password }); - setTimeout(() => { - setIsSubmitted(false); - }, 2000); + if (!validateForm()) { + return; + } + + setIsSubmitting(true); + try { + await new Promise(resolve => setTimeout(resolve, 1000)); + console.log('Login attempt:', formData); + alert('Login bem-sucedido!'); + setFormData({ email: '', password: '' }); + } catch (error) { + setErrors({ submit: 'Erro ao fazer login. Tente novamente.' }); + } finally { + setIsSubmitting(false); } }; @@ -62,99 +85,175 @@ export default function LoginPage() { -
-
-
-
-

Bem-vindo de Volta

-

Faça login para acessar seu progresso

-
+
+
+
+

Bem-vindo de volta

+

Faça login na sua conta FitFlow Pro

+
+
-
- - - {errors.email && ( -

{errors.email}

- )} -
- -
-
+ + ); -} +} \ No newline at end of file -- 2.49.1 From 8ae1f717a3e761641a5c5fe952679b0257ed41f4 Mon Sep 17 00:00:00 2001 From: bender Date: Wed, 11 Mar 2026 19:54:53 +0000 Subject: [PATCH 2/9] Update src/app/page.tsx --- src/app/page.tsx | 764 +++++++++++++++++++++++++---------------------- 1 file changed, 409 insertions(+), 355 deletions(-) diff --git a/src/app/page.tsx b/src/app/page.tsx index 61b8efd..261beb3 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -13,374 +13,428 @@ import SocialProofOne from '@/components/sections/socialProof/SocialProofOne'; import ContactText from '@/components/sections/contact/ContactText'; import FooterLogoEmphasis from '@/components/sections/footer/FooterLogoEmphasis'; import { Activity, Apple, Brain, Dumbbell, Heart, Target, Zap, Users, Star, TrendingDown, TrendingUp } from 'lucide-react'; -import { WorkoutDataIntegration } from '@/app/components/WorkoutDataIntegration'; +import { useWorkoutStorage } from '@/hooks/useWorkoutStorage'; +import { useEffect, useState } from 'react'; export default function LandingPage() { + const { metrics: userMetrics, saveWorkout, getWorkoutsByType } = useWorkoutStorage(); + const [displayMetrics, setDisplayMetrics] = useState([ + { id: "1", value: "10.000+", description: "Passos diários rastreados em tempo real com motivação visual de progresso." }, + { id: "2", value: "500 kg", description: "Volume total de peso levantado monitorado com progressão semanal automática." }, + { id: "3", value: "150+ km", description: "Distância corrida mapeada com GPS, ritmo calculado e calorias precisas." }, + { id: "4", value: "42 dias", description: "Sequência de treinos consistentes com badges de dedicação desbloqueados." } + ]); + + useEffect(() => { + if (userMetrics) { + const updatedMetrics = [ + { + id: "1", value: userMetrics.totalDistance > 0 ? `${Math.round(userMetrics.totalDistance).toLocaleString()}+` : "10.000+", description: "Passos diários rastreados em tempo real com motivação visual de progresso." + }, + { + id: "2", value: userMetrics.totalWeight > 0 ? `${Math.round(userMetrics.totalWeight)} kg` : "500 kg", description: "Volume total de peso levantado monitorado com progressão semanal automática." + }, + { + id: "3", value: userMetrics.totalDistance > 0 ? `${Math.round(userMetrics.totalDistance)}+ km` : "150+ km", description: "Distância corrida mapeada com GPS, ritmo calculado e calorias precisas." + }, + { + id: "4", value: userMetrics.consistency > 0 ? `${userMetrics.consistency} dias` : "42 dias", description: "Sequência de treinos consistentes com badges de dedicação desbloqueados." + } + ]; + setDisplayMetrics(updatedMetrics); + } + }, [userMetrics]); + + const handleCardioInteraction = (data: any) => { + saveWorkout({ + type: 'cardio', + date: new Date().toISOString().split('T')[0], + data: { ...data, timestamp: Date.now() } + }); + }; + + const handleTrainingInteraction = (data: any) => { + saveWorkout({ + type: 'training', + date: new Date().toISOString().split('T')[0], + data: { ...data, timestamp: Date.now() } + }); + }; + + const handleWorkoutMode = (productId: string, productName: string) => { + saveWorkout({ + type: 'training', + date: new Date().toISOString().split('T')[0], + data: { + workout: productName, + startTime: Date.now(), + productId, + } + }); + }; + + const handleNutritionSelect = (planId: string, planName: string) => { + saveWorkout({ + type: 'nutrition', + date: new Date().toISOString().split('T')[0], + data: { + plan: planName, + planId, + selectedAt: Date.now(), + } + }); + }; + return ( - - - + + -
- -
+
+ +
-
- -
+
+ +
-
- -
+
+ +
-
- -
+
+ +
-
- -
+
+ handleWorkoutMode("1", "Iniciar Série") + }, + { + id: "2", name: "Cronômetro de Descanso", price: "Automático", imageSrc: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/workout-execution-interface-showing-set--1773256980664-da11c464.png?_wi=4", imageAlt: "Descanso entre séries", onProductClick: () => handleWorkoutMode("2", "Cronômetro de Descanso") + }, + { + id: "3", name: "Registrar Progresso", price: "Carga + Reps", imageSrc: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AoRNSPr0mCBj85JKsHl7qxTHsl/performance-metrics-showcase-displaying--1773256982260-f9a5cff0.png?_wi=4", imageAlt: "Progresso salvo", onProductClick: () => handleWorkoutMode("3", "Registrar Progresso") + } + ]} + animationType="slide-up" + textboxLayout="default" + useInvertedBackground={false} + gridVariant="three-columns-all-equal-width" + /> +
-
- -
+
+ +
-
- -
+
+ +
-
- -
+
+ +
-
- -
+
+ +
-
- -
+
+ +
-
- -
+
+ +
- -
-
+ + ); -} +} \ No newline at end of file -- 2.49.1 From 531b1c297b70bedb7cb81781bcaad93cbe0394e2 Mon Sep 17 00:00:00 2001 From: bender Date: Wed, 11 Mar 2026 19:54:54 +0000 Subject: [PATCH 3/9] Update src/app/signup/page.tsx --- src/app/signup/page.tsx | 483 ++++++++++++++++++++++++++-------------- 1 file changed, 319 insertions(+), 164 deletions(-) diff --git a/src/app/signup/page.tsx b/src/app/signup/page.tsx index f4a18db..2267a83 100644 --- a/src/app/signup/page.tsx +++ b/src/app/signup/page.tsx @@ -2,91 +2,139 @@ import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider"; import NavbarStyleCentered from '@/components/navbar/NavbarStyleCentered/NavbarStyleCentered'; -import { useState } from "react"; -import { Eye, EyeOff, Mail, Lock, User, CheckCircle2, AlertCircle } from 'lucide-react'; -import Input from '@/components/form/Input'; +import ContactCTA from '@/components/sections/contact/ContactCTA'; +import FooterLogoEmphasis from '@/components/sections/footer/FooterLogoEmphasis'; +import { Mail, Lock, User, AlertCircle, Check, ArrowRight } from 'lucide-react'; +import { useState } from 'react'; + +interface FormErrors { + [key: string]: string; +} + +interface SignupFormData { + name: string; + email: string; + password: string; + confirmPassword: string; + agreedToTerms: boolean; +} export default function SignupPage() { - const [formData, setFormData] = useState({ - name: "", email: "", password: "", confirmPassword: "" + const [formData, setFormData] = useState({ + name: '', + email: '', + password: '', + confirmPassword: '', + agreedToTerms: false }); - const [showPassword, setShowPassword] = useState(false); - const [showConfirmPassword, setShowConfirmPassword] = useState(false); - const [errors, setErrors] = useState<{ [key: string]: string }>({}); - const [isSubmitted, setIsSubmitted] = useState(false); - const [passwordStrength, setPasswordStrength] = useState<"weak" | "medium" | "strong" | "">(""); + const [errors, setErrors] = useState({}); + const [isSubmitting, setIsSubmitting] = useState(false); + const [passwordStrength, setPasswordStrength] = useState(0); - const calculatePasswordStrength = (pwd: string): "weak" | "medium" | "strong" | "" => { - if (!pwd) return ""; - if (pwd.length < 8) return "weak"; - if (/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d@$!%*?&]{8}$/.test(pwd)) return "strong"; - return "medium"; - }; - - const handleInputChange = (field: string, value: string) => { - setFormData(prev => ({ - ...prev, - [field]: value - })); - - if (field === "password") { - setPasswordStrength(calculatePasswordStrength(value)); - } + const calculatePasswordStrength = (password: string) => { + let strength = 0; + if (password.length >= 8) strength++; + if (/[a-z]/.test(password) && /[A-Z]/.test(password)) strength++; + if (/\d/.test(password)) strength++; + if (/[^a-zA-Z\d]/.test(password)) strength++; + setPasswordStrength(strength); }; const validateForm = () => { - const newErrors: { [key: string]: string } = {}; + const newErrors: FormErrors = {}; if (!formData.name.trim()) { - newErrors.name = "Nome é obrigatório"; - } else if (formData.name.trim().length < 2) { - newErrors.name = "Nome deve ter no mínimo 2 caracteres"; + newErrors.name = 'Nome é obrigatório'; + } else if (formData.name.length < 2) { + newErrors.name = 'Nome deve ter pelo menos 2 caracteres'; } if (!formData.email) { - newErrors.email = "Email é obrigatório"; + newErrors.email = 'Email é obrigatório'; } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) { - newErrors.email = "Email inválido"; + newErrors.email = 'Email inválido'; } if (!formData.password) { - newErrors.password = "Senha é obrigatória"; + newErrors.password = 'Senha é obrigatória'; } else if (formData.password.length < 8) { - newErrors.password = "Senha deve ter no mínimo 8 caracteres"; + newErrors.password = 'Senha deve ter pelo menos 8 caracteres'; } if (formData.password !== formData.confirmPassword) { - newErrors.confirmPassword = "As senhas não correspondem"; + newErrors.confirmPassword = 'As senhas não correspondem'; + } + + if (!formData.agreedToTerms) { + newErrors.agreedToTerms = 'Você deve aceitar os termos e condições'; } - return newErrors; - }; - - const handleSubmit = (e: React.FormEvent) => { - e.preventDefault(); - const newErrors = validateForm(); setErrors(newErrors); + return Object.keys(newErrors).length === 0; + }; + + const handleChange = (e: React.ChangeEvent) => { + const { name, value, type, checked } = e.target; + const newValue = type === 'checkbox' ? checked : value; - if (Object.keys(newErrors).length === 0) { - setIsSubmitted(true); - console.log("Signup attempt:", formData); - setTimeout(() => { - setIsSubmitted(false); - }, 2000); + setFormData(prev => ({ + ...prev, + [name]: newValue + })); + + if (errors[name]) { + setErrors(prev => ({ + ...prev, + [name]: '' + })); + } + + if (name === 'password') { + calculatePasswordStrength(value); } }; - const getStrengthColor = () => { - switch (passwordStrength) { - case "weak": - return "text-red-500"; - case "medium": - return "text-yellow-500"; - case "strong": - return "text-green-500"; - default: - return "text-foreground/30"; + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + + if (!validateForm()) { + return; } + + setIsSubmitting(true); + try { + await new Promise(resolve => setTimeout(resolve, 1500)); + console.log('Signup attempt:', formData); + alert('Conta criada com sucesso! Faça login para continuar.'); + setFormData({ + name: '', + email: '', + password: '', + confirmPassword: '', + agreedToTerms: false + }); + setPasswordStrength(0); + } catch (error) { + setErrors({ submit: 'Erro ao criar conta. Tente novamente.' }); + } finally { + setIsSubmitting(false); + } + }; + + const getPasswordStrengthColor = () => { + if (passwordStrength === 0) return 'bg-gray-300'; + if (passwordStrength === 1) return 'bg-red-500'; + if (passwordStrength === 2) return 'bg-yellow-500'; + if (passwordStrength === 3) return 'bg-blue-500'; + return 'bg-green-500'; + }; + + const getPasswordStrengthLabel = () => { + if (passwordStrength === 0) return ''; + if (passwordStrength === 1) return 'Fraca'; + if (passwordStrength === 2) return 'Média'; + if (passwordStrength === 3) return 'Forte'; + return 'Muito Forte'; }; return ( @@ -106,168 +154,275 @@ export default function SignupPage() {
-
-
-
-
-

Começar Agora

-

Crie sua conta e inicie sua transformação

-
+
+
+
+

Comece sua jornada

+

Crie sua conta FitFlow Pro e transforme seu corpo

+
-
-
-