2025-07-25 17:37:30 +08:00

353 lines
13 KiB
TypeScript

import ChoicePaySvg from '@/assets/icons/svg/choicePay.svg';
import ReturnArrowSvg from '@/assets/icons/svg/returnArrow.svg';
import StarSvg from '@/assets/icons/svg/whiteStart.svg';
import YesSvg from '@/assets/icons/svg/yes.svg';
import PrivacyModal from '@/components/owner/qualification/privacy';
import Normal from '@/components/owner/rights/normal';
import Premium, { PayItem } from '@/components/owner/rights/premium';
import ProRights from '@/components/owner/rights/proRights';
import { maxDiscountProduct } from '@/components/owner/rights/utils';
import { ThemedText } from '@/components/ThemedText';
import { fetchApi } from '@/lib/server-api-util';
import { useIAP } from 'expo-iap';
import { useLocalSearchParams, useRouter } from "expo-router";
import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Image, ScrollView, StyleSheet, TouchableOpacity, View } from 'react-native';
import { useSafeAreaInsets } from "react-native-safe-area-context";
export default function Rights() {
const insets = useSafeAreaInsets();
const router = useRouter();
const { t } = useTranslation();
const {
connected,
products,
subscriptions,
currentPurchase,
currentPurchaseError,
requestProducts,
requestPurchase,
finishTransaction,
validateReceipt,
} = useIAP();
// 选择购买方式
const [payChoice, setPayChoice] = useState<'weChatPay' | 'apple'>('weChatPay');
// 获取路由参数
const { credit } = useLocalSearchParams<{
credit: string;
}>();
// 普通用户,会员
const [userType, setUserType] = useState<'normal' | 'premium'>('normal');
// 选择权益方式
const [payType, setPayType] = useState<string>('');
// 用户协议弹窗打开
const [showTerms, setShowTerms] = useState<boolean>(false);
// 调接口获取支付信息
const [premiumPay, setPremiumPay] = useState<PayItem[]>();
const [loading, setLoading] = useState<boolean>(false);
const getPAy = async () => {
setLoading(true);
const payInfo = await fetchApi<PayItem[]>(`/order/product-items?product_type=Membership`)
let bestValue = maxDiscountProduct(payInfo)
setPayType(bestValue?.product_code)
setPremiumPay([bestValue, ...payInfo?.filter((item) => item.product_code !== bestValue?.product_code)]);
setLoading(false);
}
useEffect(() => {
getPAy();
}, []);
// 处理购买
const handlePurchase = async (productId: string) => {
console.log(productId);
try {
// Platform-specific purchase requests (v2.7.0+)
await requestPurchase({
request: {
ios: {
sku: "MEMBERSHIP_PRO_QUARTERLY",
andDangerouslyFinishTransactionAutomaticallyIOS: false,
},
},
});
} catch (error) {
alert(productId)
console.error('Purchase failed:', error);
}
};
useEffect(() => {
console.log('connected', connected);
if (!connected) return;
const initializeStore = async () => {
try {
await requestProducts({ skus: ["MEMBERSHIP_PRO_QUARTERLY"], type: 'subs' });
// await getSubscriptions(["MEMBERSHIP_PRO_QUARTERLY"])
console.log("products", products);
} catch (error) {
console.error('Failed to initialize store:', error);
}
};
initializeStore();
}, [connected, premiumPay]);
return (
<View style={{ flex: 1 }}>
<ScrollView style={[styles.container, { paddingTop: insets.top, paddingBottom: insets.bottom + 80 }]}>
{/* 导航栏 */}
<View
style={styles.header}
>
<TouchableOpacity onPress={() => { router.push('/owner') }} style={{ padding: 16 }}>
<ReturnArrowSvg />
</TouchableOpacity>
<ThemedText style={styles.headerTitle}>
{t('rights.title', { ns: 'personal' })}
</ThemedText>
<ThemedText className='opacity-0'>123</ThemedText>
</View>
{/* 会员卡 */}
<View style={styles.card}>
{userType === 'normal' ? (
<Image source={require('@/assets/images/png/owner/normal.png')} style={{ height: 150, objectFit: 'cover', width: '100%' }} />
) : (
<Image source={require('@/assets/images/png/owner/pro.png')} style={{ height: 150, objectFit: 'cover', width: '100%' }} />
)}
<View style={styles.cardContent}>
<View style={styles.cardinfo}>
<ThemedText style={styles.cardTitle}>
{t('rights.purchase', { ns: 'personal' })}
</ThemedText>
<View style={styles.cardPoints}>
<StarSvg />
<ThemedText style={styles.cardPointsText}>{credit}</ThemedText>
</View>
</View>
</View>
</View>
{/* 会员信息 */}
<View style={styles.info}>
{/* 切换按钮 */}
<View style={styles.switchButton}>
<TouchableOpacity
onPress={() => { setUserType("normal") }}
style={[styles.switchButtonItem, { backgroundColor: userType === 'normal' ? "#FFB645" : "#fff", borderColor: userType === 'normal' ? "#FFB645" : "#E2793F" }]}
>
<ThemedText style={{ color: userType === 'normal' ? "#fff" : "#E2793F" }}> {t('rights.free', { ns: 'personal' })}</ThemedText>
</TouchableOpacity>
<TouchableOpacity
onPress={() => { setUserType("premium") }}
style={[styles.switchButtonItem, { backgroundColor: userType === 'premium' ? "#E2793F" : "#fff", borderColor: userType === 'premium' ? "#E2793F" : "#E2793F" }]}
>
<ThemedText style={{ color: userType === 'premium' ? "#fff" : "#E2793F" }}>{t('rights.premium', { ns: 'personal' })}</ThemedText>
</TouchableOpacity>
</View>
{/* 普通权益 */}
<Normal setUserType={setUserType} style={{ display: userType === 'normal' ? "flex" : "none" }} />
{/* 会员权益 */}
<Premium setPayType={setPayType} setShowTerms={setShowTerms} payType={payType} premiumPay={premiumPay} loading={loading} style={{ display: userType === 'normal' ? "none" : "flex" }} />
</View>
{/* 支付方式 */}
<View style={[styles.paymentMethod, { display: userType === 'normal' ? "none" : "flex" }]}>
<TouchableOpacity
onPress={() => { setPayChoice('weChatPay') }}
style={{ padding: 16, flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', borderBottomWidth: 1, borderBottomColor: '#FFD38D' }}
>
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 16 }}>
<ChoicePaySvg />
<ThemedText style={{ fontWeight: '700', fontSize: 16, color: "#4C320C" }}>
{t('personal:rights.weChatPay')}
</ThemedText>
</View>
<View style={[styles.payChoice, { backgroundColor: payChoice === 'weChatPay' ? '#FFB645' : '#D9D9D9' }]}>{payChoice === 'weChatPay' ? <YesSvg /> : null}</View>
</TouchableOpacity>
<TouchableOpacity
style={{ padding: 16, flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }}
onPress={() => { setPayChoice('apple') }}
>
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 16 }}>
<ChoicePaySvg />
<ThemedText style={{ fontWeight: '700', fontSize: 16, color: "#4C320C" }}>
{t('personal:rights.apple')}
</ThemedText>
</View>
<View style={[styles.payChoice, { backgroundColor: payChoice === 'apple' ? '#FFB645' : '#D9D9D9' }]}>
{payChoice === 'apple' ? <YesSvg /> : null}
</View>
</TouchableOpacity>
</View>
{/* 会员权益信息 */}
<View style={{ flex: 1, marginBottom: 80 }}>
<ProRights style={{ display: userType === 'normal' ? "none" : "flex" }} />
</View>
{/* <ApplePay /> */}
</ScrollView>
{/* 付费按钮 */}
<View style={{
padding: 16,
backgroundColor: '#fff',
borderTopWidth: 1,
borderTopColor: '#eee',
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
display: userType === 'normal' ? "none" : "flex"
}}>
<TouchableOpacity
style={styles.goPay}
onPress={async () => {
setUserType('premium');
handlePurchase(payType);
}}
activeOpacity={0.8}
>
<ThemedText style={{ color: '#fff', fontWeight: '700', fontSize: 14 }}>
{t('rights.subscribe', { ns: 'personal' })}
</ThemedText>
</TouchableOpacity>
<TouchableOpacity
onPress={async () => {
setShowTerms(true);
}}
activeOpacity={0.8}
>
<ThemedText style={{ color: '#AC7E35', fontWeight: '400', fontSize: 11, textDecorationLine: 'underline', textAlign: 'center' }}>
{t('rights.terms', { ns: 'personal' })}
</ThemedText>
</TouchableOpacity>
</View>
{/* 协议弹窗 */}
<PrivacyModal modalVisible={showTerms} setModalVisible={setShowTerms} type={"user"} />
</View>
);
}
const styles = StyleSheet.create({
payChoice: {
width: 20,
height: 20,
borderRadius: 15,
alignItems: 'center',
justifyContent: 'center',
},
paymentMethod: {
marginHorizontal: 16,
marginVertical: 16,
borderRadius: 12,
backgroundColor: '#fff',
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 5,
elevation: 5,
},
goPay: {
backgroundColor: '#E2793F',
borderRadius: 24,
paddingVertical: 10,
display: "flex",
alignItems: "center",
width: "100%",
},
switchButton: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
gap: 16,
marginBottom: 16
},
switchButtonItem: {
width: "48%",
borderRadius: 24,
paddingVertical: 6,
display: "flex",
alignItems: "center",
borderWidth: 1
},
info: {
marginHorizontal: 16,
marginVertical: 16,
padding: 16,
borderRadius: 12,
backgroundColor: '#fff',
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 5,
elevation: 5,
},
container: {
flex: 1,
backgroundColor: 'white',
},
header: {
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginVertical: 16,
},
headerTitle: {
fontSize: 20,
fontWeight: '700',
color: '#4C320C',
},
card: {
marginHorizontal: 16,
marginVertical: 16,
backgroundColor: '#FFB645',
borderRadius: 12,
},
cardContent: {
position: 'absolute',
top: 0,
right: 0,
bottom: 0,
left: 0,
padding: 16,
justifyContent: 'space-between'
},
cardinfo: {
alignItems: 'flex-end',
},
cardTitle: {
fontSize: 12,
fontWeight: '700',
color: '#E2793F',
backgroundColor: '#fff',
paddingHorizontal: 8,
paddingVertical: 2,
borderRadius: 20,
textAlign: 'center',
marginBottom: 24
},
cardPoints: {
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
gap: 4
},
cardPointsText: {
fontSize: 32,
fontWeight: '700',
color: '#4C320C',
lineHeight: 32
}
});