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(
|
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);
|
||||||
@ -144,7 +143,7 @@ const ProcessedPayment = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
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="row gx-1 gy-3 justify-content-between">
|
||||||
<div className="col-12 col-md-6">
|
<div className="col-12 col-md-6">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
@ -309,7 +308,7 @@ const ProcessedPayment = ({
|
|||||||
<div className="col-sm-6">
|
<div className="col-sm-6">
|
||||||
<strong>Email:</strong>
|
<strong>Email:</strong>
|
||||||
</div>
|
</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">
|
<div className="col-sm-6 mb-2">
|
||||||
<strong>Contact Number:</strong>
|
<strong>Contact Number:</strong>
|
||||||
@ -357,7 +356,7 @@ const ProcessedPayment = ({
|
|||||||
className="btn btn-label-primary d-flex align-items-center me-2"
|
className="btn btn-label-primary d-flex align-items-center me-2"
|
||||||
onClick={() => ProcessToPayment(currentPlan?.price)}
|
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>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,23 +1,86 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import GlobalModel from "../common/GlobalModel";
|
import GlobalModel from "../common/GlobalModel";
|
||||||
import Invoice from "./Invoice";
|
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);
|
const [isGenerateInvoice, setIsGenerateInvoice] = useState(false);
|
||||||
|
|
||||||
|
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(() => {
|
useEffect(() => {
|
||||||
if (responsePayment?.success) {
|
if (responsePayment?.success) {
|
||||||
onNext();
|
const payload = { tenantEnquireId, paymentDetailId, planId };
|
||||||
|
getSubscription(payload);
|
||||||
}
|
}
|
||||||
}, [responsePayment]);
|
}, [responsePayment]);
|
||||||
if (responsePayment) {
|
|
||||||
|
|
||||||
|
if (isError) {
|
||||||
return (
|
return (
|
||||||
<div className="container-md mt-5 text-center">
|
<div className="container-md mt-5 text-center">
|
||||||
<div className="d-flex flex-column align-items-center justify-content-center">
|
<div className="d-flex flex-column align-items-center justify-content-center">
|
||||||
<div
|
<div
|
||||||
className="spinner-border text-primary mb-3 p-1"
|
className="bg-danger p-3 rounded-circle mb-3 d-flex align-items-center justify-content-center"
|
||||||
role="status"
|
style={{ width: "70px", height: "70px" }}
|
||||||
></div>
|
>
|
||||||
<h4 className="text-primary mb-2">Verifying payment...</h4>
|
<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">
|
<p className="text-muted">
|
||||||
Please wait while we verify your transaction. Do not refresh or
|
Please wait while we verify your transaction. Do not refresh or
|
||||||
close this page.
|
close this page.
|
||||||
@ -27,8 +90,8 @@ useEffect(() => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!responsePayment?.success) {
|
|
||||||
|
|
||||||
|
if (isSuccess) {
|
||||||
return (
|
return (
|
||||||
<div className="container-md mt-3 text-center h-auto">
|
<div className="container-md mt-3 text-center h-auto">
|
||||||
{isGenerateInvoice && (
|
{isGenerateInvoice && (
|
||||||
@ -39,6 +102,7 @@ useEffect(() => {
|
|||||||
<Invoice invoiceData={responsePayment?.data} />
|
<Invoice invoiceData={responsePayment?.data} />
|
||||||
</GlobalModel>
|
</GlobalModel>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="d-flex align-items-center justify-content-center">
|
<div className="d-flex align-items-center justify-content-center">
|
||||||
<span className="bg-success p-2 p-md-3 rounded-circle">
|
<span className="bg-success p-2 p-md-3 rounded-circle">
|
||||||
<i className="bx bx-check fs-2 fw-bold text-white"></i>
|
<i className="bx bx-check fs-2 fw-bold text-white"></i>
|
||||||
@ -48,19 +112,19 @@ useEffect(() => {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</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
|
Thank you for your payment. Your <strong>subscription</strong> has
|
||||||
been successfully activated.
|
been successfully activated.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div className="mt-8">
|
<div className="mt-3">
|
||||||
<small className="text-muted">
|
<small className="text-muted">
|
||||||
A Set Password link has been sent to your registered email address .
|
A <strong>Set Password</strong> link has been sent to your
|
||||||
Please check your inbox .
|
registered email address. Please check your inbox.
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</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">
|
<a href="/" className="btn btn-info px-4 py-2 fw-semibold">
|
||||||
Go to Dashboard
|
Go to Dashboard
|
||||||
</a>
|
</a>
|
||||||
@ -79,3 +143,5 @@ useEffect(() => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default VerifiedPayment;
|
export default VerifiedPayment;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import {
|
|||||||
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";
|
import eventBus from "../services/eventBus.js";
|
||||||
|
import { blockUI } from "../utils/blockUI.js";
|
||||||
|
|
||||||
// ----------------------------Modal--------------------------
|
// ----------------------------Modal--------------------------
|
||||||
|
|
||||||
@ -39,7 +40,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
|
enabled: frequency !== null && frequency !== undefined,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -88,18 +89,53 @@ export const useCreateSelfTenant = (onSuccessCallBack, onFailureCallBack) => {
|
|||||||
return resp.data;
|
return resp.data;
|
||||||
},
|
},
|
||||||
onSuccess: (response, variables) => {
|
onSuccess: (response, variables) => {
|
||||||
|
|
||||||
dispatch(
|
dispatch(
|
||||||
setSelfTenant({
|
setSelfTenant({
|
||||||
tenantEnquireId: response?.id,
|
tenantEnquireId: response?.id,
|
||||||
planId: null,
|
planId: null,
|
||||||
details:response
|
details: response,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
if (onSuccessCallBack) onSuccessCallBack(response);
|
if (onSuccessCallBack) onSuccessCallBack(response);
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
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();
|
if (onFailureCallBack) onFailureCallBack();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||||
import { PaymentRepository } from "../repositories/PaymentRepository";
|
import { PaymentRepository } from "../repositories/PaymentRepository";
|
||||||
import showToast from "../services/toastService";
|
import showToast from "../services/toastService";
|
||||||
import { useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { blockUI, unblockUI } from "../utils/blockUI";
|
import { blockUI, unblockUI } from "../utils/blockUI";
|
||||||
|
import { setSelfTenant } from "../slices/localVariablesSlice";
|
||||||
|
|
||||||
export const removeRazorpayArtifacts=()=> {
|
export const removeRazorpayArtifacts=()=> {
|
||||||
try {
|
try {
|
||||||
@ -56,11 +57,13 @@ const closeRazorpayPopup=()=> {
|
|||||||
|
|
||||||
export const useVerifyPayment = (onSuccessCallBack, onFailureCallBack) => {
|
export const useVerifyPayment = (onSuccessCallBack, onFailureCallBack) => {
|
||||||
const client = useQueryClient();
|
const client = useQueryClient();
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: (payload) => PaymentRepository.verifyPayment(payload),
|
mutationFn: (payload) => PaymentRepository.verifyPayment(payload),
|
||||||
|
|
||||||
onSuccess: (data) => {
|
onSuccess: (data) => {
|
||||||
|
dispatch(setSelfTenant({ paymentDetailId: data?.data?.id }));
|
||||||
if (onSuccessCallBack) onSuccessCallBack(data);
|
if (onSuccessCallBack) onSuccessCallBack(data);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@ -97,10 +97,9 @@ const MakeSubscription = () => {
|
|||||||
name: "Verified",
|
name: "Verified",
|
||||||
component: () => (
|
component: () => (
|
||||||
<VerifiedPayment
|
<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),
|
sendMail: (data) => api.postPublic("/api/auth/sendmail", data),
|
||||||
getSubscription: (frequency) =>
|
getSubscription: (frequency) =>
|
||||||
api.getPublic(`/api/market/list/subscription-plan?frequency=${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)
|
// Protected routes (require auth token)
|
||||||
logout: (data) => api.post("/api/auth/logout", data),
|
logout: (data) => api.post("/api/auth/logout", data),
|
||||||
|
|||||||
@ -37,6 +37,7 @@ const localVariablesSlice = createSlice({
|
|||||||
planId: null,
|
planId: null,
|
||||||
details:null,
|
details:null,
|
||||||
frequency:null,
|
frequency:null,
|
||||||
|
paymentDetailId:null
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
reducers: {
|
reducers: {
|
||||||
@ -111,6 +112,7 @@ const localVariablesSlice = createSlice({
|
|||||||
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;
|
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