Archived
1
0

feat(frontend): Экран авторизации

This commit is contained in:
2025-11-19 17:18:19 +03:00
parent 5f60d12996
commit 20556231b9
26 changed files with 1177 additions and 183 deletions

144
apps/frontend/lib/auth.tsx Normal file
View File

@ -0,0 +1,144 @@
import React, { createContext, useContext, useEffect, useState, ReactNode } from 'react';
import { createAuthClient } from 'better-auth/react';
import { AUTH_BASE_URL } from '@/config/api';
import type { User } from '@shared-types';
// Создаем клиент Better Auth
export const authClient = createAuthClient({
baseURL: AUTH_BASE_URL,
});
interface AuthContextType {
user: User | null;
session: any | null;
loading: boolean;
signIn: (email: string, password: string) => Promise<void>;
signUp: (email: string, password: string, name: string) => Promise<void>;
signOut: () => Promise<void>;
refresh: () => Promise<void>;
}
const AuthContext = createContext<AuthContextType | undefined>(undefined);
export function AuthProvider({ children }: { children: ReactNode }) {
const [user, setUser] = useState<User | null>(null);
const [session, setSession] = useState<any | null>(null);
const [loading, setLoading] = useState(true);
const refresh = async () => {
try {
const sessionData = await authClient.getSession();
setSession(sessionData.data?.session || null);
const userData = sessionData.data?.user;
if (userData) {
setUser({
...userData,
image: userData.image ?? null,
} as User);
} else {
setUser(null);
}
} catch (error) {
console.error('Ошибка получения сессии:', error);
setSession(null);
setUser(null);
} finally {
setLoading(false);
}
};
useEffect(() => {
refresh();
}, []);
const signIn = async (email: string, password: string) => {
setLoading(true);
try {
const result = await authClient.signIn.email({
email,
password,
});
if (result.data?.user) {
const userData = result.data.user;
setUser({
...userData,
image: userData.image ?? null,
} as User);
setSession(result.data as any);
} else {
throw new Error('Ошибка входа');
}
} catch (error) {
console.error('Ошибка входа:', error);
throw error;
} finally {
setLoading(false);
}
};
const signUp = async (email: string, password: string, name: string) => {
setLoading(true);
try {
const result = await authClient.signUp.email({
email,
password,
name,
});
if (result.data?.user) {
const userData = result.data.user;
setUser({
...userData,
image: userData.image ?? null,
} as User);
setSession(result.data as any);
} else {
throw new Error('Ошибка регистрации');
}
} catch (error) {
console.error('Ошибка регистрации:', error);
throw error;
} finally {
setLoading(false);
}
};
const signOut = async () => {
setLoading(true);
try {
await authClient.signOut();
setUser(null);
setSession(null);
} catch (error) {
console.error('Ошибка выхода:', error);
throw error;
} finally {
setLoading(false);
}
};
return (
<AuthContext.Provider
value={{
user,
session,
loading,
signIn,
signUp,
signOut,
refresh,
}}
>
{children}
</AuthContext.Provider>
);
}
export function useAuth() {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error('useAuth must be used within an AuthProvider');
}
return context;
}