- Redesigned all email templates with professional corporate style - Created base layout with dark header, status cards, and footer - Updated: subscription-cancelled, account-activation, welcome, welcome-new-user, due-payments-alert - Removed emojis and gradients for cleaner look - Added multi-language support (ES, PT-BR, EN) - Fixed email delivery (sync instead of queue) - Fixed PayPal already-cancelled subscription handling - Cleaned orphan subscriptions from deleted users
126 lines
4.7 KiB
JavaScript
126 lines
4.7 KiB
JavaScript
import React, { useState, useEffect } from 'react';
|
|
import { useSearchParams, useNavigate, Link } from 'react-router-dom';
|
|
import { useTranslation } from 'react-i18next';
|
|
import api from '../services/api';
|
|
import logo from '../assets/logo-white.png';
|
|
|
|
const ActivateAccount = () => {
|
|
const { t } = useTranslation();
|
|
const [searchParams] = useSearchParams();
|
|
const navigate = useNavigate();
|
|
const [status, setStatus] = useState('loading'); // loading, success, error
|
|
const [message, setMessage] = useState('');
|
|
const [countdown, setCountdown] = useState(5);
|
|
|
|
useEffect(() => {
|
|
const token = searchParams.get('token');
|
|
|
|
if (!token) {
|
|
setStatus('error');
|
|
setMessage(t('activate.invalidLink'));
|
|
return;
|
|
}
|
|
|
|
activateAccount(token);
|
|
}, [searchParams]);
|
|
|
|
useEffect(() => {
|
|
if (status === 'success' && countdown > 0) {
|
|
const timer = setTimeout(() => setCountdown(countdown - 1), 1000);
|
|
return () => clearTimeout(timer);
|
|
} else if (status === 'success' && countdown === 0) {
|
|
navigate('/dashboard');
|
|
}
|
|
}, [status, countdown, navigate]);
|
|
|
|
const activateAccount = async (token) => {
|
|
try {
|
|
const response = await api.post('/activate', { token });
|
|
|
|
if (response.data.success) {
|
|
// Save token and user to localStorage
|
|
localStorage.setItem('token', response.data.data.token);
|
|
localStorage.setItem('user', JSON.stringify(response.data.data.user));
|
|
|
|
setStatus('success');
|
|
setMessage(t('activate.success'));
|
|
} else {
|
|
setStatus('error');
|
|
setMessage(response.data.message || t('activate.error'));
|
|
}
|
|
} catch (error) {
|
|
setStatus('error');
|
|
setMessage(error.response?.data?.message || t('activate.error'));
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="min-vh-100 d-flex align-items-center justify-content-center"
|
|
style={{ background: 'linear-gradient(135deg, #1a1a2e 0%, #16213e 100%)' }}>
|
|
<div className="container">
|
|
<div className="row justify-content-center">
|
|
<div className="col-md-6 col-lg-5">
|
|
<div className="card shadow-lg border-0">
|
|
<div className="card-body p-5 text-center">
|
|
<Link to="/">
|
|
<img src={logo} alt="WEBMoney" className="mb-4" style={{ height: '80px', width: 'auto' }} />
|
|
</Link>
|
|
|
|
{status === 'loading' && (
|
|
<>
|
|
<div className="spinner-border text-primary mb-4" role="status">
|
|
<span className="visually-hidden">{t('common.loading')}</span>
|
|
</div>
|
|
<h4 className="mb-3">{t('activate.activating')}</h4>
|
|
<p className="text-muted">{t('activate.pleaseWait')}</p>
|
|
</>
|
|
)}
|
|
|
|
{status === 'success' && (
|
|
<>
|
|
<div className="mb-4">
|
|
<i className="bi bi-check-circle-fill text-success" style={{ fontSize: '80px' }}></i>
|
|
</div>
|
|
<h4 className="mb-3 text-success">{t('activate.successTitle')}</h4>
|
|
<p className="text-muted mb-4">{message}</p>
|
|
<div className="alert alert-info">
|
|
<i className="bi bi-clock me-2"></i>
|
|
{t('activate.redirecting', { seconds: countdown })}
|
|
</div>
|
|
<Link to="/dashboard" className="btn btn-primary btn-lg w-100">
|
|
<i className="bi bi-speedometer2 me-2"></i>
|
|
{t('activate.goToDashboard')}
|
|
</Link>
|
|
</>
|
|
)}
|
|
|
|
{status === 'error' && (
|
|
<>
|
|
<div className="mb-4">
|
|
<i className="bi bi-x-circle-fill text-danger" style={{ fontSize: '80px' }}></i>
|
|
</div>
|
|
<h4 className="mb-3 text-danger">{t('activate.errorTitle')}</h4>
|
|
<p className="text-muted mb-4">{message}</p>
|
|
<div className="d-grid gap-2">
|
|
<Link to="/login" className="btn btn-primary btn-lg">
|
|
<i className="bi bi-box-arrow-in-right me-2"></i>
|
|
{t('auth.login')}
|
|
</Link>
|
|
<Link to="/" className="btn btn-outline-secondary">
|
|
<i className="bi bi-house me-2"></i>
|
|
{t('common.back')}
|
|
</Link>
|
|
</div>
|
|
</>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default ActivateAccount;
|