"use client"; import { useCallback, useMemo, useState } from "react"; import { useSession } from "../session/useSession"; import { getClientTimezone } from "@/shared/utils/locales"; import { ICreateAuthorizeRequest } from "@/entities/user/types"; import { filterNullKeysOfObject } from "@/shared/utils/filter-object"; import { createAuthorization } from "@/entities/user/actions"; import { setAuthTokenToCookie } from "@/entities/user/serverActions"; import analyticsService, { AnalyticsEvent, AnalyticsPlatform } from "@/services/analytics/analyticsService"; import { metricService } from "@/services/analytics/metricService"; import { ApiError } from "@/shared/api/httpClient"; // TODO const locale = "en"; interface IUseAuthProps { funnelId: string; googleAnalyticsId?: string; /** * Дополнительные данные для регистрации пользователя. * Будут объединены с базовым payload при авторизации. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any registrationData?: Record; } export const useAuth = ({ funnelId, googleAnalyticsId, registrationData }: IUseAuthProps) => { const { updateSession } = useSession({ funnelId, googleAnalyticsId }); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const [suggestedEmail, setSuggestedEmail] = useState(null); const getAllCookies = useCallback(() => { // Токены которые не должны передаваться на backend const EXCLUDED_COOKIES = ["accessToken", "activeSessionId"]; const cookies: Record = {}; document.cookie.split(";").forEach((cookie) => { const [name, value] = cookie.trim().split("="); if (name && value && !EXCLUDED_COOKIES.includes(name)) { cookies[name] = decodeURIComponent(value); } }); return cookies; }, []); const getAuthorizationPayload = useCallback( (email: string): ICreateAuthorizeRequest => { const timezone = getClientTimezone(); const basePayload = { timezone, locale, email, source: funnelId, sign: true, signDate: new Date().toISOString(), feature: "stripe" }; // Объединяем базовый payload с данными регистрации из воронки const mergedPayload = registrationData ? { ...basePayload, ...registrationData } : basePayload; return filterNullKeysOfObject(mergedPayload); }, [funnelId, registrationData] ); const authorization = useCallback( async (email: string) => { try { setIsLoading(true); setError(null); // Обновляем сессию с куки перед авторизацией try { const cookies = getAllCookies(); await updateSession({ cookies }); console.log( "Session updated with cookies before authorization:", cookies ); } catch (sessionError) { console.warn("Failed to update session with cookies:", sessionError); // Продолжаем авторизацию даже если обновление сессии не удалось } const payload = getAuthorizationPayload(email); const { token, userId } = await createAuthorization(payload); // Track registration events in analytics // Send EnteredEmail to Yandex Metrika and Google Analytics analyticsService.trackEvent( AnalyticsEvent.ENTERED_EMAIL, [AnalyticsPlatform.YANDEX_METRIKA, AnalyticsPlatform.GOOGLE_ANALYTICS] ); // Send Lead to Facebook Pixel analyticsService.trackEvent( AnalyticsEvent.LEAD, [AnalyticsPlatform.FACEBOOK] ); // Set user ID and properties in analytics if (userId) { analyticsService.setUserId(userId); analyticsService.setUserProperties({ email, source: funnelId, UserID: userId, }); // ✅ Отправляем UserID и email в userParams (параметры посетителя) metricService.setUserID(userId); metricService.userParams({ UserID: userId, email, }); // ✅ Отправляем email и userId в params (параметры визита) metricService.sendVisitContext({ email, userId, }); } await setAuthTokenToCookie(token); return token; } catch (err) { // Extract error message and suggestion from API error if (err instanceof ApiError && err.data) { const errorData = err.data as { errors?: Array<{ msg: string; path: string }> }; const emailError = errorData.errors?.find(e => e.path === 'email'); if (emailError) { setError(emailError.msg); // Extract suggested email from "Did you mean user@gmail.com?" message const suggestionMatch = emailError.msg.match(/Did you mean (.+)\?/); if (suggestionMatch) { setSuggestedEmail(suggestionMatch[1]); } else { setSuggestedEmail(null); } } else { setError('Email validation failed'); setSuggestedEmail(null); } } else { setError((err as Error).message); setSuggestedEmail(null); } } finally { setIsLoading(false); } }, [getAllCookies, getAuthorizationPayload, updateSession, funnelId] ); const clearError = useCallback(() => { setError(null); setSuggestedEmail(null); }, []); return useMemo( () => ({ authorization, isLoading, error, suggestedEmail, clearError, }), [authorization, isLoading, error, suggestedEmail, clearError] ); };