omnipay-savings-sdk
Version:
Omnipay Savings SDK
177 lines (176 loc) • 13.6 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const react_native_1 = require("react-native");
const SmartImage_1 = require("../Images/SmartImage");
const utils_1 = require("../../utils");
const Button_1 = require("../Button");
const currency_1 = __importDefault(require("../Input/currency"));
const Text_1 = require("../Text");
const useHandleChangeNotrim_1 = __importDefault(require("../../hooks/useHandleChangeNotrim"));
const info_1 = require("../Common/info");
const checkBox_1 = __importDefault(require("../RadioButton/checkBox"));
const SDKConfigContext_1 = require("../../contexts/SDKConfigContext");
const modal_1 = require("../Common/modal");
const react_query_1 = require("@tanstack/react-query");
const actions_1 = require("../../services/actions");
const Notification_1 = __importDefault(require("../Feedback/Notification"));
const WithdrawalDuration = (props) => {
const { numberOfTimes, withdrawalLimit, containerStyle } = props;
return ((0, jsx_runtime_1.jsxs)(react_native_1.View, Object.assign({ style: [
{
paddingVertical: (0, utils_1.ms)(10),
paddingHorizontal: (0, utils_1.ms)(10),
rowGap: (0, utils_1.ms)(7.5),
borderRadius: (0, utils_1.ms)(4),
backgroundColor: utils_1.Colors.neutral0X,
},
containerStyle,
] }, { children: [(0, jsx_runtime_1.jsx)(Text_1.Text, { fontSize: (0, utils_1.fontSz)(12), lineHeight: (0, utils_1.fontSz)(12 * 1.2), fontFamily: 'Gordita-Regular', fontWeight: "400", text: `${'Withdrawal this month'}`, color: utils_1.Colors.payLaterHeaderText, textAlign: 'center' }), (0, jsx_runtime_1.jsx)(Text_1.Text, { fontSize: (0, utils_1.fontSz)(12), lineHeight: (0, utils_1.fontSz)(12 * 1.2), fontFamily: 'Gordita-Medium', fontWeight: "900", text: `${numberOfTimes} out of ${withdrawalLimit || 3} times`, color: utils_1.Colors.payLaterHeaderText, textAlign: 'center' })] })));
};
const Withdraw = (props) => {
var _a;
const { visible, onClose, onPressContinue, resetPin, plan, withdrawalLimit, isLockedSavings, penaltyFeePercentage, isBeforeMaturity } = props;
const [agreement, setAgreement] = (0, react_1.useState)(false);
const [showSuccessNotification, setShowSuccessNotification] = (0, react_1.useState)(false);
const { primaryColor, apiKey } = (0, SDKConfigContext_1.useSDKConfig)();
const queryClient = (0, react_query_1.useQueryClient)();
const [errors, setErrors] = (0, useHandleChangeNotrim_1.default)({
code: '',
amount: '',
});
const [details, setDetails] = (0, useHandleChangeNotrim_1.default)({
code: '',
amount: '',
});
const { code, amount } = details;
const useableSavingsBalance = Number((_a = plan === null || plan === void 0 ? void 0 : plan.accountBalance) !== null && _a !== void 0 ? _a : 0);
const withdrawalAmount = Number(amount);
// Calculate penalty fee for early withdrawal from locked savings
const penaltyFee = (isLockedSavings && isBeforeMaturity && penaltyFeePercentage)
? (withdrawalAmount * penaltyFeePercentage) / 100
: 0;
const totalDeduction = withdrawalAmount + penaltyFee;
const netAmountReceived = withdrawalAmount - penaltyFee;
// Mutation for withdrawing from savings account
const { mutate: withdrawSavings, isPending: isWithdrawPending, } = (0, react_query_1.useMutation)({
mutationFn: (params) => (0, actions_1.withdrawFromSavingsAccount)(apiKey, params),
onSuccess: (response) => {
if (response === null || response === void 0 ? void 0 : response.success) {
queryClient.invalidateQueries({
queryKey: ['savingsDetails', plan === null || plan === void 0 ? void 0 : plan.savingsId, apiKey],
});
queryClient.invalidateQueries({
queryKey: ['walletBalance', apiKey],
});
queryClient.invalidateQueries({
queryKey: ['savingsListByCustomerId', apiKey],
});
queryClient.invalidateQueries({
queryKey: ['totalAccountTransactionsByCustomerId', apiKey],
});
setShowSuccessNotification(true);
}
},
onError: (error) => {
console.error('Withdraw from savings account error:', error);
},
});
function updateAmount(value) {
setDetails('amount', value);
const withdrawAmount = Number(value);
const penalty = (isLockedSavings && isBeforeMaturity && penaltyFeePercentage)
? (withdrawAmount * penaltyFeePercentage) / 100
: 0;
const total = withdrawAmount + penalty;
if (total > useableSavingsBalance) {
setErrors('amount', `Total deduction (₦${(0, utils_1.formatAsCurrency)(total)}) exceeds your balance of ${(0, utils_1.formatAsCurrency)(useableSavingsBalance)}`);
}
else {
setErrors('amount', '');
}
}
function updateCode(value) {
setDetails('code', value);
setErrors('code', '');
}
function updateAgreement() {
setAgreement(!agreement);
}
const handleWithdraw = () => {
if (!amount || Number(amount) <= 0) {
return;
}
// Convert amount to kobo (multiply by 100)
const amountInKobo = Math.round(Number(amount) * 100);
withdrawSavings({
savingsId: plan === null || plan === void 0 ? void 0 : plan.savingsId,
amount: amountInKobo,
});
};
const handleSuccessNotificationClose = () => {
setShowSuccessNotification(false);
onClose();
};
// Calculate if user is about to cross the withdrawal limit (show warning only when crossing over)
const isAboutToCrossLimit = Number(plan === null || plan === void 0 ? void 0 : plan.noOfWithdrawals) === (withdrawalLimit || 3);
// Determine if withdrawal button should be disabled
const isWithdrawDisabled = () => {
// Basic validation
if (!amount || Number(amount) <= 0 || errors.amount.length > 0) {
return true;
}
// Check if user is about to cross withdrawal limit and needs to agree
if (isAboutToCrossLimit && !agreement) {
return true;
}
return false;
};
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(modal_1.Modal, Object.assign({ visible: visible && !showSuccessNotification, title: "Withdraw", onClose: onClose, footer: (0, jsx_runtime_1.jsx)(Button_1.Button, { title: !amount || Number(amount) <= 0
? 'Withdraw'
: `Withdraw ${(0, utils_1.formatAsCurrency)(Number(amount))}`, onPress: handleWithdraw, disabled: isWithdrawDisabled(), isLoading: isWithdrawPending }) }, { children: (0, jsx_runtime_1.jsxs)(react_native_1.View, Object.assign({ style: {
paddingHorizontal: (0, utils_1.wp)(15),
minHeight: isAboutToCrossLimit || isLockedSavings ? (0, utils_1.ms)(450) : (0, utils_1.ms)(350),
// alignItems: 'center',
} }, { children: [(0, jsx_runtime_1.jsx)(SmartImage_1.SmartImage, { source: utils_1.Images.completeTransaction, style: {
width: (0, utils_1.ms)(48),
height: (0, utils_1.ms)(48),
alignSelf: 'center',
} }), !isLockedSavings && ((0, jsx_runtime_1.jsx)(WithdrawalDuration, { numberOfTimes: String((plan === null || plan === void 0 ? void 0 : plan.noOfWithdrawals) || 0), containerStyle: { marginTop: (0, utils_1.ms)(10), alignSelf: 'center' }, withdrawalLimit: withdrawalLimit })), (0, jsx_runtime_1.jsx)(Text_1.Text, { fontSize: (0, utils_1.fontSz)(14), lineHeight: (0, utils_1.fontSz)(15.11), fontWeight: "400", text: `Withdraw from your ${plan === null || plan === void 0 ? void 0 : plan.accountName} Savings Account`, color: utils_1.Colors.completeTransactionTitle, textAlign: 'center', style: {
paddingTop: (0, utils_1.ms)(30),
paddingBottom: (0, utils_1.ms)(20),
} }), (0, jsx_runtime_1.jsx)(currency_1.default, { value: amount, onChangeValue: (value) => {
updateAmount(value);
}, ignoreNegative: false, delimiter: ",", separator: ".", precision: 2, returnKeyType: "done", topComponent: (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, {}), walletAmount: useableSavingsBalance, paymentAmount: withdrawalAmount, onPressUseAllBalance: () => {
setDetails('amount', String(useableSavingsBalance));
setErrors('amount', '');
}, onEndEditing: () => { }, onFocus: () => { }, label: 'Amount', showAsterisk: false, placeholder: '', balance: useableSavingsBalance, errorMsg: errors.amount || '', showUseAllBalance: useableSavingsBalance > 0, showCurrency: true }, useableSavingsBalance.toString()), isLockedSavings && isBeforeMaturity && penaltyFeePercentage && penaltyFeePercentage > 0 && withdrawalAmount > 0 && ((0, jsx_runtime_1.jsxs)(react_native_1.View, Object.assign({ style: {
backgroundColor: utils_1.Colors.neutral0X,
borderRadius: (0, utils_1.ms)(8),
padding: (0, utils_1.ms)(16),
marginTop: (0, utils_1.ms)(32),
marginBottom: (0, utils_1.ms)(8),
} }, { children: [(0, jsx_runtime_1.jsx)(Text_1.Text, { fontSize: (0, utils_1.fontSz)(13), fontFamily: "Gordita-Medium", fontWeight: "500", text: "Fee Breakdown", color: utils_1.Colors.completeTransactionTitle, style: { marginBottom: (0, utils_1.ms)(12) } }), (0, jsx_runtime_1.jsxs)(react_native_1.View, Object.assign({ style: { rowGap: (0, utils_1.ms)(8) } }, { children: [(0, jsx_runtime_1.jsxs)(react_native_1.View, Object.assign({ style: utils_1.globalStyles.rowBetween }, { children: [(0, jsx_runtime_1.jsx)(Text_1.Text, { fontSize: (0, utils_1.fontSz)(12), fontFamily: "Gordita-Regular", fontWeight: "400", text: "Withdrawal Amount", color: utils_1.Colors.payLaterHeaderText }), (0, jsx_runtime_1.jsx)(Text_1.Text, { fontSize: (0, utils_1.fontSz)(12), fontFamily: "Gordita-Medium", fontWeight: "500", text: (0, utils_1.formatAsCurrency)(withdrawalAmount), color: utils_1.Colors.completeTransactionTitle })] })), (0, jsx_runtime_1.jsxs)(react_native_1.View, Object.assign({ style: utils_1.globalStyles.rowBetween }, { children: [(0, jsx_runtime_1.jsx)(Text_1.Text, { fontSize: (0, utils_1.fontSz)(12), fontFamily: "Gordita-Regular", fontWeight: "400", text: `Early Withdrawal Fee (${penaltyFeePercentage}%)`, color: utils_1.Colors.payLaterHeaderText }), (0, jsx_runtime_1.jsx)(Text_1.Text, { fontSize: (0, utils_1.fontSz)(12), fontFamily: "Gordita-Medium", fontWeight: "500", text: `-${(0, utils_1.formatAsCurrency)(penaltyFee)}`, color: utils_1.Colors.debitRed })] })), (0, jsx_runtime_1.jsx)(react_native_1.View, { style: {
height: 1,
backgroundColor: utils_1.Colors.neutral20,
marginVertical: (0, utils_1.ms)(4),
} }), (0, jsx_runtime_1.jsxs)(react_native_1.View, Object.assign({ style: utils_1.globalStyles.rowBetween }, { children: [(0, jsx_runtime_1.jsx)(Text_1.Text, { fontSize: (0, utils_1.fontSz)(13), fontFamily: "Gordita-Medium", fontWeight: "600", text: "You'll Receive", color: utils_1.Colors.completeTransactionTitle }), (0, jsx_runtime_1.jsx)(Text_1.Text, { fontSize: (0, utils_1.fontSz)(14), fontFamily: "Gordita-Medium", fontWeight: "600", text: (0, utils_1.formatAsCurrency)(netAmountReceived), color: utils_1.Colors.creditGreen })] }))] }))] }))), isAboutToCrossLimit && ((0, jsx_runtime_1.jsx)(info_1.Info, { text: 'Withdrawal Limit Reached, Interest at stake', containerStyle: { marginBottom: (0, utils_1.ms)(16), marginTop: (0, utils_1.ms)(32) } })), isAboutToCrossLimit && ((0, jsx_runtime_1.jsx)(checkBox_1.default, { containerStyle: { marginBottom: (0, utils_1.ms)(20), marginTop: (0, utils_1.ms)(15) }, label: 'I agree to lose my interest on my next withdrawal.', selected: agreement, onPress: () => updateAgreement() }))] })) })), showSuccessNotification && ((0, jsx_runtime_1.jsx)(Notification_1.default, { title: "Withdrawal Successful", description: `Your main account balance has been credited with ${(0, utils_1.formatAsCurrency)(Number(netAmountReceived))}`, image: utils_1.Images.credited, buttonText: "Close", onButtonPress: handleSuccessNotificationClose }))] }));
};
exports.default = Withdraw;
const styles = react_native_1.StyleSheet.create({
textFoot: {
fontFamily: 'Gordita-Regular',
fontSize: (0, utils_1.fontSz)(16),
color: utils_1.Colors.gray500,
fontWeight: '400',
},
resetPin: {
fontFamily: 'Gordita-Medium',
fontSize: (0, utils_1.fontSz)(16),
fontWeight: '500',
},
});