AW-51-newAuthentication
This commit is contained in:
parent
57eb7ab913
commit
2d7be6a578
14
package-lock.json
generated
14
package-lock.json
generated
@ -17,6 +17,7 @@
|
||||
"html-react-parser": "^3.0.16",
|
||||
"i18next": "^22.5.0",
|
||||
"i18next-react-postprocessor": "^3.1.0",
|
||||
"moment": "^2.30.1",
|
||||
"react": "^18.2.0",
|
||||
"react-circular-progressbar": "^2.1.0",
|
||||
"react-dom": "^18.2.0",
|
||||
@ -2665,6 +2666,14 @@
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/moment": {
|
||||
"version": "2.30.1",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
|
||||
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
@ -5381,6 +5390,11 @@
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"moment": {
|
||||
"version": "2.30.1",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
|
||||
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how=="
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
"html-react-parser": "^3.0.16",
|
||||
"i18next": "^22.5.0",
|
||||
"i18next-react-postprocessor": "^3.1.0",
|
||||
"moment": "^2.30.1",
|
||||
"react": "^18.2.0",
|
||||
"react-circular-progressbar": "^2.1.0",
|
||||
"react-dom": "^18.2.0",
|
||||
|
||||
@ -72,6 +72,8 @@ const api = {
|
||||
createSinglePayment: createMethod<SinglePayment.PayloadPost, SinglePayment.ResponsePost>(SinglePayment.createRequestPost),
|
||||
checkProductPurchased: createMethod<Products.PayloadGet, Products.ResponseGet>(Products.createRequest),
|
||||
getPalmistryLines: createMethod<Palmistry.Payload, Palmistry.Response>(Palmistry.createRequest),
|
||||
// New Authorization
|
||||
authorization: createMethod<User.ICreateAuthorizePayload, User.ICreateAuthorizeResponse>(User.createAuthorizeRequest),
|
||||
}
|
||||
|
||||
export type ApiContextValue = typeof api
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import routes from "@/routes";
|
||||
import { AuthPayload } from "../types";
|
||||
import { getAuthHeaders } from "../utils";
|
||||
import { getAuthHeaders, getBaseHeaders } from "../utils";
|
||||
|
||||
export type GetPayload = AuthPayload;
|
||||
|
||||
@ -130,3 +130,57 @@ export const createPatchRequest = ({ token, user }: PatchPayload): Request => {
|
||||
body,
|
||||
});
|
||||
};
|
||||
|
||||
export enum ESourceAuthorization {
|
||||
"aura.main" = "aura.main",
|
||||
"aura.palmistry" = "aura.palmistry",
|
||||
"aura.chat" = "aura.chat",
|
||||
"aura.moons" = "aura.moons"
|
||||
}
|
||||
|
||||
export enum EGender {
|
||||
"male" = "male",
|
||||
"female" = "female",
|
||||
"other" = "other"
|
||||
}
|
||||
|
||||
enum ERelationshipStatus {
|
||||
"single",
|
||||
"relationship",
|
||||
"married",
|
||||
"complicated",
|
||||
"other"
|
||||
}
|
||||
|
||||
interface ICreateAuthorizeUser {
|
||||
name: string;
|
||||
birthdate: string | null;
|
||||
gender: EGender;
|
||||
birthplace: {
|
||||
address?: string;
|
||||
coords?: string;
|
||||
}
|
||||
relationship_status: ERelationshipStatus;
|
||||
}
|
||||
|
||||
export interface ICreateAuthorizePayload {
|
||||
email: string;
|
||||
locale: string;
|
||||
timezone: string;
|
||||
source: ESourceAuthorization;
|
||||
profile?: Partial<ICreateAuthorizeUser>;
|
||||
partner?: Partial<Exclude<ICreateAuthorizeUser, "relationship_status">>;
|
||||
}
|
||||
|
||||
export interface ICreateAuthorizeResponse {
|
||||
token: string;
|
||||
}
|
||||
|
||||
export const createAuthorizeRequest = (data: ICreateAuthorizePayload): Request => {
|
||||
const body = JSON.stringify(data);
|
||||
return new Request(routes.server.dApiAuth(), {
|
||||
method: "POST",
|
||||
headers: getBaseHeaders(),
|
||||
body,
|
||||
});
|
||||
}
|
||||
@ -318,6 +318,9 @@ function App(): JSX.Element {
|
||||
no: routes.client.epeGender(),
|
||||
force: routes.client.epeBirthdate(),
|
||||
},
|
||||
purchasedProduct: {
|
||||
no: routes.client.epePayment(),
|
||||
},
|
||||
}}
|
||||
requiredParameters={[birthdate, isForceShortPath || gender]}
|
||||
/>
|
||||
@ -487,6 +490,9 @@ function App(): JSX.Element {
|
||||
no: routes.client.advisorChatGender(),
|
||||
force: routes.client.advisorChatBirthdate(),
|
||||
},
|
||||
purchasedProduct: {
|
||||
no: routes.client.advisorChatPayment(),
|
||||
},
|
||||
}}
|
||||
requiredParameters={[
|
||||
birthdate,
|
||||
@ -1075,6 +1081,7 @@ interface IShortPathOutletProps {
|
||||
function ShortPathOutlet(props: IShortPathOutletProps): JSX.Element {
|
||||
const { productKey, requiredParameters, redirectUrls, isProductPage } = props;
|
||||
const { user, token } = useAuth();
|
||||
|
||||
const api = useApi();
|
||||
const isForce = useSelector(selectors.selectIsForceShortPath);
|
||||
|
||||
|
||||
@ -4,18 +4,17 @@ import { useNavigate, useParams } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { actions, selectors } from "@/store";
|
||||
import { getClientTimezone } from "@/locales";
|
||||
import { useAuth } from "@/auth";
|
||||
import { useApi, ApiError, extractErrorMessage } from "@/api";
|
||||
import { useApi } from "@/api";
|
||||
import Title from "../Title";
|
||||
import Policy from "../Policy";
|
||||
import EmailInput from "./EmailInput";
|
||||
import MainButton from "../MainButton";
|
||||
import Loader, { LoaderColor } from "../Loader";
|
||||
import ErrorText from "../ErrorText";
|
||||
import routes from "@/routes";
|
||||
import NameInput from "./NameInput";
|
||||
import { ISubscriptionPlan } from "@/api/resources/SubscriptionPlans";
|
||||
import { useAuthentication } from "@/hooks/authentication/use-authentication";
|
||||
import { ESourceAuthorization } from "@/api/resources/User";
|
||||
|
||||
interface IEmailEnterPage {
|
||||
redirectUrl?: string;
|
||||
@ -27,33 +26,23 @@ function EmailEnterPage({
|
||||
isRequiredName = false,
|
||||
}: IEmailEnterPage): JSX.Element {
|
||||
const api = useApi();
|
||||
const { signUp } = useAuth();
|
||||
const { t, i18n } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
const navigate = useNavigate();
|
||||
const [email, setEmail] = useState("");
|
||||
const [name, setName] = useState("");
|
||||
const birthday = useSelector(selectors.selectBirthday);
|
||||
const [isDisabled, setIsDisabled] = useState(true);
|
||||
const [isValidEmail, setIsValidEmail] = useState(false);
|
||||
const [isValidName, setIsValidName] = useState(!isRequiredName);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [isAuth, setIsAuth] = useState(false);
|
||||
const [apiError, setApiError] = useState<ApiError | null>(null);
|
||||
const [error, setError] = useState<boolean>(false);
|
||||
const [subPlans, setSubPlans] = useState<ISubscriptionPlan[]>([]);
|
||||
const activeSubPlanFromStore = useSelector(selectors.selectActiveSubPlan);
|
||||
const [activeSubPlan, setActiveSubPlan] = useState<ISubscriptionPlan | null>(
|
||||
activeSubPlanFromStore
|
||||
);
|
||||
const timezone = getClientTimezone();
|
||||
const locale = i18n.language;
|
||||
const { subPlan } = useParams();
|
||||
const {
|
||||
gender,
|
||||
birthPlace,
|
||||
// flowChoice
|
||||
} = useSelector(selectors.selectQuestionnaire);
|
||||
const { error, isLoading, authorization } = useAuthentication();
|
||||
|
||||
useEffect(() => {
|
||||
if (subPlan) {
|
||||
@ -99,6 +88,13 @@ function EmailEnterPage({
|
||||
};
|
||||
|
||||
const handleValidName = (name: string) => {
|
||||
if (name) {
|
||||
dispatch(
|
||||
actions.user.update({
|
||||
username: name,
|
||||
})
|
||||
);
|
||||
}
|
||||
setName(name);
|
||||
setIsValidName(true);
|
||||
};
|
||||
@ -112,62 +108,27 @@ function EmailEnterPage({
|
||||
}, [isValidEmail, isValidName, email, name]);
|
||||
|
||||
const handleClick = () => {
|
||||
authorization();
|
||||
authorize();
|
||||
};
|
||||
|
||||
const authorization = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const auth = await api.auth({ email, timezone, locale });
|
||||
const {
|
||||
auth: { token, user },
|
||||
} = auth;
|
||||
signUp(token, user);
|
||||
const payload = {
|
||||
user: {
|
||||
profile_attributes: {
|
||||
birthday,
|
||||
gender: gender.length ? gender : "male",
|
||||
full_name: name,
|
||||
// relationship_status: !!flowChoice.length ? flowChoice : null,
|
||||
},
|
||||
birthplace_attributes: { address: birthPlace },
|
||||
},
|
||||
token,
|
||||
};
|
||||
const updatedUser = await api.updateUser(payload).catch((error) => {
|
||||
console.log("Error: ", error);
|
||||
});
|
||||
if (updatedUser?.user) {
|
||||
dispatch(actions.user.update(updatedUser.user));
|
||||
}
|
||||
if (name) {
|
||||
dispatch(
|
||||
actions.user.update({
|
||||
username: name,
|
||||
})
|
||||
);
|
||||
}
|
||||
dispatch(actions.status.update("registred"));
|
||||
dispatch(
|
||||
actions.payment.update({
|
||||
activeSubPlan,
|
||||
})
|
||||
);
|
||||
setIsLoading(false);
|
||||
setIsAuth(true);
|
||||
setTimeout(() => {
|
||||
navigate(redirectUrl);
|
||||
}, 1000);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
if (error instanceof ApiError) {
|
||||
setApiError(error as ApiError);
|
||||
} else {
|
||||
setError(true);
|
||||
}
|
||||
setIsLoading(false);
|
||||
const authorize = async () => {
|
||||
let source = ESourceAuthorization["aura.main"];
|
||||
if (window.location.pathname.includes("advisor-chat")) {
|
||||
source = ESourceAuthorization["aura.chat"];
|
||||
}
|
||||
if (window.location.pathname.includes("/epe/")) {
|
||||
source = ESourceAuthorization["aura.moons"];
|
||||
}
|
||||
await authorization(email, source);
|
||||
dispatch(
|
||||
actions.payment.update({
|
||||
activeSubPlan,
|
||||
})
|
||||
);
|
||||
setIsAuth(true);
|
||||
setTimeout(() => {
|
||||
navigate(redirectUrl);
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -220,9 +181,9 @@ function EmailEnterPage({
|
||||
>
|
||||
{isLoading && <Loader color={LoaderColor.White} />}
|
||||
{!isLoading &&
|
||||
!(!apiError && !error && !isLoading && isAuth) &&
|
||||
!(!error?.length && !isLoading && isAuth) &&
|
||||
t("_continue")}
|
||||
{!apiError && !error && !isLoading && isAuth && (
|
||||
{!error?.length && !isLoading && isAuth && (
|
||||
<img
|
||||
className={styles["success-icon"]}
|
||||
src="/SuccessIcon.png"
|
||||
@ -230,18 +191,11 @@ function EmailEnterPage({
|
||||
/>
|
||||
)}
|
||||
</MainButton>
|
||||
{(error || apiError) && (
|
||||
{!!error?.length && (
|
||||
<Title variant="h3" style={{ color: "red", margin: 0 }}>
|
||||
Something went wrong
|
||||
</Title>
|
||||
)}
|
||||
{apiError && (
|
||||
<ErrorText
|
||||
size="medium"
|
||||
isShown={Boolean(apiError)}
|
||||
message={apiError ? extractErrorMessage(apiError) : null}
|
||||
/>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,38 +1,27 @@
|
||||
import React from 'react';
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useDispatch } from "react-redux";
|
||||
|
||||
import { PatchPayload } from "@/api/resources/User";
|
||||
import { Step } from '@/hooks/palmistry/use-steps';
|
||||
import { useAuth } from "@/auth";
|
||||
import { useApi, ApiError, extractErrorMessage } from "@/api";
|
||||
import useSteps from '@/hooks/palmistry/use-steps';
|
||||
import Button from '@/components/palmistry/button/button';
|
||||
import Input from '@/components/palmistry/input/input';
|
||||
import { getClientTimezone } from "@/locales";
|
||||
import useSteps from "@/hooks/palmistry/use-steps";
|
||||
import Button from "@/components/palmistry/button/button";
|
||||
import Input from "@/components/palmistry/input/input";
|
||||
import { actions } from "@/store";
|
||||
import Title from "@/components/Title";
|
||||
import ErrorText from "@/components/ErrorText";
|
||||
import Loader, { LoaderColor } from "@/components/Loader";
|
||||
import { useAuthentication } from "@/hooks/authentication/use-authentication";
|
||||
import { ESourceAuthorization } from "@/api/resources/User";
|
||||
|
||||
const emailRegex = /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/;
|
||||
|
||||
export default function StepEmail() {
|
||||
const api = useApi();
|
||||
const { signUp } = useAuth();
|
||||
const { t, i18n } = useTranslation();
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const steps = useSteps();
|
||||
|
||||
const [email, setEmail] = React.useState(steps.storedValue);
|
||||
const [emailIsValid, setEmailIsValid] = React.useState(false);
|
||||
const [isLoading, setIsLoading] = React.useState(false);
|
||||
const [isAuth, setIsAuth] = React.useState(false);
|
||||
const [apiError, setApiError] = React.useState<ApiError | null>(null);
|
||||
const [error, setError] = React.useState<boolean>(false);
|
||||
const timezone = getClientTimezone();
|
||||
const locale = i18n.language;
|
||||
const { error, isLoading, authorization } = useAuthentication();
|
||||
|
||||
const onChangeEmail = (value: string) => {
|
||||
setEmail(value);
|
||||
@ -49,51 +38,16 @@ export default function StepEmail() {
|
||||
if (emailIsValid) {
|
||||
dispatch(actions.form.addEmail(email));
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [email]);
|
||||
|
||||
const authorization = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const auth = await api.auth({ email, timezone, locale });
|
||||
const { auth: { token, user } } = auth;
|
||||
|
||||
signUp(token, user);
|
||||
const payload: PatchPayload = {
|
||||
user: {
|
||||
profile_attributes: {
|
||||
birthday: steps.getStoredValue(Step.Birthdate),
|
||||
gender: steps.getStoredValue(Step.Gender),
|
||||
},
|
||||
},
|
||||
token,
|
||||
};
|
||||
|
||||
const relationshipStatus = steps.getStoredValue(Step.RelationshipStatus);
|
||||
if (relationshipStatus) {
|
||||
payload.user.profile_attributes!.relationship_status = relationshipStatus;
|
||||
}
|
||||
|
||||
const updatedUser = await api.updateUser(payload).catch((error) => console.log("Error: ", error));
|
||||
|
||||
if (updatedUser?.user) dispatch(actions.user.update(updatedUser.user));
|
||||
|
||||
dispatch(actions.status.update("registred"));
|
||||
|
||||
setIsLoading(false);
|
||||
setIsAuth(true);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
if (error instanceof ApiError) {
|
||||
setApiError(error as ApiError);
|
||||
} else {
|
||||
setError(true);
|
||||
}
|
||||
setIsLoading(false);
|
||||
}
|
||||
const authorize = async () => {
|
||||
await authorization(email, ESourceAuthorization["aura.palmistry"]);
|
||||
setIsAuth(true);
|
||||
};
|
||||
|
||||
const onNext = async () => {
|
||||
await authorization();
|
||||
await authorize();
|
||||
steps.saveCurrent(email);
|
||||
steps.goNext();
|
||||
};
|
||||
@ -101,7 +55,9 @@ export default function StepEmail() {
|
||||
return (
|
||||
<>
|
||||
<div className="palmistry-container__title-wrapper">
|
||||
<h2>Enter your email to get your advanced Palmistry reading with AURA</h2>
|
||||
<h2>
|
||||
Enter your email to get your advanced Palmistry reading with AURA
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<Input
|
||||
@ -119,12 +75,20 @@ export default function StepEmail() {
|
||||
|
||||
<div className="palmistry-container__policy">
|
||||
<p>
|
||||
By clicking "Continue" below you agree to AURA{' '}
|
||||
<a href="https://aura.wit.life/terms" target="_blank" rel="noreferrer nofollow">
|
||||
By clicking "Continue" below you agree to AURA{" "}
|
||||
<a
|
||||
href="https://aura.wit.life/terms"
|
||||
target="_blank"
|
||||
rel="noreferrer nofollow"
|
||||
>
|
||||
EULA
|
||||
</a>{' '}
|
||||
and{' '}
|
||||
<a href="https://aura.wit.life/privacy" target="_blank" rel="noreferrer nofollow">
|
||||
</a>{" "}
|
||||
and{" "}
|
||||
<a
|
||||
href="https://aura.wit.life/privacy"
|
||||
target="_blank"
|
||||
rel="noreferrer nofollow"
|
||||
>
|
||||
Privacy Policy
|
||||
</a>
|
||||
.
|
||||
@ -140,9 +104,11 @@ export default function StepEmail() {
|
||||
>
|
||||
{isLoading && <Loader color={LoaderColor.White} />}
|
||||
|
||||
{!isLoading && !(!apiError && !error && !isLoading && isAuth) && t("_continue")}
|
||||
{!isLoading &&
|
||||
!(!error?.length && !isLoading && isAuth) &&
|
||||
t("_continue")}
|
||||
|
||||
{!apiError && !error && !isLoading && isAuth && (
|
||||
{!error?.length && !isLoading && isAuth && (
|
||||
<img
|
||||
style={{ height: "30px", width: "auto" }}
|
||||
src="/SuccessIcon.png"
|
||||
@ -153,19 +119,11 @@ export default function StepEmail() {
|
||||
|
||||
{isLoading && <Loader color={LoaderColor.White} />}
|
||||
|
||||
{(error || apiError) && (
|
||||
{error?.length && (
|
||||
<Title variant="h3" style={{ color: "red", margin: 0 }}>
|
||||
Something went wrong
|
||||
</Title>
|
||||
)}
|
||||
|
||||
{apiError && (
|
||||
<ErrorText
|
||||
size="medium"
|
||||
isShown={Boolean(apiError)}
|
||||
message={apiError ? extractErrorMessage(apiError) : null}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,10 +1,14 @@
|
||||
import Button from '../button/button';
|
||||
import useSteps, { GenderChoice } from '../../../hooks/palmistry/use-steps';
|
||||
import Button from "../button/button";
|
||||
import useSteps, { GenderChoice } from "../../../hooks/palmistry/use-steps";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { actions } from "@/store";
|
||||
|
||||
export default function StepGender() {
|
||||
const steps = useSteps();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const onNext = (choice: GenderChoice) => {
|
||||
dispatch(actions.questionnaire.update({ gender: choice }));
|
||||
steps.saveCurrent(choice);
|
||||
steps.goNext(choice);
|
||||
};
|
||||
@ -14,7 +18,8 @@ export default function StepGender() {
|
||||
<h3 className="palmistry-container__header">What’s your gender?</h3>
|
||||
|
||||
<p className="palmistry-container__description">
|
||||
In Palmistry, everyone is a blend of masculine and feminine, so it helps to know yours.
|
||||
In Palmistry, everyone is a blend of masculine and feminine, so it helps
|
||||
to know yours.
|
||||
</p>
|
||||
|
||||
<div className="palmistry-container__button-wrapper">
|
||||
|
||||
140
src/hooks/authentication/use-authentication.ts
Normal file
140
src/hooks/authentication/use-authentication.ts
Normal file
@ -0,0 +1,140 @@
|
||||
import { 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 { actions, selectors } from "@/store";
|
||||
import moment from "moment";
|
||||
import { useCallback, useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
|
||||
|
||||
|
||||
export const useAuthentication = () => {
|
||||
const api = useApi();
|
||||
const { i18n } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
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 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).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<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,
|
||||
},
|
||||
}
|
||||
})
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [
|
||||
birthPlace,
|
||||
birthdate,
|
||||
gender,
|
||||
locale,
|
||||
partnerBirthPlace,
|
||||
partnerBirthdate,
|
||||
partnerGender,
|
||||
partnerName,
|
||||
username,
|
||||
birthtime,
|
||||
]);
|
||||
|
||||
const authorization = useCallback(async (email: string, source: ESourceAuthorization) => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const payload = getAuthorizationPayload(email, source);
|
||||
const { token } = await api.authorization(payload);
|
||||
const { user } = await api.getUser({ token });
|
||||
signUp(token, user);
|
||||
setToken(token);
|
||||
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
|
||||
}),
|
||||
[isLoading, error, token, user, authorization]
|
||||
);
|
||||
|
||||
}
|
||||
@ -215,6 +215,7 @@ const routes = {
|
||||
[dApiHost, "payment", "products", `${productKey}?email=${email}`].join(
|
||||
"/"
|
||||
),
|
||||
dApiAuth: () => [dApiHost, "users", "auth"].join("/"),
|
||||
|
||||
assistants: () => [apiHost, prefix, "ai", "assistants.json"].join("/"),
|
||||
setExternalChatIdAssistants: (chatId: string) =>
|
||||
|
||||
22
src/services/filter-object/index.ts
Normal file
22
src/services/filter-object/index.ts
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
|
||||
export function filterNullKeysOfObject<T extends object>(object: T): T {
|
||||
if (typeof object !== "object") {
|
||||
return object
|
||||
}
|
||||
return Object.keys(object)
|
||||
.filter(key => {
|
||||
if (typeof object[key as keyof T] === "object" && object[key as keyof T] !== null) {
|
||||
return Object.keys(object[key as keyof T] as object).length
|
||||
}
|
||||
if (typeof object[key as keyof T] === "string") {
|
||||
return !!(object[key as keyof T] as string).length
|
||||
}
|
||||
return object[key as keyof T] !== null
|
||||
})
|
||||
.reduce((acc, key) => {
|
||||
return Object.assign(acc, {
|
||||
[key]: typeof object[key as keyof T] === "object" ? filterNullKeysOfObject<typeof object>(object[key as keyof object]) : object[key as keyof T]
|
||||
});
|
||||
}, Array.isArray(object) ? [] : {}) as T;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user