Add src/app/login/page.tsx
This commit is contained in:
235
src/app/login/page.tsx
Normal file
235
src/app/login/page.tsx
Normal file
@@ -0,0 +1,235 @@
|
||||
"use client";
|
||||
|
||||
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';
|
||||
|
||||
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 [isSubmitting, setIsSubmitting] = useState(false);
|
||||
|
||||
const validateForm = () => {
|
||||
const newErrors: { email?: string; password?: string } = {};
|
||||
|
||||
if (!email) {
|
||||
newErrors.email = 'Email is required';
|
||||
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
|
||||
newErrors.email = 'Please enter a valid email';
|
||||
}
|
||||
|
||||
if (!password) {
|
||||
newErrors.password = 'Password is required';
|
||||
} else if (password.length < 6) {
|
||||
newErrors.password = 'Password must be at least 6 characters';
|
||||
}
|
||||
|
||||
setErrors(newErrors);
|
||||
return Object.keys(newErrors).length === 0;
|
||||
};
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
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: "/" },
|
||||
{ name: "Treino", id: "#training" },
|
||||
{ name: "Nutrição", id: "#nutrition" },
|
||||
{ name: "Comunidade", id: "#community" },
|
||||
{ name: "Perfil", id: "#profile" }
|
||||
]}
|
||||
button={{ text: "Começar Agora", href: "/signup" }}
|
||||
brandName="FitFlow Pro"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="login" data-section="login" className="min-h-screen flex items-center justify-center px-4 py-20">
|
||||
<div className="w-full max-w-md">
|
||||
<div className="rounded-2xl border border-opacity-20 p-8 backdrop-blur-sm" style={{
|
||||
backgroundColor: 'var(--color-card)',
|
||||
borderColor: 'var(--color-foreground)'
|
||||
}}>
|
||||
{/* Header */}
|
||||
<div className="mb-8 text-center">
|
||||
<h1 className="text-3xl font-bold mb-2" style={{ color: 'var(--color-foreground)' }}>
|
||||
Welcome Back
|
||||
</h1>
|
||||
<p className="text-sm" style={{ color: 'var(--color-foreground)', opacity: 0.7 }}>
|
||||
Sign in to your FitFlow Pro account
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Form */}
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
{/* Email Field */}
|
||||
<div>
|
||||
<label htmlFor="email" className="block text-sm font-medium mb-2" style={{ color: 'var(--color-foreground)' }}>
|
||||
Email Address
|
||||
</label>
|
||||
<div className="relative">
|
||||
<Mail className="absolute left-3 top-3.5 w-5 h-5" style={{ color: 'var(--color-foreground)', opacity: 0.5 }} />
|
||||
<input
|
||||
id="email"
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
placeholder="you@example.com"
|
||||
className="w-full pl-10 pr-4 py-2.5 rounded-lg border transition-all"
|
||||
style={{
|
||||
backgroundColor: 'var(--color-background)',
|
||||
borderColor: errors.email ? '#ef4444' : 'var(--color-primary-cta)',
|
||||
color: 'var(--color-foreground)',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{errors.email && (
|
||||
<p className="mt-1 text-sm font-medium" style={{ color: '#ef4444' }}>
|
||||
{errors.email}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Password Field */}
|
||||
<div>
|
||||
<label htmlFor="password" className="block text-sm font-medium mb-2" style={{ color: 'var(--color-foreground)' }}>
|
||||
Password
|
||||
</label>
|
||||
<div className="relative">
|
||||
<Lock className="absolute left-3 top-3.5 w-5 h-5" style={{ color: 'var(--color-foreground)', opacity: 0.5 }} />
|
||||
<input
|
||||
id="password"
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
placeholder="••••••••"
|
||||
className="w-full pl-10 pr-10 py-2.5 rounded-lg border transition-all"
|
||||
style={{
|
||||
backgroundColor: 'var(--color-background)',
|
||||
borderColor: errors.password ? '#ef4444' : 'var(--color-primary-cta)',
|
||||
color: 'var(--color-foreground)',
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowPassword(!showPassword)}
|
||||
className="absolute right-3 top-3.5 transition-opacity hover:opacity-75"
|
||||
>
|
||||
{showPassword ? (
|
||||
<EyeOff className="w-5 h-5" style={{ color: 'var(--color-foreground)', opacity: 0.5 }} />
|
||||
) : (
|
||||
<Eye className="w-5 h-5" style={{ color: 'var(--color-foreground)', opacity: 0.5 }} />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
{errors.password && (
|
||||
<p className="mt-1 text-sm font-medium" style={{ color: '#ef4444' }}>
|
||||
{errors.password}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Remember & Forgot */}
|
||||
<div className="flex items-center justify-between">
|
||||
<label className="flex items-center cursor-pointer">
|
||||
<input type="checkbox" className="w-4 h-4 rounded" style={{ accentColor: 'var(--color-primary-cta)' }} />
|
||||
<span className="ml-2 text-sm" style={{ color: 'var(--color-foreground)', opacity: 0.7 }}>Remember me</span>
|
||||
</label>
|
||||
<a href="#forgot" className="text-sm font-medium hover:underline" style={{ color: 'var(--color-primary-cta)' }}>
|
||||
Forgot password?
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* Submit Button */}
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isSubmitting}
|
||||
className="w-full py-2.5 rounded-lg font-semibold transition-all flex items-center justify-center gap-2 disabled:opacity-50"
|
||||
style={{
|
||||
backgroundColor: 'var(--color-primary-cta)',
|
||||
color: 'white',
|
||||
}}
|
||||
>
|
||||
{isSubmitting ? 'Signing in...' : 'Sign In'}
|
||||
{!isSubmitting && <ArrowRight className="w-4 h-4" />}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{/* Divider */}
|
||||
<div className="my-6 flex items-center gap-4">
|
||||
<div className="flex-1 h-px" style={{ backgroundColor: 'var(--color-foreground)', opacity: 0.1 }} />
|
||||
<span className="text-xs" style={{ color: 'var(--color-foreground)', opacity: 0.5 }}>OR</span>
|
||||
<div className="flex-1 h-px" style={{ backgroundColor: 'var(--color-foreground)', opacity: 0.1 }} />
|
||||
</div>
|
||||
|
||||
{/* Social Login */}
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<button
|
||||
type="button"
|
||||
className="py-2.5 rounded-lg border font-medium transition-all hover:opacity-80"
|
||||
style={{
|
||||
backgroundColor: 'var(--color-background)',
|
||||
borderColor: 'var(--color-foreground)',
|
||||
color: 'var(--color-foreground)',
|
||||
}}
|
||||
>
|
||||
Google
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="py-2.5 rounded-lg border font-medium transition-all hover:opacity-80"
|
||||
style={{
|
||||
backgroundColor: 'var(--color-background)',
|
||||
borderColor: 'var(--color-foreground)',
|
||||
color: 'var(--color-foreground)',
|
||||
}}
|
||||
>
|
||||
Apple
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Sign Up Link */}
|
||||
<p className="mt-6 text-center text-sm" style={{ color: 'var(--color-foreground)', opacity: 0.7 }}>
|
||||
Don't have an account?{' '}
|
||||
<a href="/signup" className="font-semibold hover:underline" style={{ color: 'var(--color-primary-cta)' }}>
|
||||
Sign up
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user