import React, { useEffect, useState } from "react"; import { View, Text, TouchableOpacity, StyleSheet, SafeAreaView, Alert, Share, Linking, BackHandler, ScrollView, } from "react-native"; import * as FileSystem from "expo-file-system"; import * as MediaLibrary from "expo-media-library"; import * as Sharing from "expo-sharing"; import { Image } from "expo-image"; import { useSelector, useDispatch } from "react-redux"; import { RootState } from "@/store"; import { setPaymentOrder, updatePaymentStatus } from "@/store/paymentSlice"; import Header from "@/components/common/Header"; import ShareIcon from "@/assets/icons/share.svg"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import { useSnackbar } from "@/contexts/Snackbar"; import DownloadIcon from "@/assets/icons/download.svg"; import { payments } from "@/constants/config"; import { useRouter } from "expo-router"; import { useSocket } from "@/contexts/SocketContext"; import { useTranslation } from "react-i18next"; const UpiPaymentScreen = () => { const dispatch = useDispatch(); const paymentOrder = useSelector( (state: RootState) => state.payments.paymentOrder ); const router = useRouter(); const { onPaymentConfirmation, offPaymentConfirmation, disconnect } = useSocket(); const { showSnackbar } = useSnackbar(); const insets = useSafeAreaInsets(); useEffect(() => { let backPressCount = 0; let backPressTimer: NodeJS.Timeout | null = null; const handlePaymentConfirmation = (data: any) => { console.log("Payment confirmation received:", data); dispatch( setPaymentOrder({ ...paymentOrder, ...data, }) ); offPaymentConfirmation(); disconnect(); router.replace("/payments/Confirmation"); }; onPaymentConfirmation(handlePaymentConfirmation); const backAction = () => { if (backPressCount === 0) { backPressCount++; console.log("Press back again to cancel payment"); showSnackbar("Press back again to cancel payment", "success"); backPressTimer = setTimeout(() => { backPressCount = 0; }, 2000); return true; } else { if (backPressTimer) clearTimeout(backPressTimer); offPaymentConfirmation(); disconnect(); router.back(); return true; } }; const backHandler = BackHandler.addEventListener( "hardwareBackPress", backAction ); return () => { offPaymentConfirmation(); backHandler.remove(); }; }, [onPaymentConfirmation, offPaymentConfirmation, router]); const formatAmount = (amount: number): string => { return `₹${amount.toLocaleString("en-IN")}`; }; const isPaymentExpired = (): boolean => { const expiryDate = new Date(paymentOrder.expiry_date); const currentDate = new Date(); return currentDate > expiryDate; }; const getExpiryTime = (): string => { const expiryDate = new Date(paymentOrder.expiry_date); return expiryDate.toLocaleString("en-IN"); }; const getUpiUrl = (): string => { const upiString = paymentOrder.payment_link; const upiMatch = upiString.match(/upi_string=([^&]+)/); if (upiMatch) { return decodeURIComponent(upiMatch[1]); } return `upi://pay?pa=${paymentOrder.upi_handle}&am=${paymentOrder.amount}&cu=INR&tr=${paymentOrder.order_id}`; }; const payUsingUpiApp = async (): Promise => { try { if (isPaymentExpired()) { showSnackbar(payments.LINK_EXPIRED, "error"); return; } const upiUrl = getUpiUrl(); console.log("Opening UPI URL:", upiUrl); dispatch(updatePaymentStatus("processing")); const canOpenUrl = await Linking.canOpenURL(upiUrl); if (canOpenUrl) { await Linking.openURL(upiUrl); } else { showSnackbar("UPI App Required.", "error"); } } catch (error) { console.error("Error opening UPI app:", error); dispatch(updatePaymentStatus("failed")); showSnackbar("Unable to open UPI App", "error"); } }; const shareQR = async (): Promise => { try { if (await Sharing.isAvailableAsync()) { await Share.share({ message: `Pay ${formatAmount( paymentOrder.amount )} using this QR code`, url: paymentOrder.qr_code_url, }); } else { Alert.alert("Error", "Sharing is not available on this device"); } } catch (error) { Alert.alert("Error", "Failed to share QR code"); } }; const downloadQR = async (): Promise => { try { const { status } = await MediaLibrary.requestPermissionsAsync(); if (status !== "granted") { showSnackbar("Please grant permission to save images", "error"); return; } const fileUri = FileSystem.documentDirectory + `qr-${paymentOrder.order_id}.png`; const downloadResult = await FileSystem.downloadAsync( paymentOrder.qr_code_url, fileUri ); if (downloadResult.status === 200) { const asset = await MediaLibrary.createAssetAsync(downloadResult.uri); await MediaLibrary.createAlbumAsync("Payment QR Codes", asset, false); showSnackbar("QR code saved to gallery", "success"); } else { showSnackbar("Failed to Download QR code", "error"); } } catch (error) { showSnackbar("Failed to Download QR code", "error"); } }; function handlePaymentDone() { router.push("/(tabs)/payments"); } const { t } = useTranslation(); return (
{t("payment.amount-to-be-paid")} {formatAmount(paymentOrder?.amount)} {t("payment.share-qr")} {t("payment.download-qr")} {t("payment.pay-using-upi")} {t("payment.confirm-payment")} handlePaymentDone()} style={styles.paymentDone} > {t("payment.payment-done")} ); }; const styles = StyleSheet.create({ doneText: { textAlign: "center", fontWeight: "500", fontSize: 14, lineHeight: 20, }, paymentDone: { padding: 16, borderWidth: 1, borderColor: "#DCE1E9", }, confirmTitle: { fontWeight: "400", fontSize: 14, lineHeight: 14, color: "#252A34", }, confirm: { padding: 16, flexDirection: "column", backgroundColor: "#FCFCFC", gap: 16, }, container: { flex: 1, backgroundColor: "#F3F5F8", }, loadingContainer: { flex: 1, justifyContent: "center", alignItems: "center", }, loadingText: { marginTop: 16, fontSize: 16, color: "#253342", }, header: { flexDirection: "row", alignItems: "center", paddingHorizontal: 16, paddingVertical: 12, backgroundColor: "#FFFFFF", }, backButton: { padding: 8, marginRight: 8, }, headerTitle: { fontSize: 18, fontWeight: "600", color: "#253342", }, content: { flex: 1, paddingHorizontal: 16, paddingBottom: 16, justifyContent: "space-between", }, qrFrame: { backgroundColor: "#FCFCFC", borderRadius: 8, padding: 16, alignItems: "center", marginTop: 16, }, amountSection: { alignItems: "center", marginBottom: 16, }, amountLabel: { fontSize: 14, color: "#253342", textAlign: "center", marginBottom: 4, }, amount: { fontSize: 20, fontWeight: "600", color: "#253342", textAlign: "center", marginBottom: 8, }, statusBadge: { paddingHorizontal: 12, paddingVertical: 4, borderRadius: 12, }, statusText: { fontSize: 12, fontWeight: "600", color: "#FFFFFF", }, qrCodeContainer: { marginBottom: 16, borderWidth: 2, borderColor: "#E5E9F0", padding: 16, borderRadius: 8, width: "100%", height: "auto", }, qrCode: { width: "100%", aspectRatio: 1, alignSelf: "center", }, upiIdSection: { flexDirection: "row", alignItems: "center", justifyContent: "center", marginBottom: 12, padding: 8, backgroundColor: "#F3F5F8", borderRadius: 4, }, upiIdText: { fontSize: 14, color: "#253342", marginRight: 8, fontWeight: "500", }, expirySection: { alignItems: "center", marginBottom: 16, }, expiryLabel: { fontSize: 12, color: "#6C757D", marginBottom: 2, }, expiryTime: { fontSize: 14, color: "#253342", fontWeight: "500", }, buttonsContainer: { flexDirection: "row", gap: 8, width: "100%", }, secondaryButton: { flex: 1, flexDirection: "row", alignItems: "center", justifyContent: "center", paddingVertical: 10, paddingHorizontal: 16, backgroundColor: "#F3F5F8", borderColor: "#D8DDE7", borderWidth: 1, borderRadius: 4, gap: 4, }, secondaryButtonText: { fontSize: 14, fontWeight: "500", color: "#253342", }, primaryButton: { backgroundColor: "#00876F", paddingVertical: 12, paddingHorizontal: 16, borderRadius: 4, marginTop: 16, width: "100%", alignItems: "center", }, primaryButtonText: { fontSize: 14, fontWeight: "500", color: "#FCFCFC", }, disabledButton: { backgroundColor: "#D8DDE7", }, disabledButtonText: { color: "#6C757D", }, }); export default UpiPaymentScreen;