Preview/discount pages

This commit is contained in:
Денис Катаев 2024-02-11 05:44:06 +00:00 committed by Victor Ershov
parent b1db7b943c
commit fae4569c4f
11 changed files with 121 additions and 73 deletions

5
public/address.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 48 KiB

3
public/lock.svg Normal file
View File

@ -0,0 +1,3 @@
<svg width="492" height="639" viewBox="0 0 492 639" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M430.091 191.886H399.412V159.952C399.412 71.9116 330.591 0.284637 246.001 0.284637C161.41 0.284637 92.5915 71.9116 92.5915 159.952V191.886H61.9097C45.6348 191.886 30.0266 198.615 18.5186 210.592C7.01117 222.569 0.545624 238.814 0.545624 255.753V575.088C0.545624 592.029 7.01117 608.274 18.5186 620.249C30.0266 632.224 45.6348 638.955 61.9097 638.955H430.091C446.366 638.955 461.977 632.224 473.485 620.249C484.993 608.274 491.455 592.029 491.455 575.088V255.753C491.455 238.814 484.993 222.569 473.485 210.592C461.977 198.615 446.366 191.886 430.091 191.886ZM153.958 159.952C153.958 107.134 195.255 64.1519 246.001 64.1519C296.746 64.1519 338.049 107.134 338.049 159.952V191.886H153.958V159.952ZM276.685 438.511V511.222H215.321V438.511C197.061 427.458 184.637 407.086 184.637 383.488C184.637 366.548 191.105 350.303 202.613 338.328C214.121 326.347 229.726 319.622 246.001 319.622C262.275 319.622 277.886 326.347 289.394 338.328C300.902 350.303 307.364 366.548 307.364 383.488C307.364 407.054 294.94 427.426 276.685 438.511Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -1,4 +1,7 @@
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.7071 12.7071C12.3166 13.0976 11.6834 13.0976 11.2929 12.7071L6.29289 7.70711C5.90237 7.31658 5.90237 6.68342 6.29289 6.29289L11.2929 1.29289C11.6834 0.902369 12.3166 0.902369 12.7071 1.29289C13.0976 1.68342 13.0976 2.31658 12.7071 2.70711L8.41421 7L12.7071 11.2929C13.0976 11.6834 13.0976 12.3166 12.7071 12.7071Z" fill="#858DA5" stroke="#858DA5" stroke-linecap="round" stroke-linejoin="round"></path>
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.29289 12.7071C1.68342 13.0976 2.31658 13.0976 2.70711 12.7071L7.70711 7.70711C8.09763 7.31658 8.09763 6.68342 7.70711 6.29289L2.70711 1.29289C2.31658 0.902369 1.68342 0.902369 1.29289 1.29289C0.902369 1.68342 0.902369 2.31658 1.29289 2.70711L5.58579 7L1.29289 11.2929C0.902369 11.6834 0.902369 12.3166 1.29289 12.7071Z" fill="#858DA5" stroke="#858DA5" stroke-linecap="round" stroke-linejoin="round"></path>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" fill="#2f2e37" width="16" height="16" viewBox="0 0 24 24" role="button"
title="close" class="sc-89953eaa-5 dupDFT">
<title>cross</title>
<path
d="M10.051 12l-10.051 10.051 1.949 1.949 10.051-10.051 10.051 10.051 1.949-1.949-10.051-10.051 10.051-10.051-1.949-1.949-10.051 10.051-10.051-10.051-1.949 1.949 10.051 10.051z">
</path>
</svg>

Before

Width:  |  Height:  |  Size: 1021 B

After

Width:  |  Height:  |  Size: 387 B

View File

