264 lines
8.5 KiB
TypeScript
264 lines
8.5 KiB
TypeScript
"use client"
|
||
|
||
import { useState, useEffect } from "react"
|
||
import { PhoneStep } from "./phone-step"
|
||
import { SmsStep } from "./sms-step"
|
||
import { CabinetSelectStep } from "./cabinet-select-step"
|
||
import { InnStep } from "./inn-step"
|
||
import { MarketplaceApiStep } from "./marketplace-api-step"
|
||
import { ConfirmationStep } from "./confirmation-step"
|
||
import { CheckCircle } from "lucide-react"
|
||
|
||
|
||
type AuthStep = 'phone' | 'sms' | 'cabinet-select' | 'inn' | 'marketplace-api' | 'confirmation' | 'complete'
|
||
type CabinetType = 'fulfillment' | 'seller' | 'logist' | 'wholesale'
|
||
|
||
interface OrganizationData {
|
||
name?: string
|
||
fullName?: string
|
||
address?: string
|
||
isActive?: boolean
|
||
}
|
||
|
||
interface ApiKeyValidation {
|
||
sellerId?: string
|
||
sellerName?: string
|
||
tradeMark?: string
|
||
isValid?: boolean
|
||
}
|
||
|
||
interface AuthData {
|
||
phone: string
|
||
smsCode: string
|
||
cabinetType: CabinetType | null
|
||
inn: string
|
||
organizationData: OrganizationData | null
|
||
wbApiKey: string
|
||
wbApiValidation: ApiKeyValidation | null
|
||
ozonApiKey: string
|
||
ozonApiValidation: ApiKeyValidation | null
|
||
isAuthenticated: boolean
|
||
partnerCode?: string | null
|
||
}
|
||
|
||
interface AuthFlowProps {
|
||
partnerCode?: string | null
|
||
}
|
||
|
||
export function AuthFlow({ partnerCode }: AuthFlowProps = {}) {
|
||
const [step, setStep] = useState<AuthStep>('phone')
|
||
const [authData, setAuthData] = useState<AuthData>({
|
||
phone: '',
|
||
smsCode: '',
|
||
cabinetType: null,
|
||
inn: '',
|
||
organizationData: null,
|
||
wbApiKey: '',
|
||
wbApiValidation: null,
|
||
ozonApiKey: '',
|
||
ozonApiValidation: null,
|
||
isAuthenticated: false,
|
||
partnerCode: partnerCode
|
||
})
|
||
|
||
// При завершении авторизации инициируем проверку и перенаправление
|
||
useEffect(() => {
|
||
if (step === 'complete') {
|
||
const timer = setTimeout(() => {
|
||
// Принудительно перенаправляем в дашборд
|
||
window.location.href = '/dashboard'
|
||
}, 2000) // Задержка для показа сообщения о завершении
|
||
|
||
return () => clearTimeout(timer)
|
||
}
|
||
}, [step])
|
||
|
||
const handlePhoneNext = (phone: string) => {
|
||
setAuthData(prev => ({ ...prev, phone }))
|
||
setStep('sms')
|
||
}
|
||
|
||
const handleSmsNext = async (smsCode: string) => {
|
||
setAuthData(prev => ({ ...prev, smsCode, isAuthenticated: true }))
|
||
|
||
// SMS код уже проверен в SmsStep компоненте
|
||
// Просто переходим к следующему шагу
|
||
setStep('cabinet-select')
|
||
}
|
||
|
||
const handleCabinetNext = (cabinetType: CabinetType) => {
|
||
setAuthData(prev => ({ ...prev, cabinetType }))
|
||
if (cabinetType === 'fulfillment' || cabinetType === 'logist' || cabinetType === 'wholesale') {
|
||
setStep('inn')
|
||
} else {
|
||
setStep('marketplace-api')
|
||
}
|
||
}
|
||
|
||
const handleInnNext = (inn: string, organizationData?: OrganizationData) => {
|
||
setAuthData(prev => ({
|
||
...prev,
|
||
inn,
|
||
organizationData: organizationData || null
|
||
}))
|
||
setStep('confirmation')
|
||
}
|
||
|
||
const handleMarketplaceApiNext = (apiData: {
|
||
wbApiKey?: string
|
||
wbApiValidation?: ApiKeyValidation
|
||
ozonApiKey?: string
|
||
ozonApiValidation?: ApiKeyValidation
|
||
}) => {
|
||
setAuthData(prev => ({
|
||
...prev,
|
||
wbApiKey: apiData.wbApiKey || '',
|
||
wbApiValidation: apiData.wbApiValidation || null,
|
||
ozonApiKey: apiData.ozonApiKey || '',
|
||
ozonApiValidation: apiData.ozonApiValidation || null
|
||
}))
|
||
setStep('confirmation')
|
||
}
|
||
|
||
const handleConfirmation = () => {
|
||
setStep('complete')
|
||
}
|
||
|
||
const handleSmsBack = () => {
|
||
setStep('phone')
|
||
}
|
||
|
||
const handleCabinetBack = () => {
|
||
setStep('sms')
|
||
}
|
||
|
||
const handleInnBack = () => {
|
||
setStep('cabinet-select')
|
||
}
|
||
|
||
const handleMarketplaceApiBack = () => {
|
||
setStep('cabinet-select')
|
||
}
|
||
|
||
const handleConfirmationBack = () => {
|
||
if (authData.cabinetType === 'fulfillment' || authData.cabinetType === 'logist' || authData.cabinetType === 'wholesale') {
|
||
setStep('inn')
|
||
} else {
|
||
setStep('marketplace-api')
|
||
}
|
||
}
|
||
|
||
if (step === 'complete') {
|
||
return (
|
||
<div className="min-h-screen bg-animated flex items-center justify-center p-4">
|
||
{/* Floating Particles */}
|
||
<div className="particles">
|
||
<div className="particle"></div>
|
||
<div className="particle"></div>
|
||
<div className="particle"></div>
|
||
<div className="particle"></div>
|
||
<div className="particle"></div>
|
||
<div className="particle"></div>
|
||
<div className="particle"></div>
|
||
<div className="particle"></div>
|
||
<div className="particle"></div>
|
||
</div>
|
||
|
||
<div className="text-center text-white max-w-md relative z-10">
|
||
<div className="bg-white/10 backdrop-blur rounded-2xl p-8 border border-white/20 glow-purple">
|
||
<CheckCircle className="h-20 w-20 mx-auto mb-6 text-green-400 animate-pulse" />
|
||
<h1 className="text-3xl font-bold text-gradient-bright mb-4">Добро пожаловать!</h1>
|
||
<p className="text-white/80 mb-4">Регистрация успешно завершена</p>
|
||
<div className="bg-white/5 rounded-lg p-4 mb-6">
|
||
<p className="text-white/60 text-sm mb-2">Тип кабинета:</p>
|
||
<p className="text-white font-medium">
|
||
{
|
||
authData.cabinetType === 'fulfillment' ? 'Фулфилмент' :
|
||
authData.cabinetType === 'logist' ? 'Логистика' :
|
||
authData.cabinetType === 'wholesale' ? 'Оптовик' :
|
||
'Селлер'
|
||
}
|
||
</p>
|
||
</div>
|
||
<div className="flex items-center justify-center gap-2 text-white/60 text-sm">
|
||
<div className="animate-spin h-4 w-4 border-2 border-white/20 border-t-white/60 rounded-full"></div>
|
||
Переход в личный кабинет...
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
return (
|
||
<>
|
||
{step === 'phone' && <PhoneStep onNext={handlePhoneNext} />}
|
||
{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' && (
|
||
<MarketplaceApiStep
|
||
onNext={handleMarketplaceApiNext}
|
||
onBack={handleMarketplaceApiBack}
|
||
/>
|
||
)}
|
||
{step === 'confirmation' && (
|
||
<ConfirmationStep
|
||
data={{
|
||
phone: authData.phone,
|
||
cabinetType: authData.cabinetType!,
|
||
inn: authData.inn || undefined,
|
||
organizationData: authData.organizationData || undefined,
|
||
wbApiKey: authData.wbApiKey || undefined,
|
||
wbApiValidation: authData.wbApiValidation || undefined,
|
||
ozonApiKey: authData.ozonApiKey || undefined,
|
||
ozonApiValidation: authData.ozonApiValidation || undefined
|
||
}}
|
||
onConfirm={handleConfirmation}
|
||
onBack={handleConfirmationBack}
|
||
/>
|
||
)}
|
||
{(step as string) === 'complete' && (
|
||
<div className="space-y-6 text-center">
|
||
<div className="flex justify-center">
|
||
<div className="w-16 h-16 bg-green-100 rounded-full flex items-center justify-center">
|
||
<CheckCircle className="w-10 h-10 text-green-600" />
|
||
</div>
|
||
</div>
|
||
<div className="space-y-2">
|
||
<h2 className="text-2xl font-bold text-gray-900">
|
||
Регистрация завершена!
|
||
</h2>
|
||
<p className="text-gray-600">
|
||
Ваш {authData.cabinetType === 'fulfillment' ? 'фулфилмент кабинет' :
|
||
authData.cabinetType === 'seller' ? 'селлер кабинет' :
|
||
authData.cabinetType === 'logist' ? 'логистический кабинет' : 'оптовый кабинет'}
|
||
{' '}успешно создан
|
||
</p>
|
||
</div>
|
||
<div className="animate-pulse">
|
||
<p className="text-sm text-gray-500">
|
||
Переход в личный кабинет...
|
||
</p>
|
||
</div>
|
||
</div>
|
||
)}
|
||
</>
|
||
)
|
||
}
|