152 lines
5.0 KiB
TypeScript
152 lines
5.0 KiB
TypeScript
import React, { useEffect, useState } from 'react';
|
||
import { View, Text, ScrollView, Alert } from 'react-native';
|
||
import { RouteProp, useNavigation, useRoute } from '@react-navigation/native';
|
||
import { StackNavigationProp } from '@react-navigation/stack';
|
||
import { getStyles } from './checkoutPaymentScreen.styles';
|
||
import {
|
||
Header,
|
||
StepProgress,
|
||
PaymentOption,
|
||
PrimaryButton,
|
||
} from '@components';
|
||
import { useAppTheme } from '@theme';
|
||
import { AppStackParamList } from '../../../navigation/appStack';
|
||
import { RootState, useAppDispatch, useAppSelector } from '@store';
|
||
import { getAllPaymentMethodsThunk, placeOrderThunk } from './thunk';
|
||
import { v4 } from 'react-native-uuid/dist/v4';
|
||
import { useStripePayment } from './hooks/useStripePayment';
|
||
import { useRazorPayment } from './hooks/useRazorPayment';
|
||
|
||
type CheckoutPaymentNavProp = StackNavigationProp<
|
||
AppStackParamList,
|
||
'CheckoutPaymentScreen'
|
||
>;
|
||
type CheckoutPaymentRouteProp = RouteProp<
|
||
AppStackParamList,
|
||
'CheckoutPaymentScreen'
|
||
>;
|
||
|
||
const CHECKOUT_STEPS = [
|
||
{ key: 'address', label: 'Address' },
|
||
{ key: 'payment', label: 'Payment' },
|
||
{ key: 'confirm', label: 'Confirm' },
|
||
];
|
||
|
||
// const PAYMENT_METHODS = [
|
||
// { id: 'upi', type: 'UPI' as const, label: 'UPI (Google Pay, PhonePe)' },
|
||
// { id: 'card', type: 'Card' as const, label: 'Credit / Debit Card' },
|
||
// { id: 'wallet', type: 'Wallet' as const, label: 'Wallet' },
|
||
// { id: 'cod', type: 'COD' as const, label: 'Cash on Delivery' },
|
||
// ];
|
||
|
||
export const CheckoutPaymentScreen: React.FC = () => {
|
||
const { colors } = useAppTheme();
|
||
const styles = getStyles(colors);
|
||
const route = useRoute<CheckoutPaymentRouteProp>();
|
||
const navigation = useNavigation<CheckoutPaymentNavProp>();
|
||
const dispatch = useAppDispatch();
|
||
const [selectedMethod, setSelectedMethod] = useState('upi');
|
||
const selectedAddressId = route.params?.selectedAddressId;
|
||
// console.log(selectedAddressId);
|
||
const uuid = v4();
|
||
// console.log(uuid);
|
||
const { paymentMethods, placeOrderLoading } = useAppSelector(
|
||
(state: RootState) => state.paymentMethods,
|
||
);
|
||
|
||
const { processCardPayment, isPaymentProcessing } = useStripePayment();
|
||
const { processRazorpayPayment, isPaymentProcessing: isRazorpayProcessing } =
|
||
useRazorPayment();
|
||
|
||
useEffect(() => {
|
||
dispatch(getAllPaymentMethodsThunk());
|
||
}, [dispatch]);
|
||
|
||
// console.log('paymentMethods', paymentMethods);
|
||
|
||
const selectedPaymentMethod = paymentMethods.find(
|
||
item => item.id === selectedMethod,
|
||
);
|
||
|
||
const methodName = selectedPaymentMethod?.code;
|
||
// console.log('methodName', methodName);
|
||
|
||
// useEffect(() => {
|
||
|
||
// },);
|
||
|
||
const handlePlaceOrder = async () => {
|
||
try {
|
||
const response = await dispatch(
|
||
placeOrderThunk({
|
||
addressId: selectedAddressId || '',
|
||
paymentMethodId: selectedMethod,
|
||
paymentMethod: methodName || '',
|
||
orderType: 'DELIVERY',
|
||
idempotencyKey: `idemp-key-${uuid}`,
|
||
}),
|
||
).unwrap();
|
||
|
||
if (methodName === 'CARD') {
|
||
// Delegate entire Stripe flow to the hook
|
||
const success = await processCardPayment(response);
|
||
if (success) {
|
||
navigation.navigate('OrderConfirmedScreen', {
|
||
orderId:
|
||
response.orders[0]?.orderNumber ||
|
||
'ORD-' + Math.floor(Math.random() * 900000 + 100000),
|
||
});
|
||
}
|
||
} else if (methodName === 'UPI') {
|
||
// Delegate entire Razorpay UPI flow to the hook
|
||
const success = await processRazorpayPayment(response, 'upi');
|
||
if (success) {
|
||
navigation.navigate('OrderConfirmedScreen', {
|
||
orderId:
|
||
response.orders[0]?.orderNumber ||
|
||
'ORD-' + Math.floor(Math.random() * 900000 + 100000),
|
||
});
|
||
}
|
||
} else {
|
||
// Non-card methods (COD, Wallet) – navigate directly
|
||
navigation.replace('OrderConfirmedScreen', {
|
||
orderId:
|
||
response.orders[0]?.orderNumber ||
|
||
'ORD-' + Math.floor(Math.random() * 900000 + 100000),
|
||
});
|
||
}
|
||
} catch (err: any) {
|
||
Alert.alert('Error', err || 'Failed to place order');
|
||
}
|
||
};
|
||
|
||
const isLoading =
|
||
placeOrderLoading || isPaymentProcessing || isRazorpayProcessing;
|
||
|
||
return (
|
||
<View style={styles.container}>
|
||
<Header title="Checkout" onBack={() => navigation.goBack()} />
|
||
<StepProgress steps={CHECKOUT_STEPS} activeStep={1} />
|
||
<ScrollView contentContainerStyle={styles.content}>
|
||
<Text style={styles.sectionTitle}>Select Payment Method</Text>
|
||
{paymentMethods?.map(method => (
|
||
<PaymentOption
|
||
key={method.id}
|
||
label={method.code}
|
||
icon={method.iconUrl}
|
||
isSelected={selectedMethod === method.id}
|
||
onSelect={() => setSelectedMethod(method.id)}
|
||
/>
|
||
))}
|
||
</ScrollView>
|
||
<View style={styles.footer}>
|
||
<PrimaryButton
|
||
title={isLoading ? 'Processing...' : 'Place Order'}
|
||
onPress={handlePlaceOrder}
|
||
disabled={isLoading}
|
||
/>
|
||
</View>
|
||
</View>
|
||
);
|
||
};
|