feat: migrate from useAuth to AuthContext for centralized auth state
• Полная миграция 64 компонентов с useAuth на AuthContext • Исправлена race condition в SMS регистрации • Улучшена SSR совместимость с таймаутами • Удалена дублирующая система регистрации • Обновлена документация архитектуры аутентификации Технические изменения: - AuthContext.tsx: централизованная система состояния - auth-flow.tsx: убрана агрессивная логика logout - confirmation-step.tsx: исправлена передача телефона - page.tsx: добавлена синхронизация состояния - 64 файла: миграция useAuth → useAuthContext 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -1,9 +1,10 @@
|
||||
'use client'
|
||||
|
||||
import { CheckCircle } from 'lucide-react'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { useState, useEffect } from 'react'
|
||||
|
||||
import { useAuth } from '@/hooks/useAuth'
|
||||
import { useAuthContext } from '@/contexts/AuthContext'
|
||||
|
||||
import { CabinetSelectStep } from './cabinet-select-step'
|
||||
import { ConfirmationStep } from './confirmation-step'
|
||||
@ -50,30 +51,14 @@ interface AuthFlowProps {
|
||||
}
|
||||
|
||||
export function AuthFlow({ partnerCode, referralCode }: AuthFlowProps = {}) {
|
||||
const { isAuthenticated, user } = useAuth()
|
||||
const router = useRouter()
|
||||
const { isAuthenticated, user } = useAuthContext()
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.warn('🎢 AuthFlow - Полученные props:', { partnerCode, referralCode })
|
||||
console.warn('🎢 AuthFlow - Статус авторизации:', { isAuthenticated, hasUser: !!user })
|
||||
}
|
||||
// Убираем избыточное логирование
|
||||
|
||||
// Проверяем незавершенную регистрацию: если есть токен, но нет организации - очищаем токен
|
||||
useEffect(() => {
|
||||
// Выполняем только на клиенте после гидрации
|
||||
if (typeof window === 'undefined') return
|
||||
|
||||
if (isAuthenticated && user && !user.organization) {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.warn('🧹 AuthFlow - Обнаружена незавершенная регистрация, очищаем токен')
|
||||
}
|
||||
// Очищаем токен и данные пользователя
|
||||
localStorage.removeItem('authToken')
|
||||
localStorage.removeItem('userData')
|
||||
// Перезагружаем страницу чтобы сбросить состояние useAuth
|
||||
window.location.reload()
|
||||
return
|
||||
}
|
||||
}, [isAuthenticated, user])
|
||||
// Убираем автоматический logout - это создает race condition
|
||||
// Незавершенная регистрация - это нормальное состояние
|
||||
// AuthFlow должен продолжить с шага cabinet-select
|
||||
|
||||
// Начинаем всегда с 'phone' для избежания гидрации,
|
||||
// а затем обновляем в useEffect после загрузки клиента
|
||||
@ -84,9 +69,7 @@ export function AuthFlow({ partnerCode, referralCode }: AuthFlowProps = {}) {
|
||||
const registrationType = partnerCode ? 'PARTNER' : referralCode ? 'REFERRAL' : null
|
||||
const activeCode = partnerCode || referralCode || null
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.warn('🎢 AuthFlow - Обработанные данные:', { registrationType, activeCode })
|
||||
}
|
||||
// Убираем избыточное логирование
|
||||
|
||||
const [authData, setAuthData] = useState<AuthData>({
|
||||
phone: '',
|
||||
@ -104,27 +87,48 @@ export function AuthFlow({ partnerCode, referralCode }: AuthFlowProps = {}) {
|
||||
referralCode: registrationType === 'REFERRAL' ? activeCode : null,
|
||||
})
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.warn('🎢 AuthFlow - Сохраненные в authData:', {
|
||||
partnerCode: authData.partnerCode,
|
||||
referralCode: authData.referralCode,
|
||||
})
|
||||
}
|
||||
// ⭐ КРИТИЧНО: Отслеживаем только смену шагов
|
||||
console.warn('🎯 STEP:', step)
|
||||
|
||||
// Добавляем useEffect для отслеживания изменений step
|
||||
useEffect(() => {
|
||||
console.warn('🔄 STEP CHANGED TO:', step)
|
||||
}, [step])
|
||||
|
||||
// Определяем правильный шаг после гидрации
|
||||
useEffect(() => {
|
||||
if (typeof window === 'undefined') return // Только на клиенте
|
||||
|
||||
// Убираем избыточное логирование useEffect
|
||||
|
||||
// Если у пользователя есть токен и организация - переходим к завершению
|
||||
if (isAuthenticated && user?.organization) {
|
||||
console.warn('🎢 AuthFlow - SCENARIO A: User has organization, setting step to complete')
|
||||
console.warn('🎢 AuthFlow - Organization details:', {
|
||||
id: user.organization.id,
|
||||
type: user.organization.type,
|
||||
name: user.organization.name,
|
||||
})
|
||||
setStep('complete')
|
||||
}
|
||||
// Если есть токен но нет организации - переходим к выбору кабинета
|
||||
else if (isAuthenticated && !user?.organization) {
|
||||
else if (isAuthenticated && user && !user.organization) {
|
||||
console.warn('🎢 AuthFlow - SCENARIO B/C: User authenticated but no organization, setting step to cabinet-select')
|
||||
console.warn('🎢 AuthFlow - User has token but missing organization:', {
|
||||
userId: user.id,
|
||||
phone: user.phone,
|
||||
organizationStatus: 'missing',
|
||||
})
|
||||
setStep('cabinet-select')
|
||||
}
|
||||
// Иначе остаемся на шаге телефона
|
||||
else {
|
||||
console.warn('🎢 AuthFlow - SCENARIO D: User not authenticated, setting step to phone')
|
||||
console.warn('🎢 AuthFlow - Auth status:', {
|
||||
isAuthenticated,
|
||||
userExists: !!user,
|
||||
tokenInStorage: typeof window !== 'undefined' ? !!localStorage.getItem('authToken') : 'unknown',
|
||||
})
|
||||
setStep('phone')
|
||||
}
|
||||
}, [isAuthenticated, user])
|
||||
@ -143,24 +147,24 @@ export function AuthFlow({ partnerCode, referralCode }: AuthFlowProps = {}) {
|
||||
useEffect(() => {
|
||||
if (step === 'complete') {
|
||||
const timer = setTimeout(() => {
|
||||
// Принудительно перенаправляем в дашборд
|
||||
window.location.href = '/dashboard'
|
||||
// Безопасно перенаправляем в дашборд через Next.js router
|
||||
console.warn('🎢 AuthFlow - Registration complete, redirecting to /dashboard')
|
||||
router.push('/dashboard')
|
||||
}, 2000) // Задержка для показа сообщения о завершении
|
||||
|
||||
return () => clearTimeout(timer)
|
||||
}
|
||||
}, [step])
|
||||
}, [step, router])
|
||||
|
||||
const handlePhoneNext = (phone: string) => {
|
||||
console.warn('📞 PHONE→SMS:', phone)
|
||||
setAuthData((prev) => ({ ...prev, phone }))
|
||||
setStep('sms')
|
||||
}
|
||||
|
||||
const handleSmsNext = async (smsCode: string) => {
|
||||
console.warn('✅ SMS→CABINET:', smsCode)
|
||||
setAuthData((prev) => ({ ...prev, smsCode, isAuthenticated: true }))
|
||||
|
||||
// SMS код уже проверен в SmsStep компоненте
|
||||
// Просто переходим к следующему шагу
|
||||
setStep('cabinet-select')
|
||||
}
|
||||
|
||||
@ -278,7 +282,9 @@ export function AuthFlow({ partnerCode, referralCode }: AuthFlowProps = {}) {
|
||||
{step === 'phone' && (
|
||||
<PhoneStep onNext={handlePhoneNext} registrationType={registrationType} referrerCode={activeCode} />
|
||||
)}
|
||||
{step === 'sms' && <SmsStep phone={authData.phone} onNext={handleSmsNext} onBack={handleSmsBack} />}
|
||||
{step === 'sms' && (
|
||||
<SmsStep phone={authData.phone} onNext={handleSmsNext} onBack={handleSmsBack} />
|
||||
)}
|
||||
{step === 'cabinet-select' && <CabinetSelectStep onNext={handleCabinetNext} onBack={handleCabinetBack} />}
|
||||
{step === 'inn' && <InnStep onNext={handleInnNext} onBack={handleInnBack} />}
|
||||
{step === 'marketplace-api' && (
|
||||
@ -302,6 +308,17 @@ export function AuthFlow({ partnerCode, referralCode }: AuthFlowProps = {}) {
|
||||
onBack={handleConfirmationBack}
|
||||
/>
|
||||
)}
|
||||
{/* ОТЛАДКА: Логируем authData перед передачей в ConfirmationStep */}
|
||||
{step === 'confirmation' && (() => {
|
||||
console.warn('📊 AuthFlow - Passing to ConfirmationStep:', {
|
||||
phone: authData.phone,
|
||||
phoneLength: authData.phone?.length,
|
||||
cabinetType: authData.cabinetType,
|
||||
inn: authData.inn,
|
||||
allAuthData: authData,
|
||||
})
|
||||
return null
|
||||
})()}
|
||||
{(step as string) === 'complete' && (
|
||||
<div className="space-y-6 text-center">
|
||||
<div className="flex justify-center">
|
||||
|
Reference in New Issue
Block a user