mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-28 17:43:47 +00:00
Update Login.tsx
This commit is contained in:
@@ -19,9 +19,6 @@ export default function Login() {
|
|||||||
// Extract referral code from URL
|
// Extract referral code from URL
|
||||||
const referralCode = searchParams.get('ref') || ''
|
const referralCode = searchParams.get('ref') || ''
|
||||||
|
|
||||||
const [activeTab, setActiveTab] = useState<'telegram' | 'email'>(() =>
|
|
||||||
referralCode ? 'email' : 'telegram'
|
|
||||||
)
|
|
||||||
const [authMode, setAuthMode] = useState<'login' | 'register'>(() =>
|
const [authMode, setAuthMode] = useState<'login' | 'register'>(() =>
|
||||||
referralCode ? 'register' : 'login'
|
referralCode ? 'register' : 'login'
|
||||||
)
|
)
|
||||||
@@ -88,12 +85,6 @@ export default function Login() {
|
|||||||
}
|
}
|
||||||
}, [referralCode, emailAuthConfig, botUsername])
|
}, [referralCode, emailAuthConfig, botUsername])
|
||||||
|
|
||||||
// If email auth is disabled but we initially set to email tab, switch back to telegram
|
|
||||||
useEffect(() => {
|
|
||||||
if (!isEmailAuthEnabled && activeTab === 'email') {
|
|
||||||
setActiveTab('telegram')
|
|
||||||
}
|
|
||||||
}, [isEmailAuthEnabled, activeTab])
|
|
||||||
const appName = branding ? branding.name : (import.meta.env.VITE_APP_NAME || 'VPN')
|
const appName = branding ? branding.name : (import.meta.env.VITE_APP_NAME || 'VPN')
|
||||||
const appLogo = branding?.logo_letter || import.meta.env.VITE_APP_LOGO || 'V'
|
const appLogo = branding?.logo_letter || import.meta.env.VITE_APP_LOGO || 'V'
|
||||||
const logoUrl = branding ? brandingApi.getLogoUrl(branding) : null
|
const logoUrl = branding ? brandingApi.getLogoUrl(branding) : null
|
||||||
@@ -304,195 +295,176 @@ export default function Login() {
|
|||||||
) : (
|
) : (
|
||||||
/* Card */
|
/* Card */
|
||||||
<div className="card">
|
<div className="card">
|
||||||
{/* Tabs */}
|
|
||||||
{isEmailAuthEnabled ? (
|
|
||||||
<div className="flex mb-6">
|
|
||||||
<button
|
|
||||||
className={`flex-1 py-3 text-sm font-medium transition-all border-b-2 ${
|
|
||||||
activeTab === 'telegram'
|
|
||||||
? 'border-accent-500 text-accent-400'
|
|
||||||
: 'border-transparent text-dark-500 hover:text-dark-300'
|
|
||||||
}`}
|
|
||||||
onClick={() => setActiveTab('telegram')}
|
|
||||||
>
|
|
||||||
Telegram
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className={`flex-1 py-3 text-sm font-medium transition-all border-b-2 ${
|
|
||||||
activeTab === 'email'
|
|
||||||
? 'border-accent-500 text-accent-400'
|
|
||||||
: 'border-transparent text-dark-500 hover:text-dark-300'
|
|
||||||
}`}
|
|
||||||
onClick={() => setActiveTab('email')}
|
|
||||||
>
|
|
||||||
Email
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="mb-6 pb-3 border-b border-dark-700">
|
|
||||||
<h2 className="text-lg font-medium text-dark-200 text-center">Telegram</h2>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{error && (
|
{error && (
|
||||||
<div className="bg-error-500/10 border border-error-500/30 text-error-400 px-4 py-3 rounded-xl text-sm mb-6">
|
<div className="bg-error-500/10 border border-error-500/30 text-error-400 px-4 py-3 rounded-xl text-sm mb-6">
|
||||||
{error}
|
{error}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{activeTab === 'telegram' || !isEmailAuthEnabled ? (
|
{/* Telegram auth — always visible */}
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<p className="text-center text-sm text-dark-400">
|
<p className="text-center text-sm text-dark-400">
|
||||||
{t('auth.registerHint')}
|
{t('auth.registerHint')}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{isLoading && isTelegramWebApp ? (
|
{isLoading && isTelegramWebApp ? (
|
||||||
<div className="text-center py-8">
|
<div className="text-center py-8">
|
||||||
<div className="w-8 h-8 border-2 border-accent-500 border-t-transparent rounded-full animate-spin mx-auto mb-3" />
|
<div className="w-8 h-8 border-2 border-accent-500 border-t-transparent rounded-full animate-spin mx-auto mb-3" />
|
||||||
<p className="text-sm text-dark-400">{t('auth.authenticating')}</p>
|
<p className="text-sm text-dark-400">{t('auth.authenticating')}</p>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<TelegramLoginButton botUsername={botUsername} />
|
<TelegramLoginButton botUsername={botUsername} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
|
||||||
<div className="space-y-5">
|
{/* Email auth — only when enabled */}
|
||||||
{/* Login / Register toggle */}
|
{isEmailAuthEnabled && (
|
||||||
<div className="flex bg-dark-800 rounded-lg p-1">
|
<>
|
||||||
<button
|
{/* Divider */}
|
||||||
type="button"
|
<div className="flex items-center gap-3 my-6">
|
||||||
className={`flex-1 py-2 text-sm font-medium rounded-md transition-all ${
|
<div className="flex-1 h-px bg-dark-700" />
|
||||||
authMode === 'login'
|
<span className="text-xs text-dark-500 uppercase">{t('auth.or', 'or')}</span>
|
||||||
? 'bg-accent-500 text-white'
|
<div className="flex-1 h-px bg-dark-700" />
|
||||||
: 'text-dark-400 hover:text-dark-200'
|
|
||||||
}`}
|
|
||||||
onClick={() => setAuthMode('login')}
|
|
||||||
>
|
|
||||||
{t('auth.login')}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className={`flex-1 py-2 text-sm font-medium rounded-md transition-all ${
|
|
||||||
authMode === 'register'
|
|
||||||
? 'bg-accent-500 text-white'
|
|
||||||
: 'text-dark-400 hover:text-dark-200'
|
|
||||||
}`}
|
|
||||||
onClick={() => setAuthMode('register')}
|
|
||||||
>
|
|
||||||
{t('auth.register', 'Register')}
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form className="space-y-4" onSubmit={handleEmailSubmit}>
|
<div className="space-y-5">
|
||||||
{/* First name field - only for registration */}
|
{/* Login / Register toggle */}
|
||||||
{authMode === 'register' && (
|
<div className="flex bg-dark-800 rounded-lg p-1">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={`flex-1 py-2 text-sm font-medium rounded-md transition-all ${
|
||||||
|
authMode === 'login'
|
||||||
|
? 'bg-accent-500 text-white'
|
||||||
|
: 'text-dark-400 hover:text-dark-200'
|
||||||
|
}`}
|
||||||
|
onClick={() => setAuthMode('login')}
|
||||||
|
>
|
||||||
|
{t('auth.login')}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={`flex-1 py-2 text-sm font-medium rounded-md transition-all ${
|
||||||
|
authMode === 'register'
|
||||||
|
? 'bg-accent-500 text-white'
|
||||||
|
: 'text-dark-400 hover:text-dark-200'
|
||||||
|
}`}
|
||||||
|
onClick={() => setAuthMode('register')}
|
||||||
|
>
|
||||||
|
{t('auth.register', 'Register')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form className="space-y-4" onSubmit={handleEmailSubmit}>
|
||||||
|
{/* First name field - only for registration */}
|
||||||
|
{authMode === 'register' && (
|
||||||
|
<div>
|
||||||
|
<label htmlFor="firstName" className="label">
|
||||||
|
{t('auth.firstName', 'First Name')}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="firstName"
|
||||||
|
name="firstName"
|
||||||
|
type="text"
|
||||||
|
autoComplete="given-name"
|
||||||
|
className="input"
|
||||||
|
placeholder={t('auth.firstNamePlaceholder', 'Your name (optional)')}
|
||||||
|
value={firstName}
|
||||||
|
onChange={(e) => setFirstName(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor="firstName" className="label">
|
<label htmlFor="email" className="label">
|
||||||
{t('auth.firstName', 'First Name')}
|
{t('auth.email')}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
id="firstName"
|
id="email"
|
||||||
name="firstName"
|
name="email"
|
||||||
type="text"
|
type="email"
|
||||||
autoComplete="given-name"
|
autoComplete="email"
|
||||||
|
required
|
||||||
className="input"
|
className="input"
|
||||||
placeholder={t('auth.firstNamePlaceholder', 'Your name (optional)')}
|
placeholder="you@example.com"
|
||||||
value={firstName}
|
value={email}
|
||||||
onChange={(e) => setFirstName(e.target.value)}
|
onChange={(e) => setEmail(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label htmlFor="email" className="label">
|
|
||||||
{t('auth.email')}
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
id="email"
|
|
||||||
name="email"
|
|
||||||
type="email"
|
|
||||||
autoComplete="email"
|
|
||||||
required
|
|
||||||
className="input"
|
|
||||||
placeholder="you@example.com"
|
|
||||||
value={email}
|
|
||||||
onChange={(e) => setEmail(e.target.value)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label htmlFor="password" className="label">
|
|
||||||
{t('auth.password')}
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
id="password"
|
|
||||||
name="password"
|
|
||||||
type="password"
|
|
||||||
autoComplete={authMode === 'login' ? 'current-password' : 'new-password'}
|
|
||||||
required
|
|
||||||
className="input"
|
|
||||||
placeholder="••••••••"
|
|
||||||
value={password}
|
|
||||||
onChange={(e) => setPassword(e.target.value)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Confirm password - only for registration */}
|
|
||||||
{authMode === 'register' && (
|
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor="confirmPassword" className="label">
|
<label htmlFor="password" className="label">
|
||||||
{t('auth.confirmPassword', 'Confirm Password')}
|
{t('auth.password')}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
id="confirmPassword"
|
id="password"
|
||||||
name="confirmPassword"
|
name="password"
|
||||||
type="password"
|
type="password"
|
||||||
autoComplete="new-password"
|
autoComplete={authMode === 'login' ? 'current-password' : 'new-password'}
|
||||||
required
|
required
|
||||||
className="input"
|
className="input"
|
||||||
placeholder="••••••••"
|
placeholder="••••••••"
|
||||||
value={confirmPassword}
|
value={password}
|
||||||
onChange={(e) => setConfirmPassword(e.target.value)}
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Confirm password - only for registration */}
|
||||||
|
{authMode === 'register' && (
|
||||||
|
<div>
|
||||||
|
<label htmlFor="confirmPassword" className="label">
|
||||||
|
{t('auth.confirmPassword', 'Confirm Password')}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="confirmPassword"
|
||||||
|
name="confirmPassword"
|
||||||
|
type="password"
|
||||||
|
autoComplete="new-password"
|
||||||
|
required
|
||||||
|
className="input"
|
||||||
|
placeholder="••••••••"
|
||||||
|
value={confirmPassword}
|
||||||
|
onChange={(e) => setConfirmPassword(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={isLoading}
|
||||||
|
className="btn-primary w-full py-3"
|
||||||
|
>
|
||||||
|
{isLoading ? (
|
||||||
|
<span className="flex items-center justify-center gap-2">
|
||||||
|
<span className="w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin" />
|
||||||
|
{t('common.loading')}
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
authMode === 'login' ? t('auth.login') : t('auth.register', 'Register')
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{/* Verification notice for registration */}
|
||||||
|
{authMode === 'register' && (
|
||||||
|
<p className="text-center text-xs text-dark-500">
|
||||||
|
{t('auth.verificationEmailNotice', 'After registration, a verification email will be sent to your address')}
|
||||||
|
</p>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<button
|
{/* Forgot password link - only for login */}
|
||||||
type="submit"
|
{authMode === 'login' && (
|
||||||
disabled={isLoading}
|
<div className="text-center space-y-2">
|
||||||
className="btn-primary w-full py-3"
|
<button
|
||||||
>
|
type="button"
|
||||||
{isLoading ? (
|
onClick={() => setShowForgotPassword(true)}
|
||||||
<span className="flex items-center justify-center gap-2">
|
className="text-sm text-accent-400 hover:text-accent-300 transition-colors"
|
||||||
<span className="w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin" />
|
>
|
||||||
{t('common.loading')}
|
{t('auth.forgotPassword', 'Forgot password?')}
|
||||||
</span>
|
</button>
|
||||||
) : (
|
</div>
|
||||||
authMode === 'login' ? t('auth.login') : t('auth.register', 'Register')
|
)}
|
||||||
)}
|
</div>
|
||||||
</button>
|
</>
|
||||||
</form>
|
|
||||||
|
|
||||||
{/* Verification notice for registration */}
|
|
||||||
{authMode === 'register' && (
|
|
||||||
<p className="text-center text-xs text-dark-500">
|
|
||||||
{t('auth.verificationEmailNotice', 'After registration, a verification email will be sent to your address')}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Forgot password link - only for login */}
|
|
||||||
{authMode === 'login' && (
|
|
||||||
<div className="text-center space-y-2">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => setShowForgotPassword(true)}
|
|
||||||
className="text-sm text-accent-400 hover:text-accent-300 transition-colors"
|
|
||||||
>
|
|
||||||
{t('auth.forgotPassword', 'Forgot password?')}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user