Files
Spanglish/frontend/src/app/(public)/auth/claim-account/page.tsx
T
2026-01-29 14:13:11 -03:00

173 lines
6.1 KiB
TypeScript

'use client';
import { useState, Suspense } from 'react';
import { useRouter, useSearchParams } from 'next/navigation';
import Link from 'next/link';
import { useLanguage } from '@/context/LanguageContext';
import { useAuth } from '@/context/AuthContext';
import Card from '@/components/ui/Card';
import Button from '@/components/ui/Button';
import Input from '@/components/ui/Input';
import { authApi } from '@/lib/api';
import toast from 'react-hot-toast';
function ClaimAccountContent() {
const router = useRouter();
const searchParams = useSearchParams();
const { locale: language } = useLanguage();
const { setAuthData } = useAuth();
const [loading, setLoading] = useState(false);
const [formData, setFormData] = useState({
password: '',
confirmPassword: '',
});
const token = searchParams.get('token');
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!token) {
toast.error(language === 'es' ? 'Token no válido' : 'Invalid token');
return;
}
if (formData.password !== formData.confirmPassword) {
toast.error(language === 'es' ? 'Las contraseñas no coinciden' : 'Passwords do not match');
return;
}
if (formData.password.length < 10) {
toast.error(
language === 'es'
? 'La contraseña debe tener al menos 10 caracteres'
: 'Password must be at least 10 characters'
);
return;
}
setLoading(true);
try {
const result = await authApi.confirmClaimAccount(token, { password: formData.password });
setAuthData({ user: result.user, token: result.token });
toast.success(language === 'es' ? '¡Cuenta activada!' : 'Account activated!');
router.push('/dashboard');
} catch (error: any) {
toast.error(error.message || (language === 'es' ? 'Error' : 'Failed'));
} finally {
setLoading(false);
}
};
if (!token) {
return (
<div className="section-padding min-h-[70vh] flex items-center">
<div className="container-page">
<div className="max-w-md mx-auto">
<Card className="p-8 text-center">
<div className="w-16 h-16 bg-red-100 rounded-full flex items-center justify-center mx-auto mb-4">
<svg className="w-8 h-8 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
</svg>
</div>
<h2 className="text-xl font-semibold mb-2">
{language === 'es' ? 'Enlace Inválido' : 'Invalid Link'}
</h2>
<p className="text-gray-600 mb-6">
{language === 'es'
? 'Este enlace de activación no es válido o ha expirado.'
: 'This activation link is invalid or has expired.'}
</p>
<Link href="/login">
<Button>
{language === 'es' ? 'Ir a Iniciar Sesión' : 'Go to Login'}
</Button>
</Link>
</Card>
</div>
</div>
</div>
);
}
return (
<div className="section-padding min-h-[70vh] flex items-center">
<div className="container-page">
<div className="max-w-md mx-auto">
<div className="text-center mb-8">
<h1 className="text-3xl font-bold">
{language === 'es' ? 'Activar tu Cuenta' : 'Activate Your Account'}
</h1>
<p className="mt-2 text-gray-600">
{language === 'es'
? 'Configura una contraseña para acceder a tu cuenta'
: 'Set a password to access your account'}
</p>
</div>
<Card className="p-8">
<div className="mb-6 p-4 bg-blue-50 rounded-lg">
<p className="text-sm text-blue-800">
{language === 'es'
? 'Tu cuenta fue creada durante una reservación. Establece una contraseña para acceder a tu historial de entradas y más.'
: 'Your account was created during a booking. Set a password to access your ticket history and more.'}
</p>
</div>
<form onSubmit={handleSubmit} className="space-y-6">
<Input
id="password"
label={language === 'es' ? 'Contraseña' : 'Password'}
type="password"
value={formData.password}
onChange={(e) => setFormData({ ...formData, password: e.target.value })}
required
/>
<p className="text-xs text-gray-500 -mt-4">
{language === 'es' ? 'Mínimo 10 caracteres' : 'Minimum 10 characters'}
</p>
<Input
id="confirmPassword"
label={language === 'es' ? 'Confirmar Contraseña' : 'Confirm Password'}
type="password"
value={formData.confirmPassword}
onChange={(e) => setFormData({ ...formData, confirmPassword: e.target.value })}
required
/>
<Button type="submit" className="w-full" size="lg" isLoading={loading}>
{language === 'es' ? 'Activar Cuenta' : 'Activate Account'}
</Button>
</form>
<p className="mt-6 text-center text-sm text-gray-600">
{language === 'es' ? '¿Ya tienes acceso?' : 'Already have access?'}{' '}
<Link href="/login" className="text-secondary-blue hover:underline font-medium">
{language === 'es' ? 'Iniciar Sesión' : 'Log In'}
</Link>
</p>
</Card>
</div>
</div>
</div>
);
}
function LoadingFallback() {
return (
<div className="section-padding min-h-[70vh] flex items-center justify-center">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-secondary-blue"></div>
</div>
);
}
export default function ClaimAccountPage() {
return (
<Suspense fallback={<LoadingFallback />}>
<ClaimAccountContent />
</Suspense>
);
}