import { createContext, ReactNode, useContext, useState } from 'react'; import { getMarketMerchantId, isLoggedIn, useAuth } from '@tempi/auth'; import { LOCALSTORAGE_LICENSE } from '../constants'; import { ILicense, IValidateLicenseResponse } from '../type'; import { licenseApi, validateLicense } from '../utils'; interface LicenseProviderProps { children?: ReactNode; } export const LicenseContext = createContext({}); export interface ILicenseInfo { license?: ILicense; loadingLicense?: boolean; getSyncLicense?: () => ILicense; getAsyncLicense?: () => Promise; checkValidLicense?: (featureCodes: string[]) => Promise; } export const LicenseProvider = ({ children }: LicenseProviderProps) => { const { user } = useAuth(); const merchantId = getMarketMerchantId(user); const [license, setLicense] = useState(null); const [loadingLicense, setLoadingLicense] = useState(false); const lsLicense = localStorage.getItem( LOCALSTORAGE_LICENSE.replace('', merchantId?.toString()), ); const checkLicenseInfo = (licenseInfo: ILicense) => { if (!licenseInfo?.isValid) return false; // check time - format ISO if (licenseInfo?.expireAt) { const expireAt = new Date(licenseInfo.expireAt); const now = new Date(); if (expireAt.getTime() < now.getTime()) return false; } return true; }; const getSyncLicense = () => { const currentLicense = JSON.parse(lsLicense || null); if ( currentLicense && checkLicenseInfo({ isValid: true, ...currentLicense, }) ) { const newLicense = { isValid: true, expireAt: currentLicense?.expireAt, licensedFeatures: currentLicense?.featureCodes, }; setLicense(newLicense); return newLicense; } }; const getAsyncLicense = async () => { if (isLoggedIn()) { try { setLoadingLicense(true); const { data } = await licenseApi.validateLicense({ appId: window?.config?.market?.appId, merchantId: merchantId, }); if (checkLicenseInfo(data)) { setLicense(data); localStorage.setItem( LOCALSTORAGE_LICENSE.replace( '', merchantId?.toString(), ), JSON.stringify({ featureCodes: data?.licensedFeatures, expireAt: data?.expireAt, }), ); } return { data: data }; } finally { setLoadingLicense(false); } } }; const checkValidLicense = async (featureCodes: string[]) => { let isValidLicense = false; if (license) { isValidLicense = validateLicense(license, featureCodes); } else { const data = getSyncLicense(); if (data) isValidLicense = validateLicense(data, featureCodes); } if (!isValidLicense) { const { data } = await getAsyncLicense(); if (data) isValidLicense = validateLicense(data, featureCodes); } return isValidLicense; }; return ( {children} ); }; export const useLicense = (): ILicenseInfo => { const context = useContext(LicenseContext); if (!context) { throw new Error('useLicense must be used within a LicenseProvider'); } return context; };