import { ErrorPayload, useApi } from "@/api"; import { EGender, ESourceAuthorization, ICreateAuthorizePayload, ICreateAuthorizeResponse } from "@/api/resources/User"; import { useAuth } from "@/auth"; import { getClientTimezone } from "@/locales"; import { getDateAsString } from "@/services/date"; import { filterNullKeysOfObject } from "@/services/filter-object"; import metricService, { EGoals, EMetrics } from "@/services/metric/metricService"; import { actions, selectors } from "@/store"; import moment from "moment"; import { useCallback, useMemo, useState } from "react"; import { useTranslations } from "@/hooks/translations"; import { useDispatch, useSelector } from "react-redux"; import { Response } from "@/api/resources/Login"; import { useSession } from "@/hooks/session/useSession"; export const useAuthentication = () => { const api = useApi(); const feature = useSelector(selectors.selectFeature) const { i18n } = useTranslations(); const dispatch = useDispatch(); const { updateSession } = useSession(); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const [token, setToken] = useState(null); const { user, signUp } = useAuth(); const locale = i18n.language; const { username } = useSelector(selectors.selectUser) const { name: partnerName, birthDate: partnerBirthdateFromForm } = useSelector(selectors.selectRightUser) const { gender, birthdate: birthdateFromQuestionnaire, birthtime: birthtimeFromQuestionnaire, birthPlace, partnerGender, partnerBirthdate: partnerBirthdateFromQuestionnaire, partnerBirthPlace, partnerBirthtime, } = useSelector(selectors.selectQuestionnaire) const { checked, dateOfCheck } = useSelector(selectors.selectPrivacyPolicy) const birthdateFromForm = useSelector(selectors.selectBirthdate); const birthtimeFromForm = useSelector(selectors.selectBirthtime); const birthdate = useMemo(() => { if (birthdateFromQuestionnaire?.length) { return birthdateFromQuestionnaire; } if (birthdateFromForm?.length) { return birthdateFromForm; } }, [birthdateFromForm, birthdateFromQuestionnaire]); const birthtime = useMemo(() => { if (birthtimeFromQuestionnaire?.length) { return birthtimeFromQuestionnaire; } if (birthtimeFromForm?.length) { return birthtimeFromForm; } }, [birthtimeFromForm, birthtimeFromQuestionnaire]); const partnerBirthdate = useMemo(() => { const fromQuestionnaire = `${partnerBirthdateFromQuestionnaire} ${partnerBirthtime}` if (partnerBirthdateFromQuestionnaire?.length) { return fromQuestionnaire; } return getDateAsString(partnerBirthdateFromForm) }, [partnerBirthdateFromForm, partnerBirthdateFromQuestionnaire, partnerBirthtime]) const formatDate = useCallback((date: string) => { const _date = moment(date, "YYYY-MM-DD HH:mm", true).format("YYYY-MM-DD HH:mm"); if (_date === "Invalid date") { return null; } return _date; }, []) // Функция для получения всех куки браузера const getAllCookies = useCallback(() => { const cookies: Record = {}; document.cookie.split(';').forEach(cookie => { const [name, value] = cookie.trim().split('='); if (name && value) { cookies[name] = decodeURIComponent(value); } }); return cookies; }, []); const getAuthorizationPayload = useCallback((email: string, source: ESourceAuthorization): ICreateAuthorizePayload => { const timezone = getClientTimezone(); return filterNullKeysOfObject({ timezone, locale, email, source, profile: { name: username || "", gender: EGender[gender as keyof typeof EGender] || null, birthdate: formatDate(`${birthdate} ${birthtime}`), birthplace: { address: birthPlace, }, }, partner: { name: partnerName, gender: EGender[partnerGender as keyof typeof EGender] || null, birthdate: formatDate(partnerBirthdate), birthplace: { address: partnerBirthPlace, }, }, sign: checked, signDate: dateOfCheck, feature: feature.includes("black") ? "ios" : feature }) // eslint-disable-next-line react-hooks/exhaustive-deps }, [ birthPlace, birthdate, gender, locale, partnerBirthPlace, partnerBirthdate, partnerGender, partnerName, username, birthtime, checked, dateOfCheck ]); const authorizationWithPassword = useCallback(async (email: string, password: string) => { try { setIsLoading(true); setError(null) const payload = { email, locale, timezone: getClientTimezone(), password } const loginResult = await api.login(payload); const token = "token" in loginResult ? loginResult.token : null; const userId = "userId" in loginResult ? loginResult.userId : null; const status = "status" in loginResult ? loginResult.status : null; const message = "message" in loginResult ? loginResult.message : null; if (!token) { return { status, message } } metricService.reachGoal(EGoals.ENTERED_EMAIL, [EMetrics.YANDEX, EMetrics.KLAVIYO]); metricService.reachGoal(EGoals.LEAD, [EMetrics.FACEBOOK]); const { user: userMe } = await api.getMe({ token }); if (userId?.length) { metricService.userParams({ email: user?.email, UserID: userId }) metricService.setUserID(userId); } signUp(token, userMe); setToken(token); dispatch(actions.status.update("registred")); } catch (error: unknown) { const response = (error as ErrorPayload).responseData setError((!!response && "message" in response && response.message) || (error as Error).message); return response } finally { setIsLoading(false); } }, [api, dispatch, locale, signUp]) const authorization = useCallback(async (email: string, source: ESourceAuthorization, isAnonymous = false) => { try { setIsLoading(true); setError(null) // Обновляем сессию с куки перед авторизацией try { const cookies = getAllCookies(); await updateSession({ cookies }, source); console.log('Session updated with cookies before authorization:', cookies); } catch (sessionError) { console.warn('Failed to update session with cookies:', sessionError); // Продолжаем авторизацию даже если обновление сессии не удалось } const payload = getAuthorizationPayload(email, source); const { token, userId: userIdFromApi, generatingVideo, videoId, authCode } = isAnonymous ? await api.authorizationAnonymous(payload) : await api.authorization(payload); if (!!token && !isAnonymous) { metricService.reachGoal(EGoals.ENTERED_EMAIL, [EMetrics.YANDEX, EMetrics.KLAVIYO]); metricService.reachGoal(EGoals.LEAD, [EMetrics.FACEBOOK]); } const { user: userMe } = await api.getMe({ token }); const userId = userIdFromApi || userMe?._id; if (userId?.length) { dispatch(actions.userId.update({ userId })); metricService.userParams({ hasPersonalVideo: generatingVideo || false, email: user?.email, UserID: userId }) metricService.setUserID(userId); } signUp(token, userMe, isAnonymous); setToken(token); dispatch(actions.userConfig.setAuthCode(authCode || "")); dispatch(actions.personalVideo.updateStatus({ generatingVideo: generatingVideo || false, videoId: videoId || "" })); if (generatingVideo) { metricService.reachGoal(EGoals.ROSE_VIDEO_CREATION_START, [EMetrics.YANDEX, EMetrics.KLAVIYO]); } dispatch(actions.status.update("registred")); } catch (error) { setError((error as Error).message); } finally { setIsLoading(false); } }, [api, dispatch, getAllCookies, getAuthorizationPayload, signUp, updateSession]) const anonymousAuthorization = useCallback(async ({ token, userId: userIdFromApi = "", generatingVideo = false, videoId = "", authCode = "" }: ICreateAuthorizeResponse) => { try { setIsLoading(true); setError(null) const { user: userMe } = await api.getMe({ token }); const userId = userIdFromApi || userMe?._id; if (userId?.length) { dispatch(actions.userId.update({ userId })); metricService.userParams({ hasPersonalVideo: generatingVideo || false, email: user?.email, UserID: userId }) metricService.setUserID(userId); } signUp(token, userMe, true); setToken(token); dispatch(actions.userConfig.setAuthCode(authCode || "")); dispatch(actions.personalVideo.updateStatus({ generatingVideo: generatingVideo || false, videoId: videoId || "" })); if (generatingVideo) { metricService.reachGoal(EGoals.ROSE_VIDEO_CREATION_START, [EMetrics.YANDEX, EMetrics.KLAVIYO]); } dispatch(actions.status.update("registred")); } catch (error) { setError((error as Error).message); } finally { setIsLoading(false); } }, [api, dispatch, getAuthorizationPayload, signUp]) return useMemo( () => ({ isLoading, error, token, user, authorization, authorizationWithPassword, anonymousAuthorization }), [ isLoading, error, token, user, authorization, authorizationWithPassword, anonymousAuthorization ] ); }