register logic

This commit is contained in:
2025-05-18 13:37:27 +03:00
parent be46e09aeb
commit 695c29ab62
19 changed files with 498 additions and 36 deletions

View File

@@ -0,0 +1,7 @@
import React from 'react'
const page = () => {
return <div>page</div>
}
export default page

View File

@@ -43,7 +43,8 @@ export default function ClientRegistrationForm() {
const result = await signIn('register-credentials', {
email: values.email,
password: values.password,
username: values.name,
name: values.name,
surname: values.surname,
phone_number: values.phone_number,
privacy_accepted: values.privacy_accepted.toString(),
redirect: false,

View File

@@ -45,35 +45,56 @@ interface GoogleToken extends JWT {
const authOptions: NextAuthOptions = {
providers: [
//google login flow
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
}),
// GoogleProvider({
// clientId: process.env.GOOGLE_CLIENT_ID!,
// clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
// }),
//регистрация клиента
CredentialsProvider({
id: 'register-credentials',
name: 'Register',
credentials: {
name: { label: 'Name', type: 'text' },
surname: { label: 'Surname', type: 'text' },
email: { label: 'Email', type: 'email' },
password: { label: 'Password', type: 'password' },
name: { label: 'Name', type: 'text' },
phone_number: { label: 'Phone Number', type: 'tel' },
privacy_accepted: { label: 'Privacy Accepted', type: 'boolean' },
},
async authorize(credentials) {
try {
if (
!credentials?.email ||
!credentials?.password ||
!credentials?.name ||
!credentials?.phone_number ||
!credentials?.privacy_accepted ||
!credentials?.surname
) {
throw new Error('Все поля обязательны для заполнения')
}
// console.log('Registration data:', {
// email: credentials.email,
// name: credentials.name,
// surname: credentials.surname,
// phone_number: credentials.phone_number,
// privacy_accepted: credentials.privacy_accepted,
// })
const res = await fetch(
`${process.env.BACKEND_URL}/register/clients/`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: credentials?.email,
password: credentials?.password,
name: credentials?.name,
phone_number: credentials?.phone_number,
privacy_accepted: credentials?.privacy_accepted === 'true',
email: credentials.email,
password: credentials.password,
name: credentials.name,
surname: credentials.surname,
phone_number: credentials.phone_number,
privacy_accepted: credentials.privacy_accepted === 'true',
}),
}
)
@@ -81,21 +102,25 @@ const authOptions: NextAuthOptions = {
const data = await res.json()
if (!res.ok) {
throw new Error(
data.error || data.details?.toString() || 'Registration failed'
)
console.error('Registration error response:', data)
const errorMessage =
typeof data === 'object'
? data.error || Object.values(data).flat().join(', ')
: 'Registration failed'
throw new Error(errorMessage)
}
return {
id: data.user.id.toString(),
email: data.user.email,
name: data.user.firstName,
name: data.user.name,
surname: data.user.surname,
accessToken: data.access,
refreshToken: data.refresh,
}
} catch (error) {
console.error('Registration error:', error)
return null
throw error
}
},
}),

View File

@@ -2,6 +2,8 @@ import type { Metadata } from 'next'
import './globals.css'
import Header from '@/components/Header'
import Footer from '@/components/Footer'
import { Toaster } from 'react-hot-toast'
import { Providers } from './providers/Providers'
export const metadata: Metadata = {
title: 'Отправка посылок в любую точку мира | TripWB',
@@ -17,9 +19,12 @@ export default function RootLayout({
return (
<html lang="en">
<body className="min-h-screen flex flex-col font-dispay">
<Header />
<main className="flex-grow">{children}</main>
<Footer />
<Providers>
<Header />
<main className="flex-grow">{children}</main>
<Toaster />
<Footer />
</Providers>
</body>
</html>
)

View File

@@ -0,0 +1,62 @@
'use client'
import { useSession } from 'next-auth/react'
import { useEffect } from 'react'
import useUserStore from '@/app/store/userStore'
export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
const { data: session } = useSession()
const { setUser, setAuthenticated } = useUserStore()
useEffect(() => {
const fetchUserData = async () => {
if (!session?.accessToken) {
setUser(null)
setAuthenticated(false)
return
}
const API_URL = process.env.NEXT_PUBLIC_API_URL
try {
const response = await fetch(`${API_URL}/user/`, {
headers: {
Authorization: `Bearer ${session.accessToken}`,
'Content-Type': 'application/json',
},
})
if (!response.ok) {
const errorText = await response.text()
console.error('Error response:', errorText)
throw new Error(
`Error fetching user data: ${response.status} ${errorText}`
)
}
const userData = await response.json()
setUser({
id: userData.id,
uuid: userData.uuid,
name: userData.name || session.user.name || '',
surname: userData.surname || '',
email: userData.email || session.user.email || '',
phone_number: userData.phone_number,
image: userData.image,
country: userData.country,
city: userData.city,
plan: userData.plan,
account_type: userData.account_type,
})
setAuthenticated(true)
} catch (error) {
console.error('Error in fetchUserData:', error)
}
}
fetchUserData()
}, [session, setUser, setAuthenticated])
return <>{children}</>
}

View File

@@ -0,0 +1,17 @@
'use client'
import { SessionProvider } from 'next-auth/react'
import { AuthProvider } from './AuthProvider'
export function Providers({ children }: { children: React.ReactNode }) {
return (
<SessionProvider
refetchInterval={0}
refetchOnWindowFocus={false}
refetchWhenOffline={false}
basePath="/api/auth"
>
<AuthProvider>{children}</AuthProvider>
</SessionProvider>
)
}