141 lines
4.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 { useSelector } from 'react-redux';
import uuid from 'react-native-uuid';
import { v4 } from 'react-native-uuid/dist/v4';
import { useStripePayment } from './hooks/useStripePayment';
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();
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 {
// Non-card methods (COD, UPI, Wallet) navigate directly
navigation.navigate('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;
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>
);
};