integrated payment and selft geneartion subscription api
This commit is contained in:
parent
c00ab582cc
commit
d81ffe86b7
@ -28,7 +28,6 @@ const ProcessedPayment = ({
|
||||
const { details: client, planId: selectedPlanId,frequency } = useSelector(
|
||||
(store) => store.localVariables.selfTenant
|
||||
);
|
||||
console.log(frequency)
|
||||
const [selectedPlan, setSelectedPlan] = useState(null);
|
||||
const [currentPlan, setCurrentPlan] = useState(null);
|
||||
const [failPayment, setFailPayment] = useState(null);
|
||||
@ -144,7 +143,7 @@ const ProcessedPayment = ({
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="container-sm text-start ">
|
||||
<div className="container-md text-start ">
|
||||
<div className="row gx-1 gy-3 justify-content-between">
|
||||
<div className="col-12 col-md-6">
|
||||
<div className="row">
|
||||
@ -309,7 +308,7 @@ const ProcessedPayment = ({
|
||||
<div className="col-sm-6">
|
||||
<strong>Email:</strong>
|
||||
</div>
|
||||
<div className="col-sm-6 mb-2">{client.email}</div>
|
||||
<div className="col-sm-6 mb-2 text-wrap">{client.email}</div>
|
||||
|
||||
<div className="col-sm-6 mb-2">
|
||||
<strong>Contact Number:</strong>
|
||||
@ -357,7 +356,7 @@ const ProcessedPayment = ({
|
||||
className="btn btn-label-primary d-flex align-items-center me-2"
|
||||
onClick={() => ProcessToPayment(currentPlan?.price)}
|
||||
>
|
||||
{isPending ? "Please Wait..." : "Processed To Payment"}
|
||||
{isPending ? <span><i className='bx bx-loader-alt bx-md bx-spin me-2'></i>Please Wait...</span> : "Processed To Payment"}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,23 +1,86 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import GlobalModel from "../common/GlobalModel";
|
||||
import Invoice from "./Invoice";
|
||||
import { useSelector } from "react-redux";
|
||||
import { blockUI, unblockUI } from "../../utils/blockUI";
|
||||
|
||||
const VerifiedPayment = ({ onNext, responsePayment }) => {
|
||||
import { error } from "pdf-lib";
|
||||
import { useSelfGetSubscription } from "../../hooks/useAuth";
|
||||
|
||||
|
||||
const VerifiedPayment = ({ responsePayment, setStepStatus }) => {
|
||||
const [isGenerateInvoice, setIsGenerateInvoice] = useState(false);
|
||||
useEffect(() => {
|
||||
if (responsePayment?.success) {
|
||||
onNext();
|
||||
}
|
||||
}, [responsePayment]);
|
||||
if (responsePayment) {
|
||||
|
||||
const { tenantEnquireId, paymentDetailId, planId } = useSelector(
|
||||
(store) => store.localVariables.selfTenant
|
||||
);
|
||||
|
||||
const {
|
||||
mutate: getSubscription,
|
||||
isPending,
|
||||
isError,
|
||||
isSuccess,
|
||||
error,
|
||||
} = useSelfGetSubscription(
|
||||
() => {
|
||||
unblockUI();
|
||||
setStepStatus?.((prev) => ({ ...prev, 5: "success" }));
|
||||
},
|
||||
() => {
|
||||
unblockUI();
|
||||
setStepStatus?.((prev) => ({ ...prev, 5: "failed" }));
|
||||
}
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (responsePayment?.success) {
|
||||
const payload = { tenantEnquireId, paymentDetailId, planId };
|
||||
getSubscription(payload);
|
||||
}
|
||||
}, [responsePayment]);
|
||||
|
||||
|
||||
if (isError) {
|
||||
return (
|
||||
<div className="container-md mt-5 text-center">
|
||||
<div className="d-flex flex-column align-items-center justify-content-center">
|
||||
<div
|
||||
className="spinner-border text-primary mb-3 p-1"
|
||||
role="status"
|
||||
></div>
|
||||
<h4 className="text-primary mb-2">Verifying payment...</h4>
|
||||
className="bg-danger p-3 rounded-circle mb-3 d-flex align-items-center justify-content-center"
|
||||
style={{ width: "70px", height: "70px" }}
|
||||
>
|
||||
<i className="bx bx-x fs-1 text-white fw-bold"></i>
|
||||
</div>
|
||||
|
||||
<h4 className="text-danger mb-2">Subscription Generation Failed!</h4>
|
||||
<p className="text-muted">
|
||||
Unfortunately, your subscription transaction could not be completed.
|
||||
</p>
|
||||
|
||||
<div className="mt-4 d-flex gap-3 flex-column flex-md-row justify-content-center">
|
||||
<a href="/" className="px-4 py-2 fw-semibold text-muted">
|
||||
Please review your payment details carefully and contact our
|
||||
Support Team for assistance.
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div className="alert alert-light-danger mt-4 w-75 mx-auto text-start">
|
||||
<strong>Error Details:</strong>
|
||||
<pre className="small mb-0 mt-2 text-wrap">
|
||||
{JSON.stringify(error, null, 2)}
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if (isPending) {
|
||||
return (
|
||||
<div className="container-md mt-5 text-center">
|
||||
<div className="d-flex flex-column align-items-center justify-content-center">
|
||||
<div className="spinner-border text-primary mb-3 p-1" role="status" />
|
||||
<h4 className="text-primary mb-2">Verifying Payment...</h4>
|
||||
<p className="text-muted">
|
||||
Please wait while we verify your transaction. Do not refresh or
|
||||
close this page.
|
||||
@ -27,8 +90,8 @@ useEffect(() => {
|
||||
);
|
||||
}
|
||||
|
||||
if (!responsePayment?.success) {
|
||||
|
||||
if (isSuccess) {
|
||||
return (
|
||||
<div className="container-md mt-3 text-center h-auto">
|
||||
{isGenerateInvoice && (
|
||||
@ -39,28 +102,29 @@ useEffect(() => {
|
||||
<Invoice invoiceData={responsePayment?.data} />
|
||||
</GlobalModel>
|
||||
)}
|
||||
|
||||
<div className="d-flex align-items-center justify-content-center">
|
||||
<span className="bg-success p-2 p-md-3 rounded-circle">
|
||||
<i className="bx bx-check fs-2 fw-bold text-white"></i>
|
||||
</span>
|
||||
<span className="fs-3 fs-md-2 ms-3 text-success">
|
||||
<span className="fs-3 fs-md-2 ms-3 text-success">
|
||||
Payment Successful!
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<p className="text-muted mb-4 fs-6 fs-md-5 text-center mt-8">
|
||||
<p className="text-muted mb-4 fs-6 fs-md-5 text-center mt-4">
|
||||
Thank you for your payment. Your <strong>subscription</strong> has
|
||||
been successfully activated.
|
||||
</p>
|
||||
|
||||
<div className="mt-8">
|
||||
<small className="text-muted ">
|
||||
A Set Password link has been sent to your registered email address .
|
||||
Please check your inbox .
|
||||
</small>
|
||||
</div>
|
||||
<div className="mt-3">
|
||||
<small className="text-muted">
|
||||
A <strong>Set Password</strong> link has been sent to your
|
||||
registered email address. Please check your inbox.
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<div className="d-flex flex-column flex-md-row justify-content-center gap-3 my-12 ">
|
||||
<div className="d-flex flex-column flex-md-row justify-content-center gap-3 my-4">
|
||||
<a href="/" className="btn btn-info px-4 py-2 fw-semibold">
|
||||
Go to Dashboard
|
||||
</a>
|
||||
@ -79,3 +143,5 @@ useEffect(() => {
|
||||
};
|
||||
|
||||
export default VerifiedPayment;
|
||||
|
||||
|
||||
|
||||
@ -16,6 +16,7 @@ import {
|
||||
import { removeSession } from "../utils/authUtils.js";
|
||||
import showToast from "../services/toastService.tsx";
|
||||
import eventBus from "../services/eventBus.js";
|
||||
import { blockUI } from "../utils/blockUI.js";
|
||||
|
||||
// ----------------------------Modal--------------------------
|
||||
|
||||
@ -39,7 +40,7 @@ export const useSubscription = (frequency) => {
|
||||
const resp = await AuthRepository.getSubscription(frequency);
|
||||
return resp.data;
|
||||
},
|
||||
enabled: frequency !== null && frequency !== undefined
|
||||
enabled: frequency !== null && frequency !== undefined,
|
||||
});
|
||||
};
|
||||
|
||||
@ -88,18 +89,53 @@ export const useCreateSelfTenant = (onSuccessCallBack, onFailureCallBack) => {
|
||||
return resp.data;
|
||||
},
|
||||
onSuccess: (response, variables) => {
|
||||
|
||||
dispatch(
|
||||
setSelfTenant({
|
||||
tenantEnquireId: response?.id,
|
||||
planId: null,
|
||||
details:response
|
||||
details: response,
|
||||
})
|
||||
);
|
||||
if (onSuccessCallBack) onSuccessCallBack(response);
|
||||
},
|
||||
onError: (error) => {
|
||||
showToast("Somthing worng went happend", "error");
|
||||
showToast(
|
||||
`${error?.response?.data?.errors || ""} ${
|
||||
error?.response?.data?.message || ""
|
||||
} ${error?.response?.data?.statusCode || ""}`.trim() ||
|
||||
error?.message ||
|
||||
"Something went wrong, please try again!",
|
||||
"error"
|
||||
);
|
||||
|
||||
if (onFailureCallBack) onFailureCallBack();
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useSelfGetSubscription = (
|
||||
onSuccessCallBack,
|
||||
onFailureCallBack
|
||||
) => {
|
||||
const dispatch = useDispatch();
|
||||
return useMutation({
|
||||
mutationFn: async (payload) => {
|
||||
blockUI();
|
||||
const resp = await AuthRepository.selfCreateSubscription(payload);
|
||||
return resp.data;
|
||||
},
|
||||
onSuccess: (response, variables) => {
|
||||
if (onSuccessCallBack) onSuccessCallBack(response);
|
||||
},
|
||||
onError: (error) => {
|
||||
showToast(
|
||||
`${error?.response?.data?.errors || ""} ${
|
||||
error?.response?.data?.message || ""
|
||||
} ${error?.response?.data?.statusCode || ""}`.trim() ||
|
||||
error?.message ||
|
||||
"Something went wrong, please try again!",
|
||||
"error"
|
||||
);
|
||||
if (onFailureCallBack) onFailureCallBack();
|
||||
},
|
||||
});
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { PaymentRepository } from "../repositories/PaymentRepository";
|
||||
import showToast from "../services/toastService";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { blockUI, unblockUI } from "../utils/blockUI";
|
||||
import { setSelfTenant } from "../slices/localVariablesSlice";
|
||||
|
||||
export const removeRazorpayArtifacts=()=> {
|
||||
try {
|
||||
@ -56,11 +57,13 @@ const closeRazorpayPopup=()=> {
|
||||
|
||||
export const useVerifyPayment = (onSuccessCallBack, onFailureCallBack) => {
|
||||
const client = useQueryClient();
|
||||
const dispatch = useDispatch()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: (payload) => PaymentRepository.verifyPayment(payload),
|
||||
|
||||
onSuccess: (data) => {
|
||||
dispatch(setSelfTenant({ paymentDetailId: data?.data?.id }));
|
||||
if (onSuccessCallBack) onSuccessCallBack(data);
|
||||
},
|
||||
|
||||
|
||||
@ -97,10 +97,9 @@ const MakeSubscription = () => {
|
||||
name: "Verified",
|
||||
component: () => (
|
||||
<VerifiedPayment
|
||||
onNext={() => {
|
||||
setStepStatus((prev) => ({ ...prev, 5: "success" }))
|
||||
}}
|
||||
responsePayment={responsePayment}
|
||||
responsePayment={responsePayment}
|
||||
setStepStatus={setStepStatus}
|
||||
|
||||
/>
|
||||
),
|
||||
},
|
||||
|
||||
@ -12,7 +12,9 @@ const AuthRepository = {
|
||||
sendMail: (data) => api.postPublic("/api/auth/sendmail", data),
|
||||
getSubscription: (frequency) =>
|
||||
api.getPublic(`/api/market/list/subscription-plan?frequency=${frequency}`),
|
||||
createSuscription:(data)=>api.post(`/api/Tenant/self/create`,data),
|
||||
createSuscription: (data) => api.post(`/api/Tenant/self/create`, data), // this will put entry inside enquiry table
|
||||
selfCreateSubscription: (data) =>
|
||||
api.post(`/api/Tenant/self/subscription`, data),
|
||||
|
||||
// Protected routes (require auth token)
|
||||
logout: (data) => api.post("/api/auth/logout", data),
|
||||
|
||||
@ -37,6 +37,7 @@ const localVariablesSlice = createSlice({
|
||||
planId: null,
|
||||
details:null,
|
||||
frequency:null,
|
||||
paymentDetailId:null
|
||||
},
|
||||
},
|
||||
reducers: {
|
||||
@ -111,6 +112,7 @@ const localVariablesSlice = createSlice({
|
||||
state.selfTenant.details =
|
||||
action.payload.details ?? state.selfTenant.details;
|
||||
state.selfTenant.frequency = action.payload.frequency ?? state.selfTenant.frequency;
|
||||
state.selfTenant.paymentDetailId = action.payload.paymentDetailId ?? state.selfTenant.paymentDetailId;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user