Merge branch 'edits' into 'develop'

edits

See merge request witapp/aura-webapp!153
This commit is contained in:
Daniil Chemerkin 2024-06-01 22:39:58 +00:00
commit 8dac39a275
16 changed files with 188 additions and 137 deletions

View File

@ -69,7 +69,7 @@
</head>
<body>
<!-- Yandex.Metrika counter -->
<script type="text/javascript" async="async">
<script type="text/javascript">
(function (m, e, t, r, i, k, a) {
m[i] =
m[i] ||

View File

@ -49,6 +49,8 @@ const api = {
getSubscriptionPlans: createMethod<SubscriptionPlans.Payload, SubscriptionPlans.Response>(SubscriptionPlans.createRequest),
getSubscriptionCheckout: createMethod<SubscriptionCheckout.Payload, SubscriptionCheckout.Response>(SubscriptionCheckout.createRequest),
getSubscriptionStatus: createMethod<SubscriptionStatus.Payload, SubscriptionStatus.Response>(SubscriptionStatus.createRequest),
// new get subscription status
getSubscriptionStatusNew: createMethod<SubscriptionStatus.Payload, SubscriptionStatus.ResponseNew>(SubscriptionStatus.createRequestNew),
getAiCompatCategories: createMethod<AICompatCategories.Payload, AICompatCategories.Response>(AICompatCategories.createRequest),
getAiCompat: createMethod<AICompats.Payload, AICompats.Response>(AICompats.createRequest),
getAiRequest: createMethod<AIRequests.Payload, AIRequests.Response>(AIRequests.createRequest),

View File

@ -14,3 +14,12 @@ export const createRequest = ({ token }: Payload): Request => {
const url = new URL(routes.server.subscriptionStatus())
return new Request(url, { method: 'GET', headers: getAuthHeaders(token) })
}
export interface ResponseNew {
subscription: boolean;
}
export const createRequestNew = ({ token }: Payload): Request => {
const url = new URL(routes.server.subscriptionStatusNew())
return new Request(url, { method: 'GET', headers: getAuthHeaders(token) })
}

View File

@ -222,10 +222,13 @@ function App(): JSX.Element {
token,
});
if (has_subscription && user) {
const { subscription: subscriptionStatusNew } =
await api.getSubscriptionStatusNew({ token });
if ((has_subscription || subscriptionStatusNew) && user) {
return dispatch(actions.status.update("subscribed"));
}
if (!has_subscription && user) {
if (!has_subscription && !subscriptionStatusNew && user) {
return dispatch(actions.status.update("unsubscribed"));
}
if (!user) {

View File

@ -15,4 +15,5 @@
.image {
position: absolute;
bottom: 8px;
z-index: -1;
}

View File

@ -1,6 +1,5 @@
import { IAnswer } from "@/data";
import styles from "./styles.module.css";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { useDispatch, useSelector } from "react-redux";
import { actions, selectors } from "@/store";
@ -20,34 +19,36 @@ function MultiplyAnswers({ answers }: IMultiplyAnswersProps) {
const { currentlyAffecting, gender } = useSelector(
selectors.selectQuestionnaire
);
const [selectedAnswers, setSelectedAnswers] = useState<string[]>(
currentlyAffecting?.split("$") || []
);
const handleClick = (answer: IAnswer) => {
if (selectedAnswers.includes(answer.id)) {
return setSelectedAnswers((prevState) =>
prevState.filter((item) => item !== answer.id)
if (currentlyAffecting.includes(`$${answer.id}`)) {
return dispatch(
actions.questionnaire.update({
currentlyAffecting: currentlyAffecting.replace(`$${answer.id}`, ""),
})
);
}
if (answer.id === "none_of_these") {
return setSelectedAnswers([answer.id]);
return dispatch(
actions.questionnaire.update({
currentlyAffecting: `$${answer.id}`,
})
);
}
if (
selectedAnswers.includes("none_of_these") &&
currentlyAffecting.includes("$none_of_these") &&
answer.id !== "none_of_these"
) {
return;
}
return setSelectedAnswers((prevState) => [...prevState, answer.id]);
return dispatch(
actions.questionnaire.update({
currentlyAffecting: `${currentlyAffecting}$${answer.id}`,
})
);
};
const handleNext = () => {
dispatch(
actions.questionnaire.update({
currentlyAffecting: selectedAnswers.join("$"),
})
);
navigate(
`${routes.client.questionnaireV1()}/relationships/partnerPriority`
);
@ -55,30 +56,35 @@ function MultiplyAnswers({ answers }: IMultiplyAnswersProps) {
return (
<>
{answers.map((answer, index) => (
<Answer
key={index}
answer={answer}
disabled={
selectedAnswers.includes("none_of_these") &&
answer.id !== "none_of_these"
}
classNameContainer={
selectedAnswers.includes(answer.id) ? styles["answer-active"] : ""
}
type="multiply"
active={selectedAnswers.includes(answer.id)}
gender={gender}
onClick={() => handleClick(answer)}
/>
))}
<QuestionnaireGreenButton
className={styles.button}
onClick={handleNext}
disabled={!selectedAnswers.length}
>
{t("next")}
</QuestionnaireGreenButton>
<div className={styles["multiply-answers"]}>
{answers.map((answer, index) => (
<Answer
key={index}
answer={answer}
disabled={
currentlyAffecting.includes("$none_of_these") &&
answer.id !== "none_of_these"
}
classNameContainer={
currentlyAffecting.includes(`${answer.id}`)
? styles["answer-active"]
: ""
}
type="multiply"
active={currentlyAffecting.includes(`${answer.id}`)}
gender={gender}
onClick={() => handleClick(answer)}
/>
))}
</div>
{!!currentlyAffecting.length && (
<QuestionnaireGreenButton
className={styles.button}
onClick={handleNext}
>
{t("next")}
</QuestionnaireGreenButton>
)}
</>
);
}

View File

@ -1,4 +1,19 @@
.multiply-answers {
display: flex;
flex-direction: column;
align-items: center;
gap: 11px;
z-index: 0;
padding-bottom: 116px;
width: 100%;
}
.button {
position: fixed;
bottom: calc(0dvh + 16px);
width: calc(100% - 64px);
max-width: 396px;
margin-top: 8px;
}

View File

@ -49,6 +49,7 @@
align-items: center;
gap: 11px;
margin-top: 28px;
z-index: 0;
}
.description {

View File

@ -54,7 +54,11 @@ function OnboardingPage() {
return (
<section className={`${styles.page} page`}>
<img className={styles.image} src="/leo.png" alt="Leo" />
<img
className={`${styles.image} ${styles[periodClassName]}`}
src="/leo.png"
alt="Leo"
/>
{onboardingTitles[activeIndexTitle] && (
<Title className={`${styles.title} ${styles[periodClassName]}`}>
{onboardingTitles[activeIndexTitle]}

View File

@ -16,6 +16,7 @@
margin-top: 100px;
width: 100%;
max-width: 273px;
transition: opacity 1s;
}
.title {

View File

@ -20,15 +20,17 @@
}
.image-container {
display: flex;
justify-content: center;
display: grid;
align-items: center;
justify-items: center;
grid-template-columns: calc(50% - 30px) min-content calc(50% - 30px);
width: 100%;
gap: 32px;
gap: 6px;
}
.image-container > img {
max-width: 118px;
/* max-width: 118px; */
max-height: 196px;
}
.compatibility-description-container {

View File

@ -18,7 +18,7 @@
border-top-left-radius: 15px;
border-top-right-radius: 15px;
display: grid;
grid-template-columns: 1fr min-content 1fr;
grid-template-columns: calc(50% - 28px) min-content calc(50% - 28px);
align-items: center;
gap: 4px;
padding-top: 10px;
@ -35,6 +35,8 @@
.image-container > img {
height: 196px;
width: 100%;
object-fit: contain;
}
.image-container > p {

View File

@ -10,9 +10,7 @@ import { SinglePayment, useApi, useApiCall } from "@/api";
import { useSelector } from "react-redux";
import { selectors } from "@/store";
import { useCallback, useState } from "react";
import {
ResponsePost,
} from "@/api/resources/SinglePayment";
import { ResponsePost } from "@/api/resources/SinglePayment";
import { createSinglePayment } from "@/services/singlePayment";
import Modal from "@/components/Modal";
import PaymentForm from "@/components/pages/SinglePaymentPage/PaymentForm";
@ -25,9 +23,7 @@ function AddConsultationPage() {
const api = useApi();
const tokenFromStore = useSelector(selectors.selectToken);
const [isLoading, setIsLoading] = useState(false);
const [paymentIntent, setPaymentIntent] = useState<
ResponsePost | null
>(null);
const [paymentIntent, setPaymentIntent] = useState<ResponsePost | null>(null);
const [isError, setIsError] = useState(false);
const returnUrl = `${window.location.protocol}//${
window.location.host
@ -45,29 +41,34 @@ function AddConsultationPage() {
);
const handleClick = async () => {
if (!userFromStore || !currentProduct) return;
setIsLoading(true);
const { _id, key } = currentProduct;
const paymentInfo = {
productId: _id,
key,
};
const paymentIntent = await createSinglePayment(
userFromStore,
paymentInfo,
tokenFromStore,
userFromStore.email,
userFromStore.profile.full_name,
userFromStore.profile.birthday,
returnUrl,
api
);
setPaymentIntent(paymentIntent);
setIsLoading(false);
if ("payment" in paymentIntent) {
if (paymentIntent.payment.status === "paid")
return navigate(routes.client.getInformationPartner());
return setIsError(true);
try {
if (!userFromStore || !currentProduct) return;
setIsLoading(true);
const { _id, key } = currentProduct;
const paymentInfo = {
productId: _id,
key,
};
const paymentIntent = await createSinglePayment(
userFromStore,
paymentInfo,
tokenFromStore,
userFromStore.email,
userFromStore.profile.full_name,
userFromStore.profile.birthday,
returnUrl,
api
);
setPaymentIntent(paymentIntent);
if ("payment" in paymentIntent) {
if (paymentIntent.payment.status === "paid")
return navigate(routes.client.getInformationPartner());
return setIsError(true);
}
} catch (error) {
setIsError(true);
} finally {
setIsLoading(false);
}
};

View File

@ -9,9 +9,7 @@ import FooterButton from "../../components/FooterButton";
import routes from "@/routes";
import PaymentAddress from "../../components/PaymentAddress";
import { createSinglePayment } from "@/services/singlePayment";
import {
ResponsePost,
} from "@/api/resources/SinglePayment";
import { ResponsePost } from "@/api/resources/SinglePayment";
import { useAuth } from "@/auth";
import { useSelector } from "react-redux";
import { selectors } from "@/store";
@ -26,9 +24,7 @@ function AddReportPage() {
const { user: userFromStore } = useAuth();
const api = useApi();
const tokenFromStore = useSelector(selectors.selectToken);
const [paymentIntent, setPaymentIntent] = useState<
ResponsePost | null
>(null);
const [paymentIntent, setPaymentIntent] = useState<ResponsePost | null>(null);
const [isLoading, setIsLoading] = useState(false);
const [isError, setIsError] = useState(false);
const [activeOffer, setActiveOffer] = useState(signUpOffers[0]);
@ -48,31 +44,36 @@ function AddReportPage() {
};
const handleClick = async () => {
if (!userFromStore || !activeOffer) return;
const currentProduct = getCurrentProduct(activeOffer?.productKey);
if (!currentProduct) return;
setIsLoading(true);
const { _id, key } = currentProduct;
const paymentInfo = {
productId: _id,
key,
};
const paymentIntent = await createSinglePayment(
userFromStore,
paymentInfo,
tokenFromStore,
userFromStore.email,
userFromStore.profile.full_name,
userFromStore.profile.birthday,
returnUrl,
api
);
setPaymentIntent(paymentIntent);
setIsLoading(false);
if ("payment" in paymentIntent) {
if (paymentIntent.payment.status === "paid")
return navigate(routes.client.unlimitedReadings());
return setIsError(true);
try {
if (!userFromStore || !activeOffer) return;
const currentProduct = getCurrentProduct(activeOffer?.productKey);
if (!currentProduct) return;
setIsLoading(true);
const { _id, key } = currentProduct;
const paymentInfo = {
productId: _id,
key,
};
const paymentIntent = await createSinglePayment(
userFromStore,
paymentInfo,
tokenFromStore,
userFromStore.email,
userFromStore.profile.full_name,
userFromStore.profile.birthday,
returnUrl,
api
);
setPaymentIntent(paymentIntent);
if ("payment" in paymentIntent) {
if (paymentIntent.payment.status === "paid")
return navigate(routes.client.unlimitedReadings());
return setIsError(true);
}
} catch (error) {
setIsError(true);
} finally {
setIsLoading(false);
}
};

View File

@ -16,9 +16,7 @@ import { selectors } from "@/store";
import { useCallback, useState } from "react";
import { createSinglePayment } from "@/services/singlePayment";
import Loader, { LoaderColor } from "@/components/Loader";
import {
ResponsePost,
} from "@/api/resources/SinglePayment";
import { ResponsePost } from "@/api/resources/SinglePayment";
import Modal from "@/components/Modal";
import { getPriceCentsToDollars } from "@/services/price";
import PaymentForm from "@/components/pages/SinglePaymentPage/PaymentForm";
@ -40,9 +38,7 @@ function UnlimitedReadingsPage() {
const api = useApi();
const tokenFromStore = useSelector(selectors.selectToken);
const [isLoading, setIsLoading] = useState(false);
const [paymentIntent, setPaymentIntent] = useState<
ResponsePost | null
>(null);
const [paymentIntent, setPaymentIntent] = useState<ResponsePost | null>(null);
const [isError, setIsError] = useState(false);
const returnUrl = `${window.location.protocol}//${
window.location.host
@ -60,29 +56,34 @@ function UnlimitedReadingsPage() {
);
const handleClick = async () => {
if (!userFromStore || !currentProduct) return;
setIsLoading(true);
const { _id, key } = currentProduct;
const paymentInfo = {
productId: _id,
key,
};
const paymentIntent = await createSinglePayment(
userFromStore,
paymentInfo,
tokenFromStore,
userFromStore.email,
userFromStore.profile.full_name,
userFromStore.profile.birthday,
returnUrl,
api
);
setPaymentIntent(paymentIntent);
setIsLoading(false);
if ("payment" in paymentIntent) {
if (paymentIntent.payment.status === "paid")
return navigate(routes.client.addConsultation());
return setIsError(true);
try {
if (!userFromStore || !currentProduct) return;
setIsLoading(true);
const { _id, key } = currentProduct;
const paymentInfo = {
productId: _id,
key,
};
const paymentIntent = await createSinglePayment(
userFromStore,
paymentInfo,
tokenFromStore,
userFromStore.email,
userFromStore.profile.full_name,
userFromStore.profile.birthday,
returnUrl,
api
);
setPaymentIntent(paymentIntent);
if ("payment" in paymentIntent) {
if (paymentIntent.payment.status === "paid")
return navigate(routes.client.addConsultation());
return setIsError(true);
}
} catch (error) {
setIsError(true);
} finally {
setIsLoading(false);
}
};

View File

@ -225,6 +225,8 @@ const routes = {
[apiHost, prefix, "user", "subscription_receipts", "status.json"].join(
"/"
),
subscriptionStatusNew: () =>
[dApiHost, "users", "subscription", "status"].join("/"),
subscriptionReceipts: () =>
[apiHost, prefix, "user", "subscription_receipts.json"].join("/"),
subscriptionReceipt: (id: string) =>