optionPage.tsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. import {
  2. View,
  3. Text,
  4. ScrollView,
  5. Pressable,
  6. Image,
  7. Dimensions,
  8. ImageBackground,
  9. BackHandler,
  10. Alert
  11. } from 'react-native';
  12. import React, { useCallback, useEffect, useState } from 'react';
  13. import { SafeAreaView } from 'react-native-safe-area-context';
  14. import { router, useFocusEffect, useNavigation } from 'expo-router';
  15. import { CrossLogoSvg, PreviousPageBlackSvg, RightArrowIconSvg } from '../../../../component/global/SVG';
  16. import { useChargingStore } from '../../../../providers/scan_qr_payload_store';
  17. import { walletService } from '../../../../service/walletService';
  18. import { chargeStationService } from '../../../../service/chargeStationService';
  19. const optionPage = () => {
  20. const {
  21. total_power,
  22. setTotalPower,
  23. promotion_code,
  24. setPromotionCode,
  25. sum_of_coupon,
  26. setSumOfCoupon,
  27. setCouponDetail,
  28. current_price_store,
  29. setCurrentPriceStore,
  30. setProcessedCouponStore
  31. } = useChargingStore();
  32. const buttonText = [
  33. {
  34. power: '20度電',
  35. minute: '25分鐘',
  36. total_power: 20
  37. },
  38. {
  39. power: '25度電',
  40. minute: '30分鐘',
  41. total_power: 25
  42. },
  43. {
  44. power: '30度電',
  45. minute: '40分鐘',
  46. total_power: 30
  47. },
  48. {
  49. power: '40度電',
  50. minute: '45分鐘',
  51. total_power: 40
  52. },
  53. {
  54. power: '充滿停機',
  55. minute: '最多80度電',
  56. total_power: 80
  57. }
  58. ];
  59. const screenWidth = Dimensions.get('window').width;
  60. const [useableCoupon, setUseableCoupon] = useState([]);
  61. const navigation = useNavigation();
  62. //forbid user leftswipping
  63. useEffect(() => {
  64. navigation.setOptions({
  65. gestureEnabled: false
  66. });
  67. }, [navigation]);
  68. // 优惠券注释
  69. useEffect(() => {
  70. const fetchData = async () => {
  71. try {
  72. const info = await walletService.getCustomerInfo();
  73. const coupon = await walletService.getCouponForSpecificUser(info.id);
  74. //filter by expire date is not past today.and is_consumed is fa.se.
  75. const useableConpon = coupon.filter((couponObj: any) => {
  76. const today = new Date();
  77. if (couponObj.expire_date === null) {
  78. return couponObj.is_consumed === false;
  79. }
  80. const expireDate = new Date(couponObj.expire_date);
  81. return expireDate > today && couponObj.is_consumed === false;
  82. });
  83. setUseableCoupon(useableConpon);
  84. } catch (error) {}
  85. };
  86. fetchData();
  87. }, []);
  88. const cleanupData = () => {
  89. setTotalPower(null);
  90. setSumOfCoupon(0);
  91. setPromotionCode([]);
  92. setCouponDetail([]);
  93. setProcessedCouponStore([]);
  94. };
  95. // Add this effect to handle Android back button
  96. useFocusEffect(
  97. useCallback(() => {
  98. const onBackPress = () => {
  99. cleanupData();
  100. if (router.canGoBack()) {
  101. router.back();
  102. } else {
  103. router.replace('/scanQrPage');
  104. }
  105. return true;
  106. };
  107. const subscription = BackHandler.addEventListener('hardwareBackPress', onBackPress);
  108. return () => subscription.remove();
  109. }, [])
  110. );
  111. const displayedText =
  112. promotion_code.length > 0 ? `$ ${sum_of_coupon}劵` : useableCoupon.length > 0 ? '有可用劵' : '無可用劵';
  113. return (
  114. <SafeAreaView className="flex-1 bg-white" edges={['top', 'right', 'left']}>
  115. <ScrollView className="flex-1 mx-[5%]" showsVerticalScrollIndicator={false}>
  116. <View style={{ marginTop: 25 }}>
  117. <Pressable
  118. onPress={() => {
  119. if (router.canGoBack()) {
  120. cleanupData();
  121. router.back();
  122. } else {
  123. cleanupData();
  124. router.replace('/scanQrPage');
  125. }
  126. }}
  127. >
  128. <PreviousPageBlackSvg />
  129. </Pressable>
  130. </View>
  131. <View className="flex-1 flex-col justify-center items-center">
  132. {/* top word and logo */}
  133. <View className="flex-col justify-center items-center gap-2">
  134. {/* <Text className="text-2xl"> */}
  135. <Text className="text-2xl font-[600]">選擇充電度數</Text>
  136. <Image
  137. source={require('../../../../assets/battery.png')}
  138. style={{ width: screenWidth * 0.3, height: undefined, aspectRatio: 1 }}
  139. className="mb-2 md:mb-4 lg:mb-4 xl:mb-6 "
  140. />
  141. </View>
  142. {/* middle button */}
  143. <View className="flex-1 w-full mt-6">
  144. <View className="flex-row flex-wrap justify-center items-center gap-4 ">
  145. {/* not showing full power because it needs to be full width */}
  146. {buttonText
  147. .filter((item) => item.power != '充滿停機')
  148. .map((buttonTextObj: any, index) => (
  149. <Pressable
  150. key={index}
  151. className={`${total_power === buttonTextObj.total_power ? 'bg-[#02677D]' : ''}
  152. w-[45%] border border-[#02677D] p-1 md:p-2 lg:p-3 xl:p-4 py-4 lg:py-6 rounded-xl`}
  153. onPress={() => {
  154. setTotalPower(buttonTextObj.total_power);
  155. }}
  156. >
  157. <Text
  158. className={`${
  159. total_power === buttonTextObj.total_power
  160. ? 'text-white'
  161. : 'text-[#02677D]'
  162. } text-base lg:text-lg xl:text-xl text-center`}
  163. >
  164. {buttonTextObj.power}({buttonTextObj.minute})
  165. </Text>
  166. </Pressable>
  167. ))}
  168. {/* this is 充滿停機only */}
  169. {buttonText
  170. .filter((item) => item.power === '充滿停機')
  171. .map((item, index) => (
  172. <Pressable
  173. key={index}
  174. onPress={() => {
  175. setTotalPower(item.total_power);
  176. }}
  177. className={`${
  178. total_power === item.total_power ? 'bg-[#02677D]' : ''
  179. } w-[94%] border border-[#02677D] p-1 md:p-2 lg:p-3 xl:p-4 py-4 lg:py-6 rounded-xl`}
  180. >
  181. <Text
  182. className={`${
  183. total_power === item.total_power ? 'text-white' : 'text-[#02677D]'
  184. } text-base lg:text-lg xl:text-xl text-center`}
  185. >
  186. {item.power}({item.minute})
  187. </Text>
  188. </Pressable>
  189. ))}
  190. </View>
  191. {/* coupon row */}
  192. <Pressable
  193. onPress={() => {
  194. if (!total_power) {
  195. Alert.alert(
  196. '選擇充電方案',
  197. '請先選擇充電方案再選擇優惠券',
  198. [{ text: '確定', style: 'default' }],
  199. {
  200. cancelable: true
  201. }
  202. );
  203. } else {
  204. Alert.alert('提醒您', '使用優惠券的交易每度電以正價$3.5元計算!', [
  205. { text: '我知道了', onPress: () => router.push('/selectCoupon') }
  206. ]);
  207. }
  208. }}
  209. style={{ flex: 1, borderRadius: 10, overflow: 'hidden', marginTop: 10 }}
  210. >
  211. <ImageBackground
  212. source={require('../../../../assets/coupon.png')}
  213. style={{
  214. width: '100%',
  215. height: 72,
  216. borderRadius: 24,
  217. justifyContent: 'center',
  218. alignItems: 'flex-end'
  219. }}
  220. resizeMode="contain"
  221. >
  222. <Text className="text-white text-center text-base lg:text-lg xl:text-xl pr-6 md:pr-8 lg:pr-10 xl:pr-12">
  223. {displayedText}
  224. </Text>
  225. </ImageBackground>
  226. </Pressable>
  227. </View>
  228. {/* confirm and cancel */}
  229. <View className="flex-row flex-wrap justify-center items-center gap-4 my-8 lg:my-6">
  230. <Pressable
  231. onPress={() => {
  232. cleanupData();
  233. if (router.canGoBack()) {
  234. router.back();
  235. } else {
  236. router.replace('/scanQrPage');
  237. }
  238. }}
  239. className="w-[45%] border border-[#02677D] p-1 md:p-2 lg:p-3 xl:p-4 py-4 lg:py-6 rounded-xl "
  240. >
  241. <Text className="text-[#02677D] text-base lg:text-lg xl:text-xl text-center">取消</Text>
  242. </Pressable>
  243. <Pressable
  244. onPress={() => {
  245. if (!total_power) {
  246. Alert.alert(
  247. '選擇充電方案',
  248. '請先選擇充電方案再確認',
  249. [{ text: '確定', style: 'default' }],
  250. {
  251. cancelable: true
  252. }
  253. );
  254. } else {
  255. router.push('/totalPayment');
  256. }
  257. }}
  258. className="w-[45%] border border-[#02677D] p-1 md:p-2 lg:p-3 xl:p-4 py-4 lg:py-6 rounded-xl "
  259. >
  260. <Text className="text-[#02677D] text-base lg:text-lg xl:text-xl text-center">確認</Text>
  261. </Pressable>
  262. </View>
  263. </View>
  264. </ScrollView>
  265. </SafeAreaView>
  266. );
  267. };
  268. export default optionPage;