w-aura/src/hooks/authentication/use-authentication.ts
2025-09-04 21:59:04 +00:00

282 lines
11 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<string | null>(null);
const [token, setToken] = useState<string | null>(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<string, string> = {};
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<ICreateAuthorizePayload>({
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<Response>).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
]
);
}