pze-drop-voucher
v1.0.2
Published
A lightweight, reusable React component for integrating the Pango ZMA Experience Instant DropVoucher into your application. ๐
Readme
[Beta] PZEInstantDropVoucher
A lightweight, reusable React component for integrating the Pango ZMA Experience Instant DropVoucher into your application. ๐
Features
- ๐ Easy integration with any React project
- โก Fast setup with minimal configuration
- ๐ Supports
WidgetandOverlayandNonemodes - ๐ฌ Supports event callbacks:
authorize,followOA,followOaCustom,initSuccess,click-cta,viewWidget,closeWidget - ๐ฆ Published as ESM, CJS, and TypeScript-ready
Before Integration
- Contact PangoCDP guide setup (integrate batch voucher/qr campaign/digital gift,.. and customUI,...) and get
pzeKey
Prerequisites
- Node.js >= 18.x
- React >= 18.0.0
- React Router DOM >= 6.0.0
- Vite >= 3 (ZMA Required Vite 5.x)
Usage
Basic Example
1. pzeInstantDropVoucher.page.tsx
import { PZEInstantDropVoucher } from 'pze-drop-voucher';
import React from 'react';
import PZEInstantDropVoucherHandler from './pzeInstantDropVoucher.handler';
interface IPZEInstantDropVoucherPage {
}
const PZEInstantDropVoucherPage: React.FC = ({ }: IPZEInstantDropVoucherPage) => {
const defaultMode = "Widget";
return (
<div
id="pzeInstantDropVoucher"
className="relative z-[60]"
>
<PZEInstantDropVoucher
pzeKey='pango_key'
pzeEnv='production'
pzeVersion='latest'
userAppId='your_userAppId'
defaultMode={defaultMode}
/>
<PZEInstantDropVoucherHandler />
</div>
);
};
export default PZEInstantDropVoucherPage;2. pzeInstantDropVoucher.handler.tsx
import { PZEInstantDropVoucherStore, PzeInstantDropVoucherType } from 'pze-drop-voucher';
import React, { useEffect, useRef } from 'react';
import { getRecoil, setRecoil } from 'recoil-nexus';
import { followOA } from 'zmp-sdk/apis';
import { useIngestLog } from '~/hooks/useIngestLog';
import useShareUserInfo from '~/hooks/useShareUserInfo';
import { userInfoAtom } from '~/recoil/userInfo';
interface IPZEInstantDropVoucherHandler {
}
const PZEInstantDropVoucherHandlerComponent: React.FC = ({ }: IPZEInstantDropVoucherHandler) => {
const initializedRef = useRef(false);
const { handleActionSharePhoneAndLocation, handleActionSharePhone } = useShareUserInfo();
const { ingestLog } = useIngestLog()
useEffect(() => {
if (initializedRef.current) {
return;
}
initializedRef.current = true;
PZEInstantDropVoucherStore().then((atoms: PzeInstantDropVoucherType) => {
if (!atoms.pzeInstantDropVoucherStore) {
return;
}
// handle get current userInfo
const userInfo = getRecoil(userInfoAtom);
// handle updatepzeInstantDropVoucherFollowedOA
atoms.updatepzeInstantDropVoucherFollowedOA(userInfo?.followedOA);
// handle updatepzeInstantDropVoucherUserInfo
atoms.updatepzeInstantDropVoucherUserInfo({
userName: userInfo.userName == "Guest" ? "" : userInfo.userName,
userPhone: userInfo.userPhone,
userAvatar: "https://storage.googleapis.com/pangocdp-images/p-act/public/a446a8794d04498386b34dd833fb7eef.png",
location: userInfo.location,
cdpaid: userInfo.cdpaid
});
const handlers = {
"zmp": {
"authorize": async () => {
try {
// handle call api zmp
// scope values: 1 | 2
// check scope and update to pzeInstantDropVoucher
// + 1: handleActionSharePhone
// + 2: handleActionSharePhoneAndLocation
if (!scope) {
return;
}
const userInfoUpdate: any = scope === 1
? await handleActionSharePhone()
: await handleActionSharePhoneAndLocation();
if (userInfoUpdate.userPhone && userInfoUpdate.userName) {
atoms.updatepzeInstantDropVoucherUserInfo({
userName: userInfoUpdate.userName,
userPhone: userInfoUpdate.userPhone,
userAvatar: userInfoUpdate.userAvatar || "https://storage.googleapis.com/pangocdp-images/p-act/public/a446a8794d04498386b34dd833fb7eef.png",
location: userInfoUpdate.location,
cdpaid: userInfoUpdate.cdpaid,
});
return;
} else {
// handle close popup when fail
atoms.pzeInstantDropVoucherClose();
return;
}
} catch (error: any) {
atoms.pzeInstantDropVoucherClose();
}
},
"followOA": async () => {
try {
// handle followedOA will skip call zmp
if (getRecoil(userInfoAtom)?.followedOA) {
atoms.updatepzeInstantDropVoucherFollowedOA(true);
return;
}
const oaId = userInfo.oaId;
if (!oaId) {
return;
}
await followOA({
id: oaId,
success: async () => {
// handle update current userInfo
const userInfoUpdate = { ...userInfo, followedOA: true }
setRecoil(userInfoAtom, userInfoUpdate)
// example: push event log follow-oa
await ingestLog(
'follow-oa',
{ userEvent: true },
userInfoUpdate
)
// handle updatepzeInstantDropVoucherFollowedOA
atoms.updatepzeInstantDropVoucherFollowedOA(true);
},
fail: (error: any) => {
atoms.pzeInstantDropVoucherClose();
return;
},
});
} catch (error) {
atoms.pzeInstantDropVoucherClose();
return;
}
},
"followOaCustom": async () => {
try {
// handle followedOACustom will skip call zmp
if (getRecoil(userInfoAtom)?.followedOACustom) {
atoms.updatepzeInstantDropVoucherFollowedOACustom(true);
return;
}
const oaId = atoms.pzeInstantDropVoucherStore.get(atoms.pzeCallback)?.data?.oaId;
if (!oaId) {
return;
}
// handle call followOA by oaIdCustom
} catch (error) {
atoms.pzeInstantDropVoucherClose();
return;
}
}
},
"instantDropVoucher": {
"click-cta": async () => {
const directLink = atoms.getPZECallbackData()?.data?.directLink;
// example push event log: click-cta leading to a specific directLink
},
"viewWidget": async () => {
// example: push event log click-widget
},
"closeWidget": async () => {
// example: push event log close-flow
},
"initSuccess": async () => {
// example: push event log open-flow
// ingestLog(
// 'open-flow',
// {
// userEvent: false,
// "pze": "InstantDropVoucher",
// ...eventData
// },
// userInfo)
},
},
default: () => {
console.warn('Unknown message type: ' + atoms.getPZECallbackData()?.type);
},
};
const unsub = atoms.pzeInstantDropVoucherStore.sub(atoms.pzeCallback, () => {
const callbackData = atoms.getPZECallbackData();
console.log("๐ฌ ", callbackData)
const type = callbackData?.type;
const action = callbackData?.data?.action;
if (!type || !action) {
return;
}
(handlers?.[type]?.[action] || handlers.default)();
});
return () => unsub?.();
});
}, []);
return null;
};
const PZEInstantDropVoucherHandler = React.memo(PZEInstantDropVoucherHandlerComponent);
export default PZEInstantDropVoucherHandler;