se mejora el login
This commit is contained in:
1 parent
b76ae84bf6
commit
f9855f31d7
4 files changed
+549
-227
No files matched your search
Binary file not shown.
|
After Width: | Height: | Size: 921 KiB |
+18
-13
@@ -1,5 +1,5 @@
|
||||
import { useState } from 'react';
|
||||
import { Routes, Route } from 'react-router';
|
||||
import { Routes, Route, useLocation } from 'react-router';
|
||||
import type { Course, CartItem, User } from './types/course';
|
||||
import { mockCourses } from './data/mockCourses';
|
||||
import { Navbar } from './components/layout/Navbar';
|
||||
@@ -18,6 +18,9 @@ import { CreateCourseModal } from './components/seller/CreateCourseModal';
|
||||
import { FiCheckCircle } from 'react-icons/fi';
|
||||
|
||||
export function App() {
|
||||
const location = useLocation();
|
||||
const isAuthPage = location.pathname === '/login' || location.pathname === '/register';
|
||||
|
||||
const [courses, setCourses] = useState<Course[]>(mockCourses);
|
||||
const [cartItems, setCartItems] = useState<CartItem[]>([]);
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
@@ -102,16 +105,18 @@ export function App() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Main Navigation Bar */}
|
||||
<Navbar
|
||||
currentUser={currentUser}
|
||||
onLogout={handleLogout}
|
||||
cartCount={cartItems.length}
|
||||
onOpenCart={() => setIsCartOpen(true)}
|
||||
onOpenCreateCourseModal={() => setIsCreateModalOpen(true)}
|
||||
searchQuery={searchQuery}
|
||||
onSearchChange={setSearchQuery}
|
||||
/>
|
||||
{/* Main Navigation Bar (hidden on Auth pages) */}
|
||||
{!isAuthPage && (
|
||||
<Navbar
|
||||
currentUser={currentUser}
|
||||
onLogout={handleLogout}
|
||||
cartCount={cartItems.length}
|
||||
onOpenCart={() => setIsCartOpen(true)}
|
||||
onOpenCreateCourseModal={() => setIsCreateModalOpen(true)}
|
||||
searchQuery={searchQuery}
|
||||
onSearchChange={setSearchQuery}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Main Views Container */}
|
||||
<main className="flex-1">
|
||||
@@ -224,8 +229,8 @@ export function App() {
|
||||
onCreateCourse={handleCreateCourse}
|
||||
/>
|
||||
|
||||
{/* Global Footer */}
|
||||
<Footer />
|
||||
{/* Global Footer (hidden on Auth pages) */}
|
||||
{!isAuthPage && <Footer />}
|
||||
|
||||
</div>
|
||||
);
|
||||
|
||||
+273
-111
@@ -1,8 +1,19 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useNavigate, Link } from 'react-router';
|
||||
import { BrandLogo } from '../components/common/BrandLogo';
|
||||
import { FiMail, FiLock, FiArrowRight } from 'react-icons/fi';
|
||||
import { FaGoogle, FaGithub } from 'react-icons/fa';
|
||||
import {
|
||||
FiMail,
|
||||
FiLock,
|
||||
FiEye,
|
||||
FiEyeOff,
|
||||
FiArrowRight,
|
||||
FiArrowLeft,
|
||||
FiStar,
|
||||
FiCheckCircle,
|
||||
FiBookOpen,
|
||||
FiAward,
|
||||
FiUsers
|
||||
} from 'react-icons/fi';
|
||||
import type { User } from '../types/course';
|
||||
|
||||
interface LoginViewProps {
|
||||
@@ -14,150 +25,301 @@ export const LoginView: React.FC<LoginViewProps> = ({ onShowToast, onLogin }) =>
|
||||
const navigate = useNavigate();
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
const [rememberMe, setRememberMe] = useState(true);
|
||||
|
||||
const handleMockLogin = (name: string, role: 'buyer' | 'seller', avatarUrl?: string) => {
|
||||
const mockUser: User = {
|
||||
id: Math.random().toString(36).substr(2, 9),
|
||||
name,
|
||||
email: email || '[email protected]',
|
||||
email: email || `${role}@rycourses.com`,
|
||||
role,
|
||||
avatar: avatarUrl,
|
||||
avatar: avatarUrl || 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=100&auto=format&fit=crop&q=80',
|
||||
};
|
||||
onLogin(mockUser);
|
||||
onShowToast(`¡Bienvenido de nuevo a RyCourses, ${name}!`);
|
||||
navigate('/');
|
||||
onShowToast(`¡Bienvenido de nuevo, ${name}!`);
|
||||
navigate(role === 'seller' ? '/seller' : '/courses');
|
||||
};
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
if (email && password) {
|
||||
handleMockLogin('Usuario Demo', 'buyer', 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=100&auto=format&fit=crop&q=80');
|
||||
handleMockLogin('Usuario Estudiante', 'buyer');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-[85vh] flex items-center justify-center py-12 px-4 sm:px-6 lg:px-8 relative bg-slate-950">
|
||||
{/* Glow background accents */}
|
||||
<div className="absolute top-1/4 left-1/4 w-72 h-72 bg-blue-600/10 rounded-full blur-3xl pointer-events-none" />
|
||||
<div className="absolute bottom-1/4 right-1/4 w-72 h-72 bg-cyan-500/10 rounded-full blur-3xl pointer-events-none" />
|
||||
<div className="min-h-screen grid grid-cols-1 lg:grid-cols-12 bg-slate-950 text-slate-100 font-sans selection:bg-cyan-500 selection:text-slate-950 relative overflow-hidden">
|
||||
|
||||
{/* Ambient background glow */}
|
||||
<div className="absolute -top-40 -left-40 w-96 h-96 bg-cyan-600/15 rounded-full blur-[120px] pointer-events-none" />
|
||||
<div className="absolute top-1/2 right-1/3 w-80 h-80 bg-blue-600/10 rounded-full blur-[140px] pointer-events-none" />
|
||||
|
||||
<div className="max-w-md w-full space-y-8 bg-slate-900/90 border border-slate-800 p-8 sm:p-10 rounded-3xl shadow-2xl backdrop-blur-md relative z-10">
|
||||
{/* ============================================================== */}
|
||||
{/* LEFT COLUMN: BRANDING & GRAPHIC BANNER */}
|
||||
{/* ============================================================== */}
|
||||
<div className="hidden lg:flex lg:col-span-6 xl:col-span-7 relative flex-col justify-between p-10 xl:p-14 overflow-hidden bg-slate-900/40 border-r border-slate-800/60">
|
||||
|
||||
{/* Header */}
|
||||
<div className="text-center space-y-3">
|
||||
<div className="flex justify-center">
|
||||
<BrandLogo size="lg" showSubtitle={false} />
|
||||
{/* Decorative Grid and Ambient Lights */}
|
||||
<div className="absolute inset-0 bg-[radial-gradient(#334155_1px,transparent_1px)] [background-size:20px_20px] opacity-25" />
|
||||
<div className="absolute top-1/4 left-10 w-96 h-96 bg-cyan-500/20 rounded-full blur-[140px] pointer-events-none" />
|
||||
<div className="absolute bottom-10 right-10 w-96 h-96 bg-blue-600/20 rounded-full blur-[140px] pointer-events-none" />
|
||||
|
||||
{/* Brand Header Banner */}
|
||||
<div className="relative z-10 flex items-center justify-between">
|
||||
<div className="flex items-center gap-3">
|
||||
<BrandLogo size="lg" showSubtitle={true} />
|
||||
</div>
|
||||
<h1 className="text-2xl font-bold text-white tracking-tight">
|
||||
Iniciar Sesión
|
||||
</h1>
|
||||
<p className="text-xs text-slate-400">
|
||||
Ingresa tus credenciales para acceder a tu panel y cursos
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Social logins */}
|
||||
<div className="grid grid-cols-2 gap-3 pt-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleMockLogin('Google User', 'buyer')}
|
||||
className="flex items-center justify-center gap-2 py-2.5 px-4 rounded-xl bg-slate-800 hover:bg-slate-700/80 border border-slate-700 text-xs font-semibold text-slate-200 transition"
|
||||
>
|
||||
<FaGoogle className="text-red-400" />
|
||||
<span>Google</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleMockLogin('GitHub User', 'buyer')}
|
||||
className="flex items-center justify-center gap-2 py-2.5 px-4 rounded-xl bg-slate-800 hover:bg-slate-700/80 border border-slate-700 text-xs font-semibold text-slate-200 transition"
|
||||
>
|
||||
<FaGithub className="text-white" />
|
||||
<span>GitHub</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="relative my-4">
|
||||
<div className="absolute inset-0 flex items-center">
|
||||
<div className="w-full border-t border-slate-800" />
|
||||
</div>
|
||||
<div className="relative flex justify-center text-xs">
|
||||
<span className="px-3 bg-slate-900 text-slate-500 font-medium">o continúa con correo</span>
|
||||
|
||||
<div className="flex items-center gap-1.5 px-3.5 py-1.5 rounded-full bg-slate-900/80 border border-slate-700/60 text-xs font-semibold text-slate-300 backdrop-blur-md">
|
||||
<FiCheckCircle className="text-emerald-400" />
|
||||
<span>+1,200 Cursos Disponibles</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Form */}
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-slate-300 mb-1.5">
|
||||
Correo Electrónico
|
||||
</label>
|
||||
<div className="relative">
|
||||
<FiMail className="absolute left-3.5 top-3.5 text-slate-500" />
|
||||
<input
|
||||
type="email"
|
||||
required
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
placeholder="[email protected]"
|
||||
className="w-full pl-10 pr-4 py-3 bg-slate-950 border border-slate-700/80 rounded-xl text-xs text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-cyan-500"
|
||||
{/* Hero Illustration Box */}
|
||||
<div className="relative z-10 my-auto py-6 max-w-2xl mx-auto w-full">
|
||||
|
||||
{/* Main Visual Frame */}
|
||||
<div className="relative rounded-3xl p-1.5 bg-gradient-to-b from-slate-700/60 via-slate-800/40 to-cyan-500/30 border border-slate-700/80 shadow-2xl backdrop-blur-md group">
|
||||
|
||||
{/* Embedded 3D Learning Image */}
|
||||
<div className="relative overflow-hidden rounded-[20px] aspect-[4/3]">
|
||||
<img
|
||||
src="/login-banner.jpg"
|
||||
alt="Aprende y crece en RyCourses"
|
||||
className="w-full h-full object-cover transform group-hover:scale-105 transition-transform duration-700"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-slate-950 via-slate-950/20 to-transparent" />
|
||||
</div>
|
||||
|
||||
{/* Top Badge Overlay */}
|
||||
<div className="absolute top-5 left-5 z-20 flex items-center gap-2 py-1.5 px-3.5 rounded-full bg-slate-950/80 border border-cyan-500/40 text-cyan-300 text-xs font-bold shadow-lg backdrop-blur-md">
|
||||
<FiStar className="text-yellow-400 fill-yellow-400" />
|
||||
<span>Aprende con Tecnologías Reales</span>
|
||||
</div>
|
||||
|
||||
{/* Bottom Overlay Card */}
|
||||
<div className="absolute bottom-5 left-5 right-5 z-20 p-4 rounded-2xl bg-slate-950/85 border border-slate-800/90 shadow-2xl backdrop-blur-xl space-y-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-10 h-10 rounded-xl bg-cyan-500/20 border border-cyan-500/40 flex items-center justify-center text-cyan-400 font-bold text-lg">
|
||||
🚀
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-xs font-bold text-white tracking-tight">
|
||||
Aumenta tus habilidades profesionales
|
||||
</p>
|
||||
<p className="text-[11px] text-slate-400">
|
||||
Cursos prácticos creados por mentores de la industria.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="hidden sm:flex items-center gap-1 bg-amber-500/10 px-2.5 py-1 rounded-lg border border-amber-500/30 text-amber-300 text-xs font-extrabold">
|
||||
<FiStar className="fill-amber-400 text-amber-400" />
|
||||
<span>4.9 / 5.0</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* Feature Highlights Grid */}
|
||||
<div className="relative z-10 grid grid-cols-3 gap-4 pt-4 border-t border-slate-800/60">
|
||||
<div className="flex items-center gap-3 p-3 rounded-2xl bg-slate-900/60 border border-slate-800/60">
|
||||
<div className="w-9 h-9 rounded-xl bg-cyan-500/10 border border-cyan-500/30 flex items-center justify-center text-cyan-400 shrink-0">
|
||||
<FiBookOpen className="text-base" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-xs font-bold text-white">Acceso De Por Vida</p>
|
||||
<p className="text-[10px] text-slate-400">Estudia a tu propio ritmo</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="flex items-center justify-between mb-1.5">
|
||||
<label className="block text-xs font-semibold text-slate-300">
|
||||
Contraseña
|
||||
</label>
|
||||
<a href="#" className="text-[11px] text-cyan-400 hover:underline">
|
||||
¿Olvidaste tu contraseña?
|
||||
</a>
|
||||
<div className="flex items-center gap-3 p-3 rounded-2xl bg-slate-900/60 border border-slate-800/60">
|
||||
<div className="w-9 h-9 rounded-xl bg-blue-500/10 border border-blue-500/30 flex items-center justify-center text-blue-400 shrink-0">
|
||||
<FiAward className="text-base" />
|
||||
</div>
|
||||
<div className="relative">
|
||||
<FiLock className="absolute left-3.5 top-3.5 text-slate-500" />
|
||||
<input
|
||||
type="password"
|
||||
required
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
placeholder="••••••••"
|
||||
className="w-full pl-10 pr-4 py-3 bg-slate-950 border border-slate-700/80 rounded-xl text-xs text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-cyan-500"
|
||||
/>
|
||||
<div>
|
||||
<p className="text-xs font-bold text-white">Certificados</p>
|
||||
<p className="text-[10px] text-slate-400">Acredita tus proyectos</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between pt-1">
|
||||
<label className="flex items-center gap-2 cursor-pointer text-xs text-slate-400">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={rememberMe}
|
||||
onChange={(e) => setRememberMe(e.target.checked)}
|
||||
className="rounded border-slate-700 bg-slate-950 text-cyan-500 focus:ring-cyan-500"
|
||||
/>
|
||||
<span>Recordar sesión</span>
|
||||
</label>
|
||||
<div className="flex items-center gap-3 p-3 rounded-2xl bg-slate-900/60 border border-slate-800/60">
|
||||
<div className="w-9 h-9 rounded-xl bg-emerald-500/10 border border-emerald-500/30 flex items-center justify-center text-emerald-400 shrink-0">
|
||||
<FiUsers className="text-base" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-xs font-bold text-white">+50,000 Alumnos</p>
|
||||
<p className="text-[10px] text-slate-400">Comunidad global activa</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full py-3.5 px-4 bg-gradient-to-r from-blue-600 to-cyan-500 hover:from-blue-500 hover:to-cyan-400 text-white font-bold rounded-xl text-sm shadow-lg shadow-cyan-500/25 transition-all flex items-center justify-center gap-2"
|
||||
>
|
||||
<span>Iniciar Sesión</span>
|
||||
<FiArrowRight />
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{/* Footer link */}
|
||||
<p className="text-center text-xs text-slate-400 pt-2">
|
||||
¿No tienes una cuenta aún?{' '}
|
||||
<Link to="/register" className="text-cyan-400 font-bold hover:underline">
|
||||
Regístrate gratis
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* ============================================================== */}
|
||||
{/* RIGHT COLUMN: FORM & AUTHENTICATION */}
|
||||
{/* ============================================================== */}
|
||||
<div className="lg:col-span-6 xl:col-span-5 flex flex-col justify-between p-6 sm:p-10 lg:p-12 z-10 bg-slate-950/90 backdrop-blur-2xl border-l border-slate-800/80">
|
||||
|
||||
{/* Top Header Navigation */}
|
||||
<div className="flex items-center justify-between">
|
||||
<Link to="/" className="inline-flex items-center gap-2 lg:hidden">
|
||||
<BrandLogo size="md" showSubtitle={false} />
|
||||
</Link>
|
||||
|
||||
<div className="hidden lg:block" />
|
||||
|
||||
<Link
|
||||
to="/"
|
||||
className="flex items-center gap-1.5 text-xs font-semibold text-slate-400 hover:text-cyan-400 transition-colors py-2 px-3 rounded-xl bg-slate-900/80 border border-slate-800 hover:border-cyan-500/40"
|
||||
>
|
||||
<FiArrowLeft className="text-sm" />
|
||||
<span>Volver al inicio</span>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Login Form Main Container */}
|
||||
<div className="my-auto py-8 max-w-md w-full mx-auto space-y-7">
|
||||
|
||||
{/* Section Titles */}
|
||||
<div className="space-y-2">
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-cyan-500/10 border border-cyan-500/20 text-cyan-400 text-xs font-medium">
|
||||
<span className="w-2 h-2 rounded-full bg-cyan-400 animate-pulse" />
|
||||
Tu Portal Educativo
|
||||
</div>
|
||||
<h1 className="text-3xl sm:text-4xl font-extrabold text-white tracking-tight">
|
||||
¡Hola de nuevo! <span className="inline-block animate-bounce">👋</span>
|
||||
</h1>
|
||||
<p className="text-xs sm:text-sm text-slate-400">
|
||||
Ingresa tus credenciales para continuar tu ruta de aprendizaje
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Quick Demo Access Bar */}
|
||||
<div className="p-3.5 rounded-2xl bg-slate-900/90 border border-slate-800 space-y-2">
|
||||
<p className="text-[11px] font-semibold text-slate-400 uppercase tracking-wider">
|
||||
Acceso Rápido Demo:
|
||||
</p>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleMockLogin('Carlos Estudiante', 'buyer', 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=100&auto=format&fit=crop&q=80')}
|
||||
className="flex items-center justify-center gap-2 py-2 px-3 rounded-xl bg-slate-800/80 hover:bg-cyan-950/60 border border-slate-700 hover:border-cyan-500/50 text-xs font-medium text-slate-200 hover:text-cyan-300 transition group"
|
||||
>
|
||||
<FiBookOpen className="text-cyan-400 group-hover:scale-110 transition-transform" />
|
||||
<span>Como Estudiante</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleMockLogin('Dra. Elena Instructor', 'seller', 'https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?w=100&auto=format&fit=crop&q=80')}
|
||||
className="flex items-center justify-center gap-2 py-2 px-3 rounded-xl bg-slate-800/80 hover:bg-violet-950/60 border border-slate-700 hover:border-violet-500/50 text-xs font-medium text-slate-200 hover:text-violet-300 transition group"
|
||||
>
|
||||
<FiUsers className="text-violet-400 group-hover:scale-110 transition-transform" />
|
||||
<span>Como Instructor</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Login Form */}
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
|
||||
{/* Email field */}
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-slate-300 mb-1.5">
|
||||
Correo Electrónico
|
||||
</label>
|
||||
<div className="relative">
|
||||
<FiMail className="absolute left-3.5 top-3.5 text-slate-500 text-base" />
|
||||
<input
|
||||
type="email"
|
||||
required
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
placeholder="[email protected]"
|
||||
className="w-full pl-10 pr-4 py-3 bg-slate-900/90 border border-slate-800 focus:border-cyan-500 rounded-xl text-xs text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-cyan-500/30 transition"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Password field */}
|
||||
<div>
|
||||
<div className="flex items-center justify-between mb-1.5">
|
||||
<label className="block text-xs font-semibold text-slate-300">
|
||||
Contraseña
|
||||
</label>
|
||||
<a href="#" className="text-[11px] font-medium text-cyan-400 hover:text-cyan-300 hover:underline transition">
|
||||
¿Olvidaste tu contraseña?
|
||||
</a>
|
||||
</div>
|
||||
<div className="relative">
|
||||
<FiLock className="absolute left-3.5 top-3.5 text-slate-500 text-base" />
|
||||
<input
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
required
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
placeholder="••••••••"
|
||||
className="w-full pl-10 pr-10 py-3 bg-slate-900/90 border border-slate-800 focus:border-cyan-500 rounded-xl text-xs text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-cyan-500/30 transition"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowPassword(!showPassword)}
|
||||
className="absolute right-3.5 top-3.5 text-slate-500 hover:text-slate-300 transition"
|
||||
>
|
||||
{showPassword ? <FiEyeOff className="text-base" /> : <FiEye className="text-base" />}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Remember Me */}
|
||||
<div className="flex items-center justify-between pt-1">
|
||||
<label className="flex items-center gap-2 cursor-pointer text-xs text-slate-400 hover:text-slate-300">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={rememberMe}
|
||||
onChange={(e) => setRememberMe(e.target.checked)}
|
||||
className="rounded border-slate-700 bg-slate-900 text-cyan-500 focus:ring-cyan-500/50"
|
||||
/>
|
||||
<span>Recordar este dispositivo</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{/* Submit Button */}
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full py-3.5 px-4 bg-gradient-to-r from-blue-600 via-cyan-500 to-teal-400 hover:opacity-95 text-white font-bold rounded-xl text-xs sm:text-sm shadow-lg shadow-cyan-500/25 transition-all flex items-center justify-center gap-2 group cursor-pointer"
|
||||
>
|
||||
<span>Ingresar a RyCourses</span>
|
||||
<FiArrowRight className="text-base group-hover:translate-x-1 transition-transform" />
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{/* Register Callout */}
|
||||
<div className="text-center text-xs text-slate-400 pt-2 border-t border-slate-900">
|
||||
¿Aún no eres miembro de RyCourses?{' '}
|
||||
<Link to="/register" className="text-cyan-400 font-bold hover:text-cyan-300 hover:underline transition">
|
||||
Regístrate gratis aquí
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* Footer info */}
|
||||
<div className="text-center lg:text-left text-[11px] text-slate-600">
|
||||
© 2026 RyCourses Platform. Todos los derechos reservados.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
+258
-103
@@ -1,7 +1,20 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useNavigate, Link } from 'react-router';
|
||||
import { BrandLogo } from '../components/common/BrandLogo';
|
||||
import { FiMail, FiLock, FiUser, FiArrowRight, FiCheckCircle } from 'react-icons/fi';
|
||||
import {
|
||||
FiMail,
|
||||
FiLock,
|
||||
FiUser,
|
||||
FiArrowRight,
|
||||
FiArrowLeft,
|
||||
FiCheckCircle,
|
||||
FiStar,
|
||||
FiBookOpen,
|
||||
FiAward,
|
||||
FiUsers,
|
||||
FiEye,
|
||||
FiEyeOff
|
||||
} from 'react-icons/fi';
|
||||
import { FaGraduationCap, FaChalkboardTeacher } from 'react-icons/fa';
|
||||
import type { User } from '../types/course';
|
||||
|
||||
@@ -15,6 +28,7 @@ export const RegisterView: React.FC<RegisterViewProps> = ({ onShowToast, onLogin
|
||||
const [name, setName] = useState('');
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
const [accountType, setAccountType] = useState<'buyer' | 'seller'>('buyer');
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
@@ -25,6 +39,7 @@ export const RegisterView: React.FC<RegisterViewProps> = ({ onShowToast, onLogin
|
||||
name,
|
||||
email,
|
||||
role: accountType,
|
||||
avatar: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=100&auto=format&fit=crop&q=80',
|
||||
};
|
||||
onLogin(newUser);
|
||||
onShowToast(`¡Cuenta de ${accountType === 'buyer' ? 'Estudiante' : 'Instructor'} creada con éxito!`);
|
||||
@@ -33,125 +48,265 @@ export const RegisterView: React.FC<RegisterViewProps> = ({ onShowToast, onLogin
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-[85vh] flex items-center justify-center py-12 px-4 sm:px-6 lg:px-8 relative bg-slate-950">
|
||||
<div className="max-w-md w-full space-y-8 bg-slate-900/90 border border-slate-800 p-8 sm:p-10 rounded-3xl shadow-2xl backdrop-blur-md relative z-10">
|
||||
<div className="min-h-screen grid grid-cols-1 lg:grid-cols-12 bg-slate-950 text-slate-100 font-sans selection:bg-cyan-500 selection:text-slate-950 relative overflow-hidden">
|
||||
|
||||
{/* Ambient background glow */}
|
||||
<div className="absolute -top-40 -left-40 w-96 h-96 bg-blue-600/15 rounded-full blur-[120px] pointer-events-none" />
|
||||
<div className="absolute top-1/2 right-1/3 w-80 h-80 bg-cyan-600/10 rounded-full blur-[140px] pointer-events-none" />
|
||||
|
||||
{/* ============================================================== */}
|
||||
{/* LEFT COLUMN: BRANDING BANNER */}
|
||||
{/* ============================================================== */}
|
||||
<div className="hidden lg:flex lg:col-span-6 xl:col-span-7 relative flex-col justify-between p-10 xl:p-14 overflow-hidden bg-slate-900/40 border-r border-slate-800/60">
|
||||
|
||||
{/* Header */}
|
||||
<div className="text-center space-y-3">
|
||||
<div className="flex justify-center">
|
||||
<BrandLogo size="lg" showSubtitle={false} />
|
||||
{/* Ambient Lights */}
|
||||
<div className="absolute inset-0 bg-[radial-gradient(#334155_1px,transparent_1px)] [background-size:20px_20px] opacity-25" />
|
||||
<div className="absolute top-1/4 left-10 w-96 h-96 bg-cyan-500/20 rounded-full blur-[140px] pointer-events-none" />
|
||||
<div className="absolute bottom-10 right-10 w-96 h-96 bg-blue-600/20 rounded-full blur-[140px] pointer-events-none" />
|
||||
|
||||
{/* Brand Header */}
|
||||
<div className="relative z-10 flex items-center justify-between">
|
||||
<BrandLogo size="lg" showSubtitle={true} />
|
||||
|
||||
<div className="flex items-center gap-1.5 px-3.5 py-1.5 rounded-full bg-slate-900/80 border border-slate-700/60 text-xs font-semibold text-slate-300 backdrop-blur-md">
|
||||
<FiCheckCircle className="text-emerald-400" />
|
||||
<span>Regístrate 100% Gratis</span>
|
||||
</div>
|
||||
<h1 className="text-2xl font-bold text-white tracking-tight">
|
||||
Crear Cuenta
|
||||
</h1>
|
||||
<p className="text-xs text-slate-400">
|
||||
Únete a la comunidad de RyCourses y empieza hoy mismo
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Account type selector */}
|
||||
<div className="grid grid-cols-2 gap-2 p-1 bg-slate-950 rounded-2xl border border-slate-800">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setAccountType('buyer')}
|
||||
className={`flex items-center justify-center gap-2 py-2.5 rounded-xl text-xs font-semibold transition-all ${
|
||||
accountType === 'buyer'
|
||||
? 'bg-blue-600 text-white shadow-md'
|
||||
: 'text-slate-400 hover:text-white'
|
||||
}`}
|
||||
>
|
||||
<FaGraduationCap /> Estudiante
|
||||
</button>
|
||||
{/* Hero Visual Box */}
|
||||
<div className="relative z-10 my-auto py-6 max-w-2xl mx-auto w-full">
|
||||
<div className="relative rounded-3xl p-1.5 bg-gradient-to-b from-slate-700/60 via-slate-800/40 to-cyan-500/30 border border-slate-700/80 shadow-2xl backdrop-blur-md group">
|
||||
|
||||
<div className="relative overflow-hidden rounded-[20px] aspect-[4/3]">
|
||||
<img
|
||||
src="/login-banner.jpg"
|
||||
alt="Comienza tu aprendizaje en RyCourses"
|
||||
className="w-full h-full object-cover transform group-hover:scale-105 transition-transform duration-700"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-slate-950 via-slate-950/20 to-transparent" />
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setAccountType('seller')}
|
||||
className={`flex items-center justify-center gap-2 py-2.5 rounded-xl text-xs font-semibold transition-all ${
|
||||
accountType === 'seller'
|
||||
? 'bg-violet-600 text-white shadow-md'
|
||||
: 'text-slate-400 hover:text-white'
|
||||
}`}
|
||||
>
|
||||
<FaChalkboardTeacher /> Instructor
|
||||
</button>
|
||||
<div className="absolute top-5 left-5 z-20 flex items-center gap-2 py-1.5 px-3.5 rounded-full bg-slate-950/80 border border-cyan-500/40 text-cyan-300 text-xs font-bold shadow-lg backdrop-blur-md">
|
||||
<FiStar className="text-yellow-400 fill-yellow-400" />
|
||||
<span>Aprende a Tu Propio Ritmo</span>
|
||||
</div>
|
||||
|
||||
<div className="absolute bottom-5 left-5 right-5 z-20 p-4 rounded-2xl bg-slate-950/85 border border-slate-800/90 shadow-2xl backdrop-blur-xl space-y-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-10 h-10 rounded-xl bg-cyan-500/20 border border-cyan-500/40 flex items-center justify-center text-cyan-400 font-bold text-lg">
|
||||
🎓
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-xs font-bold text-white tracking-tight">
|
||||
Obtén certificados con reconocimiento internacional
|
||||
</p>
|
||||
<p className="text-[11px] text-slate-400">
|
||||
Proyectos prácticos para enriquecer tu portafolio profesional.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Form */}
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-slate-300 mb-1.5">
|
||||
Nombre Completo
|
||||
</label>
|
||||
<div className="relative">
|
||||
<FiUser className="absolute left-3.5 top-3.5 text-slate-500" />
|
||||
<input
|
||||
type="text"
|
||||
required
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
placeholder="Carlos Mendoza"
|
||||
className="w-full pl-10 pr-4 py-3 bg-slate-950 border border-slate-700/80 rounded-xl text-xs text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-cyan-500"
|
||||
/>
|
||||
{/* Feature Highlights Grid */}
|
||||
<div className="relative z-10 grid grid-cols-3 gap-4 pt-4 border-t border-slate-800/60">
|
||||
<div className="flex items-center gap-3 p-3 rounded-2xl bg-slate-900/60 border border-slate-800/60">
|
||||
<div className="w-9 h-9 rounded-xl bg-cyan-500/10 border border-cyan-500/30 flex items-center justify-center text-cyan-400 shrink-0">
|
||||
<FiBookOpen className="text-base" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-xs font-bold text-white">Cursos Prácticos</p>
|
||||
<p className="text-[10px] text-slate-400">Proyectos reales</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-slate-300 mb-1.5">
|
||||
Correo Electrónico
|
||||
</label>
|
||||
<div className="relative">
|
||||
<FiMail className="absolute left-3.5 top-3.5 text-slate-500" />
|
||||
<input
|
||||
type="email"
|
||||
required
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
placeholder="[email protected]"
|
||||
className="w-full pl-10 pr-4 py-3 bg-slate-950 border border-slate-700/80 rounded-xl text-xs text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-cyan-500"
|
||||
/>
|
||||
<div className="flex items-center gap-3 p-3 rounded-2xl bg-slate-900/60 border border-slate-800/60">
|
||||
<div className="w-9 h-9 rounded-xl bg-blue-500/10 border border-blue-500/30 flex items-center justify-center text-blue-400 shrink-0">
|
||||
<FiAward className="text-base" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-xs font-bold text-white">Badges Digitales</p>
|
||||
<p className="text-[10px] text-slate-400">Comparte en Linkedin</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-slate-300 mb-1.5">
|
||||
Contraseña
|
||||
</label>
|
||||
<div className="relative">
|
||||
<FiLock className="absolute left-3.5 top-3.5 text-slate-500" />
|
||||
<input
|
||||
type="password"
|
||||
required
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
placeholder="Mínimo 8 caracteres"
|
||||
className="w-full pl-10 pr-4 py-3 bg-slate-950 border border-slate-700/80 rounded-xl text-xs text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-cyan-500"
|
||||
/>
|
||||
<div className="flex items-center gap-3 p-3 rounded-2xl bg-slate-900/60 border border-slate-800/60">
|
||||
<div className="w-9 h-9 rounded-xl bg-emerald-500/10 border border-emerald-500/30 flex items-center justify-center text-emerald-400 shrink-0">
|
||||
<FiUsers className="text-base" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-xs font-bold text-white">Mentores 24/7</p>
|
||||
<p className="text-[10px] text-slate-400">Soporte continuo</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2 pt-1 text-xs text-slate-400">
|
||||
<FiCheckCircle className="text-emerald-400 shrink-0" />
|
||||
<span>Acepto los términos de servicio y políticas de privacidad.</span>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full py-3.5 px-4 bg-gradient-to-r from-blue-600 to-cyan-500 hover:from-blue-500 hover:to-cyan-400 text-white font-bold rounded-xl text-sm shadow-lg shadow-cyan-500/25 transition-all flex items-center justify-center gap-2"
|
||||
>
|
||||
<span>Crear Cuenta Gratis</span>
|
||||
<FiArrowRight />
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{/* Footer link */}
|
||||
<p className="text-center text-xs text-slate-400 pt-2">
|
||||
¿Ya tienes una cuenta?{' '}
|
||||
<Link to="/login" className="text-cyan-400 font-bold hover:underline">
|
||||
Inicia sesión
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* ============================================================== */}
|
||||
{/* RIGHT COLUMN: FORM & REGISTER */}
|
||||
{/* ============================================================== */}
|
||||
<div className="lg:col-span-6 xl:col-span-5 flex flex-col justify-between p-6 sm:p-10 lg:p-12 z-10 bg-slate-950/90 backdrop-blur-2xl border-l border-slate-800/80">
|
||||
|
||||
{/* Top Navigation Header */}
|
||||
<div className="flex items-center justify-between">
|
||||
<Link to="/" className="inline-flex items-center gap-2 lg:hidden">
|
||||
<BrandLogo size="md" showSubtitle={false} />
|
||||
</Link>
|
||||
|
||||
<div className="hidden lg:block" />
|
||||
|
||||
<Link
|
||||
to="/"
|
||||
className="flex items-center gap-1.5 text-xs font-semibold text-slate-400 hover:text-cyan-400 transition-colors py-2 px-3 rounded-xl bg-slate-900/80 border border-slate-800 hover:border-cyan-500/40"
|
||||
>
|
||||
<FiArrowLeft className="text-sm" />
|
||||
<span>Volver al inicio</span>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Form Body Container */}
|
||||
<div className="my-auto py-8 max-w-md w-full mx-auto space-y-6">
|
||||
|
||||
{/* Titles */}
|
||||
<div className="space-y-2">
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-blue-500/10 border border-blue-500/20 text-cyan-400 text-xs font-medium">
|
||||
<span className="w-2 h-2 rounded-full bg-cyan-400 animate-pulse" />
|
||||
Únete a RyCourses
|
||||
</div>
|
||||
<h1 className="text-3xl sm:text-4xl font-extrabold text-white tracking-tight">
|
||||
Crear Cuenta Gratis ✨
|
||||
</h1>
|
||||
<p className="text-xs sm:text-sm text-slate-400">
|
||||
Comienza a aprender o enseñar hoy mismo en la plataforma líder.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Account type switcher */}
|
||||
<div className="grid grid-cols-2 gap-2 p-1.5 bg-slate-900/90 rounded-2xl border border-slate-800">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setAccountType('buyer')}
|
||||
className={`flex items-center justify-center gap-2 py-2.5 rounded-xl text-xs font-bold transition-all ${
|
||||
accountType === 'buyer'
|
||||
? 'bg-gradient-to-r from-blue-600 to-cyan-500 text-white shadow-lg shadow-cyan-500/20'
|
||||
: 'text-slate-400 hover:text-white'
|
||||
}`}
|
||||
>
|
||||
<FaGraduationCap className="text-base" /> Estudiante
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setAccountType('seller')}
|
||||
className={`flex items-center justify-center gap-2 py-2.5 rounded-xl text-xs font-bold transition-all ${
|
||||
accountType === 'seller'
|
||||
? 'bg-gradient-to-r from-violet-600 to-purple-500 text-white shadow-lg shadow-purple-500/20'
|
||||
: 'text-slate-400 hover:text-white'
|
||||
}`}
|
||||
>
|
||||
<FaChalkboardTeacher className="text-base" /> Instructor
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Form */}
|
||||
<form onSubmit={handleSubmit} className="space-y-3.5">
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-slate-300 mb-1">
|
||||
Nombre Completo
|
||||
</label>
|
||||
<div className="relative">
|
||||
<FiUser className="absolute left-3.5 top-3.5 text-slate-500 text-base" />
|
||||
<input
|
||||
type="text"
|
||||
required
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
placeholder="Ej. Sofía Rodríguez"
|
||||
className="w-full pl-10 pr-4 py-2.5 bg-slate-900/90 border border-slate-800 focus:border-cyan-500 rounded-xl text-xs text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-cyan-500/30 transition"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-slate-300 mb-1">
|
||||
Correo Electrónico
|
||||
</label>
|
||||
<div className="relative">
|
||||
<FiMail className="absolute left-3.5 top-3.5 text-slate-500 text-base" />
|
||||
<input
|
||||
type="email"
|
||||
required
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
placeholder="[email protected]"
|
||||
className="w-full pl-10 pr-4 py-2.5 bg-slate-900/90 border border-slate-800 focus:border-cyan-500 rounded-xl text-xs text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-cyan-500/30 transition"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-slate-300 mb-1">
|
||||
Contraseña
|
||||
</label>
|
||||
<div className="relative">
|
||||
<FiLock className="absolute left-3.5 top-3.5 text-slate-500 text-base" />
|
||||
<input
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
required
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
placeholder="Mínimo 8 caracteres"
|
||||
className="w-full pl-10 pr-10 py-2.5 bg-slate-900/90 border border-slate-800 focus:border-cyan-500 rounded-xl text-xs text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-cyan-500/30 transition"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowPassword(!showPassword)}
|
||||
className="absolute right-3.5 top-3 text-slate-500 hover:text-slate-300 transition"
|
||||
>
|
||||
{showPassword ? <FiEyeOff className="text-base" /> : <FiEye className="text-base" />}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2 pt-1 text-xs text-slate-400">
|
||||
<FiCheckCircle className="text-emerald-400 shrink-0" />
|
||||
<span>Acepto los Términos y Políticas de Privacidad.</span>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full py-3.5 px-4 bg-gradient-to-r from-blue-600 via-cyan-500 to-teal-400 hover:opacity-95 text-white font-bold rounded-xl text-xs sm:text-sm shadow-lg shadow-cyan-500/25 transition-all flex items-center justify-center gap-2 group cursor-pointer"
|
||||
>
|
||||
<span>Crear Cuenta como {accountType === 'buyer' ? 'Estudiante' : 'Instructor'}</span>
|
||||
<FiArrowRight className="text-base group-hover:translate-x-1 transition-transform" />
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{/* Login Link */}
|
||||
<div className="text-center text-xs text-slate-400 pt-2 border-t border-slate-900">
|
||||
¿Ya tienes una cuenta registrada?{' '}
|
||||
<Link to="/login" className="text-cyan-400 font-bold hover:text-cyan-300 hover:underline transition">
|
||||
Inicia sesión aquí
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* Footer info */}
|
||||
<div className="text-center lg:text-left text-[11px] text-slate-600">
|
||||
© 2026 RyCourses Platform. Todos los derechos reservados.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user