mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-28 09:33:46 +00:00
Add files via upload
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useState, useEffect, useMemo, useCallback } from 'react'
|
||||
import { useNavigate, useLocation } from 'react-router-dom'
|
||||
import { useNavigate, useLocation, useSearchParams } from 'react-router-dom'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useAuthStore } from '../store/auth'
|
||||
@@ -12,9 +12,18 @@ export default function Login() {
|
||||
const { t } = useTranslation()
|
||||
const navigate = useNavigate()
|
||||
const location = useLocation()
|
||||
const [searchParams] = useSearchParams()
|
||||
const { isAuthenticated, loginWithTelegram, loginWithEmail, registerWithEmail } = useAuthStore()
|
||||
const [activeTab, setActiveTab] = useState<'telegram' | 'email'>('telegram')
|
||||
const [authMode, setAuthMode] = useState<'login' | 'register'>('login')
|
||||
|
||||
// Extract referral code from URL
|
||||
const referralCode = searchParams.get('ref') || ''
|
||||
|
||||
const [activeTab, setActiveTab] = useState<'telegram' | 'email'>(() =>
|
||||
referralCode ? 'email' : 'telegram'
|
||||
)
|
||||
const [authMode, setAuthMode] = useState<'login' | 'register'>(() =>
|
||||
referralCode ? 'register' : 'login'
|
||||
)
|
||||
const [email, setEmail] = useState('')
|
||||
const [password, setPassword] = useState('')
|
||||
const [confirmPassword, setConfirmPassword] = useState('')
|
||||
@@ -126,7 +135,7 @@ export default function Login() {
|
||||
if (authMode === 'login') {
|
||||
await loginWithEmail(email, password)
|
||||
} else {
|
||||
await registerWithEmail(email, password, firstName || undefined)
|
||||
await registerWithEmail(email, password, firstName || undefined, referralCode || undefined)
|
||||
}
|
||||
navigate(getReturnUrl(), { replace: true })
|
||||
} catch (err: unknown) {
|
||||
@@ -185,6 +194,18 @@ export default function Login() {
|
||||
<p className="mt-2 text-dark-400">
|
||||
{t('auth.loginSubtitle')}
|
||||
</p>
|
||||
|
||||
{/* Referral Banner */}
|
||||
{referralCode && (
|
||||
<div className="mt-4 p-3 rounded-xl bg-accent-500/10 border border-accent-500/30">
|
||||
<div className="flex items-center gap-2 text-accent-400">
|
||||
<svg className="w-5 h-5 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M15 19.128a9.38 9.38 0 002.625.372 9.337 9.337 0 004.121-.952 4.125 4.125 0 00-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 018.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0111.964-3.07M12 6.375a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zm8.25 2.25a2.625 2.625 0 11-5.25 0 2.625 2.625 0 015.25 0z" />
|
||||
</svg>
|
||||
<span className="text-sm font-medium">{t('auth.referralInvite')}</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Card */}
|
||||
|
||||
@@ -1,9 +1,38 @@
|
||||
import { useState } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
||||
import { useAuthStore } from '../store/auth'
|
||||
import { authApi } from '../api/auth'
|
||||
import { notificationsApi, NotificationSettings, NotificationSettingsUpdate } from '../api/notifications'
|
||||
import { referralApi } from '../api/referral'
|
||||
import { brandingApi } from '../api/branding'
|
||||
|
||||
// Icons
|
||||
const CopyIcon = () => (
|
||||
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M15.666 3.888A2.25 2.25 0 0013.5 2.25h-3c-1.03 0-1.9.693-2.166 1.638m7.332 0c.055.194.084.4.084.612v0a.75.75 0 01-.75.75H9a.75.75 0 01-.75-.75v0c0-.212.03-.418.084-.612m7.332 0c.646.049 1.288.11 1.927.184 1.1.128 1.907 1.077 1.907 2.185V19.5a2.25 2.25 0 01-2.25 2.25H6.75A2.25 2.25 0 014.5 19.5V6.257c0-1.108.806-2.057 1.907-2.185a48.208 48.208 0 011.927-.184" />
|
||||
</svg>
|
||||
)
|
||||
|
||||
const CheckIcon = () => (
|
||||
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M4.5 12.75l6 6 9-13.5" />
|
||||
</svg>
|
||||
)
|
||||
|
||||
const ShareIcon = () => (
|
||||
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M7 8l5-5m0 0l5 5m-5-5v12" />
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M4 15v3a2 2 0 002 2h12a2 2 0 002-2v-3" />
|
||||
</svg>
|
||||
)
|
||||
|
||||
const ArrowRightIcon = () => (
|
||||
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3" />
|
||||
</svg>
|
||||
)
|
||||
|
||||
export default function Profile() {
|
||||
const { t } = useTranslation()
|
||||
@@ -15,6 +44,58 @@ export default function Profile() {
|
||||
const [confirmPassword, setConfirmPassword] = useState('')
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
const [success, setSuccess] = useState<string | null>(null)
|
||||
const [copied, setCopied] = useState(false)
|
||||
|
||||
// Referral data
|
||||
const { data: referralInfo } = useQuery({
|
||||
queryKey: ['referral-info'],
|
||||
queryFn: referralApi.getReferralInfo,
|
||||
})
|
||||
|
||||
const { data: referralTerms } = useQuery({
|
||||
queryKey: ['referral-terms'],
|
||||
queryFn: referralApi.getReferralTerms,
|
||||
})
|
||||
|
||||
const { data: branding } = useQuery({
|
||||
queryKey: ['branding'],
|
||||
queryFn: brandingApi.getBranding,
|
||||
staleTime: 60000,
|
||||
})
|
||||
|
||||
// Build referral link
|
||||
const botUsername = import.meta.env.VITE_TELEGRAM_BOT_USERNAME
|
||||
const referralLink = referralInfo?.referral_code && botUsername
|
||||
? `https://t.me/${botUsername}?start=${referralInfo.referral_code}`
|
||||
: referralInfo?.referral_link || ''
|
||||
|
||||
const copyReferralLink = () => {
|
||||
if (referralLink) {
|
||||
navigator.clipboard.writeText(referralLink)
|
||||
setCopied(true)
|
||||
setTimeout(() => setCopied(false), 2000)
|
||||
}
|
||||
}
|
||||
|
||||
const shareReferralLink = () => {
|
||||
if (!referralLink) return
|
||||
const shareText = t('referral.shareMessage', {
|
||||
percent: referralInfo?.commission_percent || 0,
|
||||
botName: branding?.name || import.meta.env.VITE_APP_NAME || 'Cabinet',
|
||||
})
|
||||
|
||||
if (navigator.share) {
|
||||
navigator.share({
|
||||
title: t('referral.title'),
|
||||
text: shareText,
|
||||
url: referralLink,
|
||||
}).catch(() => {})
|
||||
return
|
||||
}
|
||||
|
||||
const telegramUrl = `https://t.me/share/url?url=${encodeURIComponent(referralLink)}&text=${encodeURIComponent(shareText)}`
|
||||
window.open(telegramUrl, '_blank', 'noopener,noreferrer')
|
||||
}
|
||||
|
||||
const registerEmailMutation = useMutation({
|
||||
mutationFn: ({ email, password }: { email: string; password: string }) =>
|
||||
@@ -127,6 +208,50 @@ export default function Profile() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Referral Link Widget */}
|
||||
{referralTerms?.is_enabled && referralLink && (
|
||||
<div className="bento-card">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h2 className="text-lg font-semibold text-dark-100">{t('referral.yourLink')}</h2>
|
||||
<Link to="/referral" className="text-accent-400 hover:text-accent-300 transition-colors flex items-center gap-1">
|
||||
<span className="text-sm">{t('referral.title')}</span>
|
||||
<ArrowRightIcon />
|
||||
</Link>
|
||||
</div>
|
||||
<div className="flex flex-col gap-3 sm:flex-row">
|
||||
<div className="flex-1">
|
||||
<input
|
||||
type="text"
|
||||
readOnly
|
||||
value={referralLink}
|
||||
className="input w-full text-sm"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<button
|
||||
onClick={copyReferralLink}
|
||||
className={`btn-primary px-4 py-2 flex items-center gap-2 text-sm ${
|
||||
copied ? 'bg-success-500 hover:bg-success-500' : ''
|
||||
}`}
|
||||
>
|
||||
{copied ? <CheckIcon /> : <CopyIcon />}
|
||||
<span>{copied ? t('referral.copied') : t('referral.copyLink')}</span>
|
||||
</button>
|
||||
<button
|
||||
onClick={shareReferralLink}
|
||||
className="btn-secondary px-4 py-2 flex items-center gap-2 text-sm"
|
||||
>
|
||||
<ShareIcon />
|
||||
<span className="hidden sm:inline">{t('referral.shareButton')}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<p className="mt-3 text-sm text-dark-500">
|
||||
{t('referral.shareHint', { percent: referralInfo?.commission_percent || 0 })}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Email Section */}
|
||||
<div className="bento-card">
|
||||
<h2 className="text-lg font-semibold text-dark-100 mb-6">{t('profile.emailAuth')}</h2>
|
||||
|
||||
Reference in New Issue
Block a user