@ -1,5 +1,5 @@
.modal {
background: rgba(85,84,85,.8);
background: rgba(85, 84, 85, 0.8);
height: 100dvh;
position: fixed;
left: 0;
@ -24,7 +24,7 @@
z-index: 3;
border-radius: 16px;
padding: 64px 24px 16px;
transform: translate(-50%,-50%);
transform: translate(-50%, -50%);
}
.modal-content::-webkit-scrollbar {
@ -38,16 +38,16 @@
align-items: center;
border: none;
border-radius: 20px;
height: 32px;
height: 20px;
aspect-ratio: 1 / 1;
padding: 0;
right: 20px;
left: 15px;
top: 16px;
width: 32px;
cursor: pointer;
background-color: #eff2fd;
background-image: url(./close.svg);
background-repeat: no-repeat;
background-position: center;
background-color: transparent;
background-image: url(./close.svg);
}
.modal .main-btn {

View File

@ -10,6 +10,7 @@ import {
import { useState } from "react";
import { useDispatch } from "react-redux";
import { useNavigate } from "react-router-dom";
import styles from "./styles.module.css";
interface ICheckoutFormProps {
children?: JSX.Element | null;
@ -71,14 +72,18 @@ export default function CheckoutForm({
color="blue"
disabled={isProcessing || !formReady}
id="submit"
className={styles.button}
>
<img src="/lock.svg" alt="Secure" />
<span id="button-text">
{isProcessing ? "Processing..." : "Pay now"}
{isProcessing ? "Processing..." : "Start"}
</span>
</MainButton>
<Title variant="h5" style={{ color: "red" }}>
{message}
</Title>
{!!message.length && (
<Title variant="h5" style={{ color: "red" }}>
{message}
</Title>
)}
</form>
);
}

View File

@ -36,3 +36,18 @@
font-weight: 500;
margin: 0;
}
.button {
min-height: 0;
height: 50px;
text-transform: uppercase;
background-color: #4caf50;
border-radius: 25px;
font-size: 16px;
gap: 8px;
}
.button > img {
height: 18px;
margin-top: -5px;
}

View File

@ -70,9 +70,14 @@ function ApplePayButton({
if (stripeError) {
// Show error to your customer (e.g., insufficient funds)
navigate(
`${routes.client.paymentResult()}/${subscriptionReceiptId}/?redirect_status=failed`
);
return e.complete("fail");
}
navigate(`${routes.client.paymentResult()}/${subscriptionReceiptId}/`);
navigate(
`${routes.client.paymentResult()}/${subscriptionReceiptId}/?redirect_status=succeeded`
);
e.complete("success");
// Show a success message to your customer
// There's a risk of the customer closing the window before callback

View File

@ -14,7 +14,12 @@ function PayPalButton({ isLoading, handlePayPalButton }: IPayPalButton) {
className={styles["pay-pal-button"]}
onClick={handlePayPalButton}
>
{!isLoading && <img src="/paypal-logo.svg" alt="PayPal Button" />}
{!isLoading && (
<div className={styles.content}>
<img src="/paypal-logo.svg" alt="PayPal Button" />
<p>Buy Now</p>
</div>
)}
{isLoading && <Loader />}
</MainButton>
);

View File

@ -1,9 +1,22 @@
.pay-pal-button {
width: 100%;
height: 60px;
height: 50px;
display: flex;
align-items: center;
justify-content: center;
background-color: #ffc43a;
border-radius: 7px;
}
.content {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
.content > p {
margin-top: 6px;
font-size: 18px;
color: #2f2e37;
}

View File

@ -7,8 +7,8 @@ import { Elements } from "@stripe/react-stripe-js";
import ApplePayButton from "@/components/StripePage/ApplePayButton";
import CheckoutForm from "@/components/PaymentPage/methods/Stripe/CheckoutForm";
import { Stripe, loadStripe } from "@stripe/stripe-js";
import { useDispatch, useSelector } from "react-redux";
import { actions, selectors } from "@/store";
import { useSelector } from "react-redux";
import { selectors } from "@/store";
import { ISubscriptionPlan } from "@/api/resources/SubscriptionPlans";
import { useApi } from "@/api";
import { useNavigate } from "react-router-dom";
@ -26,12 +26,8 @@ function PaymentModal() {
const api = useApi();
const { token } = useAuth();
const navigate = useNavigate();
const dispatch = useDispatch();
const activeSubPlan = useSelector(selectors.selectActiveSubPlan);
const [payPalSubPlan, setPayPalSubPlan] = useState<ISubscriptionPlan>();
const subscriptionReceiptFromStore = useSelector(
selectors.selectSubscriptionReceipt
);
const [stripePromise, setStripePromise] =
useState<Promise<Stripe | null> | null>(null);
const [clientSecret, setClientSecret] = useState<string>("");
@ -40,11 +36,11 @@ function PaymentModal() {
const [subPlans, setSubPlans] = useState<ISubscriptionPlan[] | null>(null);
const [isLoading, setIsLoading] = useState(true);
const [isLoadingPayPal, setIsLoadingPayPal] = useState(false);
const [isError, setIsError] = useState(false);
const [errors, setErrors] = useState<string>("");
const [isError, setIsError] = useState<boolean>(false);
const [selectedPaymentMethod, setSelectedPaymentMethod] = useState(
EPaymentMethod.CREDIT_CARD
EPaymentMethod.PAYPAL_OR_APPLE_PAY
);
const onSelectPaymentMethod = (method: EPaymentMethod) => {
@ -76,47 +72,17 @@ function PaymentModal() {
sub_plan_id: activeSubPlan?.id || "stripe.7",
},
});
if (!subscription_receipt && !subscriptionReceiptFromStore) {
setIsError(true);
setIsLoading(false);
} else if (!subscription_receipt && subscriptionReceiptFromStore) {
const { id } = subscriptionReceiptFromStore;
const { client_secret } = subscriptionReceiptFromStore.data;
setSubscriptionReceiptId(id);
setClientSecret(client_secret);
setIsLoading(false);
} else if (subscription_receipt) {
dispatch(
actions.payment.update({
subscriptionReceipt: subscription_receipt,
})
);
const { id } = subscription_receipt;
const { client_secret } = subscription_receipt.data;
setSubscriptionReceiptId(id);
setClientSecret(client_secret);
setIsLoading(false);
}
console.log(subscription_receipt);
const { id } = subscription_receipt;
const { client_secret } = subscription_receipt.data;
setSubscriptionReceiptId(id);
setClientSecret(client_secret);
setIsLoading(false);
} catch (error) {
if (subscriptionReceiptFromStore) {
console.log(1);
const { id } = subscriptionReceiptFromStore;
const { client_secret } = subscriptionReceiptFromStore.data;
setSubscriptionReceiptId(id);
setClientSecret(client_secret);
setIsLoading(false);
return;
} else {
setIsError(true);
setIsLoading(false);
}
console.log(error);
console.error(error);
setIsError(true);
}
})();
}, [activeSubPlan?.id, api, dispatch, subscriptionReceiptFromStore, token]);
}, [activeSubPlan?.id, api, token]);
useEffect(() => {
if (!subPlans) return;
@ -191,18 +157,26 @@ function PaymentModal() {
onSelectPaymentMethod={onSelectPaymentMethod}
/>
{activeSubPlan && (
<p className={styles["sub-plan-description"]}>
You will be charged only{" "}
<b>
${getPriceFromTrial(activeSubPlan?.trial)} for your 3-day trial.
</b>
</p>
<div>
<p className={styles["sub-plan-description"]}>
You will be charged only{" "}
<b>
${getPriceFromTrial(activeSubPlan?.trial)} for your 3-day trial.
</b>
</p>
<p className={styles["sub-plan-description"]}>
We`ll <b>email you a reminder</b> before your trial period ends.
</p>
<p className={styles["sub-plan-description"]}>
Cancel anytime. The charge will appear on your bill as witapps.
</p>
</div>
)}
<div className={styles["payment-method-container"]}>
{stripePromise && clientSecret && subscriptionReceiptId && (
<Elements stripe={stripePromise} options={{ clientSecret }}>
{selectedPaymentMethod === EPaymentMethod.PAYPAL_OR_APPLE_PAY && (
<>
<div className={styles["payment-method"]}>
<ApplePayButton
activeSubPlan={activeSubPlan}
client_secret={clientSecret}
@ -215,7 +189,7 @@ function PaymentModal() {
/>
)}
{!!errors.length && <p className={styles.errors}>{errors}</p>}
</>
</div>
)}
{selectedPaymentMethod === EPaymentMethod.CREDIT_CARD && (
@ -225,6 +199,7 @@ function PaymentModal() {
)}
</div>
<SecurityPayments />
<p className={styles.address}>500 N RAINBOW BLVD LAS VEGAS, NV 89107</p>
</div>
);
}

View File

@ -5,10 +5,11 @@
justify-content: center;
min-height: 250px;
gap: 25px;
color: #2f2e37;
}
.title {
font-weight: 800;
font-weight: 700;
font-size: 20px;
line-height: 20px;
text-align: center;
@ -18,8 +19,26 @@
.sub-plan-description {
font-size: 12px;
text-align: center;
line-height: 150%;
}
.payment-method-container {
width: 100%;
}
.address {
margin-bottom: 24px;
}
.payment-method {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 16px;
}
.address {
color: gray;
font-size: 10px;
}