// import { // View, // Image, // Text, // ScrollView, // AppState, // Pressable, // ImageBackground, // ActivityIndicator, // Modal, // Alert, // TextInput, // Linking // } from 'react-native'; // import { SafeAreaView } from 'react-native-safe-area-context'; // import { router } from 'expo-router'; // import { CrossLogoSvg } from '../global/SVG'; // import { useEffect, useRef, useState } from 'react'; // import { walletService } from '../../service/walletService'; // import UnionPayImage from '../../assets/unionpay.png'; // import PayMeImage from '../../assets/payme.png'; // import { formatCouponDate, formatDate } from '../../util/lib'; // import { set } from 'date-fns'; // import { reloadAppAsync } from 'expo'; // const TopUpModal = ({ visible, onClose, onSelect, paymentOptions }) => { // const getPaymentImage = (key) => { // switch (key) { // case 'union_pay_wap_payment': // return UnionPayImage; // case 'payme_wap_payment': // return PayMeImage; // default: // return null; // } // }; // return ( // // // // 選擇支付方式 // // {Object.entries(paymentOptions).map(([key, value]) => ( // onSelect(value)} // style={{ // padding: 10, // marginBottom: 10, // borderBottomWidth: 1, // borderBottomColor: '#eee' // }} // > // // // // {key === 'union_pay_wap_payment' ? 'UnionPay' : 'PayMe'} // // // // ))} // // // 關閉 // // // // // ); // }; // const AmountInputModal = ({ visible, onClose, onConfirm }) => { // const [inputAmount, setInputAmount] = useState(''); // return ( // // // // 輸入增值金額 // // onConfirm(inputAmount)} // style={{ // backgroundColor: '#02677D', // padding: 10, // borderRadius: 5, // alignItems: 'center' // }} // > // 確認 // // // 取消 // // // // // ); // }; // export const CouponComponent = ({ // title, // price, // detail, // date // }: { // title: string; // price: string; // detail: string; // date: string; // }) => { // return ( // console.log('abc')}> // // // // $ // // {price} // // // // {title} // // // {/* //dash line */} // // // // // // // {title} // {detail} // // 有效期 // {date} // // // // // ); // }; // const WalletPageComponent = () => { // const [walletBalance, setWalletBalance] = useState(null); // const [loading, setLoading] = useState(false); // const [modalVisible, setModalVisible] = useState(false); // const [coupons, setCoupons] = useState([]); // const [paymentType, setPaymentType] = useState({}); // const [userID, setUserID] = useState(''); // const [selectedPaymentType, setSelectedPaymentType] = useState(null); // const [amount, setAmount] = useState(0); // const [amountModalVisible, setAmountModalVisible] = useState(false); // const [outTradeNo, setOutTradeNo] = useState(''); // const PAYMENT_CHECK_TIMEOUT = 5 * 60 * 1000; // 5 minutes in milliseconds // const [paymentStatus, setPaymentStatus] = useState(null); // const [isExpectingPayment, setIsExpectingPayment] = useState(false); // const appState = useRef(AppState.currentState); // const paymentInitiatedTime = useRef(null); // useEffect(() => { // const subscription = AppState.addEventListener('change', (nextAppState) => { // if ( // appState.current.match(/inactive|background/) && // nextAppState === 'active' && // isExpectingPayment && // outTradeNo && // paymentInitiatedTime.current // ) { // const currentTime = new Date().getTime(); // if (currentTime - paymentInitiatedTime.current < PAYMENT_CHECK_TIMEOUT) { // checkPaymentStatus(); // } else { // // Payment check timeout reached // setIsExpectingPayment(false); // setOutTradeNo(''); // paymentInitiatedTime.current = null; // Alert.alert( // 'Payment Timeout', // 'The payment status check has timed out. Please check your payment history.' // ); // } // } // appState.current = nextAppState; // }); // return () => { // subscription.remove(); // }; // }, [outTradeNo, isExpectingPayment]); // const checkPaymentStatus = async () => { // try { // const result = await walletService.checkPaymentStatus(outTradeNo); // setPaymentStatus(result); // console.log('checkPaymentStatus from walletPageComponent', result); // if (result[0].respcd === '0000') { // console.log(result); // // Payment successful // Alert.alert('Success', 'Payment was successful!', [ // { // text: 'OK', // onPress: async () => { // const wallet = await walletService.getWalletBalance(); // setWalletBalance(wallet); // console.log('new wallet:', wallet); // } // } // ]); // } else { // Alert.alert('Payment Failed', 'Payment was not successful. Please try again.'); // } // setIsExpectingPayment(false); // setOutTradeNo(''); // paymentInitiatedTime.current = null; // } catch (error) { // console.error('Failed to check payment status:', error); // Alert.alert('Error', 'Failed to check payment status. Please check your payment history.'); // } // }; // // useEffect(() => { // // const handleAppStateChange = (nextAppState) => { // // if (appState.match(/inactive|background/) && nextAppState === 'active') { // // console.log('App has come to the foreground!'); // // // Check payment status or update UI here // // console.log('outTradeNo', outTradeNo); // // } // // setAppState(nextAppState); // // }; // // AppState.addEventListener('change', handleAppStateChange); // // }, [appState]); // useEffect(() => { // const fetchData = async () => { // try { // setLoading(true); // const info = await walletService.getCustomerInfo(); // // const coupon = await walletService.getCouponForSpecificUser(info.id); // const wallet = await walletService.getWalletBalance(); // console.log(wallet); // setUserID(info.id); // setWalletBalance(wallet); // setCoupons(coupon); // } catch (error) { // console.log(error); // } finally { // setLoading(false); // } // }; // fetchData(); // }, []); // const formatMoney = (amount: any) => { // if (typeof amount !== 'number') { // amount = Number(amount); // } // return amount.toLocaleString('en-US'); // }; // const filterPaymentOptions = (options, allowedKeys) => { // return Object.fromEntries(Object.entries(options).filter(([key]) => allowedKeys.includes(key))); // }; // useEffect(() => { // const fetchPaymentType = async () => { // const response = await walletService.selectPaymentType(); // console.log('response', response); // const filteredPaymentTypes = filterPaymentOptions(response, ['union_pay_wap_payment', 'payme_wap_payment']); // setPaymentType(filteredPaymentTypes); // }; // fetchPaymentType(); // }, []); // const handleTopUp = (selectedValue) => { // setSelectedPaymentType(selectedValue); // setModalVisible(false); // setAmountModalVisible(true); // }; // const handleAmountConfirm = async (inputAmount) => { // setAmountModalVisible(false); // try { // const numericAmount = parseFloat(inputAmount); // if (isNaN(numericAmount) || numericAmount <= 0) { // throw new Error('Invalid amount'); // } // const response = await walletService.submitPaymentAfterSelectingType( // numericAmount, // selectedPaymentType, // 'test' // ); // setOutTradeNo(response.out_trade_no); // console.log('handleAmountConfirm outtradeno here,', response.out_trade_no); // setIsExpectingPayment(true); // paymentInitiatedTime.current = new Date().getTime(); // const payUrl = response.pay_url; // const supported = await Linking.canOpenURL(payUrl); // if (supported) { // await Linking.openURL(payUrl); // } else { // throw new Error("Can't open payment URL"); // } // } catch (error) { // console.error('Top-up failed:', error); // Alert.alert('Error', 'Failed to process top-up. Please try again.'); // } // }; // return ( // // // // // { // if (router.canGoBack()) { // router.back(); // } else { // router.replace('/accountMainPage'); // } // }} // > // // // 錢包 // // // // // 餘額 (HKD) // // // {loading ? ( // // // // ) : ( // <> // $ // {formatMoney(walletBalance)} // // )} // // { // console.log('增值'); // setModalVisible(true); // }} // > // + 增值 // // // // // // // { // router.push({ // pathname: '/paymentRecord', // params: { walletBalance: formatMoney(walletBalance) } // }); // }} // > // 付款記錄 // // // // // // 優惠券 // router.push('couponPage')}> // 顯示所有 // // // // {loading ? ( // // // // ) : ( // // {coupons // .filter( // (coupon) => // coupon.is_consumed === false && new Date(coupon.expire_date) > new Date() // ) // .slice(0, 2) // .map((coupon, index) => ( // // ))} // // )} // // // setModalVisible(false)} // onSelect={handleTopUp} // paymentOptions={paymentType} // /> // setAmountModalVisible(false)} // onConfirm={handleAmountConfirm} // /> // // ); // }; // export default WalletPageComponent; //////BELOW uses QFPay 的托管收银台页面 to 增值 //////BELOW uses QFPay 的托管收银台页面 to 增值 //////BELOW uses QFPay 的托管收银台页面 to 增值 //////BELOW uses QFPay 的托管收银台页面 to 增值 //////BELOW uses QFPay 的托管收银台页面 to 增值 import { View, Image, Text, ScrollView, AppState, Pressable, ImageBackground, ActivityIndicator, Modal, Alert, TextInput, Linking, Dimensions } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; import { router } from 'expo-router'; import { CrossLogoSvg } from '../global/SVG'; import { useEffect, useRef, useState } from 'react'; import { walletService } from '../../service/walletService'; // import UnionPayImage from '../../assets/unionpay.png'; // import PayMeImage from '../../assets/payme.png'; import { formatCouponDate, formatDate } from '../../util/lib'; import { set } from 'date-fns'; import { reloadAppAsync } from 'expo'; import sha256 from 'crypto-js/sha256'; import { useCallback } from 'react'; import { useChargingStore } from '../../providers/scan_qr_payload_store'; const AmountInputModal = ({ visible, onClose, onConfirm }) => { const amounts = [ // { amount: 1, percentage: 0 }, { amount: 200, percentage: 0 }, { amount: 500, percentage: 5 }, { amount: 1000, percentage: 10 }, { amount: 2000, percentage: 15 } ]; const getFontSize = () => { const { width } = Dimensions.get('window'); if (width < 320) return 8; if (width < 350) return 10; //super small phones if (width < 375) return 12; // Smaller phones if (width < 414) return 14; // Average phones return 16; // Larger phones }; return ( 選擇增值金額 {amounts.map((amount) => ( onConfirm(amount.amount)} style={{ backgroundColor: '#02677D', padding: 10, borderRadius: 5, width: '48%', alignItems: 'center', marginBottom: 10 }} > ${amount.amount} {amount.percentage > 0 ? ` (+${amount.percentage}%) ` : ''} ))} *括號為回贈比例 取消 ); }; export const IndividualCouponComponent = ({ title, price, detail, date, setOpacity, redeem_code, onCouponClick, noCircle }: { title: string; price: string; detail: string; onCouponClick?: (clickedCoupon: string, clickedCouponDescription: string) => void; date: string; setOpacity?: boolean; redeem_code?: string; noCircle?: boolean; }) => { const { promotion_code } = useChargingStore(); return ( {/* largest container */} {} : () => onCouponClick(redeem_code)} > {/* price column on the left */} $ {price} {/* this is a hack for good coupon display */} {/* detail column on the right */} {title} {/* if opacity is true=used coupon= no circle */} {noCircle ? ( <> ) : ( {promotion_code?.indexOf(redeem_code) + 1} )} {detail} 有效期至 {' '} {date} ); }; const WalletPageComponent = () => { const [walletBalance, setWalletBalance] = useState(null); const [loading, setLoading] = useState(false); const [modalVisible, setModalVisible] = useState(false); const [coupons, setCoupons] = useState([]); const [paymentType, setPaymentType] = useState({}); const [userID, setUserID] = useState(''); const [selectedPaymentType, setSelectedPaymentType] = useState(null); const [amount, setAmount] = useState(0); const [amountModalVisible, setAmountModalVisible] = useState(false); const [outTradeNo, setOutTradeNo] = useState(''); const PAYMENT_CHECK_TIMEOUT = 5 * 60 * 1000; // 5 minutes in milliseconds const [paymentStatus, setPaymentStatus] = useState(null); const [isExpectingPayment, setIsExpectingPayment] = useState(false); const appState = useRef(AppState.currentState); const paymentInitiatedTime = useRef(null); useEffect(() => { const fetchData = async () => { try { setLoading(true); const info = await walletService.getCustomerInfo(); const coupon = await walletService.getCouponForSpecificUser(info.id); const useableConpon = coupon.filter((couponObj: any) => { const today = new Date(); if (couponObj.expire_date === null) { return couponObj.is_consumed === false; } const expireDate = new Date(couponObj.expire_date); return expireDate > today && couponObj.is_consumed === false; }); setCoupons(useableConpon); } catch (error) { console.log(error); } finally { setLoading(false); } }; fetchData(); }, []); //monitor app state useEffect(() => { const subscription = AppState.addEventListener('change', (nextAppState) => { if ( appState.current.match(/inactive|background/) && nextAppState === 'active' && isExpectingPayment && // outTradeNo && paymentInitiatedTime.current ) { const currentTime = new Date().getTime(); if (currentTime - paymentInitiatedTime.current < PAYMENT_CHECK_TIMEOUT) { checkPaymentStatus(); } else { // Payment check timeout reached setIsExpectingPayment(false); setOutTradeNo(''); paymentInitiatedTime.current = null; Alert.alert( 'Payment Timeout', 'The payment status check has timed out. Please check your payment history.' ); } } appState.current = nextAppState; }); return () => { subscription.remove(); }; }, [outTradeNo, isExpectingPayment]); //check payment status const checkPaymentStatus = async () => { try { console.log('what is the outTradeNo?? ', outTradeNo); const result = await walletService.checkPaymentStatus(outTradeNo); setPaymentStatus(result); console.log('checkPaymentStatus from walletPageComponent', result); if (result && !result.some((item) => item.errmsg?.includes('處理中'))) { // Payment successful Alert.alert('Success', 'Payment was successful!', [ { text: '成功', onPress: async () => { const wallet = await walletService.getWalletBalance(); setWalletBalance(wallet); console.log('new wallet:', wallet); } } ]); } else { Alert.alert('Payment Failed', 'Payment was not successful. Please try again.'); } setIsExpectingPayment(false); setOutTradeNo(''); paymentInitiatedTime.current = null; } catch (error) { console.error('Failed to check payment status:', error); Alert.alert('Error', 'Failed to check payment status. Please check your payment history.'); } }; //fetch customer wallet balance useEffect(() => { const fetchData = async () => { try { setLoading(true); const info = await walletService.getCustomerInfo(); const wallet = await walletService.getWalletBalance(); console.log('wallet', wallet); console.log('type of wallet', typeof wallet); setUserID(info.id); setWalletBalance(wallet); setCoupons(coupon); } catch (error) { console.log(error); } finally { setLoading(false); } }; fetchData(); }, []); const formatMoney = (amount: any) => { if (amount === null || amount === undefined || isNaN(Number(amount))) { return 'LOADING'; } if (typeof amount !== 'number') { amount = Number(amount); } // Check if the number is a whole number if (Number.isInteger(amount)) { return amount.toLocaleString('en-US'); } // For decimal numbers, show one decimal place return Number(amount) .toFixed(1) .replace(/\B(?=(\d{3})+(?!\d))/g, ','); }; const filterPaymentOptions = (options, allowedKeys) => { return Object.fromEntries(Object.entries(options).filter(([key]) => allowedKeys.includes(key))); }; function formatTime(utcTimeString) { // Parse the UTC time string const date = new Date(utcTimeString); // Add 8 hours date.setHours(date.getHours()); // Format the date const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); const hours = String(date.getHours()).padStart(2, '0'); const minutes = String(date.getMinutes()).padStart(2, '0'); const seconds = String(date.getSeconds()).padStart(2, '0'); // Return the formatted string return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; } useEffect(() => { const fetchPaymentType = async () => { const response = await walletService.selectPaymentType(); // console.log('response', response); const filteredPaymentTypes = filterPaymentOptions(response, ['union_pay_wap_payment', 'payme_wap_payment']); setPaymentType(filteredPaymentTypes); }; fetchPaymentType(); }, []); const handleAmountConfirm = async (inputAmount) => { setAmountModalVisible(false); try { const response = await walletService.getOutTradeNo(); console.log('do i have outtrade no??', response); if (response) { setOutTradeNo(response); setIsExpectingPayment(true); paymentInitiatedTime.current = new Date().getTime(); const now = new Date(); const formattedTime = formatTime(now); console.log('formattedTime in walletPageComponent', formattedTime); const out_trade_no = response; console.log('inputAmount in walletPageComponent', inputAmount); let amount = inputAmount * 100; console.log('amount in walletPageComponent', amount); const origin = 'https://openapi-hk.qfapi.com/checkstand/#/?'; const obj = { // appcode: '6937EF25DF6D4FA78BB2285441BC05E9', appcode: '636E234FB30D43598FC8F0140A1A7282', goods_name: 'Crazy Charge 錢包增值', out_trade_no: response, paysource: 'crazycharge_checkout', return_url: 'https://www.google.com', failed_url: 'https://www.google.com', notify_url: 'https://api.crazycharge.com.hk/api/v1/clients/qfpay/webhook', sign_type: 'sha256', txamt: amount, txcurrcd: 'HKD', txdtm: formattedTime }; const paramStringify = (json, flag?) => { let str = ''; let keysArr = Object.keys(json); keysArr.sort().forEach((val) => { if (!json[val]) return; str += `${val}=${flag ? encodeURIComponent(json[val]) : json[val]}&`; }); return str.slice(0, -1); }; // const api_key = '8F59E31F6ADF4D2894365F2BB6D2FF2C'; const api_key = '3E2727FBA2DA403EA325E73F36B07824'; const params = paramStringify(obj); const sign = sha256(`${params}${api_key}`).toString(); const url = `${origin}${paramStringify(obj, true)}&sign=${sign}`; try { console.log(url); const supported = await Linking.canOpenURL(url); if (supported) { await Linking.openURL(url); } else { Alert.alert('錯誤', '請稍後再試'); } } catch (error) { console.error('Top-up failed:', error); Alert.alert('Error', 'Failed to process top-up. Please try again.'); } } else { console.log('no'); } } catch (error) { console.log(error); } }; // const handleCouponClick = async (clickedCoupon: string) => { // Alert.alert( // '立即使用優惠券', // Title // '按確認打開相機,掃描充電站上的二維碼以使用優惠券', // Message // [ // { // text: '取消', // style: 'cancel' // }, // { // text: '確認', // onPress: () => router.push('scanQrPage') // } // ] // ); // }; const handleCouponClick = async (couponName: string, couponDescription: string) => { router.push({ pathname: '/couponDetailPage', params: { couponName: couponName, couponDescription: couponDescription } }); }; const formattedAmount = formatMoney(walletBalance); return ( { if (router.canGoBack()) { router.back(); } else { router.replace('/accountMainPage'); } }} > 錢包 餘額 (HKD) {loading ? ( ) : ( <> $ {formattedAmount === 'LOADING' || amount == null ? ( ) : ( `${formattedAmount}` )} )} { setAmountModalVisible(true); }} > + 增值 { router.push({ pathname: '/paymentRecord', params: { walletBalance: formatMoney(walletBalance) } }); }} > 訂單紀錄 優惠券 router.push('couponPage')}> 顯示所有 {loading ? ( ) : ( {coupons .filter( (coupon) => coupon.is_consumed === false && new Date(coupon.expire_date) > new Date() ) .slice(0, 2) .map((coupon, index) => ( handleCouponClick(coupon.coupon.name, coupon.coupon.description)} /> ))} )} {/* setModalVisible(false)} onSelect={handleTopUp} paymentOptions={paymentType} /> */} setAmountModalVisible(false)} onConfirm={handleAmountConfirm} /> ); }; export default WalletPageComponent;