From 1450d312ce4ade3b0e8d76a2f12f81711bcf31d9 Mon Sep 17 00:00:00 2001 From: Oluwatobi Shokunbi Date: Sun, 12 Jan 2025 13:18:45 +0000 Subject: [PATCH 1/3] Code clean-up In this PR we; - Add more test - KISS more (no human lips were affected or damaged in this process) - file restructure - Add more types - clean up useRef usage - --- .DS_Store | Bin 10244 -> 8196 bytes __tests__/utils.test.ts | 97 +++++++- development/index.tsx | 4 - development/paystack.tsx | 367 ++++++++++++++---------------- development/style.ts | 14 ++ development/types/index.ts | 11 +- development/{ => utils}/helper.ts | 50 +++- development/utils/index.ts | 19 ++ package.json | 12 +- 9 files changed, 360 insertions(+), 214 deletions(-) create mode 100644 development/style.ts rename development/{ => utils}/helper.ts (56%) create mode 100644 development/utils/index.ts diff --git a/.DS_Store b/.DS_Store index 52ea7833c2bdb46368c20f22299e9a0d644b49a5..b5433102e1370bc5ecfcc0a9937e88082d44defb 100644 GIT binary patch delta 118 zcmZn(XmOBWU|?W$DortDU;r^WfEYvza8E20o2aMAsIW0$H$S7oW*z}wmd%qzGZ;4; zi`y}7EaPAlWCp4O0ts#);R@2SvG6Si7RUlw0(h7^WW zhB6?|VaR7FV8{is@)$}ybMljua`KZv`hcc&199DdFaU}$FyPQNd5cI3v#Ei>WNT3e zWgKeCf{XHU^7GPxrZ8>}6Uk;&&jVTvazs4PauBN&=#*53Vl*fG+`K{5pHZ2Up^_ny zp$O)?FtHkjfLNtC-ch$iZDUKMFXUO Zk%7SgL{Bb|>7C3ks!1~+Ox_^+2mt8#U2FgV diff --git a/__tests__/utils.test.ts b/__tests__/utils.test.ts index 7e59bd0..156eeda 100644 --- a/__tests__/utils.test.ts +++ b/__tests__/utils.test.ts @@ -7,8 +7,11 @@ import { toNumber, getAmountValueInKobo, getChannels, -} from '../development/helper'; -import { PaymentChannels } from '../development/types'; + buildKeyValueString, + dynamicSplitObjectIsValid, + paystackHtmlContent, +} from '../development//utils/helper'; +import { DynamicMultiSplitProps, PaymentChannels } from '../development/types'; describe('Utility functions work properly', () => { test('getChannels should return a stingified array with comma', () => { @@ -62,4 +65,94 @@ describe('Utility functions work properly', () => { result = isNegative(200.0); expect(result).toBe(false); }); +}); + +describe('Utility functions work properly', () => { + test('getChannels should return a stringified array with commas', () => { + let testChannels: PaymentChannels[] = ['card', 'bank']; + let expectedOutput = 'channels: ["card","bank"],'; + + const result = getChannels(testChannels); + expect(result).toBe(expectedOutput); + }); + + test('toAmountInKobo should return kobo value for amount', () => { + let result = toAmountInKobo('4600.00'); + expect(result).toBe(460000); + + result = toAmountInKobo(1200.93); + expect(result).toBe(120093); + }); + + test('getAmountValueInKobo should return kobo value for valid amounts', () => { + let result = getAmountValueInKobo('4600.00'); + expect(result).toBe(460000); + + result = getAmountValueInKobo('not_correct_money_amount'); + expect(result).toBe(0); + }); + + test('isValidDecimalMonetaryValue should return true for only valid amount', () => { + let result = isValidDecimalMonetaryValue('2500.00'); + expect(result).toBe(true); + + result = isValidDecimalMonetaryValue('2500'); + expect(result).toBe(true); + + result = isValidDecimalMonetaryValue('invalid_amount'); + expect(result).toBe(false); + }); + + test('isValidStringAmount should return true for valid amount strings', () => { + let result = isValidStringAmount('2500.00'); + expect(result).toBe(true); + + result = isValidStringAmount('not_money_amount'); + expect(result).toBe(false); + + result = isValidStringAmount('2500.'); + expect(result).toBe(false); + }); + + test('toNumber should convert string amount to number', () => { + const result = toNumber('2500.00'); + expect(result).toBe(2500); + }); + + test('isNegative should return true if amount is negative', () => { + let result = isNegative('-200.00'); + expect(result).toBe(true); + + result = isNegative(-200.0); + expect(result).toBe(true); + + result = isNegative(200.0); + expect(result).toBe(false); + }); + + test('buildKeyValueString should return correct string for key-value', () => { + let result = buildKeyValueString('key1', 'value1'); + expect(result).toBe("key1: 'value1',"); + + result = buildKeyValueString('key2', undefined); + expect(result).toBe(''); + }); + + test('dynamicSplitObjectIsValid should return true for valid split object', () => { + const validSplit: DynamicMultiSplitProps = { + type: 'percentage', + bearer_type: 'all', + subaccounts: [{ subaccount: 'sub1', share: '50' }] + }; + + let result = dynamicSplitObjectIsValid(validSplit); + expect(result).toBe(true); + }); + + test('paystackHtmlContent should return HTML with correct params', () => { + const params = "key1: 'value1', key2: 'value2'"; + const result = paystackHtmlContent(params); + expect(result).toContain("key1: 'value1',"); + expect(result).toContain("key2: 'value2'"); + }); }); \ No newline at end of file diff --git a/development/index.tsx b/development/index.tsx index 67876eb..d593cf5 100644 --- a/development/index.tsx +++ b/development/index.tsx @@ -1,4 +1,3 @@ -import { NativeModules } from 'react-native' import Paystack from './paystack'; import * as paystackProps from './types' @@ -6,6 +5,3 @@ export { Paystack, paystackProps } - -export default NativeModules.ReactNativePaystackWebviewModule - \ No newline at end of file diff --git a/development/paystack.tsx b/development/paystack.tsx index 32b45d0..d6c8f99 100644 --- a/development/paystack.tsx +++ b/development/paystack.tsx @@ -1,199 +1,176 @@ -import * as React from 'react' -import { useState, useEffect, forwardRef, useRef, useImperativeHandle } from 'react'; -import { Modal, View, ActivityIndicator, SafeAreaView } from 'react-native'; -import { WebView, WebViewNavigation } from 'react-native-webview'; -import { getAmountValueInKobo, getChannels } from './helper'; -import { PayStackProps, PayStackRef, DynamicMultiSplitProps } from './types'; - -const CLOSE_URL = 'https://standard.paystack.co/close'; - -const Paystack: React.ForwardRefRenderFunction = ( - { - paystackKey, - billingEmail, - phone, - lastName, - firstName, - amount = '0.00', - currency = 'NGN', - channels = ['card'], - refNumber, - billingName, - plan, - invoice_limit, - subaccount, - split_code, - split, - handleWebViewMessage, - onCancel, - autoStart = false, - onSuccess, - activityIndicatorColor = 'green', - modalProps, - metadata - }, - ref, -) => { - const [isLoading, setisLoading] = useState(true); - const [showModal, setshowModal] = useState(false); - const webView = useRef(null); - - useEffect(() => { - autoStartCheck(); - }, []); - - useImperativeHandle(ref, () => ({ - startTransaction() { - setshowModal(true); +import React, { + useState, + useEffect, + forwardRef, + useRef, + useImperativeHandle, + useCallback, +} from "react"; +import { + Modal, + View, + ActivityIndicator, + SafeAreaView, +} from "react-native"; +import { WebView, WebViewNavigation } from "react-native-webview"; +import { + buildKeyValueString, + dynamicSplitObjectIsValid, + getAmountValueInKobo, + getChannels, + paystackHtmlContent, +} from "./utils/helper"; +import { PayStackProps, PayStackRef } from "./types"; +import { styles } from "./style"; + +const CLOSE_URL = "https://standard.paystack.co/close"; + +const Paystack = forwardRef( + ( + { + paystackKey, + billingEmail, + phone, + lastName, + firstName, + amount = "0.00", + currency = "NGN", + channels = ["card"], + refNumber, + billingName, + plan, + invoice_limit, + subaccount, + split_code, + split, + handleWebViewMessage, + onCancel, + autoStart = false, + onSuccess, + activityIndicatorColor = "green", + modalProps, + metadata, }, - endTransaction() { - setshowModal(false); - }, - })); - - const autoStartCheck = () => { - if (autoStart) { - setshowModal(true); - } - }; - - const dynamicSplitObjectIsValid = (split:DynamicMultiSplitProps|undefined): split is DynamicMultiSplitProps => { - if ( split !== null && (typeof split === "object") && (split.type) && (split.bearer_type) && (split.subaccounts)) { - return true; - } else { return false; } - } - - const refNumberString = refNumber ? `ref: '${refNumber}',` : ''; // should only send ref number if present, else if blank, paystack will auto-generate one - - const subAccountString = subaccount ? `subaccount: '${subaccount}',` : ''; // should only send subaccount with the correct subaccoount_code if you want to enable split payment on transaction - - const splitCodeString = split_code ? `split_code: '${split_code}',` : ''; // should only send split_code with the correct split_code from the split group if you want to enable multi-split payment on transaction - //Multi-split enables merchants to split the settlement for a transaction across their payout accounts, and one or more subaccounts - - const dynamicSplitString = dynamicSplitObjectIsValid(split) ? `split: ` + JSON.stringify(split) + `,` : ''; // should only send split for dynamic multi-account split with the correct split object as defined - //Sometimes, you can't determine a split configuration until later in the purchase flow. With dynamic splits, you can create splits on the fly. This can be achieved by passing a split object - - const planCodeString = plan ? `plan: '${plan}',` : ''; // should only send plan with the predefined plan_code as generated on paystack dashboard if present, else if blank, it will be ignored. - // Please note that when plan is provided, the amount prop will be ignored - - const invoiceLimitString = invoice_limit? `invoice_limit: ${invoice_limit},` : ''; // should only send invoice limit as integer when plan subscription is specified - - const metaDataString = metadata ? `metadata: ${metadata},` : `metadata: { custom_fields: [{ display_name: '${firstName + ' ' + lastName}', variable_name: '${billingName}', value:'' }]},`; - - const Paystackcontent = ` - - - - - - - Paystack - - - - - - - `; - - const messageReceived = (data: string) => { - const webResponse = JSON.parse(data); - if (handleWebViewMessage) { - handleWebViewMessage(data); - } - switch (webResponse.event) { - case 'cancelled': - setshowModal(false); - onCancel({ status: 'cancelled' }); - break; - - case 'successful': - setshowModal(false); - const reference = webResponse.transactionRef; - - if (onSuccess) { - onSuccess({ - status: 'success', - transactionRef: reference, - data: webResponse, - }); + ref + ) => { + const [isLoading, setIsLoading] = useState(true); + const [showModal, setShowModal] = useState(false); + const webViewRef = useRef(null); + + useEffect(() => { + if (autoStart) { + setShowModal(true); + } + }, [autoStart]); + + useImperativeHandle(ref, () => ({ + startTransaction: () => setShowModal(true), + endTransaction: () => setShowModal(false), + })); + + const generatePaystackParams = () => { + + const params = [ + buildKeyValueString("key", paystackKey), + buildKeyValueString("email", billingEmail), + buildKeyValueString("firstname", firstName), + buildKeyValueString("lastname", lastName), + buildKeyValueString("phone", `${phone}`), + buildKeyValueString("amount", `${getAmountValueInKobo(amount)}`), + buildKeyValueString("currency", currency), + getChannels(channels), + buildKeyValueString("ref", refNumber), + buildKeyValueString("subaccount", subaccount), + buildKeyValueString("split_code", split_code), + buildKeyValueString("plan", plan), + buildKeyValueString("invoice_limit", invoice_limit?.toString()), + dynamicSplitObjectIsValid(split) + ? `split: ${JSON.stringify(split)},` + : "", + metadata + ? `metadata: ${metadata},` + : `metadata: { custom_fields: [{ display_name: '${firstName} ${lastName}', variable_name: '${billingName}', value: '' }]},`, + ]; + return params.filter(Boolean).join("\n"); + }; + + + const HTML_CONTENT = paystackHtmlContent(generatePaystackParams()); + + const handleMessageReceived = useCallback( + (data: string) => { + const webResponse = JSON.parse(data); + + switch (webResponse.event) { + case "cancelled": + onCancel?.({ status: "cancelled", data: webResponse }); + setShowModal(false); + break; + + case "successful": + onSuccess?.({ + status: "success", + transactionRef: webResponse.transactionRef, + data: webResponse, + }); + setShowModal(false); + break; + + default: + handleWebViewMessage?.({ status: "error", data: webResponse }); + break; } - break; - - default: - if (handleWebViewMessage) { - handleWebViewMessage(data); + }, + [handleWebViewMessage, onCancel, onSuccess] + ); + + const handleNavigationStateChange = useCallback( + (state: WebViewNavigation) => { + if (state.url === CLOSE_URL) { + setShowModal(false); } - break; - } - }; - - const onNavigationStateChange = (state: WebViewNavigation) => { - const { url } = state; - if (url === CLOSE_URL) { - setshowModal(false); - } - }; - - return ( - - - { - messageReceived(e.nativeEvent?.data); - }} - onLoadStart={() => setisLoading(true)} - onLoadEnd={() => setisLoading(false)} - onNavigationStateChange={onNavigationStateChange} - ref={webView} - cacheEnabled={false} - cacheMode={'LOAD_NO_CACHE'} - /> - - {isLoading && ( - - - - )} - - - ); -}; - -export default forwardRef(Paystack); - - - + }, + [] + ); + + const handleError = useCallback( + (error: any) => { + handleWebViewMessage?.({ status: "error", data: error }); + setShowModal(false); + }, + [handleWebViewMessage] + ); + + return ( + + + handleMessageReceived(e.nativeEvent.data)} + onLoadStart={() => setIsLoading(true)} + onLoadEnd={() => setIsLoading(false)} + onNavigationStateChange={handleNavigationStateChange} + ref={webViewRef} + cacheEnabled={false} + cacheMode="LOAD_NO_CACHE" + /> + {isLoading && ( + + + + )} + + + ); + } +); +export default Paystack; diff --git a/development/style.ts b/development/style.ts new file mode 100644 index 0000000..3e96992 --- /dev/null +++ b/development/style.ts @@ -0,0 +1,14 @@ +import { StyleSheet } from 'react-native'; + +export const styles = StyleSheet.create({ + modalContainer: { + flex: 1, + }, + webView: { + flex: 1, + }, + activityIndicatorContainer: { + justifyContent: 'center', + alignItems: 'center', + }, +}); \ No newline at end of file diff --git a/development/types/index.ts b/development/types/index.ts index 6b459e0..c744ed4 100644 --- a/development/types/index.ts +++ b/development/types/index.ts @@ -1,5 +1,11 @@ import * as React from 'react'; import { ModalProps } from 'react-native'; + +export interface PayStackRef { + startTransaction: () => void; + endTransaction: () => void; +} + export type Currency = 'NGN' | 'GHS' | 'USD' | 'ZAR' | 'KES'; export type PaymentChannels = 'bank' | 'card' | 'qr' | 'ussd' | 'mobile_money' | 'bank_transfer' | 'eft' | 'apple_pay'; @@ -10,6 +16,7 @@ export type ChargeBearerTypes = 'all' | 'all-proportional' | 'account' | 'subacc interface Response { status: string; + data?: string; } interface SuccessResponse extends Response { transactionRef?: string; @@ -24,7 +31,7 @@ export interface DynamicMultiSplitProps { type: SplitTypes; bearer_type: ChargeBearerTypes; subaccounts: DynamicSplitSubAccountInterface[]; - bearer_subaccount?: string; // only if bearer_type is 'subaccount' + bearer_subaccount?: string; reference?: string; } @@ -64,7 +71,7 @@ export interface PayStackProps { subaccount?: string; split_code?: string; split?: DynamicMultiSplitProps; - handleWebViewMessage?: (string: string) => void; + handleWebViewMessage?: (Response: Response) => void; onCancel: (Response: Response) => void; onSuccess: (SuccessResponse:SuccessResponse) => void; autoStart?: boolean; diff --git a/development/helper.ts b/development/utils/helper.ts similarity index 56% rename from development/helper.ts rename to development/utils/helper.ts index c2311fc..704f64a 100644 --- a/development/helper.ts +++ b/development/utils/helper.ts @@ -1,5 +1,5 @@ import validator from 'validator'; -import { PaymentChannels } from './types/index'; +import { DynamicMultiSplitProps, PaymentChannels, PayStackProps } from '../types/index'; const { isDecimal, isFloat, isInt, toFloat, toInt } = validator; @@ -72,3 +72,51 @@ export const getChannels = (channelsArrary: PaymentChannels[]) => { } return ''; }; + +export const buildKeyValueString = (key: string, value: string | undefined) => + value ? `${key}: '${value}',` : ''; + +export const dynamicSplitObjectIsValid = ( + split: DynamicMultiSplitProps | undefined +): split is DynamicMultiSplitProps => { + return ( + split !== null && + typeof split === "object" && + split.type && + split.bearer_type && + Array.isArray(split.subaccounts) + ); +}; + +export const paystackHtmlContent = (Params: string) => ` + + + + + + Paystack + + + + + + +`; \ No newline at end of file diff --git a/development/utils/index.ts b/development/utils/index.ts new file mode 100644 index 0000000..846a793 --- /dev/null +++ b/development/utils/index.ts @@ -0,0 +1,19 @@ +export const buildKeyValueString = (key: string, value: string | undefined) => + value ? `${key}: '${value}',` : ''; + + export const dynamicSplitObjectIsValid = (split: any): boolean => { + return ( + split !== null && + typeof split === 'object' && + split.type && + split.bearer_type && + Array.isArray(split.subaccounts) + ); + }; + + export const generateMetaDataString = (firstName: string, lastName: string, billingName: string, metadata: any) => { + return metadata + ? `metadata: ${metadata},` + : `metadata: { custom_fields: [{ display_name: '${firstName + " " + lastName}', variable_name: '${billingName}', value:'' }]},`; + }; + \ No newline at end of file diff --git a/package.json b/package.json index 9a96e44..e69b466 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "This package allows you to accept payment in your react native project using paystack ", "homepage": "https://github.com/just1and0/React-Native-Paystack-WebView#readme", "main": "production/lib/index.js", - "types": "production/lib/index.d.ts", + "types": "production/lib/types/index.d.ts", "author": "Oluwatobi Shokunbi ", "license": "MIT", "scripts": { @@ -13,15 +13,6 @@ "test": "jest", "semantic-release": "semantic-release" }, - "jest": { - "preset": "react-native", - "setupFilesAfterEnv": [ - "@testing-library/jest-native/extend-expect" - ], - "transformIgnorePatterns": [ - "node_modules/(?!(react-native|react-native-webview|@react-native|@react-navigation)/)" - ] - }, "devDependencies": { "@babel/core": "^7.22.0", "@babel/runtime": "^7.14.6", @@ -49,6 +40,7 @@ "react-native-webview": "*" }, "dependencies": { + "@types/validator": "^13.6.3", "react-native-webview": "*", "validator": "^13.6.0" }, From f24d5ae645b9e0007de0970e22013013fa019ff2 Mon Sep 17 00:00:00 2001 From: Oluwatobi Shokunbi Date: Sun, 12 Jan 2025 13:23:13 +0000 Subject: [PATCH 2/3] Update utils.test.ts --- __tests__/utils.test.ts | 62 ----------------------------------------- 1 file changed, 62 deletions(-) diff --git a/__tests__/utils.test.ts b/__tests__/utils.test.ts index 156eeda..1c75a52 100644 --- a/__tests__/utils.test.ts +++ b/__tests__/utils.test.ts @@ -68,68 +68,6 @@ describe('Utility functions work properly', () => { }); describe('Utility functions work properly', () => { - test('getChannels should return a stringified array with commas', () => { - let testChannels: PaymentChannels[] = ['card', 'bank']; - let expectedOutput = 'channels: ["card","bank"],'; - - const result = getChannels(testChannels); - expect(result).toBe(expectedOutput); - }); - - test('toAmountInKobo should return kobo value for amount', () => { - let result = toAmountInKobo('4600.00'); - expect(result).toBe(460000); - - result = toAmountInKobo(1200.93); - expect(result).toBe(120093); - }); - - test('getAmountValueInKobo should return kobo value for valid amounts', () => { - let result = getAmountValueInKobo('4600.00'); - expect(result).toBe(460000); - - result = getAmountValueInKobo('not_correct_money_amount'); - expect(result).toBe(0); - }); - - test('isValidDecimalMonetaryValue should return true for only valid amount', () => { - let result = isValidDecimalMonetaryValue('2500.00'); - expect(result).toBe(true); - - result = isValidDecimalMonetaryValue('2500'); - expect(result).toBe(true); - - result = isValidDecimalMonetaryValue('invalid_amount'); - expect(result).toBe(false); - }); - - test('isValidStringAmount should return true for valid amount strings', () => { - let result = isValidStringAmount('2500.00'); - expect(result).toBe(true); - - result = isValidStringAmount('not_money_amount'); - expect(result).toBe(false); - - result = isValidStringAmount('2500.'); - expect(result).toBe(false); - }); - - test('toNumber should convert string amount to number', () => { - const result = toNumber('2500.00'); - expect(result).toBe(2500); - }); - - test('isNegative should return true if amount is negative', () => { - let result = isNegative('-200.00'); - expect(result).toBe(true); - - result = isNegative(-200.0); - expect(result).toBe(true); - - result = isNegative(200.0); - expect(result).toBe(false); - }); - test('buildKeyValueString should return correct string for key-value', () => { let result = buildKeyValueString('key1', 'value1'); expect(result).toBe("key1: 'value1',"); From d0fc69b79625f28da661bc7c60d8c02d231392db Mon Sep 17 00:00:00 2001 From: Oluwatobi Shokunbi Date: Sun, 12 Jan 2025 17:13:29 +0000 Subject: [PATCH 3/3] review fix --- README.md | 8 ++++++++ __tests__/utils.test.ts | 3 +-- development/paystack.tsx | 9 ++++----- development/utils/constants.ts | 4 ++++ development/utils/helper.ts | 8 +++++++- development/utils/index.ts | 26 +++++++------------------- 6 files changed, 31 insertions(+), 27 deletions(-) create mode 100644 development/utils/constants.ts diff --git a/README.md b/README.md index 545bd88..22e3728 100644 --- a/README.md +++ b/README.md @@ -150,6 +150,14 @@ function Pay(){ | | - **`card_brands`**: Supported card brands, e.g., `'verve'`, `'visa'`, `'mastercard'`. | | | | | - **`supported_mobile_money_providers`**: Supported mobile money providers, e.g., `'mtn'`, `'atl'`, `'vod'`. | | | +--- +#### Refs + +| Name | use/description | extra | +| :---------------- | :----------------------------------------------------------: | --------: | +| `startTransaction`| Function triggered to start a transaction . Example usage: `paystackWebViewRef.current.startTransaction()` | default: `nill` | +| `endTransaction` | Function triggered to ends a transaction . Example usage: `paystackWebViewRef.current.endTransaction()` | default: `nill` | + --- #### Dynamic Multi-Split Payment Object structure diff --git a/__tests__/utils.test.ts b/__tests__/utils.test.ts index 1c75a52..c9da0a4 100644 --- a/__tests__/utils.test.ts +++ b/__tests__/utils.test.ts @@ -1,4 +1,3 @@ -/* eslint-disable prefer-const */ import { toAmountInKobo, isValidDecimalMonetaryValue, @@ -10,7 +9,7 @@ import { buildKeyValueString, dynamicSplitObjectIsValid, paystackHtmlContent, -} from '../development//utils/helper'; +} from '../development/utils/helper'; import { DynamicMultiSplitProps, PaymentChannels } from '../development/types'; describe('Utility functions work properly', () => { diff --git a/development/paystack.tsx b/development/paystack.tsx index d6c8f99..b7beb23 100644 --- a/development/paystack.tsx +++ b/development/paystack.tsx @@ -22,8 +22,7 @@ import { } from "./utils/helper"; import { PayStackProps, PayStackRef } from "./types"; import { styles } from "./style"; - -const CLOSE_URL = "https://standard.paystack.co/close"; +import { CLOSE_URL, DEFAULT_ACTIVITY_INDICATOR_COLOR, DEFAULT_AMOUNT, DEFAULT_CURRENCY } from "./utils/constants"; const Paystack = forwardRef( ( @@ -33,8 +32,8 @@ const Paystack = forwardRef( phone, lastName, firstName, - amount = "0.00", - currency = "NGN", + amount = DEFAULT_AMOUNT, + currency = DEFAULT_CURRENCY, channels = ["card"], refNumber, billingName, @@ -47,7 +46,7 @@ const Paystack = forwardRef( onCancel, autoStart = false, onSuccess, - activityIndicatorColor = "green", + activityIndicatorColor = DEFAULT_ACTIVITY_INDICATOR_COLOR, modalProps, metadata, }, diff --git a/development/utils/constants.ts b/development/utils/constants.ts new file mode 100644 index 0000000..fe0038b --- /dev/null +++ b/development/utils/constants.ts @@ -0,0 +1,4 @@ +export const CLOSE_URL = 'https://standard.paystack.co/close'; +export const DEFAULT_AMOUNT = '0.00'; +export const DEFAULT_CURRENCY = 'NGN'; +export const DEFAULT_ACTIVITY_INDICATOR_COLOR = 'green'; \ No newline at end of file diff --git a/development/utils/helper.ts b/development/utils/helper.ts index 704f64a..15fea94 100644 --- a/development/utils/helper.ts +++ b/development/utils/helper.ts @@ -119,4 +119,10 @@ export const paystackHtmlContent = (Params: string) => ` -`; \ No newline at end of file +`; + +export const generateMetaDataString = (firstName: string, lastName: string, billingName: string, metadata: any) => { + return metadata + ? `metadata: ${metadata},` + : `metadata: { custom_fields: [{ display_name: '${firstName + " " + lastName}', variable_name: '${billingName}', value:'' }]},`; +}; diff --git a/development/utils/index.ts b/development/utils/index.ts index 846a793..538f04e 100644 --- a/development/utils/index.ts +++ b/development/utils/index.ts @@ -1,19 +1,7 @@ -export const buildKeyValueString = (key: string, value: string | undefined) => - value ? `${key}: '${value}',` : ''; - - export const dynamicSplitObjectIsValid = (split: any): boolean => { - return ( - split !== null && - typeof split === 'object' && - split.type && - split.bearer_type && - Array.isArray(split.subaccounts) - ); - }; - - export const generateMetaDataString = (firstName: string, lastName: string, billingName: string, metadata: any) => { - return metadata - ? `metadata: ${metadata},` - : `metadata: { custom_fields: [{ display_name: '${firstName + " " + lastName}', variable_name: '${billingName}', value:'' }]},`; - }; - \ No newline at end of file +import * as Constants from './constants' +import * as Utils from './helper' + +export default { + Constants, + Utils +} \ No newline at end of file