codex/fsd-frontend-refactor #31

Merged
ksv741 merged 6 commits from codex/fsd-frontend-refactor into main 2026-06-20 23:29:09 +03:00
2 changed files with 96 additions and 2 deletions
Showing only changes of commit 79011c779f - Show all commits

View File

@ -0,0 +1,94 @@
import { useState, useEffect, useCallback, type ReactNode } from 'react';
import { SessionContext, type SessionContextValue } from '@/entities/session';
import * as sessionApi from '@/entities/session';
import type { UserResponse } from '@/shared/api/responses';
export function TestSessionProvider({ children }: { children: ReactNode }) {
const [user, setUser] = useState<UserResponse | null>(null);
const [accessToken, setAccessTokenState] = useState<string | null>(null);
const [isLoading, setIsLoading] = useState(true);
const [initialized, setInitialized] = useState(false);
const updateSession = useCallback((authData: { user: UserResponse; accessToken: string }) => {
setUser(authData.user);
setAccessTokenState(authData.accessToken);
}, []);
const clearSession = useCallback(() => {
setUser(null);
setAccessTokenState(null);
}, []);
const login = useCallback(
async (email: string, password: string) => {
const result = await sessionApi.login(email, password);
updateSession(result);
},
[updateSession],
);
const register = useCallback(
async (email: string, password: string, name?: string) => {
const result = await sessionApi.register(email, password, name);
updateSession(result);
},
[updateSession],
);
const logout = useCallback(async () => {
try {
await sessionApi.logout();
} catch {
// ignore network errors on logout
}
clearSession();
}, [clearSession]);
const updateProfileFn = useCallback(async (data: { name?: string }) => {
const result = await sessionApi.updateProfile(data);
setUser(result);
}, []);
useEffect(() => {
let mounted = true;
async function init() {
try {
const result = await sessionApi.refresh();
if (mounted) {
updateSession(result);
}
} catch {
// No valid session
} finally {
if (mounted) {
setIsLoading(false);
setInitialized(true);
}
}
}
init();
return () => {
mounted = false;
};
}, [updateSession]);
if (!initialized && isLoading) {
return <div>Загрузка...</div>;
}
const value: SessionContextValue = {
user,
accessToken,
isAuthenticated: !!user,
isLoading,
login,
register,
logout,
updateProfile: updateProfileFn,
};
return <SessionContext.Provider value={value}>{children}</SessionContext.Provider>;
}

View File

@ -2,7 +2,7 @@ import { type ReactElement } from 'react';
import { render, type RenderOptions } from '@testing-library/react'; import { render, type RenderOptions } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { MemoryRouter } from 'react-router-dom'; import { MemoryRouter } from 'react-router-dom';
import { SessionProvider } from '@/app/providers'; import { TestSessionProvider } from './TestSessionProvider';
interface CustomRenderOptions extends Omit<RenderOptions, 'wrapper'> { interface CustomRenderOptions extends Omit<RenderOptions, 'wrapper'> {
queryClient?: QueryClient; queryClient?: QueryClient;
@ -33,7 +33,7 @@ export function renderWithProviders(
initialEntries={[route]} initialEntries={[route]}
future={{ v7_startTransition: true, v7_relativeSplatPath: true }} future={{ v7_startTransition: true, v7_relativeSplatPath: true }}
> >
<SessionProvider>{children}</SessionProvider> <TestSessionProvider>{children}</TestSessionProvider>
</MemoryRouter> </MemoryRouter>
</QueryClientProvider> </QueryClientProvider>
); );