========= [[…page]].jsx ============
import { BuilderComponent, builder } from "@builder.io/react";
import { useEffect, useState } from "react";
import Footer from "@/components/Footer";
import Head from "@/components/Head";
import fallbacks from "@/utils/fallbacks";
import getCommonProps from "@/utils/getCommonProps";
import { getCookie } from "@/lib/gtm";
import TextOverlayOnImage from "../blocks/TextOverlayOnImage";
import ThreeProductGrid from "../blocks/ThreeProductGrid";
import { useAddToCartContext } from "@/context/Store";
import "../utils/widgets";
import { processPageData } from '@/utils';
// put your Public API Key you copied from Builder.io here
//builder.init(process.env.BUILDER_API_KEY)
builder.init(process.env.NEXT_PUBLIC_BUILDER_API_KEY);
export async function getStaticProps(context) {
// Page Content
const page =
(await builder
.get("page", {
userAttributes: {
urlPath: "/" + (context.params?.page?.join("/") || ""),
},
})
.toPromise()) || null;
const processedPage = await processPageData(page)
return {
props: {
page: processedPage,
...(await getCommonProps(context)),
},
revalidate: 5,
};
}
export async function getStaticPaths() {
const pages = await builder.getAll("page", {
options: { noTargeting: true },
});
return {
paths: pages.map((page) => `${page.data?.url}`),
fallback: true,
};
}
let addToCart = null
const onProductRedemption = async(data) => {
function calcShopifyToken(point_redemption_id, variant_id) {
//Fill in your loyalty api key in the line below
let api_key=""
let buckets = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
let raw_token = reverseString(variant_id.toString()) + reverseString(api_key) + reverseString(point_redemption_id.toString())
let token = ""
let rotate_amount = 1 + (point_redemption_id % 59)
for (let i = 0; i < raw_token.length; i++) {
let ord = raw_token.charCodeAt(i);
let orig_index = false;
if (ord >= 65 && ord <= 90)
orig_index = ord-65
else if (ord >= 97 && ord <= 122)
orig_index = ord - 97 + 26
else if (ord >= 48 && ord <= 57)
orig_index = ord - 48 + 52
if (orig_index) {
let new_index = (orig_index + rotate_amount) % 62;
token += buckets[new_index];
}
}
return token;
}
function reverseString(text) {
let text_as_array = text.split("");
let reverse_array = text_as_array.reverse();
let reverse_text = reverse_array.join("");
return reverse_text;
}
const {token,id,variantId,costInPoints} = data;
const generatedToken = (calcShopifyToken(id,variantId)).slice(0, 14);
console.log(generatedToken, "generated token")
//call existing add to cart flow
if(token.indexOf(generatedToken) > -1){
addToCart({
variantId: 'gid://shopify/ProductVariant/' + data.variantId,
attributes: [
{
key: "_swell_discount_type",
value: "product"
},
{
key: "_swell_redemption_id",
value: `${id}`
},
{
key: "_swell_redemption_token",
value: `${token}`
},
{
key: "_swell_discount_amount_cents",
value: "2500"
},
{
key: "_swell_loyalty_points",
value: `${costInPoints}`
},
],
variantQuantity: 1})
return true
} else {
return false
}
}
export default function Page(commonProps) {
addToCart = useAddToCartContext();
const [userData, setUserData] = useState({});
useEffect(() => {
console.log('commonProps==>',commonProps)
if(typeof window != undefined) {
setTimeout(() => {
window.yotpoWidgetsContainer?.initWidgets()
},2000)
window.onProductRedemption = onProductRedemption;
}
const userData = JSON.parse(getCookie('userData') ? decodeURIComponent(getCookie('userData')) : JSON.stringify({}));
const {customer_email = '' , customer_id = ''} = userData || {};
const userDataObj = {
customer_email,
customer_id,
auth: false
}
if(customer_email.length > 0) {
userDataObj.auth = true;
}
setUserData(userDataObj);
}, [])
const fb = fallbacks(commonProps);
if (fb) return fb;
return (
<>
<Head {...commonProps} />
<main
className={commonProps.page?.data.headerBg ? "md:-mt-[6.5rem]" : ""}
>
<BuilderComponent model="page" content={commonProps.page} />
<div
id="swell-customer-identification"
data-authenticated={userData.auth}
data-email={userData.customer_email}
data-id={userData.customer_id}
style={{display: 'none'}}>
</div>
</main>
<Footer {...commonProps} />
{/* <TextOverlayOnImage />
<ThreeProductGrid /> */}
</>
);
}
========= [[…page]].jsx End ============
So under getStaticProps function , you will find a function called processPageData inside which i am making the API call and inserting the responce in one of the builder component called productColumn .
======processPageData Function : i am modifying the component here ========
import componentAlternation from './componentAlteration'
export async function processPageData (page) {
const allComp = page?.data?.blocks;
if(!allComp.length) return page;
const compNames = allComp.map(comp => comp?.component?.name).filter(Boolean);
const compoLoader = [];
compNames.forEach(block => {
const compfun = componentAlternation[block];
if(!compfun) return;
compoLoader.push(compfun(page));
})
const resolvedComponents = await Promise.all(compoLoader);
resolvedComponents.forEach(compBlock => {
const blockIndex = page?.data?.blocks?.findIndex(block => block?.component?.name === compBlock?.component?.name);
page.data.blocks[blockIndex] = compBlock;
})
return page;
}
===== componentAlternation Function : here i am making the Shopify graphQL api call =====
import {getCollectionMetafields} from '@/lib/shopify'
const componentBlock = (pageData,compName) => {
const blocks = pageData?.data?.blocks
if(!blocks.length) return;
return blocks.find(comp => comp.component.name === compName )
}
const processProductData = (itesm) => {
return itesm.edges.map(prd => {
const prdVariant = prd?.node?.variants?.edges[0]?.node;
const image = prd?.node?.images?.edges[0]?.node;
const subsdata = prd?.node?.sellingPlanGroups.edges;
let sellingPlanGroups
if(!subsdata.length){
sellingPlanGroups = false
}else {
const group = subsdata[0]?.node;
const sellingPlans = group?.sellingPlans?.edges?.map(plan => plan?.node);
sellingPlanGroups = {...group,sellingPlans}
}
return {...prd.node,variants:prdVariant,images:image,sellingPlanGroups};
})
}
export default {
async ProductColumn(pageData) {
const componentDetails = componentBlock(pageData,'ProductColumn');
const collectionHandle = componentDetails?.component?.options?.product_collection_handle;
if(!collectionHandle) return componentDetails;
try{
const collectionData = await getCollectionMetafields(collectionHandle);
if(!collectionData.data.collectionByHandle) {
console.log('wrong product handle added in Builder');
return componentDetails
}
const products = collectionData?.data?.collectionByHandle?.products;
componentDetails.component.options['collectionProducts'] = processProductData(products);
}catch(err){
console.err('error while fetching collection data:',err);
}finally {
return componentDetails
}
}
}
Let me know if you need more info .