added upgraded subscription functionality

This commit is contained in:
pramod mahajan 2025-08-16 09:43:11 +05:30
parent 6e300389e3
commit 4af5ba8a6d
6 changed files with 172 additions and 116 deletions

View File

@ -173,7 +173,7 @@ const EditProfile = ({ TenantId,onClose }) => {
</div> </div>
<div className="d-flex justify-content-center gap-2 mt-3"> <div className="d-flex justify-content-center gap-2 mt-3">
<button type="submit" disabled={isPending} className="btn btn-sm btn-primary">Submit</button> <button type="submit" disabled={isPending} className="btn btn-sm btn-primary">{isPending ? "Please Wait..." : "Submit"}</button>
<button type="button" disabled={isPending} className="btn btn-sm btn-secondary">Camcel</button> <button type="button" disabled={isPending} className="btn btn-sm btn-secondary">Camcel</button>
</div> </div>
</form> </form>

View File

@ -1,5 +1,5 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { useAddSubscription, useSubscriptionPlan } from "../../hooks/useTenant"; import { useAddSubscription, useSubscriptionPlan, useUpgradeSubscription } from "../../hooks/useTenant";
import SegmentedControl from "./SegmentedControl"; import SegmentedControl from "./SegmentedControl";
import { useFormContext } from "react-hook-form"; import { useFormContext } from "react-hook-form";
import { CONSTANT_TEXT } from "../../utils/constants"; import { CONSTANT_TEXT } from "../../utils/constants";
@ -11,13 +11,14 @@ const SubScription = ({ onSubmitSubScription, onNext }) => {
const [frequency, setFrequency] = useState(2); const [frequency, setFrequency] = useState(2);
const [selectedPlanId, setSelectedPlanId] = useState(null); const [selectedPlanId, setSelectedPlanId] = useState(null);
const selectedTenant = useSelector( const selectedTenant = useSelector(
(store) => store.globalVariables.currentTenant?.data (store) => store.globalVariables.currentTenant
); );
const naviget = useNavigate(); const naviget = useNavigate();
const { const {
data: plans = [], data: plans = [],
isError, isError,
isLoading, isLoading,
error:subscriptionGettingError
} = useSubscriptionPlan(frequency); } = useSubscriptionPlan(frequency);
const { const {
@ -35,6 +36,11 @@ const SubScription = ({ onSubmitSubScription, onNext }) => {
} = useAddSubscription(() => { } = useAddSubscription(() => {
naviget("/tenants") naviget("/tenants")
}); });
const {
mutate : updgradeSubscription,isPending : upgrading
} = useUpgradeSubscription(()=>{
naviget("/tenants")
})
const handleSubscriptionSubmit = async () => { const handleSubscriptionSubmit = async () => {
const isValid = await trigger([ const isValid = await trigger([
"planId", "planId",
@ -48,11 +54,19 @@ const SubScription = ({ onSubmitSubScription, onNext }) => {
if (isValid) { if (isValid) {
const payload = getValues(); const payload = getValues();
// onSubmitSubScription(payload); // onSubmitSubScription(payload);
const subscriptionPayload = { ...payload, tenantId: selectedTenant.id }; let subscriptionPayload = null;
AddSubScription(subscriptionPayload);
if(selectedTenant?.operationMode === 1){
subscriptionPayload = { planId : payload.planId,currencyId :payload.currencyId,maxUsers:payload.maxUsers, tenantId: selectedTenant?.data?.id }
updgradeSubscription(subscriptionPayload)
}else{
subscriptionPayload = {...payload,tenantId: selectedTenant?.data?.id}
AddSubScription(subscriptionPayload);
}
} }
}; };
const handlePlanSelection = (plan) => { const handlePlanSelection = (plan) => {
setSelectedPlanId(plan.id); setSelectedPlanId(plan.id);
setValue("planId", plan.id); setValue("planId", plan.id);
@ -61,7 +75,8 @@ const SubScription = ({ onSubmitSubScription, onNext }) => {
}; };
const selectedPlan = plans.find((p) => p.id === selectedPlanId); const selectedPlan = plans.find((p) => p.id === selectedPlanId);
if(isLoading) return <div className="text-center">Loading....</div>
if(isError) return <div className="text-center">{subscriptionGettingError?.message}</div>
return ( return (
<div className="text-start"> <div className="text-start">
<SegmentedControl setFrequency={setFrequency} /> <SegmentedControl setFrequency={setFrequency} />
@ -208,9 +223,9 @@ const SubScription = ({ onSubmitSubScription, onNext }) => {
onClick={handleSubscriptionSubmit} onClick={handleSubscriptionSubmit}
className="btn btn-sm btn-primary" className="btn btn-sm btn-primary"
type="button" type="button"
disabled={isPending} disabled={isPending || upgrading}
> >
{isPending ? "Please Wait..." : "Submit"} {isPending || upgrading ? "Please Wait..." : "Submit"}
</button> </button>
</div> </div>
</div> </div>

View File

@ -64,83 +64,85 @@ const SubScriptionHistory = ({ tenantId }) => {
if (percentage < 80) return "warning"; if (percentage < 80) return "warning";
return "danger"; return "danger";
}; };
const SubscriptionColumns = [ // const SubscriptionColumns = [
{ // {
key: "createdAt", // key: "createdAt",
label: "Date", // label: "Date",
getValue: (e) => formatUTCToLocalTime(e?.createdAt), // getValue: (e) => formatUTCToLocalTime(e?.createdAt),
align: "text-start", // align: "text-start",
}, // },
{ // {
key: "frequency", // key: "frequency",
label: "Type", // label: "Type",
getValue: (e) => { // getValue: (e) => {
switch (e.frequency) { // switch (e.frequency) {
case 1: // case 1:
return "Monthly"; // return "Monthly";
case 3: // case 3:
return "Quarterly"; // return "Quarterly";
case 12: // case 12:
return "Yearly"; // return "Yearly";
default: // default:
return "N/A"; // return "N/A";
} // }
}, // },
align: "text-start", // align: "text-start",
}, // },
{ // {
key: "price", // key: "price",
label: "Amount", // label: "Amount",
getValue: (e) => ( // getValue: (e) => (
<> // <>
{e.currency?.symbol || "₹"} {e.price} // {e.currency?.symbol || ""} {e.price}
</> // </>
), // ),
align: "text-end", // align: "text-end",
}, // },
{ // {
key: "submittedBy", // key: "submittedBy",
label: "Submitted By", // label: "Submitted By",
getValue: (e) => // getValue: (e) =>
`${e.createdBy?.firstName ?? ""} ${ // `${e.createdBy?.firstName ?? ""} ${
e.createdBy?.lastName ?? "" // e.createdBy?.lastName ?? ""
}`.trim() || "N/A", // }`.trim() || "N/A",
customRender: (e) => ( // customRender: (e) => (
<div className="d-flex align-items-center"> // <div className="d-flex align-items-center">
<Avatar // <Avatar
size="xs" // size="xs"
classAvatar="m-0 me-2" // classAvatar="m-0 me-2"
firstName={e.createdBy?.firstName} // firstName={e.createdBy?.firstName}
lastName={e.createdBy?.lastName} // lastName={e.createdBy?.lastName}
/> // />
<span className="text-truncate"> // <span className="text-truncate">
{`${e.createdBy?.firstName ?? ""} ${ // {`${e.createdBy?.firstName ?? ""} ${
e.createdBy?.lastName ?? "" // e.createdBy?.lastName ?? ""
}`.trim() || "N/A"} // }`.trim() || "N/A"}
</span> // </span>
</div> // </div>
), // ),
align: "text-start", // align: "text-start",
}, // },
{ // {
key: "action", // key: "action",
label: "Action", // label: "Action",
customRender: (e) => ( // customRender: (e) => (
<button // <button
className="btn btn-sm btn-outline-primary" // className="btn btn-sm btn-outline-primary"
onClick={() => console.log("Action clicked for", e.id)} // onClick={() => console.log("Action clicked for", e.id)}
> // >
View // View
</button> // </button>
), // ),
align: "text-center", // align: "text-center",
}, // },
]; // ];
return ( return (
<div className="container-fluid p-2"> <div className=" p-2">
<div className="text-start mb-3"> <div className="text-start mb-3">
<p className="fw-bold">Active Subscription</p> <div className="divider text-start my-1">
<div className="divider-text">Active Subscription</div>
</div>
<div className="row"> <div className="row">
<div className="col-12 col-sm-8 border rounded p-3 shadow-sm"> <div className="col-12 col-sm-8 border rounded p-3 shadow-sm">
@ -176,37 +178,45 @@ const SubScriptionHistory = ({ tenantId }) => {
</div> </div>
</div> </div>
</div> </div>
<div className="text-start"> <div className="text-start my-2">
<table className="table border-top dataTable text-nowrap align-middle">
<thead className="align-middle">
<tr>
<th className="text-start">Date</th>
<th className="text-start">Type</th>
<th className="text-center">Amount</th>
<th className="text-start">Plan Name</th>
<th className="text-center">Action</th>
</tr>
</thead>
<tbody className="align-middle">
{data?.subscriptionHistery?.map((item) => (
<tr key={item.id}>
<td>{formatUTCToLocalTime(item.createdAt)}</td>
<td>{SUBSCRIPTION_PLAN_FREQUENCIES[item.frequency] || "N/A"}</td>
<td className="text-end pe-4 me-3">
<span className="px-3"> {item.currency?.symbol}
{item.price}</span>
</td>
<td className="ps-4">{item.planName}</td>
<td className="text-center">
<i className="bx bx-cloud-download"></i>
</td>
</tr>
))}
</tbody>
</table>
</div> </div>
<div className="divider text-start my-1">
<div className="divider-text"> <i className="bx bx-history"></i> <small>History</small></div>
</div>
<table className="table border-top dataTable text-nowrap align-middle">
<thead className="align-middle">
<tr>
<th className="text-start">Date</th>
<th className="text-start">Type</th>
<th className="text-center">Amount</th>
<th className="text-start">Plan Name</th>
<th className="text-center">Action</th>
</tr>
</thead>
<tbody className="align-middle">
{data?.subscriptionHistery?.map((item) => (
<tr key={item.id}>
<td>{formatUTCToLocalTime(item.createdAt)}</td>
<td>
{SUBSCRIPTION_PLAN_FREQUENCIES[item.frequency] || "N/A"}
</td>
<td className="text-end pe-4 me-3">
<span className="px-3">
{" "}
{item.currency?.symbol}
{item.price}
</span>
</td>
<td className="ps-4">{item.planName}</td>
<td className="text-center">
<i className="bx bx-cloud-download"></i>
</td>
</tr>
))}
</tbody>
</table>
</div> </div>
</div> </div>
); );

View File

@ -36,7 +36,7 @@ useEffect(() => {
} }
} else { } else {
// Default: no tenant selected // Default: no tenant selected
setActiveTab(0); return ;
} }
}, [HasSelectedCurrentTenant,activeTab]); }, [HasSelectedCurrentTenant,activeTab]);

View File

@ -72,7 +72,6 @@ export const useSubscriptionPlan=(freq)=>{
return useQuery({ return useQuery({
queryKey:['SubscriptionPlan',freq], queryKey:['SubscriptionPlan',freq],
queryFn:async()=>{ queryFn:async()=>{
console.log("call")
const res = await TenantRepository.getSubscriptionPlan(freq); const res = await TenantRepository.getSubscriptionPlan(freq);
return res.data; return res.data;
} }
@ -124,12 +123,43 @@ export const useAddSubscription =(onSuccessCallback)=>{
return res.data; return res.data;
}, },
onSuccess:(data,variables)=>{ onSuccess:(data,variables)=>{
const {tenantId} = variables;
showToast("Tenant Plan Added SuccessFully","success") showToast("Tenant Plan Added SuccessFully","success")
queryClient.invalidateQueries({queryKey:["Tenants"]}); queryClient.invalidateQueries({queryKey:["Tenant",tenantId]})
if(onSuccessCallback) onSuccessCallback() if(onSuccessCallback) onSuccessCallback()
}, },
onError:(error)=>{ onError:(error)=>{
showToast(error.response.message || error.message || `Something went wrong`,"error") showToast(error.response.message || error.message || `Something went wrong`,"error")
} }
}) })
} }
export const useUpgradeSubscription = (onSuccessCallback) => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (subscriptionPayload) => {
const res = await TenantRepository.upgradeSubscription(subscriptionPayload);
return res.data;
},
onSuccess: (data, variables) => {
const { tenantId } = variables;
showToast("Tenant Plan Upgraded Successfully", "success");
// Refetch tenant details
queryClient.invalidateQueries({ queryKey: ["Tenant", tenantId] });
queryClient.invalidateQueries({ queryKey: ["Tenants"] });
if (onSuccessCallback) onSuccessCallback();
},
onError: (error) => {
showToast(
error?.response?.message ||
error?.response?.data?.errors ||
error.message ||
"Something went wrong",
"error"
);
}
});
};

View File

@ -16,4 +16,5 @@ export const TenantRepository = {
updateTenantDetails :(id,data)=> api.put(`/api/Tenant/edit/${id}`,data), updateTenantDetails :(id,data)=> api.put(`/api/Tenant/edit/${id}`,data),
addSubscription: (data) => api.post("/api/Tenant/add-subscription", data), addSubscription: (data) => api.post("/api/Tenant/add-subscription", data),
upgradeSubscription :(data)=> api.put("/api/Tenant/update-subscription",data)
}; };