|
|
@@ -1,310 +1,309 @@
|
|
|
-import {
|
|
|
- Image,
|
|
|
- View,
|
|
|
- Text,
|
|
|
- Pressable,
|
|
|
- Dimensions,
|
|
|
- StyleSheet,
|
|
|
- Modal,
|
|
|
- Animated,
|
|
|
- ScrollView,
|
|
|
- Button,
|
|
|
- BackHandler,
|
|
|
- Alert
|
|
|
-} from 'react-native';
|
|
|
-
|
|
|
-import { SafeAreaView } from 'react-native-safe-area-context';
|
|
|
-import { router, useFocusEffect } from 'expo-router';
|
|
|
-import { CrossLogoSvg } from '../../../../component/global/SVG';
|
|
|
-import CouponTabViewComponent from '../../../../component/global/couponTabView';
|
|
|
-import { useCallback, useEffect, useState } from 'react';
|
|
|
-import { useChargingStore } from '../../../../providers/scan_qr_payload_store';
|
|
|
-import { ArrowRightSvg } from '../../../../component/global/SVG';
|
|
|
-import { useRef } from 'react';
|
|
|
-import NormalButton from '../../../../component/global/normal_button';
|
|
|
-
|
|
|
-//this is from optionPage => 優惠券
|
|
|
-const SelectCouponComponent = () => {
|
|
|
- const screenHeight = Dimensions.get('window').height;
|
|
|
- const {
|
|
|
- promotion_code,
|
|
|
- coupon_detail,
|
|
|
- stationID,
|
|
|
-
|
|
|
- setSumOfCoupon,
|
|
|
- setCurrentPriceStore,
|
|
|
- current_price_store,
|
|
|
- setProcessedCouponStore,
|
|
|
- setPromotionCode,
|
|
|
- setCouponDetail,
|
|
|
- setTotalPower
|
|
|
- } = useChargingStore();
|
|
|
- const [scaleValue, setScaleValue] = useState(1);
|
|
|
- const [isBottomSheetVisible, setIsBottomSheetVisible] = useState(false);
|
|
|
- const [processedCoupons, setProcessedCoupons] = useState([]);
|
|
|
- const translateY = useRef(new Animated.Value(300)).current;
|
|
|
- const showBottomSheet = () => {
|
|
|
- setIsBottomSheetVisible(true);
|
|
|
- Animated.timing(translateY, {
|
|
|
- toValue: 0,
|
|
|
- duration: 300,
|
|
|
- useNativeDriver: true
|
|
|
- }).start();
|
|
|
- };
|
|
|
- const hideBottomSheet = () => {
|
|
|
- Animated.timing(translateY, {
|
|
|
- toValue: 0,
|
|
|
- duration: 0,
|
|
|
- useNativeDriver: true
|
|
|
- }).start(() => setIsBottomSheetVisible(false));
|
|
|
- };
|
|
|
- //process coupon so that coupons with same expire date and amount are grouped together to show abcoupon x 2
|
|
|
- useEffect(() => {
|
|
|
- if (Array.isArray(coupon_detail) && coupon_detail.length > 0) {
|
|
|
- const processed = processCoupons(coupon_detail);
|
|
|
- setProcessedCoupons(processed);
|
|
|
- setProcessedCouponStore(processed);
|
|
|
- }
|
|
|
- }, [coupon_detail]);
|
|
|
-
|
|
|
- //fetch original price for coupon valid calculation
|
|
|
-
|
|
|
- const processCoupons = (coupon_details_array: any) => {
|
|
|
- //coupon_details_array contains all information. i skim it down here.
|
|
|
- if (!coupon_details_array || coupon_details_array.length === 0) {
|
|
|
- return [];
|
|
|
- }
|
|
|
- const skimmedDownArray = coupon_details_array?.map((couponDetailObj: any) => ({
|
|
|
- amount: couponDetailObj.coupon.amount,
|
|
|
- id: couponDetailObj.id,
|
|
|
- expire_date: couponDetailObj.expire_date || '永久'
|
|
|
- }));
|
|
|
-
|
|
|
- const totalCouponAmount = skimmedDownArray.reduce((acc: number, coupon: any) => acc + coupon.amount, 0);
|
|
|
- setSumOfCoupon(totalCouponAmount);
|
|
|
- //process the skimmed array by combining coupons with same expire_date and amount
|
|
|
- const processedArray = (skimmedDownArray: { amount: number; id: string; expire_date: string }[]) => {
|
|
|
- const groupedCoupons: { [key: string]: any } = {};
|
|
|
-
|
|
|
- for (const coupon of skimmedDownArray) {
|
|
|
- const key = `${coupon.amount}-${coupon.expire_date}`;
|
|
|
- if (!groupedCoupons[key]) {
|
|
|
- groupedCoupons[key] = {
|
|
|
- coupon_detail: {
|
|
|
- amount: coupon.amount,
|
|
|
- expire_date: coupon.expire_date
|
|
|
- },
|
|
|
- frequency: 1
|
|
|
- };
|
|
|
- } else {
|
|
|
- groupedCoupons[key].frequency++;
|
|
|
- }
|
|
|
- }
|
|
|
- return Object.values(groupedCoupons);
|
|
|
- };
|
|
|
- return processedArray(skimmedDownArray);
|
|
|
- };
|
|
|
- const cleanupData = () => {
|
|
|
- setPromotionCode([]);
|
|
|
- setCouponDetail([]);
|
|
|
- setProcessedCouponStore([]);
|
|
|
- setSumOfCoupon(0);
|
|
|
- setTotalPower(null);
|
|
|
- };
|
|
|
-
|
|
|
- // Add this effect to handle Android back button
|
|
|
- useFocusEffect(
|
|
|
- useCallback(() => {
|
|
|
- const onBackPress = () => {
|
|
|
- cleanupData();
|
|
|
- if (router.canGoBack()) {
|
|
|
- router.back();
|
|
|
- } else {
|
|
|
- router.replace('/scanQrPage');
|
|
|
- }
|
|
|
- return true;
|
|
|
- };
|
|
|
-
|
|
|
- BackHandler.addEventListener('hardwareBackPress', onBackPress);
|
|
|
-
|
|
|
- return () => BackHandler.removeEventListener('hardwareBackPress', onBackPress);
|
|
|
- }, [])
|
|
|
- );
|
|
|
- return (
|
|
|
- <SafeAreaView className="flex-1 bg-white" edges={['top', 'right', 'left']}>
|
|
|
- <View style={{ minHeight: screenHeight, flex: 1 }} className="mx-[5%]">
|
|
|
- <View style={{ marginTop: 25 }}>
|
|
|
- <Pressable
|
|
|
- onPress={() => {
|
|
|
- cleanupData();
|
|
|
- if (router.canGoBack()) {
|
|
|
- router.back();
|
|
|
- } else {
|
|
|
- router.replace('/optionPage');
|
|
|
- }
|
|
|
- }}
|
|
|
- >
|
|
|
- <CrossLogoSvg />
|
|
|
- </Pressable>
|
|
|
- <Text style={{ fontSize: 45, marginVertical: 25 }}>優惠券</Text>
|
|
|
- </View>
|
|
|
- <View className="flex-1">
|
|
|
- <CouponTabViewComponent titles={['可用優惠券', '已使用/失效']} />
|
|
|
- {promotion_code.length > 0 && (
|
|
|
- <View
|
|
|
- style={{
|
|
|
- position: 'absolute',
|
|
|
- alignItems: 'center',
|
|
|
- left: 0,
|
|
|
- right: 0,
|
|
|
- padding: 20,
|
|
|
- height: '100%',
|
|
|
- top: '65%'
|
|
|
- }}
|
|
|
- >
|
|
|
- <Pressable
|
|
|
- className="bg-white rounded-full items-center justify-center w-full flex flex-row"
|
|
|
- style={[styles.floatingButton, { transform: [{ scale: scaleValue }] }]}
|
|
|
- onPressIn={() => setScaleValue(0.96)}
|
|
|
- onPressOut={() => setScaleValue(1)}
|
|
|
- onPress={showBottomSheet}
|
|
|
- >
|
|
|
- <Text className="text-[#02677D] text-2xl lg:text-4xl text-center py-1 pr-4 lg:pr-6 font-[600] lg:py-4">
|
|
|
- 馬上使用
|
|
|
- </Text>
|
|
|
- <View className="flex mb-2 bg-[#02677D] rounded-full items-center justify-center w-10 h-10 relative">
|
|
|
- <ArrowRightSvg />
|
|
|
- <View className="rounded-full bg-[#02677D] h-5 w-5 absolute bottom-7 left-7 z-10 border border-white flex items-center justify-center">
|
|
|
- <Text className="text-white text-xs text-center">{promotion_code.length}</Text>
|
|
|
- </View>
|
|
|
- </View>
|
|
|
- </Pressable>
|
|
|
- </View>
|
|
|
- )}
|
|
|
- </View>
|
|
|
- </View>
|
|
|
- <Modal transparent={true} visible={isBottomSheetVisible} animationType="none">
|
|
|
- <View style={{ flex: 1 }}>
|
|
|
- <Pressable style={{ flex: 1 }} onPress={hideBottomSheet}>
|
|
|
- <View className="flex-1 bg-black/50" />
|
|
|
- </Pressable>
|
|
|
- <Animated.View
|
|
|
- style={{
|
|
|
- position: 'absolute',
|
|
|
- bottom: 0,
|
|
|
- left: 0,
|
|
|
- right: 0,
|
|
|
- height: '80%',
|
|
|
- backgroundColor: 'white',
|
|
|
- transform: [{ translateY }],
|
|
|
- borderTopLeftRadius: 30,
|
|
|
- borderTopRightRadius: 30,
|
|
|
- overflow: 'hidden'
|
|
|
- }}
|
|
|
- >
|
|
|
- <ScrollView
|
|
|
- className="flex-1 flex-col bg-white p-8 "
|
|
|
- contentContainerStyle={{ paddingBottom: 100 }}
|
|
|
- >
|
|
|
- <Text className="text-lg md:text-xl lg:text-2xl">優惠券細節</Text>
|
|
|
- <View style={{ height: 1, backgroundColor: '#ccc', marginVertical: 24 }} />
|
|
|
- {/* coupon row */}
|
|
|
- {processedCoupons &&
|
|
|
- processedCoupons?.map((couponObj: any) => (
|
|
|
- <View
|
|
|
- key={`${couponObj.coupon_detail.amount}-${couponObj.coupon_detail.expire_date}`}
|
|
|
- className="flex flex-row items-center justify-between"
|
|
|
- >
|
|
|
- <View className="flex flex-row items-start ">
|
|
|
- <Image
|
|
|
- className="w-6 lg:w-8 xl:w-10 h-6 lg:h-8 xl:h-10"
|
|
|
- source={require('../../../../assets/couponlogo.png')}
|
|
|
- />
|
|
|
- <View
|
|
|
- key={couponObj.coupon_detail.id}
|
|
|
- className="flex flex-col ml-2 lg:ml-4 "
|
|
|
- >
|
|
|
- <Text className="text-base lg:text-xl ">
|
|
|
- ${couponObj.coupon_detail.amount} 現金劵
|
|
|
- </Text>
|
|
|
- <Text className=" text-sm lg:text-base my-1 lg:mt-2 lg:mb-4 ">
|
|
|
- 有效期{' '}
|
|
|
- <Text className="font-[500] text-[#02677D]">
|
|
|
- 至 {couponObj.coupon_detail.expire_date.slice(0, 10)}
|
|
|
- </Text>
|
|
|
- </Text>
|
|
|
- </View>
|
|
|
- </View>
|
|
|
-
|
|
|
- {/* x 1 */}
|
|
|
- <View className="flex flex-row items-center ">
|
|
|
- <Text>X </Text>
|
|
|
- <View className="w-8 h-8 rounded-full bg-[#02677D] flex items-center justify-center">
|
|
|
- <Text className="text-white text-center text-lg">
|
|
|
- {couponObj.frequency}
|
|
|
- </Text>
|
|
|
- </View>
|
|
|
- </View>
|
|
|
- </View>
|
|
|
- ))}
|
|
|
- <View style={{ height: 1, backgroundColor: '#ccc', marginVertical: 12 }} />
|
|
|
- {/* 服務條款 */}
|
|
|
- <NormalButton
|
|
|
- title={<Text className="text-white text-sm lg:text-lg">立即使用</Text>}
|
|
|
- onPress={() => {
|
|
|
- setIsBottomSheetVisible(false);
|
|
|
- router.push('/totalPayment');
|
|
|
- }}
|
|
|
- extendedStyle={{ marginTop: 12, marginBottom: 24 }}
|
|
|
- />
|
|
|
- <View>
|
|
|
- <View className="">
|
|
|
- <Text className="text-base md:text-lg lg:text-xl pb-2 lg:pb-3 xl:pb-4">
|
|
|
- 服務條款與細則
|
|
|
- </Text>
|
|
|
- <View className="flex flex-col items-center space-y-2">
|
|
|
- <Text className="text-xs md:text-sm font-[300]">
|
|
|
- ・ 此券持有人可在本券有效期內於任何位於Crazy Charge
|
|
|
- 之香港分店換取同等價值充電服務,逾期無效。
|
|
|
- </Text>
|
|
|
- <Text className="text-xs lg:text-sm font-[300]">
|
|
|
- ・
|
|
|
- 此優惠券使用時,電費將以正常價格$3.5元/每度電計算,不適用於貓頭鷹時段或其他折扣時段的電力價格計算。
|
|
|
- </Text>
|
|
|
- <Text className="text-xs lg:text-sm font-[300]">
|
|
|
- ・ 此券不能用以套换現金或其他面值之現金券,持有人不獲現金或其他形式之找贖。
|
|
|
- </Text>
|
|
|
- <Text className="text-xs lg:text-sm font-[300]">
|
|
|
- ・ 使用者一旦在本 APP
|
|
|
- 內確認使用電子優惠券,即視為同意依優惠券規則進行消費抵扣,相關優惠券將立即從帳戶中扣除,且扣除後不得退還。
|
|
|
- </Text>
|
|
|
- <Text className="text-xs lg:text-sm font-[300]">
|
|
|
- ・
|
|
|
- 即便實際充電消費金額未達到電子優惠券的面額,亦不會就差額部分進行退款。優惠券的使用旨在為用戶提供充電優惠,而非現金兌換或退款工具。
|
|
|
- </Text>
|
|
|
- <Text className="text-xs lg:text-sm font-[300]">
|
|
|
- ・如有任何爭議,Crazy Charge
|
|
|
- 保留更改有關使用此現金券之條款及細則,而毋須另行通知。
|
|
|
- </Text>
|
|
|
- </View>
|
|
|
- </View>
|
|
|
- </View>
|
|
|
- </ScrollView>
|
|
|
- </Animated.View>
|
|
|
- </View>
|
|
|
- </Modal>
|
|
|
- </SafeAreaView>
|
|
|
- );
|
|
|
-};
|
|
|
-
|
|
|
-const styles = StyleSheet.create({
|
|
|
- floatingButton: {
|
|
|
- elevation: 5,
|
|
|
- shadowColor: '#000',
|
|
|
- shadowOffset: { width: 0, height: 2 },
|
|
|
- shadowOpacity: 0.25,
|
|
|
- shadowRadius: 3.84
|
|
|
- }
|
|
|
-});
|
|
|
-
|
|
|
-export default SelectCouponComponent;
|
|
|
+import {
|
|
|
+ Image,
|
|
|
+ View,
|
|
|
+ Text,
|
|
|
+ Pressable,
|
|
|
+ Dimensions,
|
|
|
+ StyleSheet,
|
|
|
+ Modal,
|
|
|
+ Animated,
|
|
|
+ ScrollView,
|
|
|
+ Button,
|
|
|
+ BackHandler,
|
|
|
+ Alert
|
|
|
+} from 'react-native';
|
|
|
+
|
|
|
+import { SafeAreaView } from 'react-native-safe-area-context';
|
|
|
+import { router, useFocusEffect } from 'expo-router';
|
|
|
+import { CrossLogoSvg } from '../../../../component/global/SVG';
|
|
|
+import CouponTabViewComponent from '../../../../component/global/couponTabView';
|
|
|
+import { useCallback, useEffect, useState } from 'react';
|
|
|
+import { useChargingStore } from '../../../../providers/scan_qr_payload_store';
|
|
|
+import { ArrowRightSvg } from '../../../../component/global/SVG';
|
|
|
+import { useRef } from 'react';
|
|
|
+import NormalButton from '../../../../component/global/normal_button';
|
|
|
+
|
|
|
+//this is from optionPage => 優惠券
|
|
|
+const SelectCouponComponent = () => {
|
|
|
+ const screenHeight = Dimensions.get('window').height;
|
|
|
+ const {
|
|
|
+ promotion_code,
|
|
|
+ coupon_detail,
|
|
|
+ stationID,
|
|
|
+
|
|
|
+ setSumOfCoupon,
|
|
|
+ setCurrentPriceStore,
|
|
|
+ current_price_store,
|
|
|
+ setProcessedCouponStore,
|
|
|
+ setPromotionCode,
|
|
|
+ setCouponDetail,
|
|
|
+ setTotalPower
|
|
|
+ } = useChargingStore();
|
|
|
+ const [scaleValue, setScaleValue] = useState(1);
|
|
|
+ const [isBottomSheetVisible, setIsBottomSheetVisible] = useState(false);
|
|
|
+ const [processedCoupons, setProcessedCoupons] = useState([]);
|
|
|
+ const translateY = useRef(new Animated.Value(300)).current;
|
|
|
+ const showBottomSheet = () => {
|
|
|
+ setIsBottomSheetVisible(true);
|
|
|
+ Animated.timing(translateY, {
|
|
|
+ toValue: 0,
|
|
|
+ duration: 300,
|
|
|
+ useNativeDriver: true
|
|
|
+ }).start();
|
|
|
+ };
|
|
|
+ const hideBottomSheet = () => {
|
|
|
+ Animated.timing(translateY, {
|
|
|
+ toValue: 0,
|
|
|
+ duration: 0,
|
|
|
+ useNativeDriver: true
|
|
|
+ }).start(() => setIsBottomSheetVisible(false));
|
|
|
+ };
|
|
|
+ //process coupon so that coupons with same expire date and amount are grouped together to show abcoupon x 2
|
|
|
+ useEffect(() => {
|
|
|
+ if (Array.isArray(coupon_detail) && coupon_detail.length > 0) {
|
|
|
+ const processed = processCoupons(coupon_detail);
|
|
|
+ setProcessedCoupons(processed);
|
|
|
+ setProcessedCouponStore(processed);
|
|
|
+ }
|
|
|
+ }, [coupon_detail]);
|
|
|
+
|
|
|
+ //fetch original price for coupon valid calculation
|
|
|
+
|
|
|
+ const processCoupons = (coupon_details_array: any) => {
|
|
|
+ //coupon_details_array contains all information. i skim it down here.
|
|
|
+ if (!coupon_details_array || coupon_details_array.length === 0) {
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+ const skimmedDownArray = coupon_details_array?.map((couponDetailObj: any) => ({
|
|
|
+ amount: couponDetailObj.coupon.amount,
|
|
|
+ id: couponDetailObj.id,
|
|
|
+ expire_date: couponDetailObj.expire_date || '永久'
|
|
|
+ }));
|
|
|
+
|
|
|
+ const totalCouponAmount = skimmedDownArray.reduce((acc: number, coupon: any) => acc + coupon.amount, 0);
|
|
|
+ setSumOfCoupon(totalCouponAmount);
|
|
|
+ //process the skimmed array by combining coupons with same expire_date and amount
|
|
|
+ const processedArray = (skimmedDownArray: { amount: number; id: string; expire_date: string }[]) => {
|
|
|
+ const groupedCoupons: { [key: string]: any } = {};
|
|
|
+
|
|
|
+ for (const coupon of skimmedDownArray) {
|
|
|
+ const key = `${coupon.amount}-${coupon.expire_date}`;
|
|
|
+ if (!groupedCoupons[key]) {
|
|
|
+ groupedCoupons[key] = {
|
|
|
+ coupon_detail: {
|
|
|
+ amount: coupon.amount,
|
|
|
+ expire_date: coupon.expire_date
|
|
|
+ },
|
|
|
+ frequency: 1
|
|
|
+ };
|
|
|
+ } else {
|
|
|
+ groupedCoupons[key].frequency++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return Object.values(groupedCoupons);
|
|
|
+ };
|
|
|
+ return processedArray(skimmedDownArray);
|
|
|
+ };
|
|
|
+ const cleanupData = () => {
|
|
|
+ setPromotionCode([]);
|
|
|
+ setCouponDetail([]);
|
|
|
+ setProcessedCouponStore([]);
|
|
|
+ setSumOfCoupon(0);
|
|
|
+ setTotalPower(null);
|
|
|
+ };
|
|
|
+
|
|
|
+ // Add this effect to handle Android back button
|
|
|
+ useFocusEffect(
|
|
|
+ useCallback(() => {
|
|
|
+ const onBackPress = () => {
|
|
|
+ cleanupData();
|
|
|
+ if (router.canGoBack()) {
|
|
|
+ router.back();
|
|
|
+ } else {
|
|
|
+ router.replace('/scanQrPage');
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ };
|
|
|
+
|
|
|
+ const subscription = BackHandler.addEventListener('hardwareBackPress', onBackPress);
|
|
|
+ return () => subscription.remove()
|
|
|
+ }, [])
|
|
|
+ );
|
|
|
+ return (
|
|
|
+ <SafeAreaView className="flex-1 bg-white" edges={['top', 'right', 'left']}>
|
|
|
+ <View style={{ minHeight: screenHeight, flex: 1 }} className="mx-[5%]">
|
|
|
+ <View style={{ marginTop: 25 }}>
|
|
|
+ <Pressable
|
|
|
+ onPress={() => {
|
|
|
+ cleanupData();
|
|
|
+ if (router.canGoBack()) {
|
|
|
+ router.back();
|
|
|
+ } else {
|
|
|
+ router.replace('/optionPage');
|
|
|
+ }
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <CrossLogoSvg />
|
|
|
+ </Pressable>
|
|
|
+ <Text style={{ fontSize: 45, marginVertical: 25 }}>優惠券</Text>
|
|
|
+ </View>
|
|
|
+ <View className="flex-1">
|
|
|
+ <CouponTabViewComponent titles={['可用優惠券', '已使用/失效']} />
|
|
|
+ {promotion_code.length > 0 && (
|
|
|
+ <View
|
|
|
+ style={{
|
|
|
+ position: 'absolute',
|
|
|
+ alignItems: 'center',
|
|
|
+ left: 0,
|
|
|
+ right: 0,
|
|
|
+ padding: 20,
|
|
|
+ height: '100%',
|
|
|
+ top: '65%'
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <Pressable
|
|
|
+ className="bg-white rounded-full items-center justify-center w-full flex flex-row"
|
|
|
+ style={[styles.floatingButton, { transform: [{ scale: scaleValue }] }]}
|
|
|
+ onPressIn={() => setScaleValue(0.96)}
|
|
|
+ onPressOut={() => setScaleValue(1)}
|
|
|
+ onPress={showBottomSheet}
|
|
|
+ >
|
|
|
+ <Text className="text-[#02677D] text-2xl lg:text-4xl text-center py-1 pr-4 lg:pr-6 font-[600] lg:py-4">
|
|
|
+ 馬上使用
|
|
|
+ </Text>
|
|
|
+ <View className="flex mb-2 bg-[#02677D] rounded-full items-center justify-center w-10 h-10 relative">
|
|
|
+ <ArrowRightSvg />
|
|
|
+ <View className="rounded-full bg-[#02677D] h-5 w-5 absolute bottom-7 left-7 z-10 border border-white flex items-center justify-center">
|
|
|
+ <Text className="text-white text-xs text-center">{promotion_code.length}</Text>
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ </Pressable>
|
|
|
+ </View>
|
|
|
+ )}
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ <Modal transparent={true} visible={isBottomSheetVisible} animationType="none">
|
|
|
+ <View style={{ flex: 1 }}>
|
|
|
+ <Pressable style={{ flex: 1 }} onPress={hideBottomSheet}>
|
|
|
+ <View className="flex-1 bg-black/50" />
|
|
|
+ </Pressable>
|
|
|
+ <Animated.View
|
|
|
+ style={{
|
|
|
+ position: 'absolute',
|
|
|
+ bottom: 0,
|
|
|
+ left: 0,
|
|
|
+ right: 0,
|
|
|
+ height: '80%',
|
|
|
+ backgroundColor: 'white',
|
|
|
+ transform: [{ translateY }],
|
|
|
+ borderTopLeftRadius: 30,
|
|
|
+ borderTopRightRadius: 30,
|
|
|
+ overflow: 'hidden'
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <ScrollView
|
|
|
+ className="flex-1 flex-col bg-white p-8 "
|
|
|
+ contentContainerStyle={{ paddingBottom: 100 }}
|
|
|
+ >
|
|
|
+ <Text className="text-lg md:text-xl lg:text-2xl">優惠券細節</Text>
|
|
|
+ <View style={{ height: 1, backgroundColor: '#ccc', marginVertical: 24 }} />
|
|
|
+ {/* coupon row */}
|
|
|
+ {processedCoupons &&
|
|
|
+ processedCoupons?.map((couponObj: any) => (
|
|
|
+ <View
|
|
|
+ key={`${couponObj.coupon_detail.amount}-${couponObj.coupon_detail.expire_date}`}
|
|
|
+ className="flex flex-row items-center justify-between"
|
|
|
+ >
|
|
|
+ <View className="flex flex-row items-start ">
|
|
|
+ <Image
|
|
|
+ className="w-6 lg:w-8 xl:w-10 h-6 lg:h-8 xl:h-10"
|
|
|
+ source={require('../../../../assets/couponlogo.png')}
|
|
|
+ />
|
|
|
+ <View
|
|
|
+ key={couponObj.coupon_detail.id}
|
|
|
+ className="flex flex-col ml-2 lg:ml-4 "
|
|
|
+ >
|
|
|
+ <Text className="text-base lg:text-xl ">
|
|
|
+ ${couponObj.coupon_detail.amount} 現金劵
|
|
|
+ </Text>
|
|
|
+ <Text className=" text-sm lg:text-base my-1 lg:mt-2 lg:mb-4 ">
|
|
|
+ 有效期{' '}
|
|
|
+ <Text className="font-[500] text-[#02677D]">
|
|
|
+ 至 {couponObj.coupon_detail.expire_date.slice(0, 10)}
|
|
|
+ </Text>
|
|
|
+ </Text>
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+
|
|
|
+ {/* x 1 */}
|
|
|
+ <View className="flex flex-row items-center ">
|
|
|
+ <Text>X </Text>
|
|
|
+ <View className="w-8 h-8 rounded-full bg-[#02677D] flex items-center justify-center">
|
|
|
+ <Text className="text-white text-center text-lg">
|
|
|
+ {couponObj.frequency}
|
|
|
+ </Text>
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ ))}
|
|
|
+ <View style={{ height: 1, backgroundColor: '#ccc', marginVertical: 12 }} />
|
|
|
+ {/* 服務條款 */}
|
|
|
+ <NormalButton
|
|
|
+ title={<Text className="text-white text-sm lg:text-lg">立即使用</Text>}
|
|
|
+ onPress={() => {
|
|
|
+ setIsBottomSheetVisible(false);
|
|
|
+ router.push('/totalPayment');
|
|
|
+ }}
|
|
|
+ extendedStyle={{ marginTop: 12, marginBottom: 24 }}
|
|
|
+ />
|
|
|
+ <View>
|
|
|
+ <View className="">
|
|
|
+ <Text className="text-base md:text-lg lg:text-xl pb-2 lg:pb-3 xl:pb-4">
|
|
|
+ 服務條款與細則
|
|
|
+ </Text>
|
|
|
+ <View className="flex flex-col items-center space-y-2">
|
|
|
+ <Text className="text-xs md:text-sm font-[300]">
|
|
|
+ ・ 此券持有人可在本券有效期內於任何位於Crazy Charge
|
|
|
+ 之香港分店換取同等價值充電服務,逾期無效。
|
|
|
+ </Text>
|
|
|
+ <Text className="text-xs lg:text-sm font-[300]">
|
|
|
+ ・
|
|
|
+ 此優惠券使用時,電費將以正常價格$3.5元/每度電計算,不適用於貓頭鷹時段或其他折扣時段的電力價格計算。
|
|
|
+ </Text>
|
|
|
+ <Text className="text-xs lg:text-sm font-[300]">
|
|
|
+ ・ 此券不能用以套换現金或其他面值之現金券,持有人不獲現金或其他形式之找贖。
|
|
|
+ </Text>
|
|
|
+ <Text className="text-xs lg:text-sm font-[300]">
|
|
|
+ ・ 使用者一旦在本 APP
|
|
|
+ 內確認使用電子優惠券,即視為同意依優惠券規則進行消費抵扣,相關優惠券將立即從帳戶中扣除,且扣除後不得退還。
|
|
|
+ </Text>
|
|
|
+ <Text className="text-xs lg:text-sm font-[300]">
|
|
|
+ ・
|
|
|
+ 即便實際充電消費金額未達到電子優惠券的面額,亦不會就差額部分進行退款。優惠券的使用旨在為用戶提供充電優惠,而非現金兌換或退款工具。
|
|
|
+ </Text>
|
|
|
+ <Text className="text-xs lg:text-sm font-[300]">
|
|
|
+ ・如有任何爭議,Crazy Charge
|
|
|
+ 保留更改有關使用此現金券之條款及細則,而毋須另行通知。
|
|
|
+ </Text>
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ </ScrollView>
|
|
|
+ </Animated.View>
|
|
|
+ </View>
|
|
|
+ </Modal>
|
|
|
+ </SafeAreaView>
|
|
|
+ );
|
|
|
+};
|
|
|
+
|
|
|
+const styles = StyleSheet.create({
|
|
|
+ floatingButton: {
|
|
|
+ elevation: 5,
|
|
|
+ shadowColor: '#000',
|
|
|
+ shadowOffset: { width: 0, height: 2 },
|
|
|
+ shadowOpacity: 0.25,
|
|
|
+ shadowRadius: 3.84
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+export default SelectCouponComponent;
|