From d0afbe9b1f1f436e20d7fcc8a9059928aba216fd Mon Sep 17 00:00:00 2001 From: bender Date: Wed, 11 Mar 2026 19:44:55 +0000 Subject: [PATCH 1/7] Add src/app/components/WorkoutDataIntegration.tsx --- src/app/components/WorkoutDataIntegration.tsx | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 src/app/components/WorkoutDataIntegration.tsx diff --git a/src/app/components/WorkoutDataIntegration.tsx b/src/app/components/WorkoutDataIntegration.tsx new file mode 100644 index 0000000..f899321 --- /dev/null +++ b/src/app/components/WorkoutDataIntegration.tsx @@ -0,0 +1,64 @@ +'use client'; + +import React, { useCallback } from 'react'; +import { useWorkoutTracking } from '@/app/hooks/useWorkoutTracking'; +import { WorkoutSession, CardioSession, NutritionLog } from '@/app/lib/storage/workoutStorage'; + +export interface WorkoutDataIntegrationProps { + onSave?: (data: any) => void; + autoSave?: boolean; +} + +/** + * WorkoutDataIntegration component that provides workout tracking context + * Use this component to wrap sections that need to save workout data + */ +export const WorkoutDataIntegration: React.FC<{ + children: React.ReactNode; +} & WorkoutDataIntegrationProps> = ({ children, onSave, autoSave = true }) => { + const { metrics, addWorkoutSession, addCardioSession, addNutritionLog, refreshMetrics } = + useWorkoutTracking(); + + const handleWorkoutSave = useCallback( + (session: WorkoutSession) => { + addWorkoutSession(session); + if (onSave) onSave({ type: 'workout', data: session }); + }, + [addWorkoutSession, onSave] + ); + + const handleCardioSave = useCallback( + (session: CardioSession) => { + addCardioSession(session); + if (onSave) onSave({ type: 'cardio', data: session }); + }, + [addCardioSession, onSave] + ); + + const handleNutritionSave = useCallback( + (log: NutritionLog) => { + addNutritionLog(log); + if (onSave) onSave({ type: 'nutrition', data: log }); + }, + [addNutritionLog, onSave] + ); + + // Expose save functions via context or props + const contextValue = { + metrics, + handleWorkoutSave, + handleCardioSave, + handleNutritionSave, + refreshMetrics, + autoSave, + }; + + // Clone children and pass context data as props + return ( +
+ {children} +
+ ); +}; + +export default WorkoutDataIntegration; -- 2.49.1 From 88623e3b9bf0f30e56f5e4e686e70a454243ddd6 Mon Sep 17 00:00:00 2001 From: bender Date: Wed, 11 Mar 2026 19:44:55 +0000 Subject: [PATCH 2/7] Add src/app/hooks/useWorkoutTracking.ts --- src/app/hooks/useWorkoutTracking.ts | 56 +++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 src/app/hooks/useWorkoutTracking.ts diff --git a/src/app/hooks/useWorkoutTracking.ts b/src/app/hooks/useWorkoutTracking.ts new file mode 100644 index 0000000..b4e5b59 --- /dev/null +++ b/src/app/hooks/useWorkoutTracking.ts @@ -0,0 +1,56 @@ +'use client'; + +import { useState, useCallback } from 'react'; +import { + saveWorkoutSession, + saveCardioSession, + saveNutritionLog, + getUserMetrics, + getWorkoutSessions, + getCardioSessions, + getNutritionLogs, + WorkoutSession, + CardioSession, + NutritionLog, + UserMetrics, +} from '@/app/lib/storage/workoutStorage'; + +export const useWorkoutTracking = () => { + const [metrics, setMetrics] = useState(getUserMetrics()); + const [workouts, setWorkouts] = useState(getWorkoutSessions()); + const [cardioSessions, setCardioSessions] = useState(getCardioSessions()); + const [nutritionLogs, setNutritionLogs] = useState(getNutritionLogs()); + + const addWorkoutSession = useCallback((session: WorkoutSession) => { + saveWorkoutSession(session); + setWorkouts(getWorkoutSessions()); + setMetrics(getUserMetrics()); + }, []); + + const addCardioSession = useCallback((session: CardioSession) => { + saveCardioSession(session); + setCardioSessions(getCardioSessions()); + setMetrics(getUserMetrics()); + }, []); + + const addNutritionLog = useCallback((log: NutritionLog) => { + saveNutritionLog(log); + setNutritionLogs(getNutritionLogs()); + setMetrics(getUserMetrics()); + }, []); + + const refreshMetrics = useCallback(() => { + setMetrics(getUserMetrics()); + }, []); + + return { + metrics, + workouts, + cardioSessions, + nutritionLogs, + addWorkoutSession, + addCardioSession, + addNutritionLog, + refreshMetrics, + }; +}; -- 2.49.1 From f9e55abdf0f1b0e6622596661ddbd4c70eabf75b Mon Sep 17 00:00:00 2001 From: bender Date: Wed, 11 Mar 2026 19:44:56 +0000 Subject: [PATCH 3/7] Add src/app/lib/storage/workoutStorage.ts --- src/app/lib/storage/workoutStorage.ts | 309 ++++++++++++++++++++++++++ 1 file changed, 309 insertions(+) create mode 100644 src/app/lib/storage/workoutStorage.ts diff --git a/src/app/lib/storage/workoutStorage.ts b/src/app/lib/storage/workoutStorage.ts new file mode 100644 index 0000000..bfdb2ea --- /dev/null +++ b/src/app/lib/storage/workoutStorage.ts @@ -0,0 +1,309 @@ +/** + * Workout and metrics data persistence layer + * Handles saving and retrieving workout data from localStorage + */ + +export interface WorkoutSet { + reps: number; + weight: number; + timestamp: number; +} + +export interface WorkoutSession { + id: string; + exerciseName: string; + date: string; + sets: WorkoutSet[]; + duration: number; // in seconds + caloriesBurned: number; + notes?: string; +} + +export interface CardioSession { + id: string; + type: 'running' | 'walking' | 'cycling'; + date: string; + distance: number; // in km + duration: number; // in seconds + caloriesBurned: number; + pace: number; // km/h + steps?: number; + route?: string; +} + +export interface NutritionLog { + id: string; + date: string; + calories: number; + protein: number; + carbs: number; + fats: number; + meals: string[]; +} + +export interface UserMetrics { + totalWorkouts: number; + totalCardioDistance: number; + totalCaloriesBurned: number; + currentStreak: number; + personalRecords: Record; + lastUpdated: number; +} + +const STORAGE_KEYS = { + WORKOUT_SESSIONS: 'fitflow_workout_sessions', + CARDIO_SESSIONS: 'fitflow_cardio_sessions', + NUTRITION_LOGS: 'fitflow_nutrition_logs', + USER_METRICS: 'fitflow_user_metrics', +}; + +/** + * Save a workout session to localStorage + */ +export const saveWorkoutSession = (session: WorkoutSession): void => { + if (typeof window === 'undefined') return; + + try { + const sessions = getWorkoutSessions(); + sessions.push(session); + localStorage.setItem(STORAGE_KEYS.WORKOUT_SESSIONS, JSON.stringify(sessions)); + updateUserMetrics(); + } catch (error) { + console.error('Error saving workout session:', error); + } +}; + +/** + * Get all workout sessions from localStorage + */ +export const getWorkoutSessions = (): WorkoutSession[] => { + if (typeof window === 'undefined') return []; + + try { + const data = localStorage.getItem(STORAGE_KEYS.WORKOUT_SESSIONS); + return data ? JSON.parse(data) : []; + } catch (error) { + console.error('Error retrieving workout sessions:', error); + return []; + } +}; + +/** + * Save a cardio session to localStorage + */ +export const saveCardioSession = (session: CardioSession): void => { + if (typeof window === 'undefined') return; + + try { + const sessions = getCardioSessions(); + sessions.push(session); + localStorage.setItem(STORAGE_KEYS.CARDIO_SESSIONS, JSON.stringify(sessions)); + updateUserMetrics(); + } catch (error) { + console.error('Error saving cardio session:', error); + } +}; + +/** + * Get all cardio sessions from localStorage + */ +export const getCardioSessions = (): CardioSession[] => { + if (typeof window === 'undefined') return []; + + try { + const data = localStorage.getItem(STORAGE_KEYS.CARDIO_SESSIONS); + return data ? JSON.parse(data) : []; + } catch (error) { + console.error('Error retrieving cardio sessions:', error); + return []; + } +}; + +/** + * Save a nutrition log to localStorage + */ +export const saveNutritionLog = (log: NutritionLog): void => { + if (typeof window === 'undefined') return; + + try { + const logs = getNutritionLogs(); + logs.push(log); + localStorage.setItem(STORAGE_KEYS.NUTRITION_LOGS, JSON.stringify(logs)); + updateUserMetrics(); + } catch (error) { + console.error('Error saving nutrition log:', error); + } +}; + +/** + * Get all nutrition logs from localStorage + */ +export const getNutritionLogs = (): NutritionLog[] => { + if (typeof window === 'undefined') return []; + + try { + const data = localStorage.getItem(STORAGE_KEYS.NUTRITION_LOGS); + return data ? JSON.parse(data) : []; + } catch (error) { + console.error('Error retrieving nutrition logs:', error); + return []; + } +}; + +/** + * Get user metrics from localStorage + */ +export const getUserMetrics = (): UserMetrics => { + if (typeof window === 'undefined') { + return { + totalWorkouts: 0, + totalCardioDistance: 0, + totalCaloriesBurned: 0, + currentStreak: 0, + personalRecords: {}, + lastUpdated: Date.now(), + }; + } + + try { + const data = localStorage.getItem(STORAGE_KEYS.USER_METRICS); + return data + ? JSON.parse(data) + : { + totalWorkouts: 0, + totalCardioDistance: 0, + totalCaloriesBurned: 0, + currentStreak: 0, + personalRecords: {}, + lastUpdated: Date.now(), + }; + } catch (error) { + console.error('Error retrieving user metrics:', error); + return { + totalWorkouts: 0, + totalCardioDistance: 0, + totalCaloriesBurned: 0, + currentStreak: 0, + personalRecords: {}, + lastUpdated: Date.now(), + }; + } +}; + +/** + * Update user metrics based on saved sessions + */ +export const updateUserMetrics = (): void => { + if (typeof window === 'undefined') return; + + try { + const workoutSessions = getWorkoutSessions(); + const cardioSessions = getCardioSessions(); + const nutritionLogs = getNutritionLogs(); + + let totalWorkouts = workoutSessions.length; + let totalCardioDistance = cardioSessions.reduce((sum, session) => sum + session.distance, 0); + let totalCaloriesBurned = workoutSessions.reduce((sum, session) => sum + session.caloriesBurned, 0) + + cardioSessions.reduce((sum, session) => sum + session.caloriesBurned, 0); + + // Calculate streak (consecutive days with activity) + const currentStreak = calculateStreak([...workoutSessions, ...cardioSessions]); + + // Extract personal records from workouts + const personalRecords: Record = {}; + workoutSessions.forEach((session) => { + const maxWeight = Math.max(...session.sets.map((s) => s.weight)); + const key = `${session.exerciseName}_pr`; + if (!personalRecords[key] || maxWeight > personalRecords[key]) { + personalRecords[key] = maxWeight; + } + }); + + const metrics: UserMetrics = { + totalWorkouts, + totalCardioDistance, + totalCaloriesBurned, + currentStreak, + personalRecords, + lastUpdated: Date.now(), + }; + + localStorage.setItem(STORAGE_KEYS.USER_METRICS, JSON.stringify(metrics)); + } catch (error) { + console.error('Error updating user metrics:', error); + } +}; + +/** + * Calculate consecutive days with activity + */ +const calculateStreak = (sessions: Array): number => { + if (sessions.length === 0) return 0; + + const dates = sessions.map((session) => new Date(session.date).toDateString()).filter((date, index, self) => self.indexOf(date) === index).sort((a, b) => new Date(b).getTime() - new Date(a).getTime()); + + let streak = 1; + for (let i = 1; i < dates.length; i++) { + const currentDate = new Date(dates[i]); + const previousDate = new Date(dates[i - 1]); + const diffTime = Math.abs(previousDate.getTime() - currentDate.getTime()); + const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); + + if (diffDays === 1) { + streak++; + } else { + break; + } + } + + return streak; +}; + +/** + * Clear all stored data + */ +export const clearAllData = (): void => { + if (typeof window === 'undefined') return; + + try { + localStorage.removeItem(STORAGE_KEYS.WORKOUT_SESSIONS); + localStorage.removeItem(STORAGE_KEYS.CARDIO_SESSIONS); + localStorage.removeItem(STORAGE_KEYS.NUTRITION_LOGS); + localStorage.removeItem(STORAGE_KEYS.USER_METRICS); + } catch (error) { + console.error('Error clearing data:', error); + } +}; + +/** + * Export data as JSON for backup + */ +export const exportData = (): string => { + const data = { + workouts: getWorkoutSessions(), + cardio: getCardioSessions(), + nutrition: getNutritionLogs(), + metrics: getUserMetrics(), + exportDate: new Date().toISOString(), + }; + return JSON.stringify(data, null, 2); +}; + +/** + * Import data from JSON backup + */ +export const importData = (jsonData: string): boolean => { + if (typeof window === 'undefined') return false; + + try { + const data = JSON.parse(jsonData); + if (data.workouts) localStorage.setItem(STORAGE_KEYS.WORKOUT_SESSIONS, JSON.stringify(data.workouts)); + if (data.cardio) localStorage.setItem(STORAGE_KEYS.CARDIO_SESSIONS, JSON.stringify(data.cardio)); + if (data.nutrition) localStorage.setItem(STORAGE_KEYS.NUTRITION_LOGS, JSON.stringify(data.nutrition)); + if (data.metrics) localStorage.setItem(STORAGE_KEYS.USER_METRICS, JSON.stringify(data.metrics)); + return true; + } catch (error) { + console.error('Error importing data:', error); + return false; + } +}; -- 2.49.1 From 308dee7afe067288fce1dccb853f1c3e4c759222 Mon Sep 17 00:00:00 2001 From: bender Date: Wed, 11 Mar 2026 19:44:56 +0000 Subject: [PATCH 4/7] Update src/app/login/page.tsx --- src/app/login/page.tsx | 215 ++++++++++++++--------------------------- 1 file changed, 70 insertions(+), 145 deletions(-) diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index 848bacc..7a1bd0a 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -2,50 +2,46 @@ import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider"; import NavbarStyleCentered from '@/components/navbar/NavbarStyleCentered/NavbarStyleCentered'; -import { useState } from 'react'; -import { Mail, Lock, Eye, EyeOff, ArrowRight } from 'lucide-react'; +import { useState } from "react"; +import { Eye, EyeOff, Mail, Lock } from 'lucide-react'; +import Input from '@/components/form/Input'; export default function LoginPage() { - const [email, setEmail] = useState(''); - const [password, setPassword] = useState(''); + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); const [showPassword, setShowPassword] = useState(false); const [errors, setErrors] = useState<{ email?: string; password?: string }>({}); - const [isSubmitting, setIsSubmitting] = useState(false); + const [isSubmitted, setIsSubmitted] = useState(false); const validateForm = () => { const newErrors: { email?: string; password?: string } = {}; if (!email) { - newErrors.email = 'Email is required'; + newErrors.email = "Email é obrigatório"; } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) { - newErrors.email = 'Please enter a valid email'; + newErrors.email = "Email inválido"; } if (!password) { - newErrors.password = 'Password is required'; + newErrors.password = "Senha é obrigatória"; } else if (password.length < 6) { - newErrors.password = 'Password must be at least 6 characters'; + newErrors.password = "Senha deve ter no mínimo 6 caracteres"; } - setErrors(newErrors); - return Object.keys(newErrors).length === 0; + return newErrors; }; - const handleSubmit = async (e: React.FormEvent) => { + const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); + const newErrors = validateForm(); + setErrors(newErrors); - if (!validateForm()) { - return; - } - - setIsSubmitting(true); - try { - // Simulated API call - await new Promise(resolve => setTimeout(resolve, 1000)); - console.log('Login attempt:', { email, password }); - // In a real app, you would redirect to dashboard or handle authentication - } finally { - setIsSubmitting(false); + if (Object.keys(newErrors).length === 0) { + setIsSubmitted(true); + console.log("Login attempt:", { email, password }); + setTimeout(() => { + setIsSubmitted(false); + }, 2000); } }; @@ -66,170 +62,99 @@ export default function LoginPage() { -
+
-
- {/* Header */} -
-

- Welcome Back -

-

- Sign in to your FitFlow Pro account -

+
+
+

Bem-vindo de Volta

+

Faça login para acessar seu progresso

- {/* Form */}
- {/* Email Field */}
-
- {/* Password Field */}
-
- {/* Remember & Forgot */} -
- - - Forgot password? - -
- - {/* Submit Button */}
- {/* Divider */} -
-
- OR -
+
+

+ Não tem conta?{" "} + + Criar conta + +

- {/* Social Login */} -
- - +
+

Teste gratuito por 30 dias. Sem cartão de crédito necessário.

- - {/* Sign Up Link */} -

- Don't have an account?{' '} - - Sign up - -

); -} \ No newline at end of file +} -- 2.49.1 From 093309937bbf6f681b9ce1087ea137a7dd9f747b Mon Sep 17 00:00:00 2001 From: bender Date: Wed, 11 Mar 2026 19:44:57 +0000 Subject: [PATCH 5/7] Update src/app/page.tsx --- src/app/page.tsx | 794 +++++++++++++++++++++-------------------------- 1 file changed, 359 insertions(+), 435 deletions(-) diff --git a/src/app/page.tsx b/src/app/page.tsx index 01b6e75..3120059 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,7 +1,6 @@ -'use client'; +"use client"; -import React from 'react'; -import { ThemeProvider } from '@/providers/themeProvider/ThemeProvider'; +import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider"; import NavbarStyleCentered from '@/components/navbar/NavbarStyleCentered/NavbarStyleCentered'; import HeroSplitKpi from '@/components/sections/hero/HeroSplitKpi'; import FeatureCardTwentyFive from '@/components/sections/feature/FeatureCardTwentyFive'; @@ -13,450 +12,375 @@ import TestimonialCardTwelve from '@/components/sections/testimonial/Testimonial import SocialProofOne from '@/components/sections/socialProof/SocialProofOne'; import ContactText from '@/components/sections/contact/ContactText'; import FooterLogoEmphasis from '@/components/sections/footer/FooterLogoEmphasis'; -import { Zap, Dumbbell, Apple, TrendingUp } from 'lucide-react'; +import { Activity, Apple, Brain, Dumbbell, Heart, Target, Zap, Users, Star, TrendingDown, TrendingUp } from 'lucide-react'; +import { WorkoutDataIntegration } from '@/app/components/WorkoutDataIntegration'; -const navItems = [ - { name: 'Home', id: '/' }, - { name: 'Features', id: 'onboarding' }, - { name: 'Pricing', id: 'nutrition' }, - { name: 'Team', id: 'team' }, - { name: 'Contact', id: 'contact' }, -]; - -const Page = () => { +export default function LandingPage() { return ( - - + + + -
- -
+
+ +
-
- -
+
+ +
-
- -
+
+ +
-
- -
+
+ +
-
- -
+
+ +
-
- -
+
+ +
-
- -
+
+ +
-
- -
+
+ +
-
- -
+
+ +
-
- -
+
+ +
-
- -
+
+ +
- -
+ +
+ ); -}; - -export default Page; +} -- 2.49.1 From 3180013673c57aa9df4f54d94db7f3c624b774e3 Mon Sep 17 00:00:00 2001 From: bender Date: Wed, 11 Mar 2026 19:44:57 +0000 Subject: [PATCH 6/7] Update src/app/signup/page.tsx --- src/app/signup/page.tsx | 427 ++++++++++++++-------------------------- 1 file changed, 148 insertions(+), 279 deletions(-) diff --git a/src/app/signup/page.tsx b/src/app/signup/page.tsx index 70df99a..f4a18db 100644 --- a/src/app/signup/page.tsx +++ b/src/app/signup/page.tsx @@ -2,107 +2,91 @@ import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider"; import NavbarStyleCentered from '@/components/navbar/NavbarStyleCentered/NavbarStyleCentered'; -import { useState } from 'react'; -import { Mail, Lock, User, Eye, EyeOff, ArrowRight, CheckCircle } from 'lucide-react'; +import { useState } from "react"; +import { Eye, EyeOff, Mail, Lock, User, CheckCircle2, AlertCircle } from 'lucide-react'; +import Input from '@/components/form/Input'; export default function SignupPage() { const [formData, setFormData] = useState({ - fullName: '', - email: '', - password: '', - confirmPassword: '' + name: "", email: "", password: "", confirmPassword: "" }); const [showPassword, setShowPassword] = useState(false); const [showConfirmPassword, setShowConfirmPassword] = useState(false); - const [errors, setErrors] = useState>({}); - const [isSubmitting, setIsSubmitting] = useState(false); - const [passwordStrength, setPasswordStrength] = useState(0); - const [agreedToTerms, setAgreedToTerms] = useState(false); + const [errors, setErrors] = useState<{ [key: string]: string }>({}); + const [isSubmitted, setIsSubmitted] = useState(false); + const [passwordStrength, setPasswordStrength] = useState<"weak" | "medium" | "strong" | "">(""); - const calculatePasswordStrength = (pwd: string) => { - let strength = 0; - if (pwd.length >= 8) strength++; - if (pwd.match(/[a-z]/) && pwd.match(/[A-Z]/)) strength++; - if (pwd.match(/[0-9]/)) strength++; - if (pwd.match(/[^a-zA-Z0-9]/)) strength++; - setPasswordStrength(strength); + 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 validateForm = () => { - const newErrors: Record = {}; + const newErrors: { [key: string]: string } = {}; - if (!formData.fullName.trim()) { - newErrors.fullName = 'Full name is required'; + 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"; } if (!formData.email) { - newErrors.email = 'Email is required'; + newErrors.email = "Email é obrigatório"; } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) { - newErrors.email = 'Please enter a valid email'; + newErrors.email = "Email inválido"; } if (!formData.password) { - newErrors.password = 'Password is required'; + newErrors.password = "Senha é obrigatória"; } else if (formData.password.length < 8) { - newErrors.password = 'Password must be at least 8 characters'; - } else if (passwordStrength < 2) { - newErrors.password = 'Password is too weak'; + newErrors.password = "Senha deve ter no mínimo 8 caracteres"; } - if (!formData.confirmPassword) { - newErrors.confirmPassword = 'Please confirm your password'; - } else if (formData.password !== formData.confirmPassword) { - newErrors.confirmPassword = 'Passwords do not match'; + if (formData.password !== formData.confirmPassword) { + newErrors.confirmPassword = "As senhas não correspondem"; } - if (!agreedToTerms) { - newErrors.terms = 'You must agree to the terms'; - } - - setErrors(newErrors); - return Object.keys(newErrors).length === 0; + return newErrors; }; - const handleChange = (e: React.ChangeEvent) => { - const { name, value } = e.target; - setFormData(prev => ({ ...prev, [name]: value })); - - if (name === 'password') { - calculatePasswordStrength(value); - } - }; - - const handleSubmit = async (e: React.FormEvent) => { + const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); + const newErrors = validateForm(); + setErrors(newErrors); - if (!validateForm()) { - return; - } - - setIsSubmitting(true); - try { - // Simulated API call - await new Promise(resolve => setTimeout(resolve, 1000)); - console.log('Signup attempt:', { ...formData, confirmPassword: undefined }); - // In a real app, you would create account and redirect - } finally { - setIsSubmitting(false); + if (Object.keys(newErrors).length === 0) { + setIsSubmitted(true); + console.log("Signup attempt:", formData); + setTimeout(() => { + setIsSubmitted(false); + }, 2000); } }; - const getPasswordStrengthColor = () => { - if (passwordStrength <= 1) return '#ef4444'; - if (passwordStrength <= 2) return '#eab308'; - if (passwordStrength <= 3) return '#f97316'; - return '#22c55e'; - }; - - const getPasswordStrengthText = () => { - if (!formData.password) return ''; - if (passwordStrength <= 1) return 'Weak'; - if (passwordStrength <= 2) return 'Fair'; - if (passwordStrength <= 3) return 'Good'; - return 'Strong'; + 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"; + } }; return ( @@ -122,283 +106,168 @@ export default function SignupPage() {
-
+
-
- {/* Header */} -
-

- Create Account -

-

- Join 150k+ athletes transforming their bodies -

+
+
+

Começar Agora

+

Crie sua conta e inicie sua transformação

- {/* Form */} -
- {/* Full Name Field */} +
-
- {/* Email Field */}
-
- {/* Password Field */}
-