fixed frquency invalid display
This commit is contained in:
parent
4bbe289c95
commit
c00ab582cc
@ -14,6 +14,7 @@ import { useDispatch, useSelector } from "react-redux";
|
|||||||
import { setSelfTenant } from "../../slices/localVariablesSlice";
|
import { setSelfTenant } from "../../slices/localVariablesSlice";
|
||||||
import { unblockUI } from "../../utils/blockUI";
|
import { unblockUI } from "../../utils/blockUI";
|
||||||
import showToast from "../../services/toastService";
|
import showToast from "../../services/toastService";
|
||||||
|
import SelectedPlanSkeleton from "./SelectedPlanSkeleton";
|
||||||
|
|
||||||
const ProcessedPayment = ({
|
const ProcessedPayment = ({
|
||||||
onNext,
|
onNext,
|
||||||
@ -22,11 +23,12 @@ const ProcessedPayment = ({
|
|||||||
setStepStatus,
|
setStepStatus,
|
||||||
resetFormStep,
|
resetFormStep,
|
||||||
}) => {
|
}) => {
|
||||||
const { frequency, planName } = useParams();
|
const { planName } = useParams();
|
||||||
|
|
||||||
const { details: client, planId: selectedPlanId } = useSelector(
|
const { details: client, planId: selectedPlanId,frequency } = useSelector(
|
||||||
(store) => store.localVariables.selfTenant
|
(store) => store.localVariables.selfTenant
|
||||||
);
|
);
|
||||||
|
console.log(frequency)
|
||||||
const [selectedPlan, setSelectedPlan] = useState(null);
|
const [selectedPlan, setSelectedPlan] = useState(null);
|
||||||
const [currentPlan, setCurrentPlan] = useState(null);
|
const [currentPlan, setCurrentPlan] = useState(null);
|
||||||
const [failPayment, setFailPayment] = useState(null);
|
const [failPayment, setFailPayment] = useState(null);
|
||||||
@ -36,7 +38,6 @@ const ProcessedPayment = ({
|
|||||||
isError: isPlanError,
|
isError: isPlanError,
|
||||||
isLoading,
|
isLoading,
|
||||||
} = useSubscription(frequency);
|
} = useSubscription(frequency);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!plans || !selectedPlanId) return;
|
if (!plans || !selectedPlanId) return;
|
||||||
const selected = plans.find((p) => p.id === selectedPlanId);
|
const selected = plans.find((p) => p.id === selectedPlanId);
|
||||||
@ -77,7 +78,7 @@ const ProcessedPayment = ({
|
|||||||
alert("Failed to load Razorpay SDK");
|
alert("Failed to load Razorpay SDK");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MakePayment({ amount: 1 });
|
MakePayment({ amount:selectedPlan?.price });
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRetry = () => {
|
const handleRetry = () => {
|
||||||
@ -154,6 +155,9 @@ const ProcessedPayment = ({
|
|||||||
and help you maximize productivity.
|
and help you maximize productivity.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{isLoading ? <SelectedPlanSkeleton/> : (<>
|
||||||
|
|
||||||
{selectedPlan && (
|
{selectedPlan && (
|
||||||
<div className="col-12 col-md-8 mb-md-3 mb-2">
|
<div className="col-12 col-md-8 mb-md-3 mb-2">
|
||||||
<div className="custom-option custom-option-basic text-start w-100 bg-light-primary border border-primary shadow-md p-3 rounded-3">
|
<div className="custom-option custom-option-basic text-start w-100 bg-light-primary border border-primary shadow-md p-3 rounded-3">
|
||||||
@ -164,8 +168,8 @@ const ProcessedPayment = ({
|
|||||||
|
|
||||||
<div className="d-flex justify-content-between mt-1">
|
<div className="d-flex justify-content-between mt-1">
|
||||||
<small className="text-muted">
|
<small className="text-muted">
|
||||||
{selectedPlan?.currency?.symbol} {selectedPlan?.price} /{" "}
|
{selectedPlan?.currency?.symbol} {selectedPlan?.price} /
|
||||||
{frequencyLabel(frequency)}
|
{frequencyLabel(frequency,false)}
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -286,6 +290,8 @@ const ProcessedPayment = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
</>)}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-12 col-md-4 ">
|
<div className="col-12 col-md-4 ">
|
||||||
|
|||||||
@ -4,9 +4,13 @@ import { useParams } from "react-router-dom";
|
|||||||
import { useSubscription } from "../../hooks/useAuth";
|
import { useSubscription } from "../../hooks/useAuth";
|
||||||
import { formatFigure, frequencyLabel } from "../../utils/appUtils";
|
import { formatFigure, frequencyLabel } from "../../utils/appUtils";
|
||||||
import { setSelfTenant } from "../../slices/localVariablesSlice";
|
import { setSelfTenant } from "../../slices/localVariablesSlice";
|
||||||
|
import SelectedPlanSkeleton from "./SelectedPlanSkeleton";
|
||||||
|
|
||||||
const SelectPlan = ({ currentStep, setStepStatus, onNext }) => {
|
const SelectPlan = ({ currentStep, setStepStatus, onNext }) => {
|
||||||
const { frequency, planName } = useParams();
|
const { frequency, planName } = useParams();
|
||||||
|
const [selectedFrequency, setSelectedFrequency] = useState(
|
||||||
|
parseInt(frequency)
|
||||||
|
);
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const client = useSelector(
|
const client = useSelector(
|
||||||
@ -20,7 +24,7 @@ const SelectPlan = ({ currentStep, setStepStatus, onNext }) => {
|
|||||||
data: plans,
|
data: plans,
|
||||||
isError: isPlanError,
|
isError: isPlanError,
|
||||||
isLoading,
|
isLoading,
|
||||||
} = useSubscription(frequency);
|
} = useSubscription(selectedFrequency);
|
||||||
|
|
||||||
const handleChange = (e) => setSelectedPlan(e.target.value);
|
const handleChange = (e) => setSelectedPlan(e.target.value);
|
||||||
|
|
||||||
@ -29,209 +33,296 @@ const SelectPlan = ({ currentStep, setStepStatus, onNext }) => {
|
|||||||
const selected = plans.find((p) => p.planName === selectedPlan);
|
const selected = plans.find((p) => p.planName === selectedPlan);
|
||||||
if (selected) {
|
if (selected) {
|
||||||
setCurrentPlan(selected);
|
setCurrentPlan(selected);
|
||||||
dispatch(setSelfTenant({ planId: selected.id }));
|
dispatch(
|
||||||
|
setSelfTenant({ planId: selected.id, frequency: selectedFrequency })
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}, [plans, selectedPlan, dispatch]);
|
}, [plans, selectedPlan, dispatch, selectedFrequency]);
|
||||||
|
|
||||||
const handleNextStep = () => {
|
const handleNextStep = () => {
|
||||||
setStepStatus((prev) => ({ ...prev, 2: "success"}));
|
dispatch(setSelfTenant({ frequency: selectedFrequency }));
|
||||||
|
setStepStatus((prev) => ({ ...prev, 2: "success" }));
|
||||||
onNext();
|
onNext();
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container text-start ">
|
<div className="container text-start ">
|
||||||
<div className="row gx-4 gy-5 align-items-center justify-content-around">
|
<div className="row gx-4 gy-5 align-items-center justify-content-around">
|
||||||
<div className="col-sm-12 col-md-6">
|
<div className="col-sm-12 col-md-6">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-12 mb-3 text-start">
|
<div className="col-12 mb-3 text-start">
|
||||||
<h4>Choose the Perfect Plan for Your Organization</h4>
|
<h4>Choose the Perfect Plan for Your Organization</h4>
|
||||||
<p className="text-muted small mb-3">
|
<p className="text-muted small mb-3">
|
||||||
Select a plan that fits your team’s needs and unlock the
|
Select a plan that fits your team’s needs and unlock the
|
||||||
features that drive productivity.
|
features that drive productivity.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div className="form-check form-check-inline mt-4">
|
||||||
|
<input
|
||||||
|
className="form-check-input"
|
||||||
|
type="radio"
|
||||||
|
name="frequencyOptions"
|
||||||
|
id="frequencyMonthly"
|
||||||
|
value={0}
|
||||||
|
checked={selectedFrequency === 0}
|
||||||
|
onChange={(e) =>
|
||||||
|
setSelectedFrequency(Number(e.target.value))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
className="form-check-label"
|
||||||
|
htmlFor="frequencyMonthly"
|
||||||
|
>
|
||||||
|
Monthly
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="form-check form-check-inline">
|
||||||
|
<input
|
||||||
|
className="form-check-input"
|
||||||
|
type="radio"
|
||||||
|
name="frequencyOptions"
|
||||||
|
id="frequencyQuarterly"
|
||||||
|
value={1}
|
||||||
|
checked={selectedFrequency === 1}
|
||||||
|
onChange={(e) =>
|
||||||
|
setSelectedFrequency(Number(e.target.value))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
className="form-check-label"
|
||||||
|
htmlFor="frequencyQuarterly"
|
||||||
|
>
|
||||||
|
Quarterly
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="form-check form-check-inline">
|
||||||
|
<input
|
||||||
|
className="form-check-input"
|
||||||
|
type="radio"
|
||||||
|
name="frequencyOptions"
|
||||||
|
id="frequencyHalfYear"
|
||||||
|
value={2}
|
||||||
|
checked={selectedFrequency === 2}
|
||||||
|
onChange={(e) =>
|
||||||
|
setSelectedFrequency(Number(e.target.value))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
className="form-check-label"
|
||||||
|
htmlFor="frequencyHalfYear"
|
||||||
|
>
|
||||||
|
Half-Yearly
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="form-check form-check-inline">
|
||||||
|
<input
|
||||||
|
className="form-check-input"
|
||||||
|
type="radio"
|
||||||
|
name="frequencyOptions"
|
||||||
|
id="frequencyYearly"
|
||||||
|
value={3}
|
||||||
|
checked={selectedFrequency === 3}
|
||||||
|
onChange={(e) =>
|
||||||
|
setSelectedFrequency(Number(e.target.value))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<label className="form-check-label" htmlFor="frequencyYearly">
|
||||||
|
Yearly
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{isLoading ? (
|
||||||
|
<SelectedPlanSkeleton />
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{plans?.map((plan) => (
|
||||||
|
<div key={plan?.id} className="col-12 col-md-4 mb-md-3 mb-2">
|
||||||
|
<div
|
||||||
|
className={`form-check custom-option custom-option-basic text-start w-100 bg-light-primary ${
|
||||||
|
selectedPlan === plan?.planName
|
||||||
|
? "border border-primary shadow-md"
|
||||||
|
: ""
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
className="form-check-label custom-option-content w-100"
|
||||||
|
htmlFor={`customRadioTemp${plan?.id}`}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
name="customRadioTemp"
|
||||||
|
className="form-check-input"
|
||||||
|
type="radio"
|
||||||
|
value={plan?.planName}
|
||||||
|
id={`customRadioTemp${plan?.id}`}
|
||||||
|
checked={selectedPlan === plan?.planName}
|
||||||
|
onChange={handleChange}
|
||||||
|
/>
|
||||||
|
<span className="custom-option-header d-flex justify-content-between align-items-center">
|
||||||
|
<span className="h6 mb-0">{plan?.planName}</span>
|
||||||
|
<span>
|
||||||
|
{plan.currency?.symbol} {plan.price} /{" "}
|
||||||
|
{frequencyLabel(selectedFrequency)}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span className="custom-option-body d-block mt-1">
|
||||||
|
<small>{plan?.description}</small>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{selectedPlan && (
|
||||||
|
<div className="col-12 text-start">
|
||||||
|
<div className="border-warning mt-3">
|
||||||
|
{(() => {
|
||||||
|
const selected = plans?.find(
|
||||||
|
(p) => p.planName === selectedPlan
|
||||||
|
);
|
||||||
|
if (!selected) return null;
|
||||||
|
|
||||||
|
const {
|
||||||
|
price,
|
||||||
|
frequency,
|
||||||
|
trialDays,
|
||||||
|
maxUser,
|
||||||
|
maxStorage,
|
||||||
|
currency,
|
||||||
|
features,
|
||||||
|
} = selected;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="row g-2 mb-3">
|
||||||
|
<div className="col-sm-6 col-md-4">
|
||||||
|
<div className="border rounded-3 p-2 bg-light">
|
||||||
|
<i className="bx bx-user me-1 text-primary"></i>
|
||||||
|
<strong>Max Users:</strong> {maxUser}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-sm-6 col-md-4">
|
||||||
|
<div className="border rounded-3 p-2 bg-light">
|
||||||
|
<i className="bx bx-hdd me-1 text-primary"></i>
|
||||||
|
<strong>Max Storage:</strong> {maxStorage} MB
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-sm-6 col-md-4">
|
||||||
|
<div className="border rounded-3 p-2 bg-light">
|
||||||
|
<i className="bx bx-time-five me-1 text-primary"></i>
|
||||||
|
<strong>Trial Days:</strong> {trialDays}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h6 className="fw-bold text-secondary mb-2">
|
||||||
|
Included Features
|
||||||
|
</h6>
|
||||||
|
<div className="row">
|
||||||
|
{features &&
|
||||||
|
Object.entries(features?.modules || {})
|
||||||
|
.filter(([key]) => key !== "id")
|
||||||
|
.map(([key, mod]) => (
|
||||||
|
<div
|
||||||
|
key={key}
|
||||||
|
className="col-4 mb-2 d-flex align-items-center"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
className={`fa-regular ${
|
||||||
|
mod.enabled
|
||||||
|
? "fa-circle-check text-success"
|
||||||
|
: "fa-circle-xmark text-danger"
|
||||||
|
}`}
|
||||||
|
></i>
|
||||||
|
<small className="ms-1">{mod.name}</small>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h6 className="fw-bold text-secondary mt-3 mb-2">
|
||||||
|
Support
|
||||||
|
</h6>
|
||||||
|
<ul className="list-unstyled d-flex flex-wrap gap-3 align-items-center mb-0 small">
|
||||||
|
{features?.supports?.emailSupport && (
|
||||||
|
<li className="d-flex align-items-center">
|
||||||
|
<i className="bx bx-envelope text-primary me-1 fs-5"></i>
|
||||||
|
Email Support
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
{features?.supports?.phoneSupport && (
|
||||||
|
<li className="d-flex align-items-center">
|
||||||
|
<i className="bx bx-phone text-primary me-1 fs-5"></i>
|
||||||
|
Phone Support
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
{features?.supports?.prioritySupport && (
|
||||||
|
<li className="d-flex align-items-center">
|
||||||
|
<i className="bx bx-star text-warning me-1 fs-5"></i>
|
||||||
|
Priority Support
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<hr className="divider border-2" />
|
||||||
|
<div className="d-flex flex-column co-12">
|
||||||
|
<div className="d-flex justify-content-between">
|
||||||
|
<h6 className="fs-6 m-0">Duration</h6>
|
||||||
|
<h5 className="fs-6 m-0">
|
||||||
|
{frequencyLabel(frequency, true)}
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="d-flex justify-content-between">
|
||||||
|
<h6 className="fs-4">Total Price</h6>
|
||||||
|
<h5 className="fs-3">
|
||||||
|
{formatFigure(price, {
|
||||||
|
type: "currency",
|
||||||
|
currency: currency.currencyCode,
|
||||||
|
})}
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
})()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{plans?.map((plan) => (
|
{/* Image Section */}
|
||||||
<div key={plan?.id} className="col-12 col-md-4 mb-md-3 mb-2">
|
<div className="d-none d-md-flex col-md-6 justify-content-center align-items-center">
|
||||||
<div
|
<img
|
||||||
className={`form-check custom-option custom-option-basic text-start w-100 bg-light-primary ${
|
src="/public/img/illustrations/undraw_pricing.png"
|
||||||
selectedPlan === plan?.planName
|
alt="image"
|
||||||
? "border border-primary shadow-md"
|
className="img-fluid"
|
||||||
: ""
|
style={{
|
||||||
}`}
|
maxWidth: "70%",
|
||||||
>
|
height: "auto",
|
||||||
<label
|
objectFit: "contain",
|
||||||
className="form-check-label custom-option-content w-100"
|
}}
|
||||||
htmlFor={`customRadioTemp${plan?.id}`}
|
/>
|
||||||
>
|
</div>
|
||||||
<input
|
</div>
|
||||||
name="customRadioTemp"
|
|
||||||
className="form-check-input"
|
|
||||||
type="radio"
|
|
||||||
value={plan?.planName}
|
|
||||||
id={`customRadioTemp${plan?.id}`}
|
|
||||||
checked={selectedPlan === plan?.planName}
|
|
||||||
onChange={handleChange}
|
|
||||||
/>
|
|
||||||
<span className="custom-option-header d-flex justify-content-between align-items-center">
|
|
||||||
<span className="h6 mb-0">{plan?.planName}</span>
|
|
||||||
<span>
|
|
||||||
{plan.currency?.symbol} {plan.price} /{" "}
|
|
||||||
{frequencyLabel(frequency)}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
<span className="custom-option-body d-block mt-1">
|
|
||||||
<small>{plan?.description}</small>
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
|
|
||||||
{selectedPlan && (
|
<div className="col-12 d-flex justify-content-end mt-3">
|
||||||
<div className="col-12 text-start">
|
<button
|
||||||
<div className="border-warning mt-3">
|
type="submit"
|
||||||
{(() => {
|
className="btn btn-label-primary d-flex align-items-center me-2"
|
||||||
const selected = plans?.find(
|
onClick={handleNextStep}
|
||||||
(p) => p.planName === selectedPlan
|
>
|
||||||
);
|
Next <i className="bx bx-chevron-right"></i>
|
||||||
if (!selected) return null;
|
</button>
|
||||||
|
|
||||||
const {
|
|
||||||
price,
|
|
||||||
frequency,
|
|
||||||
trialDays,
|
|
||||||
maxUser,
|
|
||||||
maxStorage,
|
|
||||||
currency,
|
|
||||||
features,
|
|
||||||
} = selected;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="row g-2 mb-3">
|
|
||||||
<div className="col-sm-6 col-md-4">
|
|
||||||
<div className="border rounded-3 p-2 bg-light">
|
|
||||||
<i className="bx bx-user me-1 text-primary"></i>
|
|
||||||
<strong>Max Users:</strong> {maxUser}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="col-sm-6 col-md-4">
|
|
||||||
<div className="border rounded-3 p-2 bg-light">
|
|
||||||
<i className="bx bx-hdd me-1 text-primary"></i>
|
|
||||||
<strong>Max Storage:</strong> {maxStorage} MB
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="col-sm-6 col-md-4">
|
|
||||||
<div className="border rounded-3 p-2 bg-light">
|
|
||||||
<i className="bx bx-time-five me-1 text-primary"></i>
|
|
||||||
<strong>Trial Days:</strong> {trialDays}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h6 className="fw-bold text-secondary mb-2">
|
|
||||||
Included Features
|
|
||||||
</h6>
|
|
||||||
<div className="row">
|
|
||||||
{features &&
|
|
||||||
Object.entries(features?.modules || {})
|
|
||||||
.filter(([key]) => key !== "id")
|
|
||||||
.map(([key, mod]) => (
|
|
||||||
<div
|
|
||||||
key={key}
|
|
||||||
className="col-4 mb-2 d-flex align-items-center"
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
className={`fa-regular ${
|
|
||||||
mod.enabled
|
|
||||||
? "fa-circle-check text-success"
|
|
||||||
: "fa-circle-xmark text-danger"
|
|
||||||
}`}
|
|
||||||
></i>
|
|
||||||
<small className="ms-1">{mod.name}</small>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h6 className="fw-bold text-secondary mt-3 mb-2">
|
|
||||||
Support
|
|
||||||
</h6>
|
|
||||||
<ul className="list-unstyled d-flex flex-wrap gap-3 align-items-center mb-0 small">
|
|
||||||
{features?.supports?.emailSupport && (
|
|
||||||
<li className="d-flex align-items-center">
|
|
||||||
<i className="bx bx-envelope text-primary me-1 fs-5"></i>
|
|
||||||
Email Support
|
|
||||||
</li>
|
|
||||||
)}
|
|
||||||
{features?.supports?.phoneSupport && (
|
|
||||||
<li className="d-flex align-items-center">
|
|
||||||
<i className="bx bx-phone text-primary me-1 fs-5"></i>
|
|
||||||
Phone Support
|
|
||||||
</li>
|
|
||||||
)}
|
|
||||||
{features?.supports?.prioritySupport && (
|
|
||||||
<li className="d-flex align-items-center">
|
|
||||||
<i className="bx bx-star text-warning me-1 fs-5"></i>
|
|
||||||
Priority Support
|
|
||||||
</li>
|
|
||||||
)}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<hr className="divider border-2" />
|
|
||||||
<div className="d-flex flex-column co-12">
|
|
||||||
<div className="d-flex justify-content-between">
|
|
||||||
<h6 className="fs-6 m-0">Duration</h6>
|
|
||||||
<h5 className="fs-6 m-0">
|
|
||||||
{frequencyLabel(frequency, true)}
|
|
||||||
</h5>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="d-flex justify-content-between">
|
|
||||||
<h6 className="fs-4">Total Price</h6>
|
|
||||||
<h5 className="fs-3">
|
|
||||||
{formatFigure(price, {
|
|
||||||
type: "currency",
|
|
||||||
currency: currency.currencyCode,
|
|
||||||
})}
|
|
||||||
</h5>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
})()}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Image Section */}
|
|
||||||
<div className="d-none d-md-flex col-md-6 justify-content-center align-items-center">
|
|
||||||
<img
|
|
||||||
src="/public/img/illustrations/undraw_pricing.png"
|
|
||||||
alt="image"
|
|
||||||
className="img-fluid"
|
|
||||||
style={{
|
|
||||||
maxWidth: "70%",
|
|
||||||
height: "auto",
|
|
||||||
objectFit: "contain",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="col-12 d-flex justify-content-end mt-3">
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
className="btn btn-label-primary d-flex align-items-center me-2"
|
|
||||||
onClick={handleNextStep}
|
|
||||||
>
|
|
||||||
Next <i className="bx bx-chevron-right"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
88
src/components/UserSubscription/SelectedPlanSkeleton.jsx
Normal file
88
src/components/UserSubscription/SelectedPlanSkeleton.jsx
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
|
||||||
|
const SkeletonLine = ({ height = 16, width = "100%", className = "" }) => (
|
||||||
|
<div
|
||||||
|
className={`skeleton mb-2 ${className}`}
|
||||||
|
style={{
|
||||||
|
height,
|
||||||
|
width,
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
);
|
||||||
|
|
||||||
|
const SelectedPlanSkeleton = () => {
|
||||||
|
return (
|
||||||
|
<div className="row">
|
||||||
|
{/* Plan Summary Card */}
|
||||||
|
<div className="col-12 col-md-8 mb-md-3 mb-2">
|
||||||
|
<div className="custom-option custom-option-basic text-start w-100 bg-light border shadow-md p-3 rounded-3">
|
||||||
|
<div className="d-flex justify-content-between align-items-center mb-2">
|
||||||
|
<SkeletonLine height={20} width="40%" />
|
||||||
|
<SkeletonLine height={20} width="25px" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<SkeletonLine height={16} width="60%" />
|
||||||
|
<SkeletonLine height={14} width="80%" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Plan Details */}
|
||||||
|
<div className="col-12 text-start mt-2">
|
||||||
|
<div className="border rounded-3 p-3 bg-light">
|
||||||
|
{/* Stats (Max Users, Storage, Trial Days) */}
|
||||||
|
<div className="row g-2 mb-3">
|
||||||
|
{[...Array(3)].map((_, i) => (
|
||||||
|
<div className="col-sm-6 col-md-4" key={i}>
|
||||||
|
<div className="border rounded-3 p-2 bg-white d-flex align-items-center">
|
||||||
|
<SkeletonLine height={18} width="80%" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Included Features */}
|
||||||
|
<h6 className="fw-bold text-secondary mb-2">
|
||||||
|
<SkeletonLine height={18} width="40%" />
|
||||||
|
</h6>
|
||||||
|
<div className="row">
|
||||||
|
{[...Array(6)].map((_, i) => (
|
||||||
|
<div
|
||||||
|
className="col-4 mb-2 d-flex align-items-center"
|
||||||
|
key={i}
|
||||||
|
>
|
||||||
|
<SkeletonLine height={14} width="70%" />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Support */}
|
||||||
|
<h6 className="fw-bold text-secondary mt-3 mb-2">
|
||||||
|
<SkeletonLine height={18} width="30%" />
|
||||||
|
</h6>
|
||||||
|
<div className="d-flex flex-wrap gap-3 mb-2">
|
||||||
|
{[...Array(3)].map((_, i) => (
|
||||||
|
<SkeletonLine key={i} height={14} width="100px" />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr className="divider border-2" />
|
||||||
|
|
||||||
|
{/* Duration and Total */}
|
||||||
|
<div className="d-flex flex-column">
|
||||||
|
<div className="d-flex justify-content-between mb-1">
|
||||||
|
<SkeletonLine height={16} width="40%" />
|
||||||
|
<SkeletonLine height={16} width="30%" />
|
||||||
|
</div>
|
||||||
|
<div className="d-flex justify-content-between">
|
||||||
|
<SkeletonLine height={20} width="50%" />
|
||||||
|
<SkeletonLine height={22} width="40%" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SelectedPlanSkeleton;
|
||||||
@ -15,6 +15,7 @@ import {
|
|||||||
} from "../slices/localVariablesSlice.jsx";
|
} from "../slices/localVariablesSlice.jsx";
|
||||||
import { removeSession } from "../utils/authUtils.js";
|
import { removeSession } from "../utils/authUtils.js";
|
||||||
import showToast from "../services/toastService.tsx";
|
import showToast from "../services/toastService.tsx";
|
||||||
|
import eventBus from "../services/eventBus.js";
|
||||||
|
|
||||||
// ----------------------------Modal--------------------------
|
// ----------------------------Modal--------------------------
|
||||||
|
|
||||||
@ -38,6 +39,7 @@ export const useSubscription = (frequency) => {
|
|||||||
const resp = await AuthRepository.getSubscription(frequency);
|
const resp = await AuthRepository.getSubscription(frequency);
|
||||||
return resp.data;
|
return resp.data;
|
||||||
},
|
},
|
||||||
|
enabled: frequency !== null && frequency !== undefined
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -94,7 +96,6 @@ export const useCreateSelfTenant = (onSuccessCallBack, onFailureCallBack) => {
|
|||||||
details:response
|
details:response
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
debugger
|
|
||||||
if (onSuccessCallBack) onSuccessCallBack(response);
|
if (onSuccessCallBack) onSuccessCallBack(response);
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import SelectPlan from "../../components/UserSubscription/SelectPlan";
|
|||||||
import Review from "../../components/UserSubscription/Review";
|
import Review from "../../components/UserSubscription/Review";
|
||||||
|
|
||||||
const MakeSubscription = () => {
|
const MakeSubscription = () => {
|
||||||
const [currentStep, setCurrentStep] = useState(1);
|
const [currentStep, setCurrentStep] = useState(2);
|
||||||
const [responsePayment, setResponsePayment] = useState(null);
|
const [responsePayment, setResponsePayment] = useState(null);
|
||||||
|
|
||||||
const [stepStatus, setStepStatus] = useState({
|
const [stepStatus, setStepStatus] = useState({
|
||||||
|
|||||||
@ -36,6 +36,7 @@ const localVariablesSlice = createSlice({
|
|||||||
tenantEnquireId: null,
|
tenantEnquireId: null,
|
||||||
planId: null,
|
planId: null,
|
||||||
details:null,
|
details:null,
|
||||||
|
frequency:null,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
reducers: {
|
reducers: {
|
||||||
@ -109,6 +110,7 @@ const localVariablesSlice = createSlice({
|
|||||||
action.payload.planId ?? state.selfTenant.planId;
|
action.payload.planId ?? state.selfTenant.planId;
|
||||||
state.selfTenant.details =
|
state.selfTenant.details =
|
||||||
action.payload.details ?? state.selfTenant.details;
|
action.payload.details ?? state.selfTenant.details;
|
||||||
|
state.selfTenant.frequency = action.payload.frequency ?? state.selfTenant.frequency;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -136,17 +136,18 @@ export const formatFigure = (
|
|||||||
return new Intl.NumberFormat(locale, formatterOptions).format(amount);
|
return new Intl.NumberFormat(locale, formatterOptions).format(amount);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const frequencyLabel = (freq,isLong=false) => {
|
export const frequencyLabel = (freq, isLong = false) => {
|
||||||
switch (freq) {
|
const frequency = parseInt(freq, 10);
|
||||||
case 0:
|
switch (frequency) {
|
||||||
return isLong ? "1 Month" : "1 mo";
|
case 0:
|
||||||
case 1:
|
return isLong ? "1 Month" : "1 mo";
|
||||||
return isLong ? "3 Months" : "3 mo";
|
case 1:
|
||||||
case 2:
|
return isLong ? "Quarterly (3 Months)" : "3 mo";
|
||||||
return isLong ? "6 Months" : "6 mo";
|
case 2:
|
||||||
case 3:
|
return isLong ? "6 Months" : "6 mo";
|
||||||
return isLong ? "1 Year" : "1 yr";
|
case 3:
|
||||||
default:
|
return isLong ? "1 Year" : "1 yr";
|
||||||
return "mo";
|
default:
|
||||||
}
|
return isLong ? "Unknown" : "N/A";
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user