|
|
@@ -1,901 +1,958 @@
|
|
|
-// import {
|
|
|
-// View,
|
|
|
-// Text,
|
|
|
-// ScrollView,
|
|
|
-// 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, useState } from 'react';
|
|
|
-// import { walletService } from '../../service/walletService';
|
|
|
-
|
|
|
-// import { formatCouponDate, formatDate } from '../../util/lib';
|
|
|
-// import { set } from 'date-fns';
|
|
|
-
|
|
|
-// const TopUpModal = ({ visible, onClose, onSelect, paymentOptions }) => {
|
|
|
-// return (
|
|
|
-// <Modal animationType="fade" transparent={true} visible={visible} onRequestClose={onClose}>
|
|
|
-// <View
|
|
|
-// style={{
|
|
|
-// flex: 1,
|
|
|
-// justifyContent: 'center',
|
|
|
-// alignItems: 'center',
|
|
|
-// backgroundColor: 'rgba(0,0,0,0.5)'
|
|
|
-// }}
|
|
|
-// >
|
|
|
-// <View
|
|
|
-// style={{
|
|
|
-// backgroundColor: 'white',
|
|
|
-// padding: 20,
|
|
|
-// borderRadius: 10,
|
|
|
-// width: '80%',
|
|
|
-// maxHeight: '80%'
|
|
|
-// }}
|
|
|
-// >
|
|
|
-// <Text style={{ fontSize: 20, marginBottom: 20 }}>選擇支付方式</Text>
|
|
|
-// <ScrollView>
|
|
|
-// {Object.entries(paymentOptions).map(([key, value]) => (
|
|
|
-// <Pressable
|
|
|
-// key={key}
|
|
|
-// onPress={() => onSelect(value)}
|
|
|
-// style={{
|
|
|
-// padding: 10,
|
|
|
-// marginBottom: 10,
|
|
|
-// borderBottomWidth: 1,
|
|
|
-// borderBottomColor: '#eee'
|
|
|
-// }}
|
|
|
-// >
|
|
|
-// <Text>{key}</Text>
|
|
|
-// </Pressable>
|
|
|
-// ))}
|
|
|
-// </ScrollView>
|
|
|
-// <Pressable onPress={onClose} style={{ padding: 10, alignItems: 'center', marginTop: 10 }}>
|
|
|
-// <Text style={{ color: 'red' }}>關閉</Text>
|
|
|
-// </Pressable>
|
|
|
-// </View>
|
|
|
-// </View>
|
|
|
-// </Modal>
|
|
|
-// );
|
|
|
-// };
|
|
|
+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 AmountInputModal = ({ visible, onClose, onConfirm }) => {
|
|
|
-// const [inputAmount, setInputAmount] = useState('');
|
|
|
+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 (
|
|
|
+ <Modal animationType="fade" transparent={true} visible={visible} onRequestClose={onClose}>
|
|
|
+ <View
|
|
|
+ style={{
|
|
|
+ flex: 1,
|
|
|
+ justifyContent: 'center',
|
|
|
+ alignItems: 'center',
|
|
|
+ backgroundColor: 'rgba(0,0,0,0.5)'
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <View
|
|
|
+ style={{
|
|
|
+ backgroundColor: 'white',
|
|
|
+ padding: 20,
|
|
|
+ borderRadius: 10,
|
|
|
+ width: '80%',
|
|
|
+ maxHeight: '80%'
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <Text style={{ fontSize: 20, marginBottom: 20 }}>選擇支付方式</Text>
|
|
|
+ <ScrollView>
|
|
|
+ {Object.entries(paymentOptions).map(([key, value]) => (
|
|
|
+ <Pressable
|
|
|
+ key={key}
|
|
|
+ onPress={() => onSelect(value)}
|
|
|
+ style={{
|
|
|
+ padding: 10,
|
|
|
+ marginBottom: 10,
|
|
|
+ borderBottomWidth: 1,
|
|
|
+ borderBottomColor: '#eee'
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <View className="flex flex-row items-center space-x-2">
|
|
|
+ <Image
|
|
|
+ source={getPaymentImage(key)}
|
|
|
+ style={{ width: 40, height: 40, marginRight: 10 }}
|
|
|
+ resizeMode="contain"
|
|
|
+ />
|
|
|
+ <Text className="tracking-wider">
|
|
|
+ {key === 'union_pay_wap_payment' ? 'UnionPay' : 'PayMe'}
|
|
|
+ </Text>
|
|
|
+ </View>
|
|
|
+ </Pressable>
|
|
|
+ ))}
|
|
|
+ </ScrollView>
|
|
|
+ <Pressable onPress={onClose} style={{ padding: 10, alignItems: 'center', marginTop: 10 }}>
|
|
|
+ <Text style={{ color: 'red' }}>關閉</Text>
|
|
|
+ </Pressable>
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ </Modal>
|
|
|
+ );
|
|
|
+};
|
|
|
+const AmountInputModal = ({ visible, onClose, onConfirm }) => {
|
|
|
+ const [inputAmount, setInputAmount] = useState('');
|
|
|
|
|
|
-// return (
|
|
|
-// <Modal animationType="fade" transparent={true} visible={visible} onRequestClose={onClose}>
|
|
|
-// <View
|
|
|
-// style={{
|
|
|
-// flex: 1,
|
|
|
-// justifyContent: 'center',
|
|
|
-// alignItems: 'center',
|
|
|
-// backgroundColor: 'rgba(0,0,0,0.5)'
|
|
|
-// }}
|
|
|
-// >
|
|
|
-// <View
|
|
|
-// style={{
|
|
|
-// backgroundColor: 'white',
|
|
|
-// padding: 20,
|
|
|
-// borderRadius: 10,
|
|
|
-// width: '80%'
|
|
|
-// }}
|
|
|
-// >
|
|
|
-// <Text style={{ fontSize: 20, marginBottom: 20 }}>輸入增值金額</Text>
|
|
|
-// <TextInput
|
|
|
-// style={{
|
|
|
-// borderWidth: 1,
|
|
|
-// borderColor: '#ccc',
|
|
|
-// borderRadius: 5,
|
|
|
-// padding: 10,
|
|
|
-// marginBottom: 20,
|
|
|
-// fontSize: 18
|
|
|
-// }}
|
|
|
-// keyboardType="numeric"
|
|
|
-// placeholder="輸入金額"
|
|
|
-// value={inputAmount}
|
|
|
-// onChangeText={setInputAmount}
|
|
|
-// />
|
|
|
-// <Pressable
|
|
|
-// onPress={() => onConfirm(inputAmount)}
|
|
|
-// style={{
|
|
|
-// backgroundColor: '#02677D',
|
|
|
-// padding: 10,
|
|
|
-// borderRadius: 5,
|
|
|
-// alignItems: 'center'
|
|
|
-// }}
|
|
|
-// >
|
|
|
-// <Text style={{ color: 'white', fontSize: 18 }}>確認</Text>
|
|
|
-// </Pressable>
|
|
|
-// <Pressable onPress={onClose} style={{ padding: 10, alignItems: 'center', marginTop: 10 }}>
|
|
|
-// <Text style={{ color: 'red' }}>取消</Text>
|
|
|
-// </Pressable>
|
|
|
-// </View>
|
|
|
-// </View>
|
|
|
-// </Modal>
|
|
|
-// );
|
|
|
-// };
|
|
|
+ return (
|
|
|
+ <Modal animationType="fade" transparent={true} visible={visible} onRequestClose={onClose}>
|
|
|
+ <View
|
|
|
+ style={{
|
|
|
+ flex: 1,
|
|
|
+ justifyContent: 'center',
|
|
|
+ alignItems: 'center',
|
|
|
+ backgroundColor: 'rgba(0,0,0,0.5)'
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <View
|
|
|
+ style={{
|
|
|
+ backgroundColor: 'white',
|
|
|
+ padding: 20,
|
|
|
+ borderRadius: 10,
|
|
|
+ width: '80%'
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <Text style={{ fontSize: 20, marginBottom: 20 }}>輸入增值金額</Text>
|
|
|
+ <TextInput
|
|
|
+ style={{
|
|
|
+ borderWidth: 1,
|
|
|
+ borderColor: '#ccc',
|
|
|
+ borderRadius: 5,
|
|
|
+ padding: 10,
|
|
|
+ marginBottom: 20,
|
|
|
+ fontSize: 18
|
|
|
+ }}
|
|
|
+ keyboardType="numeric"
|
|
|
+ placeholder="輸入金額"
|
|
|
+ value={inputAmount}
|
|
|
+ onChangeText={setInputAmount}
|
|
|
+ />
|
|
|
+ <Pressable
|
|
|
+ onPress={() => onConfirm(inputAmount)}
|
|
|
+ style={{
|
|
|
+ backgroundColor: '#02677D',
|
|
|
+ padding: 10,
|
|
|
+ borderRadius: 5,
|
|
|
+ alignItems: 'center'
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <Text style={{ color: 'white', fontSize: 18 }}>確認</Text>
|
|
|
+ </Pressable>
|
|
|
+ <Pressable onPress={onClose} style={{ padding: 10, alignItems: 'center', marginTop: 10 }}>
|
|
|
+ <Text style={{ color: 'red' }}>取消</Text>
|
|
|
+ </Pressable>
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ </Modal>
|
|
|
+ );
|
|
|
+};
|
|
|
|
|
|
-// export const IndividualCouponComponent = ({
|
|
|
-// title,
|
|
|
-// price,
|
|
|
-// detail,
|
|
|
-// date
|
|
|
-// }: {
|
|
|
-// title: string;
|
|
|
-// price: string;
|
|
|
-// detail: string;
|
|
|
-// date: string;
|
|
|
-// }) => {
|
|
|
-// return (
|
|
|
-// <Pressable onPress={() => console.log('abc')}>
|
|
|
-// <View className="bg-[#e7f2f8] h-[124px] rounded-xl flex-row mb-3">
|
|
|
-// <View className="bg-white mx-3 my-3 w-[28%] rounded-xl">
|
|
|
-// <View className="flex-row justify-center items-center pr-4 pt-4 ">
|
|
|
-// <Text className="color-[#02677d] text-2xl pl-2 pr-1">$</Text>
|
|
|
-// <Text className="color-[#02677d] text-3xl font-bold" adjustsFontSizeToFit={true}>
|
|
|
-// {price}
|
|
|
-// </Text>
|
|
|
-// </View>
|
|
|
-// <View className="items-center justify-center">
|
|
|
-// <Text className="text-base mt-1">{title}</Text>
|
|
|
-// </View>
|
|
|
-// </View>
|
|
|
+export const IndividualCouponComponent = ({
|
|
|
+ title,
|
|
|
+ price,
|
|
|
+ detail,
|
|
|
+ date
|
|
|
+}: {
|
|
|
+ title: string;
|
|
|
+ price: string;
|
|
|
+ detail: string;
|
|
|
+ date: string;
|
|
|
+}) => {
|
|
|
+ return (
|
|
|
+ <Pressable onPress={() => console.log('abc')}>
|
|
|
+ <View className="bg-[#e7f2f8] h-[124px] rounded-xl flex-row mb-3">
|
|
|
+ <View className="bg-white mx-3 my-3 w-[28%] rounded-xl">
|
|
|
+ <View className="flex-row justify-center items-center pr-4 pt-4 ">
|
|
|
+ <Text className="color-[#02677d] text-2xl pl-2 pr-1">$</Text>
|
|
|
+ <Text className="color-[#02677d] text-3xl font-bold" adjustsFontSizeToFit={true}>
|
|
|
+ {price}
|
|
|
+ </Text>
|
|
|
+ </View>
|
|
|
+ <View className="items-center justify-center">
|
|
|
+ <Text className="text-base mt-1">{title}</Text>
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
|
|
|
-// {/* //dash line */}
|
|
|
-// <View style={{ overflow: 'hidden' }}>
|
|
|
-// <View
|
|
|
-// style={{
|
|
|
-// borderStyle: 'dashed',
|
|
|
-// borderWidth: 1,
|
|
|
-// borderColor: '#CCCCCC',
|
|
|
-// margin: -1,
|
|
|
-// width: 0,
|
|
|
-// marginRight: 0,
|
|
|
-// height: '100%'
|
|
|
-// }}
|
|
|
-// >
|
|
|
-// <View style={{ height: 60 }}></View>
|
|
|
-// </View>
|
|
|
-// </View>
|
|
|
+ {/* //dash line */}
|
|
|
+ <View style={{ overflow: 'hidden' }}>
|
|
|
+ <View
|
|
|
+ style={{
|
|
|
+ borderStyle: 'dashed',
|
|
|
+ borderWidth: 1,
|
|
|
+ borderColor: '#CCCCCC',
|
|
|
+ margin: -1,
|
|
|
+ width: 0,
|
|
|
+ marginRight: 0,
|
|
|
+ height: '100%'
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <View style={{ height: 60 }}></View>
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
|
|
|
-// <View className="flex-col flex-1 m-[5%] justify-center ">
|
|
|
-// <Text className="text-lg">{title}</Text>
|
|
|
-// <Text className="color-[#888888] text-sm">{detail}</Text>
|
|
|
-// <View className="flex-row items-center ">
|
|
|
-// <Text className="text-base">有效期 </Text>
|
|
|
-// <Text className="text-base font-bold text-[#02677d]">{date}</Text>
|
|
|
-// </View>
|
|
|
-// </View>
|
|
|
-// </View>
|
|
|
-// </Pressable>
|
|
|
-// );
|
|
|
-// };
|
|
|
+ <View className="flex-col flex-1 m-[5%] justify-center ">
|
|
|
+ <Text className="text-lg">{title}</Text>
|
|
|
+ <Text className="color-[#888888] text-sm">{detail}</Text>
|
|
|
+ <View className="flex-row items-center ">
|
|
|
+ <Text className="text-base">有效期 </Text>
|
|
|
+ <Text className="text-base font-bold text-[#02677d]">{date}</Text>
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ </Pressable>
|
|
|
+ );
|
|
|
+};
|
|
|
|
|
|
-// const WalletPageComponent = () => {
|
|
|
-// const [walletBalance, setWalletBalance] = useState<string | null>(null);
|
|
|
-// const [loading, setLoading] = useState<boolean>(false);
|
|
|
-// const [modalVisible, setModalVisible] = useState(false);
|
|
|
-// const [coupons, setCoupons] = useState([]);
|
|
|
-// const [paymentType, setPaymentType] = useState({});
|
|
|
-// const [userID, setUserID] = useState('');
|
|
|
-// const [selectedPaymentType, setSelectedPaymentType] = useState<string | null>(null);
|
|
|
-// const [amount, setAmount] = useState<number>(0);
|
|
|
-// const [amountModalVisible, setAmountModalVisible] = useState(false);
|
|
|
-// const [outTradeNo, setOutTradeNo] = useState('');
|
|
|
-// 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);
|
|
|
-// }
|
|
|
-// };
|
|
|
+const WalletPageComponent = () => {
|
|
|
+ const [walletBalance, setWalletBalance] = useState<string | null>(null);
|
|
|
+ const [loading, setLoading] = useState<boolean>(false);
|
|
|
+ const [modalVisible, setModalVisible] = useState(false);
|
|
|
+ const [coupons, setCoupons] = useState([]);
|
|
|
+ const [paymentType, setPaymentType] = useState({});
|
|
|
+ const [userID, setUserID] = useState('');
|
|
|
+ const [selectedPaymentType, setSelectedPaymentType] = useState<string | null>(null);
|
|
|
+ const [amount, setAmount] = useState<number>(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);
|
|
|
|
|
|
-// fetchData();
|
|
|
-// }, []);
|
|
|
+ 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;
|
|
|
+ });
|
|
|
|
|
|
-// const formatMoney = (amount: any) => {
|
|
|
-// if (typeof amount !== 'number') {
|
|
|
-// amount = Number(amount);
|
|
|
-// }
|
|
|
-// return amount.toLocaleString('en-US');
|
|
|
-// };
|
|
|
+ return () => {
|
|
|
+ subscription.remove();
|
|
|
+ };
|
|
|
+ }, [outTradeNo, isExpectingPayment]);
|
|
|
|
|
|
-// useEffect(() => {
|
|
|
-// const fetchPaymentType = async () => {
|
|
|
-// const response = await walletService.selectPaymentType();
|
|
|
-// console.log('response', response);
|
|
|
-// setPaymentType(response);
|
|
|
-// };
|
|
|
-// fetchPaymentType();
|
|
|
-// }, []);
|
|
|
+ const checkPaymentStatus = async () => {
|
|
|
+ try {
|
|
|
+ const result = await walletService.checkPaymentStatus(outTradeNo);
|
|
|
+ setPaymentStatus(result);
|
|
|
+ console.log('checkPaymentStatus from walletPageComponent', result);
|
|
|
+ if (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.');
|
|
|
+ }
|
|
|
+ };
|
|
|
|
|
|
-// const handleRedirect = async () => {
|
|
|
-// const payUrl = response.pay_url;
|
|
|
+ // 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);
|
|
|
+ // };
|
|
|
|
|
|
-// try {
|
|
|
-// const supported = await Linking.canOpenURL(payUrl);
|
|
|
-// if (supported) {
|
|
|
-// await Linking.openURL(payUrl);
|
|
|
-// } else {
|
|
|
-// console.log("Don't know how to open URI: " + payUrl);
|
|
|
-// alert('WeChat Pay is not available on this device.');
|
|
|
-// }
|
|
|
-// } catch (err) {
|
|
|
-// console.error('An error occurred', err);
|
|
|
-// alert('An error occurred while trying to open WeChat Pay.');
|
|
|
-// }
|
|
|
-// };
|
|
|
+ // AppState.addEventListener('change', handleAppStateChange);
|
|
|
+ // }, [appState]);
|
|
|
|
|
|
-// const handleTopUp = (selectedValue) => {
|
|
|
-// setSelectedPaymentType(selectedValue);
|
|
|
-// setModalVisible(false);
|
|
|
-// setAmountModalVisible(true);
|
|
|
-// };
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+ };
|
|
|
|
|
|
-// const handleAmountConfirm = async (inputAmount) => {
|
|
|
-// setAmount(inputAmount);
|
|
|
-// setAmountModalVisible(false);
|
|
|
+ fetchData();
|
|
|
+ }, []);
|
|
|
|
|
|
-// try {
|
|
|
-// if (amount) {
|
|
|
-// const response = await walletService.submitPaymentAfterSelectingType(
|
|
|
-// amount,
|
|
|
-// selectedPaymentType,
|
|
|
-// 'test'
|
|
|
-// );
|
|
|
-// const handleRedirect = async () => {
|
|
|
-// const payUrl = response.pay_url;
|
|
|
-// setOutTradeNo(response.out_trade_no);
|
|
|
-// try {
|
|
|
-// const supported = await Linking.canOpenURL(payUrl);
|
|
|
-// if (supported) {
|
|
|
-// await Linking.openURL(payUrl);
|
|
|
-// } else {
|
|
|
-// console.log("Don't know how to open URI: " + payUrl);
|
|
|
-// }
|
|
|
-// } catch (err) {
|
|
|
-// console.error('An error occurred', err);
|
|
|
-// alert('An error occurred while trying to open WeChat Pay.');
|
|
|
-// }
|
|
|
-// };
|
|
|
-// handleRedirect();
|
|
|
-// }
|
|
|
-// // Placeholder for API call
|
|
|
-// console.log('Top-up Initiated', `Payment Type: ${selectedPaymentType}\nAmount: $${inputAmount}`);
|
|
|
-// } catch (error) {
|
|
|
-// console.error('Top-up failed:', error);
|
|
|
-// Alert.alert('Error', 'Failed to process top-up. Please try again.');
|
|
|
-// }
|
|
|
-// };
|
|
|
+ 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();
|
|
|
+ }, []);
|
|
|
|
|
|
-// return (
|
|
|
-// <SafeAreaView className="flex-1 bg-white" edges={['top', 'right', 'left']}>
|
|
|
-// <ScrollView className="flex-1 ">
|
|
|
-// <View className="flex-1 mx-[5%]">
|
|
|
-// <View style={{ marginTop: 25 }}>
|
|
|
-// <Pressable
|
|
|
-// onPress={() => {
|
|
|
-// if (router.canGoBack()) {
|
|
|
-// router.back();
|
|
|
-// } else {
|
|
|
-// router.replace('/accountMainPage');
|
|
|
-// }
|
|
|
-// }}
|
|
|
-// >
|
|
|
-// <CrossLogoSvg />
|
|
|
-// </Pressable>
|
|
|
-// <Text style={{ fontSize: 45, marginVertical: 25 }}>錢包</Text>
|
|
|
-// </View>
|
|
|
-// <View>
|
|
|
-// <ImageBackground
|
|
|
-// className="flex-col-reverse shadow-lg"
|
|
|
-// style={{ height: 200 }}
|
|
|
-// source={require('../../assets/walletCard1.png')}
|
|
|
-// resizeMode="contain"
|
|
|
-// >
|
|
|
-// <View className="mx-[5%] pb-6">
|
|
|
-// <Text className="text-white text-xl">餘額 (HKD)</Text>
|
|
|
-// <View className="flex-row items-center justify-between ">
|
|
|
-// <Text style={{ fontSize: 52 }} className=" text-white font-bold">
|
|
|
-// {loading ? (
|
|
|
-// <View className="items-center justify-center">
|
|
|
-// <ActivityIndicator />
|
|
|
-// </View>
|
|
|
-// ) : (
|
|
|
-// <>
|
|
|
-// <Text>$</Text>
|
|
|
-// {formatMoney(walletBalance)}
|
|
|
-// </>
|
|
|
-// )}
|
|
|
-// </Text>
|
|
|
-// <Pressable
|
|
|
-// className="rounded-2xl items-center justify-center p-3 px-5 pr-6 "
|
|
|
-// style={{
|
|
|
-// backgroundColor: 'rgba(231, 242, 248, 0.2)'
|
|
|
-// }}
|
|
|
-// onPress={() => {
|
|
|
-// console.log('增值');
|
|
|
-// setModalVisible(true);
|
|
|
-// }}
|
|
|
-// >
|
|
|
-// <Text className="text-white font-bold">+ 增值</Text>
|
|
|
-// </Pressable>
|
|
|
-// </View>
|
|
|
-// </View>
|
|
|
-// </ImageBackground>
|
|
|
-// </View>
|
|
|
-// <View className="flex-row-reverse mt-2 mb-6">
|
|
|
-// <Pressable
|
|
|
-// onPress={() => {
|
|
|
-// router.push({
|
|
|
-// pathname: '/paymentRecord',
|
|
|
-// params: { walletBalance: formatMoney(walletBalance) }
|
|
|
-// });
|
|
|
-// }}
|
|
|
-// >
|
|
|
-// <Text className="text-[#02677D] text-lg underline">付款記錄</Text>
|
|
|
-// </Pressable>
|
|
|
-// </View>
|
|
|
-// </View>
|
|
|
+ const handleTopUp = (selectedValue) => {
|
|
|
+ setSelectedPaymentType(selectedValue);
|
|
|
+ setModalVisible(false);
|
|
|
+ setAmountModalVisible(true);
|
|
|
+ };
|
|
|
|
|
|
-// <View className="w-full h-1 bg-[#DBE4E8]" />
|
|
|
+ const handleAmountConfirm = async (inputAmount) => {
|
|
|
+ setAmountModalVisible(false);
|
|
|
|
|
|
-// <View className="flex-row justify-between mx-[5%] pt-6 pb-3">
|
|
|
-// <Text className="text-xl">優惠券</Text>
|
|
|
-// <Pressable onPress={() => router.push('couponPage')}>
|
|
|
-// <Text className="text-xl text-[#888888]">顯示所有</Text>
|
|
|
-// </Pressable>
|
|
|
-// </View>
|
|
|
+ try {
|
|
|
+ const numericAmount = parseFloat(inputAmount);
|
|
|
+ if (isNaN(numericAmount) || numericAmount <= 0) {
|
|
|
+ throw new Error('Invalid amount');
|
|
|
+ }
|
|
|
|
|
|
-// <View className="flex-1 flex-col mx-[5%]">
|
|
|
-// {loading ? (
|
|
|
-// <View className="items-center justify-center">
|
|
|
-// <ActivityIndicator />
|
|
|
-// </View>
|
|
|
-// ) : (
|
|
|
-// <View>
|
|
|
-// {coupons
|
|
|
-// .filter(
|
|
|
-// (coupon) =>
|
|
|
-// coupon.is_consumed === false && new Date(coupon.expire_date) > new Date()
|
|
|
-// )
|
|
|
-// .slice(0, 2)
|
|
|
-// .map((coupon, index) => (
|
|
|
-// <IndividualCouponComponent
|
|
|
-// key={index}
|
|
|
-// title={coupon.name}
|
|
|
-// price={coupon.amount}
|
|
|
-// detail={coupon.description}
|
|
|
-// date={formatCouponDate(coupon.expire_date)}
|
|
|
-// />
|
|
|
-// ))}
|
|
|
-// </View>
|
|
|
-// )}
|
|
|
-// </View>
|
|
|
-// </ScrollView>
|
|
|
-// <TopUpModal
|
|
|
-// visible={modalVisible}
|
|
|
-// onClose={() => setModalVisible(false)}
|
|
|
-// onSelect={handleTopUp}
|
|
|
-// paymentOptions={paymentType}
|
|
|
-// />
|
|
|
-// <AmountInputModal
|
|
|
-// visible={amountModalVisible}
|
|
|
-// onClose={() => setAmountModalVisible(false)}
|
|
|
-// onConfirm={handleAmountConfirm}
|
|
|
-// />
|
|
|
-// </SafeAreaView>
|
|
|
-// );
|
|
|
-// };
|
|
|
+ const response = await walletService.submitPaymentAfterSelectingType(
|
|
|
+ numericAmount,
|
|
|
+ selectedPaymentType,
|
|
|
+ 'test'
|
|
|
+ );
|
|
|
|
|
|
-// export default WalletPageComponent;
|
|
|
+ setOutTradeNo(response.out_trade_no);
|
|
|
+ console.log('handleAmountConfirm outtradeno here,', response.out_trade_no);
|
|
|
+ console.log('just state outTradeNo here,', outTradeNo);
|
|
|
+ setIsExpectingPayment(true);
|
|
|
+ paymentInitiatedTime.current = new Date().getTime();
|
|
|
|
|
|
-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 payUrl = response.pay_url;
|
|
|
+ const supported = await Linking.canOpenURL(payUrl);
|
|
|
|
|
|
-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;
|
|
|
+ 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 (
|
|
|
- <Modal animationType="fade" transparent={true} visible={visible} onRequestClose={onClose}>
|
|
|
- <View
|
|
|
- style={{
|
|
|
- flex: 1,
|
|
|
- justifyContent: 'center',
|
|
|
- alignItems: 'center',
|
|
|
- backgroundColor: 'rgba(0,0,0,0.5)'
|
|
|
- }}
|
|
|
- >
|
|
|
- <View
|
|
|
- style={{
|
|
|
- backgroundColor: 'white',
|
|
|
- padding: 20,
|
|
|
- borderRadius: 10,
|
|
|
- width: '80%',
|
|
|
- maxHeight: '80%'
|
|
|
- }}
|
|
|
- >
|
|
|
- <Text style={{ fontSize: 20, marginBottom: 20 }}>選擇支付方式</Text>
|
|
|
- <ScrollView>
|
|
|
- {Object.entries(paymentOptions).map(([key, value]) => (
|
|
|
- <Pressable
|
|
|
- key={key}
|
|
|
- onPress={() => onSelect(value)}
|
|
|
- style={{
|
|
|
- padding: 10,
|
|
|
- marginBottom: 10,
|
|
|
- borderBottomWidth: 1,
|
|
|
- borderBottomColor: '#eee'
|
|
|
- }}
|
|
|
- >
|
|
|
- <View className="flex flex-row items-center space-x-2">
|
|
|
- <Image
|
|
|
- source={getPaymentImage(key)}
|
|
|
- style={{ width: 40, height: 40, marginRight: 10 }}
|
|
|
- resizeMode="contain"
|
|
|
- />
|
|
|
- <Text className="tracking-wider">
|
|
|
- {key === 'union_pay_wap_payment' ? 'UnionPay' : 'PayMe'}
|
|
|
+ <SafeAreaView className="flex-1 bg-white" edges={['top', 'right', 'left']}>
|
|
|
+ <ScrollView className="flex-1 ">
|
|
|
+ <View className="flex-1 mx-[5%]">
|
|
|
+ <View style={{ marginTop: 25 }}>
|
|
|
+ <Pressable
|
|
|
+ onPress={() => {
|
|
|
+ if (router.canGoBack()) {
|
|
|
+ router.back();
|
|
|
+ } else {
|
|
|
+ router.replace('/accountMainPage');
|
|
|
+ }
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <CrossLogoSvg />
|
|
|
+ </Pressable>
|
|
|
+ <Text style={{ fontSize: 45, marginVertical: 25 }}>錢包</Text>
|
|
|
+ </View>
|
|
|
+ <View>
|
|
|
+ <ImageBackground
|
|
|
+ className="flex-col-reverse shadow-lg"
|
|
|
+ style={{ height: 200 }}
|
|
|
+ source={require('../../assets/walletCard1.png')}
|
|
|
+ resizeMode="contain"
|
|
|
+ >
|
|
|
+ <View className="mx-[5%] pb-6">
|
|
|
+ <Text className="text-white text-xl">餘額 (HKD)</Text>
|
|
|
+ <View className="flex-row items-center justify-between ">
|
|
|
+ <Text style={{ fontSize: 52 }} className=" text-white font-bold">
|
|
|
+ {loading ? (
|
|
|
+ <View className="items-center justify-center">
|
|
|
+ <ActivityIndicator />
|
|
|
+ </View>
|
|
|
+ ) : (
|
|
|
+ <>
|
|
|
+ <Text>$</Text>
|
|
|
+ {formatMoney(walletBalance)}
|
|
|
+ </>
|
|
|
+ )}
|
|
|
</Text>
|
|
|
+ <Pressable
|
|
|
+ className="rounded-2xl items-center justify-center p-3 px-5 pr-6 "
|
|
|
+ style={{
|
|
|
+ backgroundColor: 'rgba(231, 242, 248, 0.2)'
|
|
|
+ }}
|
|
|
+ onPress={() => {
|
|
|
+ console.log('增值');
|
|
|
+ setModalVisible(true);
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <Text className="text-white font-bold">+ 增值</Text>
|
|
|
+ </Pressable>
|
|
|
</View>
|
|
|
- </Pressable>
|
|
|
- ))}
|
|
|
- </ScrollView>
|
|
|
- <Pressable onPress={onClose} style={{ padding: 10, alignItems: 'center', marginTop: 10 }}>
|
|
|
- <Text style={{ color: 'red' }}>關閉</Text>
|
|
|
- </Pressable>
|
|
|
+ </View>
|
|
|
+ </ImageBackground>
|
|
|
+ </View>
|
|
|
+ <View className="flex-row-reverse mt-2 mb-6">
|
|
|
+ <Pressable
|
|
|
+ onPress={() => {
|
|
|
+ router.push({
|
|
|
+ pathname: '/paymentRecord',
|
|
|
+ params: { walletBalance: formatMoney(walletBalance) }
|
|
|
+ });
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <Text className="text-[#02677D] text-lg underline">付款記錄</Text>
|
|
|
+ </Pressable>
|
|
|
+ </View>
|
|
|
</View>
|
|
|
- </View>
|
|
|
- </Modal>
|
|
|
- );
|
|
|
-};
|
|
|
-const AmountInputModal = ({ visible, onClose, onConfirm }) => {
|
|
|
- const [inputAmount, setInputAmount] = useState('');
|
|
|
|
|
|
- return (
|
|
|
- <Modal animationType="fade" transparent={true} visible={visible} onRequestClose={onClose}>
|
|
|
- <View
|
|
|
- style={{
|
|
|
- flex: 1,
|
|
|
- justifyContent: 'center',
|
|
|
- alignItems: 'center',
|
|
|
- backgroundColor: 'rgba(0,0,0,0.5)'
|
|
|
- }}
|
|
|
- >
|
|
|
- <View
|
|
|
- style={{
|
|
|
- backgroundColor: 'white',
|
|
|
- padding: 20,
|
|
|
- borderRadius: 10,
|
|
|
- width: '80%'
|
|
|
- }}
|
|
|
- >
|
|
|
- <Text style={{ fontSize: 20, marginBottom: 20 }}>輸入增值金額</Text>
|
|
|
- <TextInput
|
|
|
- style={{
|
|
|
- borderWidth: 1,
|
|
|
- borderColor: '#ccc',
|
|
|
- borderRadius: 5,
|
|
|
- padding: 10,
|
|
|
- marginBottom: 20,
|
|
|
- fontSize: 18
|
|
|
- }}
|
|
|
- keyboardType="numeric"
|
|
|
- placeholder="輸入金額"
|
|
|
- value={inputAmount}
|
|
|
- onChangeText={setInputAmount}
|
|
|
- />
|
|
|
- <Pressable
|
|
|
- onPress={() => onConfirm(inputAmount)}
|
|
|
- style={{
|
|
|
- backgroundColor: '#02677D',
|
|
|
- padding: 10,
|
|
|
- borderRadius: 5,
|
|
|
- alignItems: 'center'
|
|
|
- }}
|
|
|
- >
|
|
|
- <Text style={{ color: 'white', fontSize: 18 }}>確認</Text>
|
|
|
- </Pressable>
|
|
|
- <Pressable onPress={onClose} style={{ padding: 10, alignItems: 'center', marginTop: 10 }}>
|
|
|
- <Text style={{ color: 'red' }}>取消</Text>
|
|
|
+ <View className="w-full h-1 bg-[#DBE4E8]" />
|
|
|
+
|
|
|
+ <View className="flex-row justify-between mx-[5%] pt-6 pb-3">
|
|
|
+ <Text className="text-xl">優惠券</Text>
|
|
|
+ <Pressable onPress={() => router.push('couponPage')}>
|
|
|
+ <Text className="text-xl text-[#888888]">顯示所有</Text>
|
|
|
</Pressable>
|
|
|
</View>
|
|
|
- </View>
|
|
|
- </Modal>
|
|
|
+
|
|
|
+ <View className="flex-1 flex-col mx-[5%]">
|
|
|
+ {loading ? (
|
|
|
+ <View className="items-center justify-center">
|
|
|
+ <ActivityIndicator />
|
|
|
+ </View>
|
|
|
+ ) : (
|
|
|
+ <View>
|
|
|
+ {coupons
|
|
|
+ .filter(
|
|
|
+ (coupon) =>
|
|
|
+ coupon.is_consumed === false && new Date(coupon.expire_date) > new Date()
|
|
|
+ )
|
|
|
+ .slice(0, 2)
|
|
|
+ .map((coupon, index) => (
|
|
|
+ <IndividualCouponComponent
|
|
|
+ key={index}
|
|
|
+ title={coupon.name}
|
|
|
+ price={coupon.amount}
|
|
|
+ detail={coupon.description}
|
|
|
+ date={formatCouponDate(coupon.expire_date)}
|
|
|
+ />
|
|
|
+ ))}
|
|
|
+ </View>
|
|
|
+ )}
|
|
|
+ </View>
|
|
|
+ </ScrollView>
|
|
|
+ <TopUpModal
|
|
|
+ visible={modalVisible}
|
|
|
+ onClose={() => setModalVisible(false)}
|
|
|
+ onSelect={handleTopUp}
|
|
|
+ paymentOptions={paymentType}
|
|
|
+ />
|
|
|
+ <AmountInputModal
|
|
|
+ visible={amountModalVisible}
|
|
|
+ onClose={() => setAmountModalVisible(false)}
|
|
|
+ onConfirm={handleAmountConfirm}
|
|
|
+ />
|
|
|
+ </SafeAreaView>
|
|
|
);
|
|
|
};
|
|
|
|
|
|
-export const IndividualCouponComponent = ({
|
|
|
- title,
|
|
|
- price,
|
|
|
- detail,
|
|
|
- date
|
|
|
-}: {
|
|
|
- title: string;
|
|
|
- price: string;
|
|
|
- detail: string;
|
|
|
- date: string;
|
|
|
-}) => {
|
|
|
- return (
|
|
|
- <Pressable onPress={() => console.log('abc')}>
|
|
|
- <View className="bg-[#e7f2f8] h-[124px] rounded-xl flex-row mb-3">
|
|
|
- <View className="bg-white mx-3 my-3 w-[28%] rounded-xl">
|
|
|
- <View className="flex-row justify-center items-center pr-4 pt-4 ">
|
|
|
- <Text className="color-[#02677d] text-2xl pl-2 pr-1">$</Text>
|
|
|
- <Text className="color-[#02677d] text-3xl font-bold" adjustsFontSizeToFit={true}>
|
|
|
- {price}
|
|
|
- </Text>
|
|
|
- </View>
|
|
|
- <View className="items-center justify-center">
|
|
|
- <Text className="text-base mt-1">{title}</Text>
|
|
|
- </View>
|
|
|
- </View>
|
|
|
+export default WalletPageComponent;
|
|
|
|
|
|
- {/* //dash line */}
|
|
|
- <View style={{ overflow: 'hidden' }}>
|
|
|
- <View
|
|
|
- style={{
|
|
|
- borderStyle: 'dashed',
|
|
|
- borderWidth: 1,
|
|
|
- borderColor: '#CCCCCC',
|
|
|
- margin: -1,
|
|
|
- width: 0,
|
|
|
- marginRight: 0,
|
|
|
- height: '100%'
|
|
|
- }}
|
|
|
- >
|
|
|
- <View style={{ height: 60 }}></View>
|
|
|
- </View>
|
|
|
- </View>
|
|
|
+//////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
|
|
|
+// } 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';
|
|
|
+
|
|
|
+// const AmountInputModal = ({ visible, onClose, onConfirm }) => {
|
|
|
+// const [inputAmount, setInputAmount] = useState('');
|
|
|
+
|
|
|
+// return (
|
|
|
+// <Modal animationType="fade" transparent={true} visible={visible} onRequestClose={onClose}>
|
|
|
+// <View
|
|
|
+// style={{
|
|
|
+// flex: 1,
|
|
|
+// justifyContent: 'center',
|
|
|
+// alignItems: 'center',
|
|
|
+// backgroundColor: 'rgba(0,0,0,0.5)'
|
|
|
+// }}
|
|
|
+// >
|
|
|
+// <View
|
|
|
+// style={{
|
|
|
+// backgroundColor: 'white',
|
|
|
+// padding: 20,
|
|
|
+// borderRadius: 10,
|
|
|
+// width: '80%'
|
|
|
+// }}
|
|
|
+// >
|
|
|
+// <Text style={{ fontSize: 20, marginBottom: 20 }}>輸入增值金額</Text>
|
|
|
+// <TextInput
|
|
|
+// style={{
|
|
|
+// borderWidth: 1,
|
|
|
+// borderColor: '#ccc',
|
|
|
+// borderRadius: 5,
|
|
|
+// padding: 10,
|
|
|
+// marginBottom: 20,
|
|
|
+// fontSize: 18
|
|
|
+// }}
|
|
|
+// keyboardType="numeric"
|
|
|
+// placeholder="輸入金額"
|
|
|
+// value={inputAmount}
|
|
|
+// onChangeText={setInputAmount}
|
|
|
+// />
|
|
|
+// <Pressable
|
|
|
+// onPress={() => onConfirm(inputAmount)}
|
|
|
+// style={{
|
|
|
+// backgroundColor: '#02677D',
|
|
|
+// padding: 10,
|
|
|
+// borderRadius: 5,
|
|
|
+// alignItems: 'center'
|
|
|
+// }}
|
|
|
+// >
|
|
|
+// <Text style={{ color: 'white', fontSize: 18 }}>確認</Text>
|
|
|
+// </Pressable>
|
|
|
+// <Pressable onPress={onClose} style={{ padding: 10, alignItems: 'center', marginTop: 10 }}>
|
|
|
+// <Text style={{ color: 'red' }}>取消</Text>
|
|
|
+// </Pressable>
|
|
|
+// </View>
|
|
|
+// </View>
|
|
|
+// </Modal>
|
|
|
+// );
|
|
|
+// };
|
|
|
+
|
|
|
+// export const IndividualCouponComponent = ({
|
|
|
+// title,
|
|
|
+// price,
|
|
|
+// detail,
|
|
|
+// date
|
|
|
+// }: {
|
|
|
+// title: string;
|
|
|
+// price: string;
|
|
|
+// detail: string;
|
|
|
+// date: string;
|
|
|
+// }) => {
|
|
|
+// return (
|
|
|
+// <Pressable onPress={() => console.log('abc')}>
|
|
|
+// <View className="bg-[#e7f2f8] h-[124px] rounded-xl flex-row mb-3">
|
|
|
+// <View className="bg-white mx-3 my-3 w-[28%] rounded-xl">
|
|
|
+// <View className="flex-row justify-center items-center pr-4 pt-4 ">
|
|
|
+// <Text className="color-[#02677d] text-2xl pl-2 pr-1">$</Text>
|
|
|
+// <Text className="color-[#02677d] text-3xl font-bold" adjustsFontSizeToFit={true}>
|
|
|
+// {price}
|
|
|
+// </Text>
|
|
|
+// </View>
|
|
|
+// <View className="items-center justify-center">
|
|
|
+// <Text className="text-base mt-1">{title}</Text>
|
|
|
+// </View>
|
|
|
+// </View>
|
|
|
|
|
|
- <View className="flex-col flex-1 m-[5%] justify-center ">
|
|
|
- <Text className="text-lg">{title}</Text>
|
|
|
- <Text className="color-[#888888] text-sm">{detail}</Text>
|
|
|
- <View className="flex-row items-center ">
|
|
|
- <Text className="text-base">有效期 </Text>
|
|
|
- <Text className="text-base font-bold text-[#02677d]">{date}</Text>
|
|
|
- </View>
|
|
|
- </View>
|
|
|
- </View>
|
|
|
- </Pressable>
|
|
|
- );
|
|
|
-};
|
|
|
+// {/* //dash line */}
|
|
|
+// <View style={{ overflow: 'hidden' }}>
|
|
|
+// <View
|
|
|
+// style={{
|
|
|
+// borderStyle: 'dashed',
|
|
|
+// borderWidth: 1,
|
|
|
+// borderColor: '#CCCCCC',
|
|
|
+// margin: -1,
|
|
|
+// width: 0,
|
|
|
+// marginRight: 0,
|
|
|
+// height: '100%'
|
|
|
+// }}
|
|
|
+// >
|
|
|
+// <View style={{ height: 60 }}></View>
|
|
|
+// </View>
|
|
|
+// </View>
|
|
|
|
|
|
-const WalletPageComponent = () => {
|
|
|
- const [walletBalance, setWalletBalance] = useState<string | null>(null);
|
|
|
- const [loading, setLoading] = useState<boolean>(false);
|
|
|
- const [modalVisible, setModalVisible] = useState(false);
|
|
|
- const [coupons, setCoupons] = useState([]);
|
|
|
- const [paymentType, setPaymentType] = useState({});
|
|
|
- const [userID, setUserID] = useState('');
|
|
|
- const [selectedPaymentType, setSelectedPaymentType] = useState<string | null>(null);
|
|
|
- const [amount, setAmount] = useState<number>(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);
|
|
|
+// <View className="flex-col flex-1 m-[5%] justify-center ">
|
|
|
+// <Text className="text-lg">{title}</Text>
|
|
|
+// <Text className="color-[#888888] text-sm">{detail}</Text>
|
|
|
+// <View className="flex-row items-center ">
|
|
|
+// <Text className="text-base">有效期 </Text>
|
|
|
+// <Text className="text-base font-bold text-[#02677d]">{date}</Text>
|
|
|
+// </View>
|
|
|
+// </View>
|
|
|
+// </View>
|
|
|
+// </Pressable>
|
|
|
+// );
|
|
|
+// };
|
|
|
|
|
|
- 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;
|
|
|
- });
|
|
|
+// const WalletPageComponent = () => {
|
|
|
+// const [walletBalance, setWalletBalance] = useState<string | null>(null);
|
|
|
+// const [loading, setLoading] = useState<boolean>(false);
|
|
|
+// const [modalVisible, setModalVisible] = useState(false);
|
|
|
+// const [coupons, setCoupons] = useState([]);
|
|
|
+// const [paymentType, setPaymentType] = useState({});
|
|
|
+// const [userID, setUserID] = useState('');
|
|
|
+// const [selectedPaymentType, setSelectedPaymentType] = useState<string | null>(null);
|
|
|
+// const [amount, setAmount] = useState<number>(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);
|
|
|
|
|
|
- return () => {
|
|
|
- subscription.remove();
|
|
|
- };
|
|
|
- }, [outTradeNo, isExpectingPayment]);
|
|
|
+// 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;
|
|
|
+// });
|
|
|
|
|
|
- const checkPaymentStatus = async () => {
|
|
|
- try {
|
|
|
- const result = await walletService.checkPaymentStatus(outTradeNo);
|
|
|
- setPaymentStatus(result);
|
|
|
- console.log('checkPaymentStatus from walletPageComponent', result);
|
|
|
- if (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.');
|
|
|
- }
|
|
|
- };
|
|
|
+// return () => {
|
|
|
+// subscription.remove();
|
|
|
+// };
|
|
|
+// }, [outTradeNo, isExpectingPayment]);
|
|
|
|
|
|
- // 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);
|
|
|
- // };
|
|
|
+// const checkPaymentStatus = async () => {
|
|
|
+// try {
|
|
|
+// const result = await walletService.checkPaymentStatus(outTradeNo);
|
|
|
+// setPaymentStatus(result);
|
|
|
+// console.log('checkPaymentStatus from walletPageComponent', result);
|
|
|
+// if (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.');
|
|
|
+// }
|
|
|
+// };
|
|
|
|
|
|
- // AppState.addEventListener('change', handleAppStateChange);
|
|
|
- // }, [appState]);
|
|
|
+// useEffect(() => {
|
|
|
+// const fetchData = async () => {
|
|
|
+// try {
|
|
|
+// setLoading(true);
|
|
|
+// const info = await walletService.getCustomerInfo();
|
|
|
|
|
|
- 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);
|
|
|
- }
|
|
|
- };
|
|
|
+// const wallet = await walletService.getWalletBalance();
|
|
|
+// console.log(wallet);
|
|
|
+// setUserID(info.id);
|
|
|
+// setWalletBalance(wallet);
|
|
|
+// setCoupons(coupon);
|
|
|
+// } catch (error) {
|
|
|
+// console.log(error);
|
|
|
+// } finally {
|
|
|
+// setLoading(false);
|
|
|
+// }
|
|
|
+// };
|
|
|
|
|
|
- fetchData();
|
|
|
- }, []);
|
|
|
+// 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 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)));
|
|
|
+// };
|
|
|
|
|
|
- const handleTopUp = (selectedValue) => {
|
|
|
- setSelectedPaymentType(selectedValue);
|
|
|
- setModalVisible(false);
|
|
|
- setAmountModalVisible(true);
|
|
|
- };
|
|
|
+// function formatTime(utcTimeString) {
|
|
|
+// // Parse the UTC time string
|
|
|
+// const date = new Date(utcTimeString);
|
|
|
|
|
|
- const handleAmountConfirm = async (inputAmount) => {
|
|
|
- setAmountModalVisible(false);
|
|
|
+// // Add 8 hours
|
|
|
+// date.setHours(date.getHours());
|
|
|
|
|
|
- try {
|
|
|
- const numericAmount = parseFloat(inputAmount);
|
|
|
- if (isNaN(numericAmount) || numericAmount <= 0) {
|
|
|
- throw new Error('Invalid amount');
|
|
|
- }
|
|
|
+// // 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');
|
|
|
|
|
|
- const response = await walletService.submitPaymentAfterSelectingType(
|
|
|
- numericAmount,
|
|
|
- selectedPaymentType,
|
|
|
- 'test'
|
|
|
- );
|
|
|
+// // Return the formatted string
|
|
|
+// return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
|
|
+// }
|
|
|
|
|
|
- setOutTradeNo(response.out_trade_no);
|
|
|
- console.log('handleAmountConfirm outtradeno here,', response.out_trade_no);
|
|
|
- console.log('just state outTradeNo here,', outTradeNo);
|
|
|
- setIsExpectingPayment(true);
|
|
|
- paymentInitiatedTime.current = new Date().getTime();
|
|
|
+// 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 payUrl = response.pay_url;
|
|
|
- const supported = await Linking.canOpenURL(payUrl);
|
|
|
+// const handleAmountConfirm = async (inputAmount) => {
|
|
|
+// setAmountModalVisible(false);
|
|
|
+// try {
|
|
|
+// const response = await walletService.getOutTradeNo();
|
|
|
+// if (response) {
|
|
|
+// setIsExpectingPayment(true);
|
|
|
+// paymentInitiatedTime.current = new Date().getTime();
|
|
|
+// const now = new Date();
|
|
|
+// const formattedTime = formatTime(now);
|
|
|
+// console.log(formattedTime);
|
|
|
+// const out_trade_no = response;
|
|
|
+
|
|
|
+// let amount = parseInt(inputAmount, 10) * 100;
|
|
|
+// const origin = 'https://openapi-hk.qfapi.com/checkstand/#/?';
|
|
|
+// const obj = {
|
|
|
+// appcode: process.env.QFPAY_CODE,
|
|
|
+// goods_name: 'Crazy Charge 錢包增值',
|
|
|
+// out_trade_no: out_trade_no,
|
|
|
+// 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
|
|
|
+// };
|
|
|
|
|
|
- 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.');
|
|
|
- }
|
|
|
- };
|
|
|
+// 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);
|
|
|
+// };
|
|
|
|
|
|
- return (
|
|
|
- <SafeAreaView className="flex-1 bg-white" edges={['top', 'right', 'left']}>
|
|
|
- <ScrollView className="flex-1 ">
|
|
|
- <View className="flex-1 mx-[5%]">
|
|
|
- <View style={{ marginTop: 25 }}>
|
|
|
- <Pressable
|
|
|
- onPress={() => {
|
|
|
- if (router.canGoBack()) {
|
|
|
- router.back();
|
|
|
- } else {
|
|
|
- router.replace('/accountMainPage');
|
|
|
- }
|
|
|
- }}
|
|
|
- >
|
|
|
- <CrossLogoSvg />
|
|
|
- </Pressable>
|
|
|
- <Text style={{ fontSize: 45, marginVertical: 25 }}>錢包</Text>
|
|
|
- </View>
|
|
|
- <View>
|
|
|
- <ImageBackground
|
|
|
- className="flex-col-reverse shadow-lg"
|
|
|
- style={{ height: 200 }}
|
|
|
- source={require('../../assets/walletCard1.png')}
|
|
|
- resizeMode="contain"
|
|
|
- >
|
|
|
- <View className="mx-[5%] pb-6">
|
|
|
- <Text className="text-white text-xl">餘額 (HKD)</Text>
|
|
|
- <View className="flex-row items-center justify-between ">
|
|
|
- <Text style={{ fontSize: 52 }} className=" text-white font-bold">
|
|
|
- {loading ? (
|
|
|
- <View className="items-center justify-center">
|
|
|
- <ActivityIndicator />
|
|
|
- </View>
|
|
|
- ) : (
|
|
|
- <>
|
|
|
- <Text>$</Text>
|
|
|
- {formatMoney(walletBalance)}
|
|
|
- </>
|
|
|
- )}
|
|
|
- </Text>
|
|
|
- <Pressable
|
|
|
- className="rounded-2xl items-center justify-center p-3 px-5 pr-6 "
|
|
|
- style={{
|
|
|
- backgroundColor: 'rgba(231, 242, 248, 0.2)'
|
|
|
- }}
|
|
|
- onPress={() => {
|
|
|
- console.log('增值');
|
|
|
- setModalVisible(true);
|
|
|
- }}
|
|
|
- >
|
|
|
- <Text className="text-white font-bold">+ 增值</Text>
|
|
|
- </Pressable>
|
|
|
- </View>
|
|
|
- </View>
|
|
|
- </ImageBackground>
|
|
|
- </View>
|
|
|
- <View className="flex-row-reverse mt-2 mb-6">
|
|
|
- <Pressable
|
|
|
- onPress={() => {
|
|
|
- router.push({
|
|
|
- pathname: '/paymentRecord',
|
|
|
- params: { walletBalance: formatMoney(walletBalance) }
|
|
|
- });
|
|
|
- }}
|
|
|
- >
|
|
|
- <Text className="text-[#02677D] text-lg underline">付款記錄</Text>
|
|
|
- </Pressable>
|
|
|
- </View>
|
|
|
- </View>
|
|
|
+// const api_key = process.env.QFPAY_KEY;
|
|
|
+// const params = paramStringify(obj);
|
|
|
+// const sign = sha256(`${params}${api_key}`).toString();
|
|
|
+// const url = `${origin}${paramStringify(obj, true)}&sign=${sign}`;
|
|
|
+
|
|
|
+// try {
|
|
|
+// 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);
|
|
|
+// }
|
|
|
+// };
|
|
|
|
|
|
- <View className="w-full h-1 bg-[#DBE4E8]" />
|
|
|
+// return (
|
|
|
+// <SafeAreaView className="flex-1 bg-white" edges={['top', 'right', 'left']}>
|
|
|
+// <ScrollView className="flex-1 ">
|
|
|
+// <View className="flex-1 mx-[5%]">
|
|
|
+// <View style={{ marginTop: 25 }}>
|
|
|
+// <Pressable
|
|
|
+// onPress={() => {
|
|
|
+// if (router.canGoBack()) {
|
|
|
+// router.back();
|
|
|
+// } else {
|
|
|
+// router.replace('/accountMainPage');
|
|
|
+// }
|
|
|
+// }}
|
|
|
+// >
|
|
|
+// <CrossLogoSvg />
|
|
|
+// </Pressable>
|
|
|
+// <Text style={{ fontSize: 45, marginVertical: 25 }}>錢包</Text>
|
|
|
+// </View>
|
|
|
+// <View>
|
|
|
+// <ImageBackground
|
|
|
+// className="flex-col-reverse shadow-lg"
|
|
|
+// style={{ height: 200 }}
|
|
|
+// source={require('../../assets/walletCard1.png')}
|
|
|
+// resizeMode="contain"
|
|
|
+// >
|
|
|
+// <View className="mx-[5%] pb-6">
|
|
|
+// <Text className="text-white text-xl">餘額 (HKD)</Text>
|
|
|
+// <View className="flex-row items-center justify-between ">
|
|
|
+// <Text style={{ fontSize: 52 }} className=" text-white font-bold">
|
|
|
+// {loading ? (
|
|
|
+// <View className="items-center justify-center">
|
|
|
+// <ActivityIndicator />
|
|
|
+// </View>
|
|
|
+// ) : (
|
|
|
+// <>
|
|
|
+// <Text>$</Text>
|
|
|
+// {formatMoney(walletBalance)}
|
|
|
+// </>
|
|
|
+// )}
|
|
|
+// </Text>
|
|
|
+// <Pressable
|
|
|
+// className="rounded-2xl items-center justify-center p-3 px-5 pr-6 "
|
|
|
+// style={{
|
|
|
+// backgroundColor: 'rgba(231, 242, 248, 0.2)'
|
|
|
+// }}
|
|
|
+// onPress={() => {
|
|
|
+// console.log('增值');
|
|
|
+// setAmountModalVisible(true);
|
|
|
+// }}
|
|
|
+// >
|
|
|
+// <Text className="text-white font-bold">+ 增值</Text>
|
|
|
+// </Pressable>
|
|
|
+// </View>
|
|
|
+// </View>
|
|
|
+// </ImageBackground>
|
|
|
+// </View>
|
|
|
+// <View className="flex-row-reverse mt-2 mb-6">
|
|
|
+// <Pressable
|
|
|
+// onPress={() => {
|
|
|
+// router.push({
|
|
|
+// pathname: '/paymentRecord',
|
|
|
+// params: { walletBalance: formatMoney(walletBalance) }
|
|
|
+// });
|
|
|
+// }}
|
|
|
+// >
|
|
|
+// <Text className="text-[#02677D] text-lg underline">付款記錄</Text>
|
|
|
+// </Pressable>
|
|
|
+// </View>
|
|
|
+// </View>
|
|
|
|
|
|
- <View className="flex-row justify-between mx-[5%] pt-6 pb-3">
|
|
|
- <Text className="text-xl">優惠券</Text>
|
|
|
- <Pressable onPress={() => router.push('couponPage')}>
|
|
|
- <Text className="text-xl text-[#888888]">顯示所有</Text>
|
|
|
- </Pressable>
|
|
|
- </View>
|
|
|
+// <View className="w-full h-1 bg-[#DBE4E8]" />
|
|
|
|
|
|
- <View className="flex-1 flex-col mx-[5%]">
|
|
|
- {loading ? (
|
|
|
- <View className="items-center justify-center">
|
|
|
- <ActivityIndicator />
|
|
|
- </View>
|
|
|
- ) : (
|
|
|
- <View>
|
|
|
- {coupons
|
|
|
- .filter(
|
|
|
- (coupon) =>
|
|
|
- coupon.is_consumed === false && new Date(coupon.expire_date) > new Date()
|
|
|
- )
|
|
|
- .slice(0, 2)
|
|
|
- .map((coupon, index) => (
|
|
|
- <IndividualCouponComponent
|
|
|
- key={index}
|
|
|
- title={coupon.name}
|
|
|
- price={coupon.amount}
|
|
|
- detail={coupon.description}
|
|
|
- date={formatCouponDate(coupon.expire_date)}
|
|
|
- />
|
|
|
- ))}
|
|
|
- </View>
|
|
|
- )}
|
|
|
- </View>
|
|
|
- </ScrollView>
|
|
|
- <TopUpModal
|
|
|
- visible={modalVisible}
|
|
|
- onClose={() => setModalVisible(false)}
|
|
|
- onSelect={handleTopUp}
|
|
|
- paymentOptions={paymentType}
|
|
|
- />
|
|
|
- <AmountInputModal
|
|
|
- visible={amountModalVisible}
|
|
|
- onClose={() => setAmountModalVisible(false)}
|
|
|
- onConfirm={handleAmountConfirm}
|
|
|
- />
|
|
|
- </SafeAreaView>
|
|
|
- );
|
|
|
-};
|
|
|
+// <View className="flex-row justify-between mx-[5%] pt-6 pb-3">
|
|
|
+// <Text className="text-xl">優惠券</Text>
|
|
|
+// <Pressable onPress={() => router.push('couponPage')}>
|
|
|
+// <Text className="text-xl text-[#888888]">顯示所有</Text>
|
|
|
+// </Pressable>
|
|
|
+// </View>
|
|
|
|
|
|
-export default WalletPageComponent;
|
|
|
+// <View className="flex-1 flex-col mx-[5%]">
|
|
|
+// {loading ? (
|
|
|
+// <View className="items-center justify-center">
|
|
|
+// <ActivityIndicator />
|
|
|
+// </View>
|
|
|
+// ) : (
|
|
|
+// <View>
|
|
|
+// {coupons
|
|
|
+// .filter(
|
|
|
+// (coupon) =>
|
|
|
+// coupon.is_consumed === false && new Date(coupon.expire_date) > new Date()
|
|
|
+// )
|
|
|
+// .slice(0, 2)
|
|
|
+// .map((coupon, index) => (
|
|
|
+// <IndividualCouponComponent
|
|
|
+// key={index}
|
|
|
+// title={coupon.name}
|
|
|
+// price={coupon.amount}
|
|
|
+// detail={coupon.description}
|
|
|
+// date={formatCouponDate(coupon.expire_date)}
|
|
|
+// />
|
|
|
+// ))}
|
|
|
+// </View>
|
|
|
+// )}
|
|
|
+// </View>
|
|
|
+// </ScrollView>
|
|
|
+// {/* <TopUpModal
|
|
|
+// visible={modalVisible}
|
|
|
+// onClose={() => setModalVisible(false)}
|
|
|
+// onSelect={handleTopUp}
|
|
|
+// paymentOptions={paymentType}
|
|
|
+// /> */}
|
|
|
+// <AmountInputModal
|
|
|
+// visible={amountModalVisible}
|
|
|
+// onClose={() => setAmountModalVisible(false)}
|
|
|
+// onConfirm={handleAmountConfirm}
|
|
|
+// />
|
|
|
+// </SafeAreaView>
|
|
|
+// );
|
|
|
+// };
|
|
|
+
|
|
|
+// export default WalletPageComponent;
|