import React, { useState } from "react"; import { View, Text, StyleSheet, TouchableOpacity, TextInput, ScrollView, Platform, KeyboardAvoidingView, Alert, } from "react-native"; import { useDispatch, useSelector } from "react-redux"; import { Formik } from "formik"; import * as Yup from "yup"; import Header from "../../components/common/Header"; import { RootState } from "@/store/rootReducer"; import { BASE_URL, payments } from "@/constants/config"; import api from "@/services/axiosClient"; import { setPaymentOrder } from "@/store/paymentSlice"; import { Overlay } from "@/components/common/Overlay"; import { useFocusEffect, useRouter } from "expo-router"; import { useSocket } from "@/contexts/SocketContext"; import { useSnackbar } from "@/contexts/Snackbar"; const validationSchema = Yup.object().shape({ paymentType: Yup.string().required("Please select a payment option"), customAmount: Yup.string().when("paymentType", { is: "custom", then: (schema) => schema .required("Amount is required") .test("valid-number", "Please enter a valid amount", (value) => { const numValue = parseFloat(value); return !isNaN(numValue) && numValue > 0; }) .test( "min-amount", `Minimum amount is ₹${payments.MIN_AMOUNT}`, (value) => { const numValue = parseFloat(value); return !isNaN(numValue) && numValue >= payments.MIN_AMOUNT; } ), otherwise: (schema) => schema.notRequired(), }), }); const SelectAmountScreen = () => { const dueAmount = useSelector( (state: RootState) => state.payments?.due_amount || 0 ); const { showSnackbar } = useSnackbar(); const router = useRouter(); const [isFetching, setIsFetching] = useState(false); const { registerTransaction } = useSocket(); const quickAmounts = [50, 100, 500, 1000]; const initialValues = { paymentType: "due", customAmount: "", }; const existingPaymentOrder = useSelector( (state: RootState) => state.payments?.paymentOrder ); const dispatch = useDispatch(); useFocusEffect( React.useCallback(() => { console.log( "SelectAmountScreen focused - clearing paymentOrder and remounting" ); // Clear the payment order dispatch(setPaymentOrder(null)); setIsFetching(false); }, [dispatch]) ); const handleSubmit = async (values: any) => { setIsFetching(true); const paymentAmount = values.paymentType === "due" ? dueAmount : parseFloat(values.customAmount); try { let orderData = existingPaymentOrder; if ( existingPaymentOrder && existingPaymentOrder.amount === paymentAmount ) { console.log( "Order for current amount already exists, using existing order" ); orderData = existingPaymentOrder; } else { console.log("Creating new order for amount:", paymentAmount); const res = await api.post(`/api/v1/create-order`, { amount: paymentAmount, }); console.log(res.data, "response from select amount"); if (res.data && res.data.success) { orderData = res.data.data; dispatch(setPaymentOrder(orderData)); } else { throw new Error("Failed to create order"); } } try { await registerTransaction(orderData?.transaction_id); console.log("Transaction registered successfully"); router.push("/payments/payEmi"); } catch (socketError) { console.error("Socket connection failed:", socketError); throw socketError; } } catch (err) { console.error(err, "Error in creating order."); showSnackbar("Something went wrong.", "error"); } finally { setIsFetching(false); } console.log("Payment Amount:", paymentAmount); }; return ( <> {({ values, errors, touched, handleChange, handleBlur, handleSubmit, setFieldValue, isValid, dirty, }) => { const handleQuickAmountPress = (amount: number) => { const currentAmount = values.customAmount ? parseFloat(values.customAmount) : 0; const newAmount = currentAmount + amount; setFieldValue("customAmount", newAmount.toString()); }; const getPaymentAmount = () => { if (values.paymentType === "due") { return dueAmount; } return values.customAmount ? parseFloat(values.customAmount) : 0; }; // Improved button state logic const isPayButtonEnabled = () => { if (values.paymentType === "due") return true; // For custom amount, check if it's valid and meets minimum requirement if (values.paymentType === "custom") { const amount = parseFloat(values.customAmount); return ( values.customAmount && !isNaN(amount) && amount >= payments.MIN_AMOUNT && !errors.customAmount ); } return false; }; return (
setFieldValue("paymentType", "due")} > {values.paymentType === "due" && ( )} Pay amount due ₹{dueAmount?.toFixed(2)} setFieldValue("paymentType", "custom")} > {values.paymentType === "custom" && ( )} Enter custom amount { const numericText = text.replace(/[^0-9.]/g, ""); const parts = numericText.split("."); const formattedText = parts.length > 2 ? parts[0] + "." + parts.slice(1).join("") : numericText; setFieldValue("customAmount", formattedText, true); setFieldValue("paymentType", "custom"); }} onBlur={handleBlur("customAmount")} placeholder="₹" placeholderTextColor="#94A3B8" keyboardType="numeric" onFocus={() => setFieldValue("paymentType", "custom")} // Add return key handling returnKeyType="done" /> {touched.customAmount && errors.customAmount ? errors.customAmount : `Minimum: ₹${payments.MIN_AMOUNT}`} {quickAmounts.map((amount) => ( handleQuickAmountPress(amount)} > +₹{amount} ))} {/* General form error */} {touched.paymentType && errors.paymentType && ( {errors.paymentType} )} handleSubmit()} disabled={!isPayButtonEnabled()} > {getPaymentAmount() < payments.MIN_AMOUNT ? ( Select Amount ) : ( Pay ₹{getPaymentAmount().toFixed(2)} )} ); }} ); }; const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#F3F4F6", }, content: { flex: 1, paddingHorizontal: 16, }, // Add scroll content style for better keyboard handling scrollContent: { paddingBottom: 20, }, selectAmountContainer: { paddingTop: 16, gap: 16, }, option: { backgroundColor: "#FCFCFC", borderRadius: 8, padding: 16, borderWidth: 1, borderColor: "transparent", flexDirection: "row", alignItems: "center", justifyContent: "space-between", minHeight: 56, }, selectedOption: { borderColor: "#009E71", }, errorOption: { borderColor: "#EF4444", }, customOption: { backgroundColor: "#FCFCFC", borderRadius: 8, padding: 16, borderWidth: 1, borderColor: "transparent", minHeight: 180, }, radioContainer: { flexDirection: "row", alignItems: "center", flex: 1, marginBottom: 16, }, radioDot: { width: 18, height: 18, borderRadius: 9, borderWidth: 2, borderColor: "#D1D5DB", alignItems: "center", justifyContent: "center", marginRight: 12, }, selectedRadioDot: { borderColor: "#009E71", }, radioInner: { width: 8, height: 8, borderRadius: 4, backgroundColor: "#009E71", }, radioLabel: { fontSize: 14, color: "#252936", fontWeight: "400", }, amountText: { fontSize: 14, color: "#252936", fontWeight: "400", }, inputContainer: { marginBottom: 16, }, textInput: { backgroundColor: "#FFFFFF", borderWidth: 1, borderColor: "#D8DDE7", borderRadius: 4, paddingHorizontal: 8, paddingVertical: 10, fontSize: 14, color: "#252936", height: 40, }, errorInput: { borderColor: "#EF4444", }, helperContainer: { marginTop: 4, }, helperText: { fontSize: 14, color: "#565F70", }, errorText: { color: "#EF4444", }, generalErrorText: { fontSize: 14, color: "#EF4444", textAlign: "center", marginTop: 8, }, chipsContainer: { flexDirection: "row", gap: 8, flexWrap: "wrap", }, chip: { backgroundColor: "#F3F4F6", borderWidth: 1, borderColor: "#D8DDE7", borderRadius: 4, paddingHorizontal: 8, paddingVertical: 4, minWidth: 68, alignItems: "center", justifyContent: "center", height: 28, }, chipText: { fontSize: 14, color: "#252936", fontWeight: "500", }, buttonContainer: { padding: 16, backgroundColor: "#F3F4F6", }, payButton: { backgroundColor: "#009E71", borderRadius: 4, paddingVertical: 8, paddingHorizontal: 16, alignItems: "center", justifyContent: "center", height: 40, }, disabledButton: { backgroundColor: "#94A3B8", }, payButtonText: { fontSize: 14, color: "#FCFCFC", fontWeight: "500", }, }); export default SelectAmountScreen;