Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | 469x 15894x 15893x 15893x 15893x 15893x 15893x 15893x 15893x 15893x 15893x 15893x 15893x 41x 41x 15893x 15894x 15894x 15894x 15894x 15893x 107307x 15893x 15893x 15893x 15893x 15893x 15893x 15893x 15893x | import { useLocation, useParams } from "react-router-dom";
import { TPublicForm } from "./types";
import { useQuery, useQueryClient } from "react-query";
import { useAppSelector } from "@redux/hooks";
import { selectPaymentFormID } from "@redux/slices/products";
import { CampaignMapperValues } from "features/Minibuilders/PaymentFormMinibuilder/useCreateCampaignFn";
import { FormType, useGetRebrandedFormTypes } from "@sections/PayBuilder/utils";
import { customInstance } from "@services/api";
// this hook aims to get form data of the current form in view
export const useGetFormData = () => {
const queryClient = useQueryClient();
const { state } = useLocation();
const { id } = useParams();
const isValidId = Boolean(Number(id)) && !!id && !isNaN(Number(id));
// We are adding isNaN check to only use pathaname if we have id(number)
const idFromPathName = Number(location.pathname.slice(1));
const idToUse = isNaN(idFromPathName) ? id : String(idFromPathName);
const peekedFormId = useAppSelector(selectPaymentFormID);
const formId = idToUse || state?.id || peekedFormId;
/**
* CRITICAL FIX: Check if data already exists in cache BEFORE making a query.
* useGetPublicForm (at the top level) is the primary data fetcher.
* This hook should only read from cache, not trigger additional API calls.
*/
const existingPublicData = queryClient.getQueryData<TPublicForm>([
"public-form-id",
id,
]);
const loggedUserFormData = queryClient.getQueryData<TPublicForm>([
"get-payment-form-by-id",
formId,
]);
// If we already have data in cache, don't make another query
const hasExistingData = existingPublicData || loggedUserFormData;
// when user is not logged in we have this form data
const { data: publicData, isLoading } = useQuery({
queryKey: ["public-form-id", id],
queryFn: async () => {
// Safety check: should never execute with invalid ID due to enabled check
Iif (!isValidId) {
throw new Error(`Invalid product ID: ${id}`);
}
return customInstance({
url: `/products/${id}`,
});
},
// CRITICAL: Only enable if we have a valid ID AND don't have cached data
enabled: isValidId && !hasExistingData,
// If we have existing data, use it immediately
initialData: existingPublicData,
// Prevent duplicate API calls when multiple components mount
staleTime: 1000 * 60 * 2, // Consider data fresh for 2 minutes
cacheTime: 1000 * 60 * 5, // Keep in cache for 5 minutes
// Don't retry on invalid IDs
retry: false,
});
return { data: publicData || loggedUserFormData, isLoading };
};
export default function useCheckFormType() {
const { search, state } = useLocation();
const searchParams = new URLSearchParams(search);
const rebrandedFormTypes = useGetRebrandedFormTypes();
// tot get data from API and when data is from API we use it instead of the useLocation values
const { data, isLoading } = useGetFormData();
const type: CampaignMapperValues = data?.typeName
? data?.typeName
: searchParams.get("type") ||
state?.campaignName ||
state?.campaign ||
state?.campaignType;
const isFormType = (formType: FormType) => type === formType;
const isFundraiser = isFormType(FormType.FUNDRAISERS);
// This change is added since in BE it's called standard and in FE it's product. TODO: refactor
const isProduct =
isFormType(FormType.STANDARDS) || isFormType(FormType.PRODUCTS);
const isEvent = isFormType(FormType.EVENTS);
const isSweepstake = isFormType(FormType.SWEEPSTAKE);
const isMembership = isFormType(FormType.MEMBERSHIPS);
const isInvoice = isFormType(FormType.INVOICES);
const isNewCustomerViewForm = rebrandedFormTypes.includes(type);
return {
isFundraiser,
isProduct,
isEvent,
isMembership,
formType: type,
isNewCustomerViewForm,
isSweepstake,
isInvoice,
isLoading,
};
}
|