256 lines
12 KiB
TypeScript
256 lines
12 KiB
TypeScript
'use client';
|
|
|
|
import React, { useState } from 'react';
|
|
import { X, User, Lock, Mail, Phone, MapPin, Sparkles, LogIn, UserPlus, Shield, LogOut } from 'lucide-react';
|
|
import { useAuth } from '@/context/AuthContext';
|
|
import { useBrand } from '@/context/BrandContext';
|
|
import Link from 'next/link';
|
|
|
|
export const AuthModal: React.FC = () => {
|
|
const { user, login, register, logout, isAuthModalOpen, closeAuthModal } = useAuth();
|
|
const { currentBrand } = useBrand();
|
|
|
|
const [mode, setMode] = useState<'login' | 'register'>('login');
|
|
const [identifier, setIdentifier] = useState('');
|
|
const [name, setName] = useState('');
|
|
const [email, setEmail] = useState('');
|
|
const [phone, setPhone] = useState('');
|
|
const [city, setCity] = useState('Cali');
|
|
const [address, setAddress] = useState('');
|
|
const [error, setError] = useState<string | null>(null);
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
if (!isAuthModalOpen) return null;
|
|
|
|
const handleLoginSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
setError(null);
|
|
setLoading(true);
|
|
const res = await login(identifier);
|
|
setLoading(false);
|
|
if (!res.success) {
|
|
setError(res.error || 'Error al iniciar sesión');
|
|
}
|
|
};
|
|
|
|
const handleRegisterSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
setError(null);
|
|
setLoading(true);
|
|
const res = await register({ name, email, phone, city, address });
|
|
setLoading(false);
|
|
if (!res.success) {
|
|
setError(res.error || 'Error al registrarse');
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="fixed inset-0 z-50 bg-black/80 backdrop-blur-md flex items-center justify-center p-4 animate-in fade-in">
|
|
<div className="bg-neutral-900 border border-neutral-800 rounded-3xl max-w-md w-full p-6 space-y-4 shadow-2xl relative">
|
|
<button
|
|
onClick={closeAuthModal}
|
|
className="absolute top-4 right-4 text-neutral-400 hover:text-white p-1 rounded-full cursor-pointer"
|
|
>
|
|
<X className="w-5 h-5" />
|
|
</button>
|
|
|
|
{/* If user is already logged in: View Profile */}
|
|
{user ? (
|
|
<div className="space-y-4 text-center">
|
|
<div className={`w-16 h-16 rounded-3xl bg-gradient-to-br ${currentBrand.colors.primaryGradient} flex items-center justify-center text-white font-black text-2xl mx-auto shadow-lg`}>
|
|
{user.name.charAt(0).toUpperCase()}
|
|
</div>
|
|
<div>
|
|
<h3 className="font-black text-white text-lg">{user.name}</h3>
|
|
<p className="text-xs text-neutral-400">{user.email}</p>
|
|
<div className="inline-block mt-1">
|
|
<span className={`text-[10px] font-bold px-2.5 py-0.5 rounded-full border ${
|
|
user.role === 'admin'
|
|
? 'bg-purple-500/20 text-purple-300 border-purple-500/40'
|
|
: user.role === 'operator'
|
|
? 'bg-fuchsia-500/20 text-fuchsia-300 border-fuchsia-500/40'
|
|
: 'bg-emerald-500/20 text-emerald-300 border-emerald-500/40'
|
|
}`}>
|
|
{user.role === 'admin' ? '👑 Administrador' : user.role === 'operator' ? '📦 Operador Logística' : '🛍️ Cliente Registrado'}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="bg-neutral-950/80 border border-neutral-800 rounded-2xl p-3 text-left text-xs space-y-1.5 text-neutral-300">
|
|
<p><strong>📱 Celular:</strong> {user.phone}</p>
|
|
<p><strong>📍 Ciudad:</strong> {user.city || 'Cali'}</p>
|
|
{user.address && <p><strong>🏠 Dirección:</strong> {user.address}</p>}
|
|
</div>
|
|
|
|
{user.role === 'admin' || user.role === 'operator' ? (
|
|
<Link
|
|
href="/admin"
|
|
onClick={closeAuthModal}
|
|
className={`w-full bg-gradient-to-r ${currentBrand.colors.primaryGradient} text-white font-black text-xs py-3 rounded-xl flex items-center justify-center gap-1.5 shadow-md`}
|
|
>
|
|
<Shield className="w-4 h-4" />
|
|
<span>Ir al Panel de Control Admin</span>
|
|
</Link>
|
|
) : null}
|
|
|
|
<button
|
|
onClick={logout}
|
|
className="w-full bg-neutral-800 hover:bg-red-950/40 hover:border-red-500/50 border border-transparent text-neutral-300 hover:text-red-300 font-bold text-xs py-2.5 rounded-xl flex items-center justify-center gap-1.5 cursor-pointer transition-all"
|
|
>
|
|
<LogOut className="w-4 h-4" />
|
|
<span>Cerrar Sesión</span>
|
|
</button>
|
|
</div>
|
|
) : (
|
|
/* Login or Register */
|
|
<div className="space-y-4">
|
|
<div className="flex items-center space-x-2">
|
|
<div className={`w-9 h-9 rounded-xl bg-gradient-to-br ${currentBrand.colors.primaryGradient} flex items-center justify-center text-white font-black shadow-md`}>
|
|
{currentBrand.shortName[0]}
|
|
</div>
|
|
<div>
|
|
<h3 className="font-black text-white text-base leading-tight">
|
|
{mode === 'login' ? 'Iniciar Sesión' : 'Crear Cuenta'}
|
|
</h3>
|
|
<p className="text-xs text-neutral-400">
|
|
{mode === 'login'
|
|
? 'Accede para gestionar pedidos o entrar como admin'
|
|
: 'Regístrate para compras rápidas y seguimiento'}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Mode Switch Tabs */}
|
|
<div className="grid grid-cols-2 p-1 bg-neutral-950 border border-neutral-800 rounded-2xl">
|
|
<button
|
|
type="button"
|
|
onClick={() => { setMode('login'); setError(null); }}
|
|
className={`text-xs font-bold py-2 rounded-xl transition-all cursor-pointer ${
|
|
mode === 'login' ? 'bg-white text-neutral-950 shadow' : 'text-neutral-400 hover:text-white'
|
|
}`}
|
|
>
|
|
Ingresar
|
|
</button>
|
|
<button
|
|
type="button"
|
|
onClick={() => { setMode('register'); setError(null); }}
|
|
className={`text-xs font-bold py-2 rounded-xl transition-all cursor-pointer ${
|
|
mode === 'register' ? 'bg-white text-neutral-950 shadow' : 'text-neutral-400 hover:text-white'
|
|
}`}
|
|
>
|
|
Registrarme
|
|
</button>
|
|
</div>
|
|
|
|
{error && (
|
|
<div className="bg-red-950/80 border border-red-500 text-red-300 text-xs px-3.5 py-2.5 rounded-xl animate-in fade-in">
|
|
{error}
|
|
</div>
|
|
)}
|
|
|
|
{mode === 'login' ? (
|
|
<form onSubmit={handleLoginSubmit} className="space-y-3 text-xs">
|
|
<div>
|
|
<label className="block text-neutral-400 font-bold mb-1">Correo Electrónico o Celular *</label>
|
|
<input
|
|
type="text"
|
|
required
|
|
placeholder="ej: carlos@dripzone.co o 3134848203"
|
|
value={identifier}
|
|
onChange={(e) => setIdentifier(e.target.value)}
|
|
className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2.5 text-white outline-hidden focus:border-purple-400"
|
|
/>
|
|
</div>
|
|
|
|
<button
|
|
type="submit"
|
|
disabled={loading}
|
|
className={`w-full bg-gradient-to-r ${currentBrand.colors.primaryGradient} text-white font-black py-3 rounded-xl shadow-lg flex items-center justify-center gap-1.5 cursor-pointer active:scale-95 transition-all`}
|
|
>
|
|
<LogIn className="w-4 h-4" />
|
|
<span>{loading ? 'Accediendo...' : 'Iniciar Sesión'}</span>
|
|
</button>
|
|
|
|
<p className="text-[11px] text-center text-neutral-500">
|
|
Tip Admin: Puedes ingresar con <strong>carlos@dripzone.co</strong> o <strong>3134848203</strong>.
|
|
</p>
|
|
</form>
|
|
) : (
|
|
<form onSubmit={handleRegisterSubmit} className="space-y-3 text-xs">
|
|
<div>
|
|
<label className="block text-neutral-400 font-bold mb-1">Nombre Completo *</label>
|
|
<input
|
|
type="text"
|
|
required
|
|
placeholder="ej: Andrés Morales"
|
|
value={name}
|
|
onChange={(e) => setName(e.target.value)}
|
|
className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-white outline-hidden focus:border-purple-400"
|
|
/>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-2 gap-2">
|
|
<div>
|
|
<label className="block text-neutral-400 font-bold mb-1">Correo Electrónico *</label>
|
|
<input
|
|
type="email"
|
|
required
|
|
placeholder="andres@gmail.com"
|
|
value={email}
|
|
onChange={(e) => setEmail(e.target.value)}
|
|
className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-white outline-hidden focus:border-purple-400"
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<label className="block text-neutral-400 font-bold mb-1">Celular *</label>
|
|
<input
|
|
type="tel"
|
|
required
|
|
placeholder="3112345678"
|
|
value={phone}
|
|
onChange={(e) => setPhone(e.target.value)}
|
|
className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-white outline-hidden focus:border-purple-400"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-2 gap-2">
|
|
<div>
|
|
<label className="block text-neutral-400 font-bold mb-1">Ciudad</label>
|
|
<input
|
|
type="text"
|
|
value={city}
|
|
onChange={(e) => setCity(e.target.value)}
|
|
className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-white outline-hidden focus:border-purple-400"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label className="block text-neutral-400 font-bold mb-1">Dirección Entrega</label>
|
|
<input
|
|
type="text"
|
|
placeholder="Calle 5 # 34-12"
|
|
value={address}
|
|
onChange={(e) => setAddress(e.target.value)}
|
|
className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-white outline-hidden focus:border-purple-400"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<button
|
|
type="submit"
|
|
disabled={loading}
|
|
className={`w-full bg-gradient-to-r ${currentBrand.colors.primaryGradient} text-white font-black py-3 rounded-xl shadow-lg flex items-center justify-center gap-1.5 cursor-pointer active:scale-95 transition-all`}
|
|
>
|
|
<UserPlus className="w-4 h-4" />
|
|
<span>{loading ? 'Creando cuenta...' : 'Crear mi Cuenta Gratis'}</span>
|
|
</button>
|
|
</form>
|
|
)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|