From aa1fc0061173534a59128252b18bfc26b8411141 Mon Sep 17 00:00:00 2001 From: "pramod.mahajan" Date: Sat, 25 Oct 2025 15:37:38 +0530 Subject: [PATCH 001/146] initially setup paymentgatway --- src/hooks/usePayments.jsx | 37 ++++++++ src/pages/Home/SubscriptionSummary.jsx | 117 +++++++++++++++++++++++++ src/repositories/PaymentRepository.jsx | 7 ++ src/router/AppRoutes.jsx | 3 + 4 files changed, 164 insertions(+) create mode 100644 src/hooks/usePayments.jsx create mode 100644 src/pages/Home/SubscriptionSummary.jsx create mode 100644 src/repositories/PaymentRepository.jsx diff --git a/src/hooks/usePayments.jsx b/src/hooks/usePayments.jsx new file mode 100644 index 00000000..42ce6558 --- /dev/null +++ b/src/hooks/usePayments.jsx @@ -0,0 +1,37 @@ +import { useMutation, useQueryClient } from "@tanstack/react-query"; +import { PaymentRepository } from "../repositories/PaymentRepository"; + +export const useMakePayment = (onSuccessCallBack) => { + const client = useQueryClient(); + return useMutation({ + mutationFn: (payload) => PaymentRepository.makePayment(payload), + onSuccess: (_, varibales) => { + if (onSuccessCallBack) onSuccessCallBack(); + }, + onError: (error) => { + showToast( + error.message || + error.response.message || + "Something went wrong.Please try again later.", + "error" + ); + }, + }); +}; +export const useVerifyPayment = () => { + const client = useQueryClient(); + return useMutation({ + mutationFn: (payload) => PaymentRepository.verifyPayment(payload), + onSuccess: (_, varibales) => { + if (onSuccessCallBack) onSuccessCallBack(); + }, + onError: (error) => { + showToast( + error.message || + error.response.message || + "Something went wrong.Please try again later.", + "error" + ); + }, + }); +}; diff --git a/src/pages/Home/SubscriptionSummary.jsx b/src/pages/Home/SubscriptionSummary.jsx new file mode 100644 index 00000000..733ec81a --- /dev/null +++ b/src/pages/Home/SubscriptionSummary.jsx @@ -0,0 +1,117 @@ +import React from "react"; + +const SubscriptionSummary = () => { + const options = [ + { + id: 1, + title: "Design", + description: "Cake sugar plum fruitcake I love sweet roll jelly-o.", + svg: ( + + + + ), + }, + { + id: 2, + title: "Development", + description: "Cake sugar plum fruitcake I love sweet roll jelly-o.", + svg: ( + + + + ), + }, + { + id: 3, + title: "Native App", + description: "Cake sugar plum fruitcake I love sweet roll jelly-o.", + svg: ( + + + + ), + }, + ]; + + return ( +
+ {/* Section title aligned at start */} +
+

Summary

+
+ +
+
+
+ {options.map((opt) => ( +
+
+ +
+
+ ))} +
+
+ +
+ {/* Add your right-side content here */} +
+
+
+ + ); +}; + +export default SubscriptionSummary; diff --git a/src/repositories/PaymentRepository.jsx b/src/repositories/PaymentRepository.jsx new file mode 100644 index 00000000..f3e7b5c5 --- /dev/null +++ b/src/repositories/PaymentRepository.jsx @@ -0,0 +1,7 @@ +import { api } from "../utils/axiosClient"; + + +export const PaymentRepository = { + makePayment: () => api.post(`/api/Payment/create-order`), + verifyPayment: () => api.post(`/api/Payment/verify-payment`), +}; diff --git a/src/router/AppRoutes.jsx b/src/router/AppRoutes.jsx index ac736d7b..f97be55f 100644 --- a/src/router/AppRoutes.jsx +++ b/src/router/AppRoutes.jsx @@ -54,6 +54,7 @@ import ProjectPage from "../pages/project/ProjectPage"; import { ComingSoonPage } from "../pages/Misc/ComingSoonPage"; import ImageGalleryPage from "../pages/Gallary/ImageGallaryPage"; import CollectionPage from "../pages/collections/CollectionPage"; +import SubscriptionSummary from "../pages/Home/SubscriptionSummary"; const router = createBrowserRouter( [ { @@ -70,9 +71,11 @@ const router = createBrowserRouter( { path: "/reset-password", element: }, { path: "/legal-info", element: }, { path: "/auth/changepassword", element: }, + ], }, { path: "/auth/switch/org", element: }, + { path: "/request", element: }, { element: , errorElement: , From e95a78e1a35e9a1359ba93ffaffdd131ab47658e Mon Sep 17 00:00:00 2001 From: "pramod.mahajan" Date: Wed, 29 Oct 2025 10:58:28 +0530 Subject: [PATCH 002/146] added payment getway using raz razorpay --- index.html | 5 + public/assets/css/core-extend.css | 149 ++++++++ public/img/illustrations/undraw_pricing.png | Bin 0 -> 69916 bytes public/img/illustrations/undraw_pricing.svg | 1 + src/components/UserSubscription/Invoice.jsx | 306 +++++++++++++++ .../UserSubscription/ProcessedPayment.jsx | 358 ++++++++++++++++++ .../UserSubscription/SelectPlan.jsx | 238 ++++++++++++ .../UserSubscription/SubscriptionForm.jsx | 259 +++++++++++++ .../UserSubscription/SubscriptionLayout.jsx | 57 +++ .../UserSubscription/VerifiedPayment.jsx | 81 ++++ src/hooks/useAuth.jsx | 28 ++ src/hooks/usePayments.jsx | 192 ++++++++-- src/pages/Home/HomeSchema.jsx | 27 ++ src/pages/Home/MakeSubscription.jsx | 127 +++++++ src/pages/Home/SubscriptionPlans.jsx | 22 +- src/repositories/AuthRepository.jsx | 1 + src/router/AppRoutes.jsx | 3 +- src/slices/localVariablesSlice.jsx | 15 +- src/utils/appUtils.js | 14 + src/utils/blockUI.js | 32 ++ 20 files changed, 1882 insertions(+), 33 deletions(-) create mode 100644 public/img/illustrations/undraw_pricing.png create mode 100644 public/img/illustrations/undraw_pricing.svg create mode 100644 src/components/UserSubscription/Invoice.jsx create mode 100644 src/components/UserSubscription/ProcessedPayment.jsx create mode 100644 src/components/UserSubscription/SelectPlan.jsx create mode 100644 src/components/UserSubscription/SubscriptionForm.jsx create mode 100644 src/components/UserSubscription/SubscriptionLayout.jsx create mode 100644 src/components/UserSubscription/VerifiedPayment.jsx create mode 100644 src/pages/Home/HomeSchema.jsx create mode 100644 src/pages/Home/MakeSubscription.jsx create mode 100644 src/utils/blockUI.js diff --git a/index.html b/index.html index 0ac2d657..69b46b21 100644 --- a/index.html +++ b/index.html @@ -95,6 +95,11 @@ + + + + + diff --git a/public/assets/css/core-extend.css b/public/assets/css/core-extend.css index 1ecc882c..aec7ebc9 100644 --- a/public/assets/css/core-extend.css +++ b/public/assets/css/core-extend.css @@ -3,6 +3,27 @@ --bs-nav-link-font-size: 0.7375rem; --bg-border-color :#f8f6f6 } +/* ===========================% Background_Colors %========================================================== */ +.bg-light-primary { + background-color: color-mix(in srgb, var(--bs-primary) 10.4%, transparent); + border:var(--bs-primary-border-subtle) +} +.bg-light-secondary { + background-color: color-mix(in srgb, var(--bs-secondary) 10.4%, transparent); +} +.bg-light-danger { + background-color: color-mix(in srgb, var(--bs-danger) 10.4%, transparent); +} +.bg-light-success { + background-color: color-mix(in srgb, var(--bs-success) 10.4%, transparent); +} + +.bg-light-info { + background-color: color-mix(in srgb, var(--bs-info) 10.4%, transparent); +} +.bg-light-warning { + background-color: color-mix(in srgb, var(--bs-warning) 10.4%, transparent); +} .card-header { padding: 0.5rem var(--bs-card-cap-padding-x); @@ -25,6 +46,101 @@ font-size: 2rem; .text-md-b { font-weight: normal; } +.stepper-container { + position: relative; +} + +.timeline-horizontal { + position: relative; + padding: 0; + margin: 0; +} + +.timeline-item { + position: relative; + flex: 1; +} + +.timeline-point { + width: 20px; + height: 20px; + border-radius: 50%; + background: #dee2e6; + color: #6c757d; + display: flex; + justify-content: center; + align-items: center; + font-weight: 600; + z-index: 2; + position: relative; + padding: 3px; + transition: all 0.3s ease; +} + +.timeline-point.completed { + background-color: var(--bs-success); + color: #fff; + box-shadow: 0 0 5px rgba(25, 135, 84, 0.5); +} + +.timeline-point.failed { + background-color: var(--bs-danger); + color: #fff; + box-shadow: 0 0 5px rgba(220, 53, 69, 0.5); +} + +.timeline-point.active { + background-color: var(--bs-info); + color: #fff; + transform: scale(1.15); + box-shadow: 0 0 6px rgba(13, 202, 240, 0.5); +} + +.timeline-line-horizontal { + content: ""; + position: absolute; + top: 10px; + left: 50%; + width: 100%; + height: 2px; + background-color: #dee2e6; + z-index: 1; + transition: background-color 0.3s ease; +} + +/* Make line green for completed sections */ +.timeline-item.completed ~ .timeline-line-horizontal { + background-color: var(--bs-success); +} + +/* Optional: subtle pulse for active step */ +.timeline-point.active::after { + content: ""; + position: absolute; + width: 25px; + height: 25px; + border-radius: 50%; + border: 2px solid var(--bs-info); + animation: pulse 1.5s infinite; + opacity: 0.6; +} + +@keyframes pulse { + 0% { + transform: scale(1); + opacity: 0.6; + } + 70% { + transform: scale(1.5); + opacity: 0; + } + 100% { + transform: scale(1); + opacity: 0; + } +} + + .text-xxs { font-size: 0.55rem; } /* 8px */ .text-xs { font-size: 0.75rem; } /* 12px */ @@ -294,3 +410,36 @@ font-weight: normal; .w-8-xl{ width: 2rem; } .w-10-xl{ width: 2.5rem; } } + + +/* ------------------------Text------------------------- */ +@media (min-width: 576px) { + .fs-sm-1 { font-size: calc(1.3rem + 1.6vw) !important; } + .fs-sm-2 { font-size: calc(1.2rem + 1.2vw) !important; } + .fs-sm-3 { font-size: calc(1.1rem + 0.8vw) !important; } + .fs-sm-4 { font-size: calc(1rem + 0.5vw) !important; } + .fs-sm-5 { font-size: 1.05rem !important; } + .fs-sm-6 { font-size: 0.9rem !important; } + + .fs-sm-tiny { font-size: 72% !important; } + .fs-sm-big { font-size: 115% !important; } + .fs-sm-large { font-size: 155% !important; } + .fs-sm-xlarge { font-size: 175% !important; } + .fs-sm-xxlarge { font-size: calc(1.6rem + 3.5vw) !important; } +} + +/* 💻 Medium devices (≥768px) */ +@media (min-width: 768px) { + .fs-md-1 { font-size: calc(1.4125rem + 1.95vw) !important; } + .fs-md-2 { font-size: calc(1.3625rem + 1.35vw) !important; } + .fs-md-3 { font-size: calc(1.3rem + 0.6vw) !important; } + .fs-md-4 { font-size: calc(1.275rem + 0.3vw) !important; } + .fs-md-5 { font-size: 1.125rem !important; } + .fs-md-6 { font-size: 0.9375rem !important; } + + .fs-md-tiny { font-size: 70% !important; } + .fs-md-big { font-size: 112% !important; } + .fs-md-large { font-size: 150% !important; } + .fs-md-xlarge { font-size: 170% !important; } + .fs-md-xxlarge { font-size: calc(1.725rem + 5.7vw) !important; } +} \ No newline at end of file diff --git a/public/img/illustrations/undraw_pricing.png b/public/img/illustrations/undraw_pricing.png new file mode 100644 index 0000000000000000000000000000000000000000..151bb16a2ace1851b5d7113a040bf282224f5ba8 GIT binary patch literal 69916 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 literal 0 HcmV?d00001 diff --git a/public/img/illustrations/undraw_pricing.svg b/public/img/illustrations/undraw_pricing.svg new file mode 100644 index 00000000..8966ea28 --- /dev/null +++ b/public/img/illustrations/undraw_pricing.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/UserSubscription/Invoice.jsx b/src/components/UserSubscription/Invoice.jsx new file mode 100644 index 00000000..2583a451 --- /dev/null +++ b/src/components/UserSubscription/Invoice.jsx @@ -0,0 +1,306 @@ +import React, { useRef, useState } from "react"; +import html2canvas from "html2canvas"; +import jsPDF from "jspdf"; +import { formatFigure } from "../../utils/appUtils"; + +const Invoice = ({ invoiceData, currencySymbol }) => { + const [isGenerating, setIsGenerating] = useState(false); + const invoiceRef = useRef(null); + + const data = invoiceData || { + razorpayPaymentDetails: { + amount: 19999, + bankDetails: null, + captured: true, + cardDetails: { + cardId: null, + cardType: null, + emi: false, + international: false, + issuer: null, + last4Digits: null, + network: null, + subType: null, + }, + contact: "+919145445127", + createdAt: "2025-10-25T06:46:30", + currency: "INR", + description: "", + email: "avn18042001@gmail.com", + errorCode: "", + errorDescription: "", + fee: 707.97, + internationalPayment: true, + method: "card", + orderId: "order_RXbzfh8d1X1SSg", + paymentId: "pay_RXc08bJHVpjytP", + status: "captured", + tax: 108, + upiDetails: null, + walletDetails: null, + }, + razorpayOrderDetails: { + amount: 19999, + amountDue: 0, + amountPaid: 19999, + attempts: 1, + createdAt: "2025-10-25T06:46:02", + currency: "INR", + orderId: "order_RXbzfh8d1X1SSg", + receipt: "rec_aae16ec3-9571-4c96-bd77-59950fdce236", + status: "paid", + }, + }; + + const formatAmount = (amount) => { + return currencySymbol + amount.toFixed(2); + }; + + const formatDate = (dateString) => { + const date = new Date(dateString); + return date.toLocaleDateString("en-IN", { + year: "numeric", + month: "short", + day: "numeric", + hour: "2-digit", + minute: "2-digit", + }); + }; + + const downloadPDF = async () => { + setIsGenerating(true); + + try { + const invoice = invoiceRef.current; + const canvas = await html2canvas(invoice, { + scale: 2, + useCORS: true, + logging: false, + backgroundColor: "#ffffff", + }); + + const imgData = canvas.toDataURL("image/png"); + const pdf = new jsPDF({ + orientation: "portrait", + unit: "mm", + format: "a4", + }); + + const imgWidth = 210; + const pageHeight = 297; + const imgHeight = (canvas.height * imgWidth) / canvas.width; + + pdf.addImage(imgData, "PNG", 0, 0, imgWidth, imgHeight); + + const paymentId = data.razorpayPaymentDetails.paymentId; + pdf.save(`Invoice_${paymentId}.pdf`); + } catch (error) { + console.error("Error generating PDF:", error); + alert("Failed to generate PDF. Please try again."); + } finally { + setIsGenerating(false); + } + }; + + const payment = data.razorpayPaymentDetails; + const order = data.razorpayOrderDetails; + const subtotal = payment.amount - payment.fee - payment.tax; + + return ( +
+ + +
+
+ {/* Header */} +
+
+

INVOICE

+ Payment Receipt +
+
+
+ INV-{payment.paymentId.slice(-8).toUpperCase()} +
+
+
+ Date: {formatDate(payment.createdAt)} +
+
+ Payment ID: {payment.paymentId} +
+
+ + {order.status.toUpperCase()} + +
+
+ +
+ + {/* Billing Details */} +
+
+
Bill To
+

{payment.customerName || "N/A"}

+

{payment.email || "N/A"}

+

{payment.contact || "N/A"}

+
+
+
+ Payment Information +
+

+ Order ID: {order.orderId} +

+

+ Receipt: {order.receipt} +

+

+ Method:{" "} + {payment.method.charAt(0).toUpperCase() + + payment.method.slice(1)} +

+
+
+ +
+ + {/* Transaction Details */} +
+
+ Transaction Details +
+
+
+
+ Payment Status + + {payment.status.charAt(0).toUpperCase() + + payment.status.slice(1)} + +
+
+
+
+ Currency + {payment.currency} +
+
+
+
+ Card Type + + {payment.cardDetails?.cardType || + payment.method.toUpperCase()} + +
+
+
+
+ Last 4 Digits + + {payment.cardDetails?.last4Digits || "N/A"} + +
+
+
+
+ International + + {payment.internationalPayment ? "Yes" : "No"} + +
+
+
+
+ Captured + + {payment.captured ? "Yes" : "No"} + +
+
+
+
+ +
+ + {/* Amount Breakdown */} +
+
+ Payment Summary +
+
+
+ + + + + + + + + + + + + + + + + + + +
Subtotal{formatFigure(subtotal.toFixed(2),{ + type: "currency", + currency: payment.currency, + })}
Processing Fee{formatFigure(payment.fee.toFixed(2),{ + type: "currency", + currency: payment.currency, + })}
Tax{formatFigure(payment.tax.toFixed(2),{ + type: "currency", + currency: payment.currency, + })}
Total Paid + {formatFigure(payment.amount, { + type: "currency", + currency: payment.currency, + })} +
+
+
+
+ +
+ + {/* Footer */} +
+

+ Thank you for your payment! +

+ + This is a computer-generated invoice and does not require a + signature. + + + Generated on:{" "} + {new Date().toLocaleDateString("en-IN", { + year: "numeric", + month: "long", + day: "numeric", + hour: "2-digit", + minute: "2-digit", + })} + +
+
+
+
+ ); +}; + +export default Invoice; diff --git a/src/components/UserSubscription/ProcessedPayment.jsx b/src/components/UserSubscription/ProcessedPayment.jsx new file mode 100644 index 00000000..69f70e3a --- /dev/null +++ b/src/components/UserSubscription/ProcessedPayment.jsx @@ -0,0 +1,358 @@ +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 { 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 { useMakePayment } from "../../hooks/usePayments"; +import { formatFigure, frequencyLabel } from "../../utils/appUtils"; + +const ProcessedPayment = ({ + onNext, + resetPaymentStep, + setCurrentStep, + setStepStatus, + resetFormStep, +}) => { + const { frequency, planName } = useParams(); + + const { details: client, planId: selectedPlanId } = useSelector( + (store) => store.localVariables.selfTenant + ); + const [selectedPlan, setSelectedPlan] = useState(null); + const [currentPlan, setCurrentPlan] = useState(null); + const [failPayment, setFailPayment] = useState(null); + + const { + data: plans, + isError: isPlanError, + isLoading, + } = useSubscription(frequency); + + useEffect(() => { + if (!plans || !selectedPlanId) return; + const selected = plans.find((p) => p.id === selectedPlanId); + setSelectedPlan(selected); + }, [plans, selectedPlanId]); + + const loadScript = (src) => + new Promise((resolve) => { + const script = document.createElement("script"); + script.src = src; + script.onload = () => resolve(true); + script.onerror = () => resolve(false); + document.body.appendChild(script); + }); + + const { mutate: MakePayment, isPending } = useMakePayment( + (response) => { + + unblockUI(); + onNext(response); + }, + (fail) => { + + unblockUI(); + setFailPayment(fail); + onNext(fail); + }, + currentPlan + ); + + const ProcessToPayment = async () => { + setStepStatus((prev) => ({ ...prev, 3: "success" })); + setCurrentStep(4); + const res = await loadScript( + "https://checkout.razorpay.com/v1/checkout.js" + ); + if (!res) { + alert("Failed to load Razorpay SDK"); + return; + } + MakePayment({ amount: 1 }); + }; + + const handleRetry = () => { + setFailPayment(null); + if (typeof resetPaymentStep === "function") resetPaymentStep(); + }; + const handlPrevious=()=>{ + setCurrentStep, + setStepStatus((prev) => ({ ...prev, 2: "pending",3:"pending" })); + setCurrentStep(2); + } + + // useEffect(() => { + // if (!client || Object.keys(client).length === 0) { + // setFailPayment(null); + // if (typeof resetFormStep === "function") { + // resetFormStep(); + // } + // } + // }, [client]); + + if (failPayment) { + return ( +
+ ); + } + return ( +
+
+
+
+
+

You’ve Selected the Perfect Plan for Your Organization

+

+ Great choice! This plan is tailored to meet your team’s needs + and help you maximize productivity. +

+
+ {selectedPlan && ( +
+
+
+ {selectedPlan?.planName} + +
+ +
+ + {selectedPlan?.currency?.symbol} {selectedPlan?.price} /{" "} + {frequencyLabel(frequency)} + +
+ + + {selectedPlan?.description} + +
+
+ )} + + {selectedPlan && ( +
+
+ {(() => { + const { + planName, + description, + price, + frequency, + trialDays, + maxUser, + maxStorage, + currency, + features, + } = selectedPlan; + return ( + <> +
+
+
+ + Max Users: {maxUser} +
+
+
+
+ + Max Storage: {maxStorage} MB +
+
+
+
+ + Trial Days: {trialDays} +
+
+
+ +
+ Included Features +
+
+ {features && + Object.entries(features?.modules || {}) + .filter(([key]) => key !== "id") + .map(([key, mod]) => ( +
+ + {mod.name} +
+ ))} +
+ +
+ Support +
+
    + {features?.supports?.emailSupport && ( +
  • + + Email Support +
  • + )} + {features?.supports?.phoneSupport && ( +
  • + + Phone Support +
  • + )} + {features?.supports?.prioritySupport && ( +
  • + + Priority Support +
  • + )} +
+
+
+
+
Duration
+
+ {frequencyLabel(selectedPlan?.frequency, true)} +
+
+ +
+
Total Price
+
+ {formatFigure(selectedPlan?.price, { + type: "currency", + currency: selectedPlan?.currency.currencyCode, + })} +
+
+
+ + ); + })()} +
+
+ )} +
+
+
+ + {client && ( +
+
Confirm your organization details.
+
+
+ Name: +
+
{client.firstName} {client.lastName}
+ + +
+ Email: +
+
{client.email}
+ +
+ Contact Number: +
+
{client.contactNumber}
+ +
+ Organization Name: +
+
{client.organizationName}
+ + + +
+ Onboarding Date: +
+
+ {formatUTCToLocalTime(client.onBoardingDate)} +
+ +
+ Billing Address: +
+
{client.billingAddress}
+ +
+ Industry : +
+
{client?.industry?.name}
+
+
+ )} +
+
+
+ + +
+
+ ); +}; + +export default ProcessedPayment; diff --git a/src/components/UserSubscription/SelectPlan.jsx b/src/components/UserSubscription/SelectPlan.jsx new file mode 100644 index 00000000..7bc3cd56 --- /dev/null +++ b/src/components/UserSubscription/SelectPlan.jsx @@ -0,0 +1,238 @@ +import React, { useEffect, useState } from "react"; +import { useDispatch, useSelector } from "react-redux"; +import { useParams } from "react-router-dom"; +import { useSubscription } from "../../hooks/useAuth"; +import { formatFigure, frequencyLabel } from "../../utils/appUtils"; +import { setSelfTenant } from "../../slices/localVariablesSlice"; + +const SelectPlan = ({ currentStep, setStepStatus, onNext }) => { + const { frequency, planName } = useParams(); + const dispatch = useDispatch(); + + const client = useSelector( + (store) => store.localVariables.selfTenant.details + ); + const [selectedPlan, setSelectedPlan] = useState(planName); + const [currentPlan, setCurrentPlan] = useState(null); + const [failPayment, setFailPayment] = useState(null); + + const { + data: plans, + isError: isPlanError, + isLoading, + } = useSubscription(frequency); + + 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 })); + } + }, [plans, selectedPlan, dispatch]); + + const handleNextStep = () => { + setStepStatus((prev) => ({ ...prev, 2: "success"})); + onNext(); + }; + + return ( +
+
+
+
+
+

Choose the Perfect Plan for Your Organization

+

+ Select a plan that fits your team’s needs and unlock the + features that drive productivity. +

+
+ + {plans?.map((plan) => ( +
+
+ +
+
+ ))} + + {selectedPlan && ( +
+
+ {(() => { + const selected = plans?.find( + (p) => p.planName === selectedPlan + ); + if (!selected) return null; + + const { + price, + frequency, + trialDays, + maxUser, + maxStorage, + currency, + features, + } = selected; + + return ( + <> +
+
+
+ + Max Users: {maxUser} +
+
+
+
+ + Max Storage: {maxStorage} MB +
+
+
+
+ + Trial Days: {trialDays} +
+
+
+ +
+ Included Features +
+
+ {features && + Object.entries(features?.modules || {}) + .filter(([key]) => key !== "id") + .map(([key, mod]) => ( +
+ + {mod.name} +
+ ))} +
+ +
+ Support +
+
    + {features?.supports?.emailSupport && ( +
  • + + Email Support +
  • + )} + {features?.supports?.phoneSupport && ( +
  • + + Phone Support +
  • + )} + {features?.supports?.prioritySupport && ( +
  • + + Priority Support +
  • + )} +
+ +
+
+
+
Duration
+
+ {frequencyLabel(frequency, true)} +
+
+ +
+
Total Price
+
+ {formatFigure(price, { + type: "currency", + currency: currency.currencyCode, + })} +
+
+
+ + ); + })()} +
+
+ )} +
+
+ + {/* Image Section */} +
+ image +
+
+ +
+ +
+
+ + ); +}; + +export default SelectPlan; diff --git a/src/components/UserSubscription/SubscriptionForm.jsx b/src/components/UserSubscription/SubscriptionForm.jsx new file mode 100644 index 00000000..d9317580 --- /dev/null +++ b/src/components/UserSubscription/SubscriptionForm.jsx @@ -0,0 +1,259 @@ +import React, { useState, useMemo } from "react"; +import { useForm } from "react-hook-form"; +import { + OrganizationDefaultValue, + OrganizationSchema, +} from "../../pages/Home/HomeSchema"; +import { zodResolver } from "@hookform/resolvers/zod"; +import Label from "../common/Label"; +import { orgSize, reference } from "../../utils/constants"; +import DatePicker from "../common/DatePicker"; +import { useCreateTenant, useIndustries } from "../../hooks/useTenant"; +import { useCreateSelfTenant } from "../../hooks/useAuth"; +import { blockUI } from "../../utils/blockUI"; + +const SubscriptionForm = ({ currentStep, setCurrentStep, setStepStatus }) => { + const { data, isError, isLoading: industryLoading } = useIndustries(); + const { + register, + handleSubmit, + control, + formState: { errors }, + reset, + } = useForm({ + resolver: zodResolver(OrganizationSchema), + defaultValues: OrganizationDefaultValue, + }); + + const { mutate: CreateTenant, isPending } = useCreateSelfTenant( + (resp) => { + debugger + setStepStatus((prev) => ({ ...prev, [currentStep]: "success" })); + setCurrentStep((prev) => prev + 1); + }, + (error) => { + setStepStatus((prev) => ({ ...prev, [currentStep]: "failed" })); + } + ); + + const onSubmit = (data) => { + CreateTenant(data); + // reset(); + }; + return ( +
+
+
+
+
+
+
+ {/* First Name */} +
+ + + {errors.firstName && ( +
+ {errors.firstName.message} +
+ )} +
+ + {/* Last Name */} +
+ + + {errors.lastName && ( +
+ {errors.lastName.message} +
+ )} +
+ + {/* Email */} +
+ + + {errors.email && ( +
{errors.email.message}
+ )} +
+ + {/* Contact Number */} +
+ + + {errors.contactNumber && ( +
+ {errors.contactNumber.message} +
+ )} +
+ + {/* Billing Address */} +
+ + + {errors.about && (
{ - + {errors.oragnizationSize && (
{ - + {errors.industryId && (
{ privacy policy & terms -
{errors.terms && (
{ aria-label="Click me " className="btn btn-primary d-grid w-100" > - {Loading ? "Please Wait..." :" Request Demo"} + {Loading ? "Please Wait..." : " Request Demo"} @@ -313,4 +323,4 @@ const RegisterPage = () => { ); }; -export default RegisterPage; \ No newline at end of file +export default RegisterPage; From c216ea11622b4ff0814344882d87b8fd429584c8 Mon Sep 17 00:00:00 2001 From: Vikas Nale Date: Mon, 3 Nov 2025 12:32:34 +0530 Subject: [PATCH 019/146] some minor label changes --- public/img/icons/diamond-info - Copy.svg | 5 +++ public/img/icons/google-play-icon.png | Bin 3576 -> 4457 bytes src/pages/Home/LandingPage.jsx | 47 +++++++++++++---------- 3 files changed, 31 insertions(+), 21 deletions(-) create mode 100644 public/img/icons/diamond-info - Copy.svg diff --git a/public/img/icons/diamond-info - Copy.svg b/public/img/icons/diamond-info - Copy.svg new file mode 100644 index 00000000..5f24f9ef --- /dev/null +++ b/public/img/icons/diamond-info - Copy.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/img/icons/google-play-icon.png b/public/img/icons/google-play-icon.png index 117bcb16157e765ced14c248cf20b0161c8dc165..1365ff35e55a82c4c448f1ee533ca2364928940c 100644 GIT binary patch literal 4457 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 literal 3576 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 {
{" "}
- keyboard + keyboard
Inventory Management

@@ -448,7 +448,7 @@ const LandingPage = () => { {" "} @@ -639,7 +639,7 @@ const LandingPage = () => { aria-expanded="true" aria-controls="accordionOne" > - What is MarcoPMS? + What is OnFieldWork.com? @@ -696,7 +696,7 @@ const LandingPage = () => { aria-expanded="false" aria-controls="accordionThree" > - How secure is Marco PMS? + How secure is OnFieldWork.com?

{ data-bs-parent="#accordionExample" >
- Security is at the core of Marco PMS. We use + Security is at the core of OnFieldWork.com. We use industry-standard encryption (SSL/TLS) to protect data in transit and advanced encryption to safeguard data at rest. Role-based access controls ensure that only @@ -766,13 +766,13 @@ const LandingPage = () => { data-bs-parent="#accordionExample" >
- Marco PMS operate under a proprietary license combined - with a subscription model. This means customers don’t - own the software but are granted the right to access and - use it through the cloud under our Terms of Service. - Depending on the plan, licensing may be based on users, - features, or usage, and you can upgrade, downgrade, or - cancel at any time. non! + OnFieldWork.com operate under a proprietary license + combined with a subscription model. This means customers + don’t own the software but are granted the right to + access and use it through the cloud under our Terms of + Service. Depending on the plan, licensing may be based + on users, features, or usage, and you can upgrade, + downgrade, or cancel at any time. non!
@@ -786,7 +786,7 @@ const LandingPage = () => { aria-expanded="false" aria-controls="accordionSix" > - Can I customize Marco PMS for my business needs? + Can I customize OnFieldWork.com for my business needs?
{ data-bs-parent="#accordionExample" >
- Yes, Marco PMS is designed to be flexible and adaptable. - You can customize workflows, user roles, permissions, - and reporting to match your organization’s unique - processes. Depending on your plan, we also support - advanced customization such as integrating with + Yes, OnFieldWork.com is designed to be flexible and + adaptable. You can customize workflows, user roles, + permissions, and reporting to match your organization’s + unique processes. Depending on your plan, we also + support advanced customization such as integrating with third-party tools, adding custom fields, and tailoring modules to fit your business requirements.
@@ -835,7 +835,12 @@ const LandingPage = () => { alt="hero elements" >
-
+
{" "}

@@ -1176,7 +1181,7 @@ const LandingPage = () => { src="/img/brand/marco.png" width="50" /> - Marco PMS + OnFieldWork.com

@@ -1264,7 +1269,7 @@ const LandingPage = () => { apple icon Date: Fri, 7 Nov 2025 11:36:27 +0530 Subject: [PATCH 020/146] Giving some extra gap in document view form. --- src/components/Documents/DocumentVersionList.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Documents/DocumentVersionList.jsx b/src/components/Documents/DocumentVersionList.jsx index ea1bdc13..851b927f 100644 --- a/src/components/Documents/DocumentVersionList.jsx +++ b/src/components/Documents/DocumentVersionList.jsx @@ -74,7 +74,7 @@ const DocumentVersionList = ({ firstName={currentDoc.uploadedBy?.firstName} lastName={currentDoc.uploadedBy?.lastName} /> - + {`${currentDoc.uploadedBy?.firstName ?? ""} ${currentDoc.uploadedBy?.lastName ?? ""}`.trim() || "N/A"} @@ -216,7 +216,7 @@ const DocumentVersionList = ({ firstName={document.verifiedBy?.firstName} lastName={document.verifiedBy?.lastName} /> - + {`${document.verifiedBy?.firstName ?? ""} ${document.verifiedBy?.lastName ?? ""}`.trim() || "N/A"} From c3d1b468614f46e0440b97ba06ea9a639960710b Mon Sep 17 00:00:00 2001 From: Kartik Sharma Date: Fri, 7 Nov 2025 11:43:22 +0530 Subject: [PATCH 021/146] Increasing some gap in document view button and uploaded by and approved at. --- src/components/Documents/DocumentVersionList.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Documents/DocumentVersionList.jsx b/src/components/Documents/DocumentVersionList.jsx index 851b927f..9061c52c 100644 --- a/src/components/Documents/DocumentVersionList.jsx +++ b/src/components/Documents/DocumentVersionList.jsx @@ -196,7 +196,7 @@ const DocumentVersionList = ({ firstName={document.uploadedBy?.firstName} lastName={document.uploadedBy?.lastName} /> - + {`${document.uploadedBy?.firstName ?? ""} ${document.uploadedBy?.lastName ?? ""}`.trim() || "N/A"} From 9ef1e390418aa900d7bdd35c2bd88a932ad02710 Mon Sep 17 00:00:00 2001 From: Kartik Sharma Date: Fri, 7 Nov 2025 12:34:57 +0530 Subject: [PATCH 022/146] Changes in Directory card and Notes view at the UI. --- src/components/Directory/CardViewContact.jsx | 2 +- src/components/Directory/NoteCardDirectoryEditable.jsx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/Directory/CardViewContact.jsx b/src/components/Directory/CardViewContact.jsx index 8e6c8068..0b446da0 100644 --- a/src/components/Directory/CardViewContact.jsx +++ b/src/components/Directory/CardViewContact.jsx @@ -61,7 +61,7 @@ const CardViewContact = ({ (contact?.name || "").trim().split(" ")[1]?.charAt(0) || "" } />{" "} - {contact?.name} + {contact?.name}
{IsActive && ( diff --git a/src/components/Directory/NoteCardDirectoryEditable.jsx b/src/components/Directory/NoteCardDirectoryEditable.jsx index 5ef8d08f..bc6ff517 100644 --- a/src/components/Directory/NoteCardDirectoryEditable.jsx +++ b/src/components/Directory/NoteCardDirectoryEditable.jsx @@ -87,7 +87,7 @@ const NoteCardDirectoryEditable = ({ />
contactProfile(noteItem.contactId)} > @@ -98,7 +98,7 @@ const NoteCardDirectoryEditable = ({
-
+
by{" "} @@ -184,7 +184,7 @@ const NoteCardDirectoryEditable = ({ ) : (
)} From 5f2a567600f52ec12a6e68fb4142ff5932ce5f66 Mon Sep 17 00:00:00 2001 From: Kartik Sharma Date: Fri, 7 Nov 2025 12:51:28 +0530 Subject: [PATCH 023/146] Document Filter should close automatically when navigating to another menu from Project Profile page --- .../Documents/DocumentFilterPanel.jsx | 420 +++++++++--------- 1 file changed, 213 insertions(+), 207 deletions(-) diff --git a/src/components/Documents/DocumentFilterPanel.jsx b/src/components/Documents/DocumentFilterPanel.jsx index edc613e1..04f54956 100644 --- a/src/components/Documents/DocumentFilterPanel.jsx +++ b/src/components/Documents/DocumentFilterPanel.jsx @@ -13,230 +13,236 @@ import { useParams } from "react-router-dom"; const DocumentFilterPanel = forwardRef( ({ entityTypeId, onApply, setFilterdata }, ref) => { - const [resetKey, setResetKey] = useState(0); - const { status } = useParams(); + const [resetKey, setResetKey] = useState(0); + const { status } = useParams(); - const { data, isError, isLoading, error } = - useDocumentFilterEntities(entityTypeId); + const { data, isError, isLoading, error } = + useDocumentFilterEntities(entityTypeId); - //changes + useEffect(() => { + return () => { + closePanel(); + }; + }, []); - const dynamicDocumentFilterDefaultValues = useMemo(() => { - return { - ...DocumentFilterDefaultValues, - uploadedByIds: DocumentFilterDefaultValues.uploadedByIds || [], - documentCategoryIds: DocumentFilterDefaultValues.documentCategoryIds || [], - documentTypeIds: DocumentFilterDefaultValues.documentTypeIds || [], - documentTagIds: DocumentFilterDefaultValues.documentTagIds || [], - startDate: DocumentFilterDefaultValues.startDate, - endDate: DocumentFilterDefaultValues.endDate, + //changes + + const dynamicDocumentFilterDefaultValues = useMemo(() => { + return { + ...DocumentFilterDefaultValues, + uploadedByIds: DocumentFilterDefaultValues.uploadedByIds || [], + documentCategoryIds: DocumentFilterDefaultValues.documentCategoryIds || [], + documentTypeIds: DocumentFilterDefaultValues.documentTypeIds || [], + documentTagIds: DocumentFilterDefaultValues.documentTagIds || [], + startDate: DocumentFilterDefaultValues.startDate, + endDate: DocumentFilterDefaultValues.endDate, + }; + + }, [status]); + + const methods = useForm({ + resolver: zodResolver(DocumentFilterSchema), + defaultValues: dynamicDocumentFilterDefaultValues, + }); + + const { handleSubmit, reset, setValue, watch } = methods; + + // Watch values from form + const isUploadedAt = watch("isUploadedAt"); + const isVerified = watch("isVerified"); + + // Close the offcanvas (bootstrap specific) + const closePanel = () => { + document.querySelector(".offcanvas.show .btn-close")?.click(); }; - }, [status]); + useImperativeHandle(ref, () => ({ + resetFieldValue: (name, value) => { + if (value !== undefined) { + setValue(name, value); + } else { + reset({ ...methods.getValues(), [name]: DocumentFilterDefaultValues[name] }); + } + }, + getValues: methods.getValues, // optional, to read current filter state + })); - const methods = useForm({ - resolver: zodResolver(DocumentFilterSchema), - defaultValues: dynamicDocumentFilterDefaultValues, - }); - - const { handleSubmit, reset, setValue, watch } = methods; - - // Watch values from form - const isUploadedAt = watch("isUploadedAt"); - const isVerified = watch("isVerified"); - - // Close the offcanvas (bootstrap specific) - const closePanel = () => { - document.querySelector(".offcanvas.show .btn-close")?.click(); - }; - - useImperativeHandle(ref, () => ({ - resetFieldValue: (name, value) => { - if (value !== undefined) { - setValue(name, value); - } else { - reset({ ...methods.getValues(), [name]: DocumentFilterDefaultValues[name] }); + //changes + useEffect(() => { + if (data && setFilterdata) { + setFilterdata(data); } - }, - getValues: methods.getValues, // optional, to read current filter state - })); + }, [data, setFilterdata]); - //changes - useEffect(() => { - if (data && setFilterdata) { - setFilterdata(data); - } - }, [data, setFilterdata]); + const onSubmit = (values) => { + onApply({ + ...values, + startDate: values.startDate + ? moment.utc(values.startDate, "DD-MM-YYYY").toISOString() + : null, + endDate: values.endDate + ? moment.utc(values.endDate, "DD-MM-YYYY").toISOString() + : null, + }); + // closePanel(); + }; - const onSubmit = (values) => { - onApply({ - ...values, - startDate: values.startDate - ? moment.utc(values.startDate, "DD-MM-YYYY").toISOString() - : null, - endDate: values.endDate - ? moment.utc(values.endDate, "DD-MM-YYYY").toISOString() - : null, - }); - // closePanel(); - }; + const onClear = () => { + reset(DocumentFilterDefaultValues); + setResetKey((prev) => prev + 1); + onApply(DocumentFilterDefaultValues); + // closePanel(); + }; - const onClear = () => { - reset(DocumentFilterDefaultValues); - setResetKey((prev) => prev + 1); - onApply(DocumentFilterDefaultValues); - // closePanel(); - }; + if (isLoading) return
Loading...
; + if (isError) + return
Error: {error?.message || "Something went wrong!"}
; - if (isLoading) return
Loading...
; - if (isError) - return
Error: {error?.message || "Something went wrong!"}
; - - const { - uploadedBy = [], - documentCategory = [], - documentType = [], - documentTag = [], - } = data?.data || {}; + const { + uploadedBy = [], + documentCategory = [], + documentType = [], + documentTag = [], + } = data?.data || {}; - return ( - -
- {/* Date Range Section */} -
-
- -
- - + return ( + + + {/* Date Range Section */} +
+
+ +
+ + +
+
+ + +
+ + {/* Dropdown Filters */} +
+ + + + +
+ + {/* Status Filter */} +
+ +
+ + + + +
- -
- - {/* Dropdown Filters */} -
- - - - -
- - {/* Status Filter */} -
- -
- - - - - + {/* Footer Buttons */} +
+ +
-
- - {/* Footer Buttons */} -
- - -
- - - ); -}); + + + ); + }); export default DocumentFilterPanel; From a656907695bbc3a84f70c3f9e3baabcb5fc7a6d6 Mon Sep 17 00:00:00 2001 From: "pramod.mahajan" Date: Fri, 7 Nov 2025 14:47:09 +0530 Subject: [PATCH 024/146] migrated suscripton onfield to main sub-branch --- .../UserSubscription/ProcessedPayment.jsx | 110 ++++++--- src/components/UserSubscription/Review.jsx | 11 + .../UserSubscription/SelectPlan.jsx | 222 +++++++++++++----- .../SelectedPlaneSkeleton.jsx | 4 +- .../UserSubscription/SubscriptionForm.jsx | 28 ++- .../UserSubscription/SubscriptionLayout.jsx | 4 +- .../UserSubscription/VerifiedPayment.jsx | 1 + src/hooks/usePayments.jsx | 38 ++- src/pages/Home/HomeSchema.jsx | 8 +- src/pages/Home/MakeSubscription.jsx | 72 +++++- src/pages/Home/SubscriptionPlans.jsx | 4 +- src/router/AppRoutes.jsx | 11 +- src/slices/localVariablesSlice.jsx | 13 +- src/utils/appUtils.js | 123 ++++++---- 14 files changed, 459 insertions(+), 190 deletions(-) create mode 100644 src/components/UserSubscription/Review.jsx 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) => (
-