@oxyhq/services
Version:
259 lines (249 loc) • 9.44 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _react = _interopRequireWildcard(require("react"));
var _reactNative = require("react-native");
var _index = require("../styles/index.js");
var _themeUtils = require("../utils/themeUtils.js");
var _GroupedPillButtons = _interopRequireDefault(require("../components/internal/GroupedPillButtons.js"));
var _useThemeStyles = require("../hooks/useThemeStyles.js");
var _reactNativeQrcodeSvg = _interopRequireDefault(require("react-native-qrcode-svg"));
var _index2 = require("../components/payment/index.js");
var _jsxRuntime = require("react/jsx-runtime");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
const getUniqueItemTypes = items => {
const types = items.map(item => item.type);
return Array.from(new Set(types));
};
const PaymentGatewayScreen = props => {
const {
navigate,
goBack,
theme,
onPaymentResult,
amount,
currency = 'FAIR',
onClose,
paymentItems = [],
description = ''
} = props;
// DEV ENFORCEMENT: Only allow one type of payment item
if (process.env.NODE_ENV !== 'production' && paymentItems.length > 0) {
const uniqueTypes = getUniqueItemTypes(paymentItems);
if (uniqueTypes.length > 1) {
throw new Error(`PaymentGatewayScreen: paymentItems contains mixed types (${uniqueTypes.join(', ')}). Only one type is allowed per payment.`);
}
}
// Step states
const [currentStep, setCurrentStep] = (0, _react.useState)(0);
const [paymentMethod, setPaymentMethod] = (0, _react.useState)('card');
const [cardDetails, setCardDetails] = (0, _react.useState)({
number: '',
expiry: '',
cvv: ''
});
const [isPaying, setIsPaying] = (0, _react.useState)(false);
// Animations
const fadeAnim = (0, _react.useRef)(new _reactNative.Animated.Value(1)).current;
const slideAnim = (0, _react.useRef)(new _reactNative.Animated.Value(0)).current;
const scaleAnim = (0, _react.useRef)(new _reactNative.Animated.Value(1)).current;
const progressAnim = (0, _react.useRef)(new _reactNative.Animated.Value(0.2)).current;
const normalizedTheme = (0, _themeUtils.normalizeTheme)(theme);
const colors = (0, _index.useThemeColors)(normalizedTheme);
const themeStyles = (0, _useThemeStyles.useThemeStyles)(normalizedTheme);
const styles = (0, _react.useMemo)(() => (0, _index2.createPaymentStyles)(colors), [colors]);
// Determine if the payment is for a recurring item (subscription)
const isRecurring = paymentItems.length > 0 && paymentItems[0].type === 'subscription';
// Filter payment methods: remove 'faircoin' if recurring
const availablePaymentMethods = (0, _react.useMemo)(() => {
if (isRecurring) {
return _index2.PAYMENT_METHODS.filter(m => m.key !== 'faircoin');
}
return _index2.PAYMENT_METHODS;
}, [isRecurring]);
// Animation transitions
const animateTransition = (0, _react.useCallback)(nextStep => {
_reactNative.Animated.timing(scaleAnim, {
toValue: 0.95,
duration: 150,
useNativeDriver: _reactNative.Platform.OS !== 'web'
}).start();
_reactNative.Animated.timing(fadeAnim, {
toValue: 0,
duration: 200,
useNativeDriver: _reactNative.Platform.OS !== 'web'
}).start(() => {
setCurrentStep(nextStep);
slideAnim.setValue(-50);
scaleAnim.setValue(0.95);
_reactNative.Animated.parallel([_reactNative.Animated.timing(fadeAnim, {
toValue: 1,
duration: 300,
useNativeDriver: _reactNative.Platform.OS !== 'web'
}), _reactNative.Animated.spring(slideAnim, {
toValue: 0,
tension: 80,
friction: 8,
useNativeDriver: _reactNative.Platform.OS !== 'web'
}), _reactNative.Animated.spring(scaleAnim, {
toValue: 1,
tension: 80,
friction: 8,
useNativeDriver: _reactNative.Platform.OS !== 'web'
})]).start();
});
}, [fadeAnim, slideAnim, scaleAnim]);
const nextStep = (0, _react.useCallback)(() => {
if (currentStep < 4) {
_reactNative.Animated.timing(progressAnim, {
toValue: (currentStep + 2) / 5,
duration: 300,
useNativeDriver: false
}).start();
animateTransition(currentStep + 1);
}
}, [currentStep, progressAnim, animateTransition]);
const prevStep = (0, _react.useCallback)(() => {
if (currentStep > 0) {
_reactNative.Animated.timing(progressAnim, {
toValue: currentStep / 5,
duration: 300,
useNativeDriver: false
}).start();
animateTransition(currentStep - 1);
}
}, [currentStep, progressAnim, animateTransition]);
// Pay handler - TODO: Replace with actual payment API
const handlePay = (0, _react.useCallback)(() => {
setIsPaying(true);
setTimeout(() => {
setIsPaying(false);
nextStep();
}, 1500);
}, [nextStep]);
const handleDone = (0, _react.useCallback)(() => {
if (onPaymentResult) {
onPaymentResult({
success: true
});
}
navigate?.('AccountOverview');
}, [onPaymentResult, navigate]);
const handleClose = (0, _react.useCallback)(() => {
if (onPaymentResult) {
onPaymentResult({
success: false,
error: 'cancelled'
});
}
if (onClose) {
onClose();
} else if (goBack) {
goBack();
}
}, [onPaymentResult, onClose, goBack]);
// Validate amount
if (!amount || isNaN(Number(amount)) || Number(amount) <= 0) {
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
style: styles.errorContainer,
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
style: styles.errorText,
children: "Invalid or missing payment amount."
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_GroupedPillButtons.default, {
buttons: [{
text: 'Close',
onPress: handleClose,
icon: 'close',
variant: 'primary'
}],
colors: colors
})]
});
}
// FairCoin address - TODO: Replace with dynamic address from backend
const faircoinAddress = 'f1abc1234FAIRCOINADDRESS';
const {
width: windowWidth
} = (0, _reactNative.useWindowDimensions)();
const isMobile = windowWidth < 600;
const qrSize = !isMobile ? Math.min(windowWidth * 0.3, 220) : Math.min(windowWidth * 0.8, 300);
const animations = {
fadeAnim,
slideAnim,
scaleAnim
};
const renderCurrentStep = () => {
switch (currentStep) {
case 0:
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_index2.PaymentSummaryStep, {
paymentItems: paymentItems,
amount: amount,
currency: currency,
description: description,
colors: colors,
animations: animations,
onClose: handleClose,
onNext: nextStep
});
case 1:
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_index2.PaymentMethodStep, {
availablePaymentMethods: availablePaymentMethods,
selectedMethod: paymentMethod,
onSelectMethod: setPaymentMethod,
colors: colors,
animations: animations,
onBack: prevStep,
onNext: nextStep
});
case 2:
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_index2.PaymentDetailsStep, {
paymentMethod: paymentMethod,
cardDetails: cardDetails,
onCardDetailsChange: setCardDetails,
colors: colors,
animations: animations,
faircoinAddress: faircoinAddress,
isMobile: isMobile,
qrSize: qrSize,
onBack: prevStep,
onNext: nextStep,
QRCodeComponent: _reactNativeQrcodeSvg.default
});
case 3:
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_index2.PaymentReviewStep, {
amount: amount,
currency: currency,
paymentMethod: paymentMethod,
cardDetails: cardDetails,
colors: colors,
animations: animations,
isPaying: isPaying,
onBack: prevStep,
onPay: handlePay
});
case 4:
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_index2.PaymentSuccessStep, {
colors: colors,
animations: animations,
onDone: handleDone
});
default:
return null;
}
};
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
style: [styles.container, {
backgroundColor: themeStyles.backgroundColor
}],
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, {
style: styles.content,
showsVerticalScrollIndicator: false,
children: renderCurrentStep()
})
});
};
var _default = exports.default = PaymentGatewayScreen;
//# sourceMappingURL=PaymentGatewayScreen.js.map