import { ErrorPayload, useApi } from "@/api"; import { EGender, ESourceAuthorization, ICreateAuthorizePayload } 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 } 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"; export const useAuthentication = () => { const api = useApi(); const feature = useSelector(selectors.selectFeature) const { i18n } = useTranslations(); const dispatch = useDispatch(); 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 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 }) // 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 } } const { user } = await api.getUser({ token }); if (userId?.length) { metricService.userParams({ email: user.email, UserID: userId }) metricService.setUserID(userId); } signUp(token, user); 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) => { try { setIsLoading(true); setError(null) const payload = getAuthorizationPayload(email, source); const { token, userId, generatingVideo, videoId, authCode } = await api.authorization(payload); const { user } = await api.getUser({ token }); if (userId?.length) { metricService.userParams({ hasPersonalVideo: generatingVideo || false, email: user.email, UserID: userId }) metricService.setUserID(userId); } signUp(token, user); setToken(token); if (authCode?.length) { dispatch(actions.userConfig.setAuthCode(authCode)); } dispatch(actions.personalVideo.updateStatus({ generatingVideo: generatingVideo || false, videoId: videoId || "" })); if (generatingVideo) { metricService.reachGoal(EGoals.ROSE_VIDEO_CREATION_START) } 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, }), [ isLoading, error, token, user, authorization, authorizationWithPassword, ] ); }