mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-28 17:43:47 +00:00
fix: add resend email cooldown and allow email change for all auth types
Add 60-second cooldown timer on resend verification email button to prevent spam. Remove auth_type restriction on change email button so OAuth users can also change their email.
This commit is contained in:
@@ -2902,6 +2902,7 @@
|
||||
"notVerified": "Not verified",
|
||||
"verificationRequired": "Please verify your email to use email login.",
|
||||
"resendVerification": "Resend Verification Email",
|
||||
"resendIn": "Resend in {{seconds}} sec.",
|
||||
"verificationResent": "Verification email resent!",
|
||||
"canLoginWithEmail": "You can now log in using your email and password.",
|
||||
"emailAlreadyRegistered": "This email is already linked to another account. If this is your email, log in with it or contact support.",
|
||||
|
||||
@@ -2402,6 +2402,7 @@
|
||||
"notVerified": "تایید نشده",
|
||||
"verificationRequired": "لطفاً ایمیل خود را تایید کنید تا از ورود با ایمیل استفاده کنید.",
|
||||
"resendVerification": "ارسال مجدد ایمیل تایید",
|
||||
"resendIn": "ارسال مجدد در {{seconds}} ثانیه",
|
||||
"verificationResent": "ایمیل تایید مجدداً ارسال شد!",
|
||||
"canLoginWithEmail": "اکنون میتوانید با ایمیل و رمز عبور وارد شوید.",
|
||||
"emailAlreadyRegistered": "این ایمیل قبلاً به حساب دیگری متصل شده است. اگر این ایمیل شماست، با آن وارد شوید یا با پشتیبانی تماس بگیرید.",
|
||||
|
||||
@@ -3454,6 +3454,7 @@
|
||||
"notVerified": "Не подтверждён",
|
||||
"verificationRequired": "Подтвердите email для использования входа по почте.",
|
||||
"resendVerification": "Отправить письмо повторно",
|
||||
"resendIn": "Повторить через {{seconds}} сек.",
|
||||
"verificationResent": "Письмо отправлено повторно!",
|
||||
"canLoginWithEmail": "Теперь вы можете входить с помощью email и пароля.",
|
||||
"emailAlreadyRegistered": "Этот email уже привязан к другому аккаунту. Если это ваш email, войдите через него или обратитесь в поддержку.",
|
||||
|
||||
@@ -2401,6 +2401,7 @@
|
||||
"notVerified": "未验证",
|
||||
"verificationRequired": "请验证邮箱以使用邮箱登录。",
|
||||
"resendVerification": "重新发送验证邮件",
|
||||
"resendIn": "{{seconds}} 秒后重新发送",
|
||||
"verificationResent": "验证邮件已重新发送!",
|
||||
"canLoginWithEmail": "现在您可以使用邮箱和密码登录。",
|
||||
"emailAlreadyRegistered": "此邮箱已绑定到其他账户。如果这是您的邮箱,请使用邮箱登录或联系客服。",
|
||||
|
||||
@@ -77,6 +77,7 @@ export default function Profile() {
|
||||
const [changeCode, setChangeCode] = useState('');
|
||||
const [changeError, setChangeError] = useState<string | null>(null);
|
||||
const [resendCooldown, setResendCooldown] = useState(0);
|
||||
const [verificationResendCooldown, setVerificationResendCooldown] = useState(0);
|
||||
const newEmailInputRef = useRef<HTMLInputElement>(null);
|
||||
const codeInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
@@ -171,6 +172,7 @@ export default function Profile() {
|
||||
onSuccess: () => {
|
||||
setSuccess(t('profile.verificationResent'));
|
||||
setError(null);
|
||||
setVerificationResendCooldown(UI.RESEND_COOLDOWN_SEC);
|
||||
},
|
||||
onError: (err: { response?: { data?: { detail?: string } } }) => {
|
||||
setError(err.response?.data?.detail || t('common.error'));
|
||||
@@ -228,7 +230,7 @@ export default function Profile() {
|
||||
},
|
||||
});
|
||||
|
||||
// Resend cooldown timer
|
||||
// Resend cooldown timers
|
||||
useEffect(() => {
|
||||
if (resendCooldown <= 0) return;
|
||||
const timer = setInterval(() => {
|
||||
@@ -237,6 +239,14 @@ export default function Profile() {
|
||||
return () => clearInterval(timer);
|
||||
}, [resendCooldown]);
|
||||
|
||||
useEffect(() => {
|
||||
if (verificationResendCooldown <= 0) return;
|
||||
const timer = setInterval(() => {
|
||||
setVerificationResendCooldown((prev) => Math.max(0, prev - 1));
|
||||
}, 1000);
|
||||
return () => clearInterval(timer);
|
||||
}, [verificationResendCooldown]);
|
||||
|
||||
// Auto-focus inputs on step change
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
@@ -454,34 +464,34 @@ export default function Profile() {
|
||||
<Button
|
||||
onClick={() => resendVerificationMutation.mutate()}
|
||||
loading={resendVerificationMutation.isPending}
|
||||
disabled={verificationResendCooldown > 0}
|
||||
>
|
||||
{t('profile.resendVerification')}
|
||||
{verificationResendCooldown > 0
|
||||
? t('profile.resendIn', { seconds: verificationResendCooldown })
|
||||
: t('profile.resendVerification')}
|
||||
</Button>
|
||||
{(user.auth_type === 'telegram' || user.auth_type === 'email') && (
|
||||
<button
|
||||
onClick={() => setChangeEmailStep('email')}
|
||||
className="text-sm text-accent-400 transition-colors hover:text-accent-300"
|
||||
>
|
||||
{t('profile.changeEmail.button')}
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
onClick={() => setChangeEmailStep('email')}
|
||||
className="text-sm text-accent-400 transition-colors hover:text-accent-300"
|
||||
>
|
||||
{t('profile.changeEmail.button')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{user.email_verified &&
|
||||
(user.auth_type === 'telegram' || user.auth_type === 'email') && (
|
||||
<div className="flex items-center justify-between">
|
||||
<p className="text-sm text-dark-400">{t('profile.canLoginWithEmail')}</p>
|
||||
<button
|
||||
onClick={() => setChangeEmailStep('email')}
|
||||
className="flex items-center gap-2 text-sm text-accent-400 transition-colors hover:text-accent-300"
|
||||
>
|
||||
<PencilIcon />
|
||||
<span>{t('profile.changeEmail.button')}</span>
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
{user.email_verified && (
|
||||
<div className="flex items-center justify-between">
|
||||
<p className="text-sm text-dark-400">{t('profile.canLoginWithEmail')}</p>
|
||||
<button
|
||||
onClick={() => setChangeEmailStep('email')}
|
||||
className="flex items-center gap-2 text-sm text-accent-400 transition-colors hover:text-accent-300"
|
||||
>
|
||||
<PencilIcon />
|
||||
<span>{t('profile.changeEmail.button')}</span>
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Inline email change flow */}
|
||||
<AnimatePresence>
|
||||
|
||||
Reference in New Issue
Block a user