diff --git a/src/components/UserSubscription/ProcessedPayment.jsx b/src/components/UserSubscription/ProcessedPayment.jsx index 247b68e9..c671301c 100644 --- a/src/components/UserSubscription/ProcessedPayment.jsx +++ b/src/components/UserSubscription/ProcessedPayment.jsx @@ -2,16 +2,19 @@ import React, { useState, useMemo, useEffect } from "react"; import { useSubscription } from "../../hooks/useAuth"; import { useParams } from "react-router-dom"; import { useCreateTenant, useIndustries } from "../../hooks/useTenant"; - +import { + formatCurrency, + formatFigure, + frequencyLabel, +} from "../../utils/appUtils"; import { formatUTCToLocalTime } from "../../utils/dateUtils"; import { PaymentRepository } from "../../repositories/PaymentRepository"; import { useDispatch, useSelector } from "react-redux"; import { setSelfTenant } from "../../slices/localVariablesSlice"; import { unblockUI } from "../../utils/blockUI"; import showToast from "../../services/toastService"; +import SelectedPlanSkeleton from "./SelectedPlaneSkeleton"; import { useMakePayment } from "../../hooks/usePayments"; -import SelectedPlaneSkeleton from "./SelectedPlaneSkeleton"; -import { formatFigure, frequencyLabel } from "../../utils/appUtils"; const ProcessedPayment = ({ onNext, @@ -35,6 +38,9 @@ const ProcessedPayment = ({ data: plans, isError: isPlanError, isLoading, + isError, + isRefetching, + refetch, } = useSubscription(frequency); useEffect(() => { if (!plans || !selectedPlanId) return; @@ -74,11 +80,11 @@ const ProcessedPayment = ({ alert("Failed to load Razorpay SDK"); return; } - const payload = { - amount: { amount: selectedPlan?.price }, - currencyCode: selectedPlan?.currency?.currencyCode, - }; - MakePayment(payload); + let price = 0; + price = + frequencyLabel(selectedPlan?.frequency, true, true)?.planDurationInInt * + selectedPlan?.price; + MakePayment({ amount: price }); }; const handleRetry = () => { @@ -144,7 +150,7 @@ const ProcessedPayment = ({ ); } return ( -
+
@@ -155,9 +161,33 @@ const ProcessedPayment = ({ and help you maximize productivity.

- + {isError && ( +
+

{error?.message}

+ {error?.name} + + {isRefetching ? ( + <> + {" "} + Retrying... + + ) : ( + "Try to refetch" + )} + +
+ )} {isLoading ? ( - + ) : ( <> {selectedPlan && ( @@ -165,21 +195,27 @@ const ProcessedPayment = ({
- {selectedPlan?.planName} + {selectedPlan?.description}
- - {selectedPlan?.currency?.symbol} {selectedPlan?.price}{" "} - /{frequencyLabel(frequency, false)} + + Price -{" "} + + {selectedPlan.currency?.symbol} {selectedPlan.price}{" "} + per {frequencyLabel(frequency)} +
- - {selectedPlan?.description} - +
+ {selectedPlan?.planName} + + billed {frequencyLabel(frequency, true)} + +
)} @@ -284,11 +320,18 @@ const ProcessedPayment = ({
Total Price
- {formatFigure(selectedPlan?.price, { - type: "currency", - currency: - selectedPlan?.currency.currencyCode, - })} + {formatFigure( + frequencyLabel( + selectedPlan?.frequency, + true, + true + )?.planDurationInInt * price, + { + type: "currency", + currency: + selectedPlan?.currency.currencyCode, + } + )}
@@ -319,7 +362,7 @@ const ProcessedPayment = ({
Email:
-
{client.email}
+
{client.email}
Contact Number: @@ -352,20 +395,29 @@ const ProcessedPayment = ({ )}
-
+
+
diff --git a/src/components/UserSubscription/Review.jsx b/src/components/UserSubscription/Review.jsx new file mode 100644 index 00000000..a7c6ccd4 --- /dev/null +++ b/src/components/UserSubscription/Review.jsx @@ -0,0 +1,11 @@ +import React from 'react' + +const Review = () => { + return ( +
+ +
+ ) +} + +export default Review diff --git a/src/components/UserSubscription/SelectPlan.jsx b/src/components/UserSubscription/SelectPlan.jsx index a5d0dd1b..75571680 100644 --- a/src/components/UserSubscription/SelectPlan.jsx +++ b/src/components/UserSubscription/SelectPlan.jsx @@ -4,11 +4,14 @@ import { useParams } from "react-router-dom"; import { useSubscription } from "../../hooks/useAuth"; import { formatFigure, frequencyLabel } from "../../utils/appUtils"; import { setSelfTenant } from "../../slices/localVariablesSlice"; +import { error } from "pdf-lib"; +import { useForm } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { CouponDiscount } from "../../pages/Home/HomeSchema"; import SelectedPlanSkeleton from "./SelectedPlaneSkeleton"; - const SelectPlan = ({ currentStep, setStepStatus, onNext }) => { - const { frequency, planName } = useParams(); + const { frequency, planId } = useParams(); const [selectedFrequency, setSelectedFrequency] = useState( parseInt(frequency) ); @@ -17,39 +20,68 @@ const SelectPlan = ({ currentStep, setStepStatus, onNext }) => { const client = useSelector( (store) => store.localVariables.selfTenant.details ); - const [selectedPlan, setSelectedPlan] = useState(planName); + const [selectedPlan, setSelectedPlan] = useState(planId); const [currentPlan, setCurrentPlan] = useState(null); const [failPayment, setFailPayment] = useState(null); const { data: plans, - isError: isPlanError, + isError, isLoading, + error, + refetch, + isRefetching, } = useSubscription(selectedFrequency); - const handleChange = (e) => setSelectedPlan(e.target.value); + const handleChange = (e) => { + setSelectedPlan(e.target.value); + }; useEffect(() => { - if (!plans || !selectedPlan) return; - const selected = plans.find((p) => p.planName === selectedPlan); - if (selected) { - setCurrentPlan(selected); - dispatch( - setSelfTenant({ planId: selected.id, frequency: selectedFrequency }) - ); - } - }, [plans, selectedPlan, dispatch, selectedFrequency]); + if (!plans || plans.length === 0) return; + + // Prefer route param if exists, else default to first plan + const matchingPlan = plans.find((p) => p.planId === planId) || plans[0]; + + setSelectedPlan(matchingPlan.id); + setCurrentPlan(matchingPlan); + + // Dispatch correct plan + frequency only once data is ready + dispatch( + setSelfTenant({ + planId: matchingPlan.id, + frequency: selectedFrequency, + }) + ); + }, [plans, selectedFrequency, planId, dispatch]); const handleNextStep = () => { - dispatch(setSelfTenant({ frequency: selectedFrequency })); + if (!selectedPlan) { + toast.warning("Please select a plan before continuing."); + return; + } + + dispatch( + setSelfTenant({ + planId: selectedPlan, + frequency: selectedFrequency, + }) + ); + setStepStatus((prev) => ({ ...prev, 2: "success" })); onNext(); }; + const { + register, + handleSubmit, + formState: { errors }, + } = useForm({ resolver: zodResolver(CouponDiscount) }); + return (
-
-
+
+

Choose the Perfect Plan for Your Organization

@@ -138,53 +170,89 @@ const SelectPlan = ({ currentStep, setStepStatus, onNext }) => {
+ {isError && ( +
+

{error?.message}

+ {error?.name} + + {isRefetching ? ( + <> + {" "} + Retrying... + + ) : ( + "Try to refetch" + )} + +
+ )} + {isLoading ? ( ) : ( <> - {plans?.map((plan) => ( -
+
+ {plans?.map((plan) => (
- + + + Price -{" "} + + {plan.currency?.symbol} {plan.price} per{" "} + {frequencyLabel(selectedFrequency)} + + + + billed {frequencyLabel(selectedFrequency, true)} + + + +
-
- ))} + ))} +
{selectedPlan && (
{(() => { const selected = plans?.find( - (p) => p.planName === selectedPlan + (p) => p.id === selectedPlan ); if (!selected) return null; @@ -201,26 +269,25 @@ const SelectPlan = ({ currentStep, setStepStatus, onNext }) => { return ( <>
-
+
Max Users: {maxUser}
-
+
Max Storage: {maxStorage} MB
-
+
Trial Days: {trialDays}
-
Included Features
@@ -244,7 +311,6 @@ const SelectPlan = ({ currentStep, setStepStatus, onNext }) => {
))}
-
Support
@@ -268,8 +334,29 @@ const SelectPlan = ({ currentStep, setStepStatus, onNext }) => { )} - -
+
+
+ +
+
+ {" "} + +
+
+ {/* {errors.coupon && ({error.coupon.message})} */}{" "} + + Currently, no coupon codes are available!{" "} + +
Duration
@@ -281,10 +368,17 @@ const SelectPlan = ({ currentStep, setStepStatus, onNext }) => {
Total Price
- {formatFigure(price, { - type: "currency", - currency: currency.currencyCode, - })} + {formatFigure( + frequencyLabel( + selectedFrequency, + true, + true + )?.planDurationInInt * price, + { + type: "currency", + currency: currency.currencyCode, + } + )}
@@ -300,13 +394,13 @@ const SelectPlan = ({ currentStep, setStepStatus, onNext }) => {
{/* Image Section */} -
+
image {
-
+
); -const SelectedPlaneSkeleton = () => { +const SelectedPlanSkeleton = () => { return (
{/* Plan Summary Card */} @@ -85,4 +85,4 @@ const SelectedPlaneSkeleton = () => { ); }; -export default SelectedPlaneSkeleton; +export default SelectedPlanSkeleton; diff --git a/src/components/UserSubscription/SubscriptionForm.jsx b/src/components/UserSubscription/SubscriptionForm.jsx index d9317580..fda0a334 100644 --- a/src/components/UserSubscription/SubscriptionForm.jsx +++ b/src/components/UserSubscription/SubscriptionForm.jsx @@ -27,7 +27,6 @@ const SubscriptionForm = ({ currentStep, setCurrentStep, setStepStatus }) => { const { mutate: CreateTenant, isPending } = useCreateSelfTenant( (resp) => { - debugger setStepStatus((prev) => ({ ...prev, [currentStep]: "success" })); setCurrentStep((prev) => prev + 1); }, @@ -46,6 +45,7 @@ const SubscriptionForm = ({ currentStep, setCurrentStep, setStepStatus }) => {
+

Please provide your personal and organizational information to help us set up your account.

{/* First Name */} @@ -112,6 +112,7 @@ const SubscriptionForm = ({ currentStep, setCurrentStep, setStepStatus }) => { {...register("contactNumber")} inputMode="tel" placeholder="+91 9876543210" + maxLength={13} /> {errors.contactNumber && (
@@ -160,6 +161,7 @@ const SubscriptionForm = ({ currentStep, setCurrentStep, setStepStatus }) => { + + {errors.organizationSize && (
{errors.organizationSize.message} @@ -194,13 +198,17 @@ const SubscriptionForm = ({ currentStep, setCurrentStep, setStepStatus }) => { {industryLoading ? ( ) : ( - data?.map((indu) => ( - - )) + <> + + {data?.map((indu) => ( + + ))} + )} + {errors.industryId && (
{errors.industryId.message} @@ -218,6 +226,7 @@ const SubscriptionForm = ({ currentStep, setCurrentStep, setStepStatus }) => { className="form-select shadow-none border py-1 px-2 small" {...register("reference")} > + {reference.map((org) => (