5 Commits 5190b1f51c ... 9d1e625184

Tác giả SHA1 Thông báo Ngày
  kuns 9d1e625184 perf: 优化页面显示 2 tuần trước cách đây
  kuns 4ac692e376 perf: 删除不必要的页面 2 tuần trước cách đây
  kuns 625ba58985 perf: 页面国际化完成 2 tuần trước cách đây
  kuns a10e9174a0 feat: 继续页面国际化编译 2 tuần trước cách đây
  kuns 4eb6f96a99 fix: 修复修改不了密码的问题 4 tuần trước cách đây

+ 1 - 1
.env.development

@@ -1,2 +1,2 @@
 EXPO_PUBLIC_NODE_ENV=development
-EXPO_PUBLIC_API_URL=http://47.115.173.98:12000/api/v1
+EXPO_PUBLIC_API_URL=https://api.crazycharge.com.hk/api/v1

+ 0 - 13
app/(auth)/(tabs)/(charging)/chargingFinishPageFromTab.tsx

@@ -1,13 +0,0 @@
-import { View } from 'react-native';
-import React from 'react';
-import ChargingFinishPageFromTabComponent from '../../../../component/chargingPage/chargingFinishPageFromTabComponent';
-
-const ChargingFinishPageFromTab = () => {
-    return (
-        <View className="flex-1">
-            <ChargingFinishPageFromTabComponent />
-        </View>
-    );
-};
-
-export default ChargingFinishPageFromTab;

+ 39 - 27
app/(auth)/(tabs)/(home)/optionPage.tsx

@@ -1,3 +1,4 @@
+// app/(auth)/(tabs)/(home)/optionPage.tsx
 import {
     View,
     Text,
@@ -12,12 +13,14 @@ import {
 import React, { useCallback, useEffect, useState } from 'react';
 import { SafeAreaView } from 'react-native-safe-area-context';
 import { router, useFocusEffect, useNavigation } from 'expo-router';
-import { CrossLogoSvg, PreviousPageBlackSvg, RightArrowIconSvg } from '../../../../component/global/SVG';
+import { PreviousPageBlackSvg } from '../../../../component/global/SVG';
 import { useChargingStore } from '../../../../providers/scan_qr_payload_store';
 import { walletService } from '../../../../service/walletService';
 import { chargeStationService } from '../../../../service/chargeStationService';
+import { useTranslation } from '../../../../util/hooks/useTranslation';
 
 const optionPage = () => {
+    const { t } = useTranslation();
     const {
         total_power,
         setTotalPower,
@@ -32,28 +35,28 @@ const optionPage = () => {
     } = useChargingStore();
     const buttonText = [
         {
-            power: '20度電',
-            minute: '25分鐘',
+            power: t('chargingOption.option.kwh_20'),
+            minute: t('chargingOption.option.min_25'),
             total_power: 20
         },
         {
-            power: '25度電',
-            minute: '30分鐘',
+            power: t('chargingOption.option.kwh_25'),
+            minute: t('chargingOption.option.min_30'),
             total_power: 25
         },
         {
-            power: '30度電',
-            minute: '40分鐘',
+            power: t('chargingOption.option.kwh_30'),
+            minute: t('chargingOption.option.min_40'),
             total_power: 30
         },
         {
-            power: '40度電',
-            minute: '45分鐘',
+            power: t('chargingOption.option.kwh_40'),
+            minute: t('chargingOption.option.min_45'),
             total_power: 40
         },
         {
-            power: '充滿停機',
-            minute: '最多80度電',
+            power: t('chargingOption.option.full_charge'),
+            minute: t('chargingOption.option.up_to_80kwh'),
             total_power: 80
         }
     ];
@@ -117,7 +120,11 @@ const optionPage = () => {
     );
 
     const displayedText =
-        promotion_code.length > 0 ? `$ ${sum_of_coupon}劵` : useableCoupon.length > 0 ? '有可用劵' : '無可用劵';
+        promotion_code.length > 0 
+            ? t('chargingOption.option.coupon_value', { value: sum_of_coupon }) 
+            : useableCoupon.length > 0 
+                ? t('chargingOption.option.available_coupon') 
+                : t('chargingOption.option.no_coupon');
 
     return (
         <SafeAreaView className="flex-1 bg-white" edges={['top', 'right', 'left']}>
@@ -140,8 +147,7 @@ const optionPage = () => {
                 <View className="flex-1 flex-col justify-center items-center">
                     {/* top word and logo */}
                     <View className="flex-col justify-center items-center gap-2">
-                        {/* <Text className="text-2xl"> */}
-                        <Text className="text-2xl font-[600]">選擇充電度數</Text>
+                        <Text className="text-2xl font-[600]">{t('chargingOption.option.select_charge_amount')}</Text>
                         <Image
                             source={require('../../../../assets/battery.png')}
                             style={{ width: screenWidth * 0.3, height: undefined, aspectRatio: 1 }}
@@ -153,7 +159,7 @@ const optionPage = () => {
                       <View className="flex-row flex-wrap justify-center items-center gap-4 ">
                           {/* not showing full power because it needs to be full width */}
                           {buttonText
-                              .filter((item) => item.power != '充滿停機')
+                              .filter((item) => item.power != t('chargingOption.option.full_charge'))
                               .map((buttonTextObj: any, index) => (
                                   <Pressable
                                       key={index}
@@ -176,7 +182,7 @@ const optionPage = () => {
                               ))}
                           {/* this is 充滿停機only */}
                           {buttonText
-                              .filter((item) => item.power === '充滿停機')
+                              .filter((item) => item.power === t('chargingOption.option.full_charge'))
                               .map((item, index) => (
                                   <Pressable
                                       key={index}
@@ -202,16 +208,18 @@ const optionPage = () => {
                             onPress={() => {
                                 if (!total_power) {
                                     Alert.alert(
-                                        '選擇充電方案',
-                                        '請先選擇充電方案再選擇優惠券',
-                                        [{ text: '確定', style: 'default' }],
+                                        t('chargingOption.option.alert.select_plan_title'),
+                                        t('chargingOption.option.alert.select_plan_message'),
+                                        [{ text: t('common.confirm'), style: 'default' }],
                                         {
                                             cancelable: true
                                         }
                                     );
                                 } else {
-                                    Alert.alert('提醒您', '使用優惠券的交易每度電以正價$3.5元計算!', [
-                                        { text: '我知道了', onPress: () => router.push('/selectCoupon') }
+                                    Alert.alert(
+                                        t('chargingOption.option.alert.reminder_title'), 
+                                        t('chargingOption.option.alert.reminder_message'), [
+                                        { text: t('common.confirm'), onPress: () => router.push('/selectCoupon') }
                                     ]);
                                 }
                             }}
@@ -248,15 +256,17 @@ const optionPage = () => {
                             }}
                             className="w-[45%] border border-[#02677D] p-1 md:p-2 lg:p-3 xl:p-4 py-4 lg:py-6 rounded-xl "
                         >
-                            <Text className="text-[#02677D] text-base lg:text-lg xl:text-xl text-center">取消</Text>
+                            <Text className="text-[#02677D] text-base lg:text-lg xl:text-xl text-center">
+                                {t('common.cancel')}
+                            </Text>
                         </Pressable>
                         <Pressable
                             onPress={() => {
                                 if (!total_power) {
                                     Alert.alert(
-                                        '選擇充電方案',
-                                        '請先選擇充電方案再確認',
-                                        [{ text: '確定', style: 'default' }],
+                                        t('chargingOption.option.alert.select_plan_title'),
+                                        t('chargingOption.option.alert.confirm_plan_message'),
+                                        [{ text: t('common.confirm'), style: 'default' }],
                                         {
                                             cancelable: true
                                         }
@@ -267,7 +277,9 @@ const optionPage = () => {
                             }}
                             className="w-[45%] border border-[#02677D] p-1 md:p-2 lg:p-3 xl:p-4 py-4 lg:py-6 rounded-xl "
                         >
-                            <Text className="text-[#02677D] text-base lg:text-lg xl:text-xl text-center">確認</Text>
+                            <Text className="text-[#02677D] text-base lg:text-lg xl:text-xl text-center">
+                                {t('common.confirm')}
+                            </Text>
                         </Pressable>
                     </View>
                 </View>
@@ -276,4 +288,4 @@ const optionPage = () => {
     );
 };
 
-export default optionPage;
+export default optionPage;

+ 23 - 25
app/(auth)/(tabs)/(home)/selectCoupon.tsx

@@ -1,3 +1,4 @@
+// app/(auth)/(tabs)/(home)/selectCoupon.tsx
 import {
     Image,
     View,
@@ -8,9 +9,7 @@ import {
     Modal,
     Animated,
     ScrollView,
-    Button,
-    BackHandler,
-    Alert
+    BackHandler
 } from 'react-native';
 
 import { SafeAreaView } from 'react-native-safe-area-context';
@@ -22,9 +21,11 @@ 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';
+import { useTranslation } from '../../../../util/hooks/useTranslation';
 
 //this is from optionPage => 優惠券
 const SelectCouponComponent = () => {
+    const { t } = useTranslation();
     const screenHeight = Dimensions.get('window').height;
     const {
         promotion_code,
@@ -77,7 +78,7 @@ const SelectCouponComponent = () => {
         const skimmedDownArray = coupon_details_array?.map((couponDetailObj: any) => ({
             amount: couponDetailObj.coupon.amount,
             id: couponDetailObj.id,
-            expire_date: couponDetailObj.expire_date || '永久'
+            expire_date: couponDetailObj.expire_date || t('common.permanent')
         }));
 
         const totalCouponAmount = skimmedDownArray.reduce((acc: number, coupon: any) => acc + coupon.amount, 0);
@@ -145,10 +146,10 @@ const SelectCouponComponent = () => {
                     >
                         <CrossLogoSvg />
                     </Pressable>
-                    <Text style={{ fontSize: 45, marginVertical: 25 }}>優惠券</Text>
+                    <Text style={{ fontSize: 45, marginVertical: 25 }}>{t('selectCoupons.coupons.title')}</Text>
                 </View>
                 <View className="flex-1">
-                    <CouponTabViewComponent titles={['可用優惠券', '已使用/失效']} />
+                    <CouponTabViewComponent titles={[t('selectCoupons.coupons.available'), t('selectCoupons.coupons.used_expired')]} />
                     {promotion_code.length > 0 && (
                         <View
                             style={{
@@ -169,7 +170,7 @@ const SelectCouponComponent = () => {
                                 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">
-                                    馬上使用
+                                    {t('common.use_now')}
                                 </Text>
                                 <View className="flex mb-2 bg-[#02677D] rounded-full items-center justify-center w-10 h-10 relative">
                                     <ArrowRightSvg />
@@ -205,7 +206,7 @@ const SelectCouponComponent = () => {
                             className="flex-1 flex-col bg-white p-8 "
                             contentContainerStyle={{ paddingBottom: 100 }}
                         >
-                            <Text className="text-lg md:text-xl lg:text-2xl">優惠券細節</Text>
+                            <Text className="text-lg md:text-xl lg:text-2xl">{t('selectCoupons.coupon_details')}</Text>
                             <View style={{ height: 1, backgroundColor: '#ccc', marginVertical: 24 }} />
                             {/* coupon row */}
                             {processedCoupons &&
@@ -224,12 +225,14 @@ const SelectCouponComponent = () => {
                                                 className="flex flex-col ml-2 lg:ml-4 "
                                             >
                                                 <Text className="text-base lg:text-xl ">
-                                                    ${couponObj.coupon_detail.amount} 現金劵
+                                                    ${couponObj.coupon_detail.amount} {t('selectCoupons.coupons.cash_voucher')}
                                                 </Text>
                                                 <Text className=" text-sm lg:text-base my-1 lg:mt-2 lg:mb-4 ">
-                                                    有效期{'  '}
+                                                    {t('selectCoupons.coupons.valid_until')}{'  '}
                                                     <Text className="font-[500] text-[#02677D]">
-                                                        至 {couponObj.coupon_detail.expire_date.slice(0, 10)}
+                                                        {couponObj.coupon_detail.expire_date === t('common.permanent') 
+                                                            ? t('common.permanent') 
+                                                            : t('common.to_date', { date: couponObj.coupon_detail.expire_date.slice(0, 10) })}
                                                     </Text>
                                                 </Text>
                                             </View>
@@ -249,7 +252,7 @@ const SelectCouponComponent = () => {
                             <View style={{ height: 1, backgroundColor: '#ccc', marginVertical: 12 }} />
                             {/* 服務條款 */}
                             <NormalButton
-                                title={<Text className="text-white text-sm lg:text-lg">立即使用</Text>}
+                                title={<Text className="text-white text-sm lg:text-lg">{t('common.use_now')}</Text>}
                                 onPress={() => {
                                     setIsBottomSheetVisible(false);
                                     router.push('/totalPayment');
@@ -259,31 +262,26 @@ const SelectCouponComponent = () => {
                             <View>
                                 <View className="">
                                     <Text className="text-base md:text-lg lg:text-xl pb-2 lg:pb-3 xl:pb-4">
-                                        服務條款與細則
+                                        {t('selectCoupons.coupon.terms_and_conditions')}
                                     </Text>
                                     <View className="flex flex-col items-center space-y-2">
                                         <Text className="text-xs md:text-sm font-[300]">
-                                            ・ 此券持有人可在本券有效期內於任何位於Crazy Charge
-                                            之香港分店換取同等價值充電服務,逾期無效。
+                                            {t('selectCoupons.coupon.term1')}
                                         </Text>
                                         <Text className="text-xs lg:text-sm  font-[300]">
-                                            ・
-                                            此優惠券使用時,電費將以正常價格$3.5元/每度電計算,不適用於貓頭鷹時段或其他折扣時段的電力價格計算。
+                                            {t('selectCoupons.coupon.term2')}
                                         </Text>
                                         <Text className="text-xs lg:text-sm  font-[300]">
-                                            ・ 此券不能用以套换現金或其他面值之現金券,持有人不獲現金或其他形式之找贖。
+                                            {t('selectCoupons.coupon.term3')}
                                         </Text>
                                         <Text className="text-xs lg:text-sm  font-[300]">
-                                            ・ 使用者一旦在本 APP
-                                            內確認使用電子優惠券,即視為同意依優惠券規則進行消費抵扣,相關優惠券將立即從帳戶中扣除,且扣除後不得退還。
+                                            {t('selectCoupons.coupon.term4')}
                                         </Text>
                                         <Text className="text-xs lg:text-sm  font-[300]">
-                                            ・
-                                            即便實際充電消費金額未達到電子優惠券的面額,亦不會就差額部分進行退款。優惠券的使用旨在為用戶提供充電優惠,而非現金兌換或退款工具。
+                                            {t('selectCoupons.coupon.term5')}
                                         </Text>
                                         <Text className="text-xs lg:text-sm  font-[300]">
-                                            ・如有任何爭議,Crazy Charge
-                                            保留更改有關使用此現金券之條款及細則,而毋須另行通知。
+                                            {t('selectCoupons.coupon.term6')}
                                         </Text>
                                     </View>
                                 </View>
@@ -306,4 +304,4 @@ const styles = StyleSheet.create({
     }
 });
 
-export default SelectCouponComponent;
+export default SelectCouponComponent;

+ 60 - 56
app/(auth)/(tabs)/(home)/totalPayment.tsx

@@ -1,3 +1,4 @@
+// app/(auth)/(tabs)/(home)/totalPayment.tsx
 import { router, useFocusEffect, useNavigation } from 'expo-router';
 import {
     View,
@@ -25,7 +26,10 @@ import axios from 'axios';
 import sha256 from 'crypto-js/sha256';
 import { walletService } from '../../../../service/walletService';
 import AsyncStorage from '@react-native-async-storage/async-storage';
+import { useTranslation } from '../../../../util/hooks/useTranslation';
+
 const TotalPayment = () => {
+    const { t } = useTranslation();
     const {
         promotion_code,
         stationID,
@@ -79,9 +83,9 @@ const TotalPayment = () => {
                 // More specific error handling
                 if (axios.isAxiosError(error)) {
                     const errorMessage = error.response?.data?.message || 'Network error occurred';
-                    Alert.alert('Error', `Unable to fetch price: ${errorMessage}`, [
+                    Alert.alert(t('common.error'), `${t('wallet.error_fetching_balance')}: ${errorMessage}`, [
                         {
-                            text: 'OK',
+                            text: t('common.ok'),
                             onPress: () => {
                                 cleanupData();
                                 router.push('/mainPage');
@@ -89,9 +93,9 @@ const TotalPayment = () => {
                         }
                     ]);
                 } else {
-                    Alert.alert('Error', 'An unexpected error occurred while fetching the price', [
+                    Alert.alert(t('common.error'), t('wallet.error_fetching_balance'), [
                         {
-                            text: 'OK',
+                            text: t('common.ok'),
                             onPress: () => {
                                 cleanupData();
                                 router.push('/mainPage');
@@ -142,8 +146,8 @@ const TotalPayment = () => {
                     setOutTradeNo('');
                     paymentInitiatedTime.current = null;
                     Alert.alert(
-                        'Payment Timeout',
-                        'The payment status check has timed out. Please check your payment history.'
+                        t('payment.payment_timeout_title'),
+                        t('payment.payment_timeout_message')
                     );
                 }
             }
@@ -166,14 +170,14 @@ const TotalPayment = () => {
             // console.log('outTradeNo in scanQR Page checkpaymentstatus ', outTradeNo);
             const result = await walletService.checkPaymentStatus(outTradeNo);
             setPaymentStatus(result);
-            // console.log('checkPaymentStatus from scan QR checkpaymentStatus', result);
+            // console.log('checkPaymentStatus from scan QR checkpaymentstatus', result);
 
-            if (result && !result.some((item) => item.errmsg?.includes('處理中'))) {
+            if (result && !result.some((item) => item.errmsg?.includes(t('payment.processing')))) {
                 // Payment successful
                 // console.log('totalFee', totalFee);
-                Alert.alert('付款已成功', `你已成功增值。請重新掃描去啟動充電槍。`, [
+                Alert.alert(t('payment.payment_success_title'), t('payment.payment_success_message', { amount: totalPrice }), [
                     {
-                        text: '確認',
+                        text: t('payment.confirm'),
                         onPress: async () => {
                             cleanupData();
                             router.push('/mainPage');
@@ -181,9 +185,9 @@ const TotalPayment = () => {
                     }
                 ]);
             } else {
-                Alert.alert('付款失敗', '請再試一次。', [
+                Alert.alert(t('payment.payment_failed_title'), t('payment.payment_failed_message'), [
                     {
-                        text: '確定',
+                        text: t('payment.ok'),
                         onPress: () => {
                             cleanupData();
                             router.push('/mainPage');
@@ -196,7 +200,7 @@ const TotalPayment = () => {
             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.');
+            Alert.alert(t('common.error'), t('payment.payment_status_check_failed'));
         }
     };
     const showLoadingAndNavigate = async () => {
@@ -222,31 +226,31 @@ const TotalPayment = () => {
             let car, user_id, walletBalance, price_for_pay;
             setLoading(true);
             if (currentPriceTotalPayment === null) {
-                Alert.alert('Please wait', 'Still loading price information...');
+                Alert.alert(t('payment.processing'), t('payment.wait_loading_price'));
                 return;
             }
             //fetch car with proper try catch
             try {
                 car = await chargeStationService.getUserDefaultCars();
                 if (!car?.data?.id) {
-                    Alert.alert('Failed to fetch UDCC', 'Please try again later');
+                    Alert.alert(t('payment.error_title'), t('payment.failed_fetch_udcc'));
                     return;
                 }
             } catch (error) {
                 console.error('Failed to fetch user default car:', error);
-                Alert.alert('Failed to fetch UDC', 'Please try again later');
+                Alert.alert(t('payment.error_title'), t('payment.failed_fetch_udc'));
                 return;
             }
             //fetch user id with proper try catch
             try {
                 user_id = await authenticationService.getUserInfo();
                 if (!user_id?.data?.id) {
-                    Alert.alert('Failed to fetch userID', 'Please try again later');
+                    Alert.alert(t('payment.error_title'), t('payment.failed_fetch_userid'));
                     return;
                 }
             } catch (error) {
                 console.error('Failed to fetch user ID:', error);
-                Alert.alert('Failed to fetch user ID', 'Please try again later');
+                Alert.alert(t('payment.error_title'), t('payment.failed_fetch_userid'));
                 return;
             }
 
@@ -255,7 +259,7 @@ const TotalPayment = () => {
                 walletBalance = await walletService.getWalletBalance();
             } catch (error) {
                 console.error('Failed to fetch user wallet:', error);
-                Alert.alert('Failed to fetch user wallet', 'Please try again later');
+                Alert.alert(t('payment.error_title'), t('payment.failed_fetch_wallet'));
                 return;
             }
 
@@ -276,11 +280,11 @@ const TotalPayment = () => {
 
                     if (unpaidPenalties.length > 0) {
                         Alert.alert(
-                            '未付罰款',
-                            '您有未支付的罰款。請先支付罰款後再重新掃描充電。',
+                            t('payment.unpaid_penalty_title'),
+                            t('payment.unpaid_penalty_message'),
                             [
                                 {
-                                    text: '查看詳情',
+                                    text: t('payment.view_details'),
                                     onPress: () => {
                                         // Navigate to a page showing penalty details
                                         cleanupData();
@@ -298,7 +302,7 @@ const TotalPayment = () => {
                                     }
                                 },
                                 {
-                                    text: '返回',
+                                    text: t('scanQr.back'),
                                     onPress: () => {
                                         cleanupData();
                                         if (router.canGoBack()) {
@@ -315,7 +319,7 @@ const TotalPayment = () => {
                     }
                 }
             } catch (error) {
-                Alert.alert('Error', 'Failed to fetch reservation histories for penalty checking purpose');
+                Alert.alert(t('common.error'), t('scanQr.failed_fetch_reservations'));
             }
 
             const now = new Date();
@@ -347,9 +351,9 @@ const TotalPayment = () => {
 
             // check if user has enough wallet, if not, link to qf pay page
             if (totalPrice === null) {
-                Alert.alert('Error', 'Unable to fetch totalPrice', [
+                Alert.alert(t('common.error'), t('scanQr.failed_fetch_totalprice'), [
                     {
-                        text: 'OK',
+                        text: t('common.ok'),
                         onPress: () => {
                             cleanupData();
                             router.push('/mainPage');
@@ -383,9 +387,9 @@ const TotalPayment = () => {
                     if (response.error) {
                         console.log('Error1', response.error);
                         // Handle error response from the service
-                        Alert.alert('掃描失敗 請稍後再試。', response.message || '未知錯誤', [
+                        Alert.alert(t('payment.scan_failed'), response.message || t('payment.unknown_error'), [
                             {
-                                text: '返回主頁',
+                                text: t('payment.back_main'),
                                 onPress: () => {
                                     cleanupData();
                                     router.push('/mainPage');
@@ -396,18 +400,18 @@ const TotalPayment = () => {
                     }
 
                     if (response === 200 || response === 201) {
-                        Alert.alert('啟動成功', '請按下確認並等待頁面稍後自動跳轉至充電介面', [
+                        Alert.alert(t('payment.charging_started_title'), t('payment.charging_started_message'), [
                             {
-                                text: '確認',
+                                text: t('payment.confirm'),
                                 onPress: showLoadingAndNavigate
                             }
                         ]);
                     } else {
                         console.log('Error111', response, payloadForPay.connector);
 
-                        Alert.alert('掃描失敗 請稍後再試。', response.error_msg || '未知錯誤', [
+                        Alert.alert(t('payment.scan_failed'), response.error_msg || t('payment.unknown_error'), [
                             {
-                                text: '返回主頁',
+                                text: t('payment.back_main'),
                                 onPress: () => {
                                     cleanupData();
                                     router.push('/mainPage');
@@ -417,9 +421,9 @@ const TotalPayment = () => {
                     }
                 } catch (error) {
                     console.error('Payment submission failed:', error);
-                    Alert.alert('錯誤', '付款提交失敗,請稍後再試。', [
+                    Alert.alert(t('common.error'), t('payment.payment_submit_failed'), [
                         {
-                            text: 'OK',
+                            text: t('common.ok'),
                             onPress: () => {
                                 cleanupData();
                                 router.push('/mainPage');
@@ -467,7 +471,7 @@ const TotalPayment = () => {
                 const obj = {
                     // appcode: '6937EF25DF6D4FA78BB2285441BC05E9',
                     appcode: '636E234FB30D43598FC8F0140A1A7282',
-                    goods_name: 'Crazy Charge 錢包增值',
+                    goods_name: t('payment.wallet_top_up'),
                     out_trade_no: response,
                     paysource: 'crazycharge_checkout',
                     return_url: 'https://crazycharge.com.hk/completed',
@@ -498,26 +502,26 @@ const TotalPayment = () => {
                 try {
                     const supported = await Linking.canOpenURL(url);
                     if (supported) {
-                        Alert.alert('', '偵測到您錢包餘額不足,現在為您跳轉到充值頁面', [
+                        Alert.alert('', t('payment.insufficient_balance_redirect'), [
                             {
-                                text: '確定',
+                                text: t('payment.ok'),
                                 onPress: async () => {
                                     await Linking.openURL(url);
                                 }
                             }
                         ]);
                     } else {
-                        Alert.alert('錯誤', '請稍後再試');
+                        Alert.alert(t('common.error'), t('payment.try_again_later'));
                     }
                 } catch (error) {
                     console.error('Top-up failed:', error);
-                    Alert.alert('Error', '一次性付款失敗,請稍後再試');
+                    Alert.alert(t('common.error'), t('payment.one_time_payment_failed'));
                 }
             } else {
-                Alert.alert('Error', 'failed to fetch outTradeNo.');
+                Alert.alert(t('common.error'), t('payment.failed_fetch_outtrade'));
             }
         } catch (error) {
-            Alert.alert('錯誤', '一次性付款失敗,請稍後再試');
+            Alert.alert(t('common.error'), t('payment.one_time_payment_failed'));
         }
     };
 
@@ -527,7 +531,7 @@ const TotalPayment = () => {
                 <View className="flex-1 justify-center items-center bg-black/50">
                     <View className="bg-white p-6 rounded-lg items-center">
                         <ActivityIndicator size="large" color="#02677D" />
-                        <Text className="mt-3">請稍候...</Text>
+                        <Text className="mt-3">{t('common.please_wait')}</Text>
                     </View>
                 </View>
             </Modal>
@@ -547,29 +551,29 @@ const TotalPayment = () => {
                     </Pressable>
                 </View>
                 <View style={{ marginTop: 25 }}>
-                    <Text style={{ fontSize: 45, paddingBottom: 12 }}>付款概要</Text>
+                    <Text style={{ fontSize: 45, paddingBottom: 12 }}>{t('payment.summary_title')}</Text>
 
                     <View>
                         <View className="flex-row justify-between">
-                            <Text className="text-base lg:text-lg ">充電費用</Text>
+                            <Text className="text-base lg:text-lg ">{t('payment.charging_fee')}</Text>
                             <Text className="text-base lg:text-lg">
-                                HK $ {currentPriceTotalPayment ? currentPriceTotalPayment * total_power : 'Loading...'}
+                                HK $ {currentPriceTotalPayment ? currentPriceTotalPayment * total_power : t('common.loading')}
                             </Text>
                         </View>
 
                         <Text style={styles.grayColor} className="text-sm lg:text-base mt-4">
-                            結算電度數 : {total_power == 80 ? '充滿停機' : `${total_power} KWh`}
+                            {t('payment.settled_kwh')}: {total_power == 80 ? t('payment.full_charge') : `${total_power} KWh`}
                         </Text>
                         <Text style={styles.grayColor} className="text-sm lg:text-base mt-4">
-                            每度電價錢 : $ {currentPriceTotalPayment ? currentPriceTotalPayment : 'Loading...'}
+                            {t('payment.price_per_kwh')}: $ {currentPriceTotalPayment ? currentPriceTotalPayment : t('common.loading')}
                         </Text>
                         <Text style={styles.grayColor} className="text-sm lg:text-base mt-4">
-                          注: 跨時段充電將按不同時段的單價分別計费,實際充電量可能浮動
+                          {t('payment.note')}
                         </Text>
                         <View className="h-0.5 my-3 bg-[#f4f4f4]" />
 
                         {processed_coupon_store && processed_coupon_store.length > 0 && (
-                            <Text className="text-base lg:text-lg mb-4 lg:mb-6">優惠劵</Text>
+                            <Text className="text-base lg:text-lg mb-4 lg:mb-6">{t('payment.coupon')}</Text>
                         )}
                         {processed_coupon_store &&
                             processed_coupon_store?.map((couponObj: any) => (
@@ -584,12 +588,12 @@ const TotalPayment = () => {
                                         />
                                         <View key={couponObj.coupon_detail.id} className="flex flex-col ml-2 lg:ml-4 ">
                                             <Text className="text-base lg:text-xl text-[#888888] ">
-                                                ${couponObj.coupon_detail.amount} 現金劵
+                                                ${couponObj.coupon_detail.amount} {t('wallet.coupon.cash_voucher')}
                                             </Text>
                                             <Text className=" text-sm lg:text-base my-1 lg:mt-2 lg:mb-4 text-[#888888]">
-                                                有效期{'  '}
+                                                {t('wallet.coupon.valid_until')}{'  '}
                                                 <Text className="font-[500] text-[#02677D]">
-                                                    至 {couponObj.coupon_detail.expire_date.slice(0, 10)}
+                                                    {t('common.to_date', { date: couponObj.coupon_detail.expire_date.slice(0, 10) })}
                                                 </Text>
                                             </Text>
                                         </View>
@@ -611,8 +615,8 @@ const TotalPayment = () => {
                             <View className="h-0.5 my-3 bg-[#f4f4f4]" />
                         )}
                         <View className="flex-row justify-between">
-                            <Text className="text-xl">總計</Text>
-                            <Text className="text-3xl">HK$ {totalPrice !== null ? totalPrice : 'Loading...'}</Text>
+                            <Text className="text-xl">{t('payment.total')}</Text>
+                            <Text className="text-3xl">HK$ {totalPrice !== null ? totalPrice : t('common.loading')}</Text>
                         </View>
                         <View className="mt-4 ">
                             <NormalButton
@@ -624,7 +628,7 @@ const TotalPayment = () => {
                                             fontWeight: '800'
                                         }}
                                     >
-                                        {loading ? '處理中...' : '付款確認'}
+                                        {loading ? t('common.processing') : t('payment.confirm_payment')}
                                     </Text>
                                 }
                                 onPress={handlePay}
@@ -647,4 +651,4 @@ const styles = StyleSheet.create({
     greenColor: {
         color: '#02677D'
     }
-});
+});

+ 8 - 5
component/accountPages/assistancePageComponent.tsx

@@ -1,11 +1,14 @@
+// component/accountPages/assistancePageComponent.tsx
 import { View, Text, ScrollView, Pressable, Linking, Alert } from 'react-native';
-import React, { useContext } from 'react';
+import React from 'react';
 import { SafeAreaView } from 'react-native-safe-area-context';
 import { router } from 'expo-router';
-import { CrossLogoSvg, RightArrowIconSvg } from '../global/SVG';
+import { CrossLogoSvg } from '../global/SVG';
 import { handleGoWhatsApp } from '../../util/index';
+import { useTranslation } from '../../util/hooks/useTranslation';
 
 const AssistancePageComponent = () => {
+    const { t } = useTranslation();
 
     return (
         <SafeAreaView className="flex-1 bg-white" edges={['top', 'right', 'left']}>
@@ -18,11 +21,11 @@ const AssistancePageComponent = () => {
                     >
                         <CrossLogoSvg />
                     </Pressable>
-                    <Text style={{ fontSize: 45, marginVertical: 25 }}>排除解難</Text>
+                    <Text style={{ fontSize: 45, marginVertical: 25 }}>{t('assistance.troubleshooting')}</Text>
                 </View>
                 <View>
                     <Text className="text-lg">
-                        如果您在使用該應用程式時遇到任何問題,請透過WhatsApp聯絡我們的客戶服務人員:
+                        {t('assistance.description')}
                     </Text>
                     <Pressable onPress={handleGoWhatsApp}>
                         <Text className="text-3xl font-semibold underline text-[#02677D] pt-2">+852 9138 2139</Text>
@@ -33,4 +36,4 @@ const AssistancePageComponent = () => {
     );
 };
 
-export default AssistancePageComponent;
+export default AssistancePageComponent;

+ 19 - 68
component/chargingPage/chargingFinishPageComponent.tsx

@@ -1,3 +1,4 @@
+// component/chargingPage/chargingFinishPageComponent.tsx
 import { View, Text, ScrollView, Image, StyleSheet, Pressable } from 'react-native';
 import React from 'react';
 import { SafeAreaView } from 'react-native-safe-area-context';
@@ -5,6 +6,7 @@ import Svg, { Path, Rect } from 'react-native-svg';
 import NormalButton from '../global/normal_button';
 import SlideInImage from '../global/slideInImage';
 import { router, useLocalSearchParams } from 'expo-router';
+import { useTranslation } from '../../util/hooks/useTranslation';
 
 const BatteryLogoSvg = () => (
     <Svg width="40" height="40" viewBox="0 0 40 40" fill="none">
@@ -78,6 +80,7 @@ const TemperatureIconSvg = () => (
 );
 
 const ChargingFinishPageComponent = ({ data }: { data: any }) => {
+    const { t } = useTranslation();
     const chargingData = Array.isArray(data) ? data[0] : data;
     const [isMoreInfoButtonPressed, setIsMoreInfoButtonPressed] = React.useState<boolean>(true);
 
@@ -102,14 +105,9 @@ const ChargingFinishPageComponent = ({ data }: { data: any }) => {
                 <View style={{ marginTop: 25, flex: 1 }}>
                     <View className="flex-row items-center">
                         <TickLogoSvg />
-                        <Text className="text-3xl pl-2">完成充電</Text>
+                        <Text className="text-3xl pl-2">{t('charging_finish.charging_completed')}</Text>
                     </View>
                     <View className="items-center pt-4 justify-center">
-                        {/* <SlideInImage source={require('../../assets/car.png')} />
-
-                        <Text className="text-2xl font-light pb-4">
-                            {chargingData.car.car_brand.name} {chargingData.car.car_type.name}
-                        </Text> */}
                     </View>
 
                     <View style={{ borderWidth: 1 }} className="border-[#EEEEEE] rounded-2xl">
@@ -119,7 +117,7 @@ const ChargingFinishPageComponent = ({ data }: { data: any }) => {
                                     <BatteryLogoSvg />
                                     <View className="flex-column ">
                                         <Text className="text-sm" style={styles.grayColor}>
-                                            已充電
+                                            {t('charging_finish.charged')}
                                         </Text>
                                         <Text style={styles.greenColor} className="text-4xl font-light">
                                             {`${chargingData.Soc}%`}
@@ -132,7 +130,7 @@ const ChargingFinishPageComponent = ({ data }: { data: any }) => {
                                     <View className="flex-column">
                                         {/* actualEnd_time - actual start time */}
                                         <Text className="text-sm" style={styles.grayColor}>
-                                            充電歷時
+                                            {t('charging_finish.charging_duration')}
                                         </Text>
                                         <View className="flex-row items-end">
                                             <Text style={styles.greenColor} className="text-4xl font-light">
@@ -140,73 +138,26 @@ const ChargingFinishPageComponent = ({ data }: { data: any }) => {
                                                 {durationInMinutes}
                                             </Text>
                                             <Text style={styles.greenColor} className="text-sm font-light">
-                                                mins
+                                                {t('charging_finish.minutes')}
                                             </Text>
                                         </View>
                                     </View>
                                 </View>
                             </View>
                             <View className="h-0.5 w-full my-4 bg-[#EEEEEE]" />
-                            {/* {isMoreInfoButtonPressed ? (
-                                <>
-                                    <View className="h-[100px] flex-row items-center">
-                                        <View className="flex-1 flex-column items-center space-y-2">
-                                            <LightingLogoSvg />
-                                            <Text style={styles.grayColor} className="text-base">
-                                                充電功率
-                                            </Text>
-                                            <Text style={styles.greenColor} className="font-bold text-base">
-                                                {chargingData.connector.Power / 1000}kW
-                                            </Text>
-                                        </View>
-                                        <View className="flex-1 flex-column items-center space-y-2">
-                                            <BatteryIconSvg />
-                                            <Text style={styles.grayColor} className="text-base">
-                                                實際功率
-                                            </Text>
-                                            <Text style={styles.greenColor} className="font-bold text-base">
-                                                {chargingData.connector.Power / 1000}kW
-                                            </Text>
-                                        </View>
-                                    </View>
-                                    <Pressable
-                                        onPress={() => {
-                                            setIsMoreInfoButtonPressed(!isMoreInfoButtonPressed);
-                                        }}
-                                        style={{ padding: 2 }}
-                                    >
-                                        <View className="flex-row pt-4 items-center justify-center">
-                                            <Text className="text-sm">收起 </Text>
-                                            <UpArrowSvg />
-                                        </View>
-                                    </Pressable>
-                                </>
-                            ) : (
-                                <Pressable
-                                    onPress={() => {
-                                        setIsMoreInfoButtonPressed(!isMoreInfoButtonPressed);
-                                    }}
-                                    style={{ padding: 2 }}
-                                >
-                                    <View className="flex-row items-center justify-center">
-                                        <Text className="text-sm">更多資訊 </Text>
-                                        <DownArrowSvg />
-                                    </View>
-                                </Pressable>
-                            )} */}
                         </View>
                     </View>
 
                     <View>
-                        <Text className="text-xl py-4">收費概要</Text>
+                        <Text className="text-xl py-4">{t('charging_finish.fee_summary')}</Text>
                         <View className="flex-row justify-between">
-                            <Text className="text-base">充電費用</Text>
+                            <Text className="text-base">{t('charging_finish.charging_fee')}</Text>
                             <Text className="text-base">HK$ {chargingData.total_fee}</Text>
                         </View>
                         <Text style={styles.grayColor} className="text-base">
                             {chargingData.total_power === null
-                                ? '充滿停機'
-                                : `按每度電結算: ${Math.floor(chargingData.total_power)} kWh`}
+                                ? t('charging_finish.full_charge')
+                                : `${t('charging_finish.settled_per_kwh')}${Math.floor(chargingData.total_power)} kWh`}
                         </Text>
                         <View className="h-0.5 my-3 bg-[#f4f4f4]" />
                         {chargingData.withdraw_fee === 0 ? (
@@ -214,7 +165,7 @@ const ChargingFinishPageComponent = ({ data }: { data: any }) => {
                         ) : (
                             <View className="flex-row justify-between">
                                 <Text className="text-base" style={styles.grayColor}>
-                                    退還充電按金
+                                    {t('charging_finish.refund_deposit')}
                                 </Text>
                                 <Text className="text-base">HK$ ${chargingData.withdraw}</Text>
                             </View>
@@ -222,7 +173,7 @@ const ChargingFinishPageComponent = ({ data }: { data: any }) => {
 
                         <View className="h-0.5 my-3 bg-[#f4f4f4]" />
                         <View className="flex-row justify-between ">
-                            <Text className="text-xl">總計</Text>
+                            <Text className="text-xl">{t('charging_finish.total')}</Text>
                             <Text className="text-xl">HK$ ${chargingData.total_fee - chargingData.withdraw_fee}</Text>
                         </View>
                         <View className="mt-4"></View>
@@ -230,23 +181,23 @@ const ChargingFinishPageComponent = ({ data }: { data: any }) => {
 
                     <View className="w-full h-1 bg-[#DBE4E8]" />
                     <View className="space-y-4 my-4">
-                        <Text className="text-xl ">付款資訊</Text>
+                        <Text className="text-xl ">{t('charging_finish.payment_info')}</Text>
                         <View>
                             <Text className="text-base" style={styles.grayColor}>
-                                訂單編號
+                                {t('charging_finish.order_number')}
                             </Text>
                             <Text className="text-base">CXZ-16336958</Text>
                         </View>
                         <View>
                             <Text className="text-base" style={styles.grayColor}>
-                                付款方式
+                                {t('charging_finish.payment_method')}
                             </Text>
-                            <Text className="text-base">預付銀包</Text>
+                            <Text className="text-base">{t('charging_finish.prepaid_wallet')}</Text>
                         </View>
                     </View>
 
                     <NormalButton
-                        title={<Text style={{ color: '#fff', fontSize: 18 }}>返回主頁</Text>}
+                        title={<Text style={{ color: '#fff', fontSize: 18 }}>{t('charging_finish.return_home')}</Text>}
                         onPress={() => {
                             router.push('mainPage');
                         }}
@@ -266,4 +217,4 @@ const styles = StyleSheet.create({
     greenColor: {
         color: '#02677D'
     }
-});
+});

+ 0 - 266
component/chargingPage/chargingFinishPageFromTabComponent.tsx

@@ -1,266 +0,0 @@
-import { View, Text, ScrollView, Image, StyleSheet, Pressable } from 'react-native';
-import React from 'react';
-import { SafeAreaView } from 'react-native-safe-area-context';
-import Svg, { Path, Rect } from 'react-native-svg';
-import NormalButton from '../global/normal_button';
-import SlideInImage from '../global/slideInImage';
-import { router } from 'expo-router';
-
-const BatteryLogoSvg = () => (
-    <Svg width="40" height="40" viewBox="0 0 40 40" fill="none">
-        <Rect width="40" height="40" rx="20" fill="#02677D" />
-        <Path
-            d="M25.1202 32.2255V28.7039H22.5962L26.274 22.8746V26.3962H28.798L25.1202 32.2255ZM14.8798 31.925C14.5597 31.925 14.2914 31.8168 14.0748 31.6002C13.8583 31.3837 13.75 31.1153 13.75 30.7952V11.4804C13.75 11.1603 13.8583 10.8919 14.0748 10.6754C14.2914 10.4589 14.5597 10.3506 14.8798 10.3506H17.1394V8.17511H21.7547V10.3506H24.0168C24.3373 10.3506 24.6053 10.4589 24.8208 10.6754C25.0364 10.8919 25.1441 11.1603 25.1441 11.4804V20.1703C24.8108 20.1863 24.4899 20.2228 24.1814 20.2796C23.8729 20.3365 23.5689 20.4179 23.2692 20.5236V12.2135H15.6249V27.514H18.2452C18.2452 28.3441 18.3758 29.1342 18.637 29.8842C18.8982 30.6342 19.2708 31.3145 19.7547 31.925H14.8798Z"
-            fill="#FAFAFA"
-        />
-    </Svg>
-);
-const DownArrowSvg = () => (
-    <Svg width="12" height="7" viewBox="0 0 12 7" fill="none">
-        <Path
-            d="M6.00002 6.70762L0.346191 1.05383L1.40002 0L6.00002 4.6L10.6 0L11.6538 1.05383L6.00002 6.70762Z"
-            fill="#222222"
-        />
-    </Svg>
-);
-const UpArrowSvg = () => (
-    <Svg width="12" height="7" viewBox="0 0 12 7" fill="none">
-        <Path
-            d="M6.00002 0.29238L11.6538 5.94617L10.6 7L6.00002 2.4L1.40002 7L0.346191 5.94617L6.00002 0.29238Z"
-            fill="#222222"
-        />
-    </Svg>
-);
-const TimeClockLogoSvg = () => (
-    <Svg width="40" height="40" viewBox="0 0 40 40" fill="none">
-        <Rect width="40" height="40" rx="20" fill="#02677D" />
-        <Path
-            d="M23.6559 24.7652L24.7652 23.6559L20.7894 19.6799V14.7368H19.2105V20.3198L23.6559 24.7652ZM20.0018 30C18.6187 30 17.3186 29.7375 16.1016 29.2126C14.8846 28.6877 13.826 27.9753 12.9258 27.0755C12.0255 26.1757 11.3129 25.1175 10.7877 23.9011C10.2626 22.6846 10 21.3849 10 20.0018C10 18.6187 10.2625 17.3186 10.7874 16.1016C11.3123 14.8846 12.0247 13.826 12.9245 12.9258C13.8243 12.0256 14.8825 11.3129 16.0989 10.7877C17.3154 10.2626 18.6151 10 19.9982 10C21.3813 10 22.6814 10.2625 23.8984 10.7874C25.1154 11.3123 26.174 12.0247 27.0742 12.9245C27.9744 13.8243 28.6871 14.8825 29.2123 16.0989C29.7374 17.3154 30 18.6151 30 19.9982C30 21.3813 29.7375 22.6814 29.2126 23.8984C28.6877 25.1154 27.9753 26.174 27.0755 27.0742C26.1757 27.9744 25.1175 28.6871 23.9011 29.2123C22.6846 29.7374 21.3849 30 20.0018 30ZM20 28.4211C22.3333 28.4211 24.3202 27.6009 25.9605 25.9605C27.6009 24.3202 28.4211 22.3333 28.4211 20C28.4211 17.6667 27.6009 15.6798 25.9605 14.0395C24.3202 12.3991 22.3333 11.5789 20 11.5789C17.6667 11.5789 15.6798 12.3991 14.0395 14.0395C12.3991 15.6798 11.5789 17.6667 11.5789 20C11.5789 22.3333 12.3991 24.3202 14.0395 25.9605C15.6798 27.6009 17.6667 28.4211 20 28.4211Z"
-            fill="#FAFAFA"
-        />
-    </Svg>
-);
-
-const TickLogoSvg = () => (
-    <Svg width="40" height="40" viewBox="0 0 40 40" fill="none">
-        <Rect width="40" height="40" rx="20" fill="#02677D" />
-        <Path
-            d="M15.9168 30L6.41684 20.5L8.79184 18.125L15.9168 25.25L31.2085 9.95837L33.5835 12.3334L15.9168 30Z"
-            fill="#FAFAFA"
-        />
-    </Svg>
-);
-
-const BatteryIconSvg = () => (
-    <Svg width="20" height="31" viewBox="0 0 20 31" fill="none">
-        <Path
-            d="M15.1282 30.8013V26.4103H12.5641L16.5384 19.1987V23.5898H19.1026L15.1282 30.8013ZM1.98716 30C1.60574 30 1.28603 29.871 1.02803 29.613C0.770005 29.355 0.640991 29.0353 0.640991 28.6539V3.81408C0.640991 3.4327 0.770005 3.11299 1.02803 2.85496C1.28603 2.59696 1.60574 2.46796 1.98716 2.46796H4.67949V0H10.3205V2.46796H13.0194C13.4018 2.46796 13.7206 2.59696 13.9759 2.85496C14.2313 3.11299 14.359 3.4327 14.359 3.81408V15.3205C11.9872 15.6261 9.99466 16.68 8.38141 18.4824C6.76816 20.2847 5.96153 22.4252 5.96153 24.9038C5.96153 25.8398 6.0876 26.7383 6.33974 27.5994C6.59188 28.4605 6.96046 29.2607 7.44549 30H1.98716Z"
-            fill="#02677D"
-        />
-    </Svg>
-);
-
-const LightingLogoSvg = () => (
-    <Svg width="21" height="30" viewBox="0 0 21 30" fill="none">
-        <Path
-            d="M5.75631 29.8077L7.42297 18.3333H0.3396L12.8076 0.352539H13.5768L11.9422 13.3333H20.2756L6.52552 29.8077H5.75631Z"
-            fill="#02677D"
-        />
-    </Svg>
-);
-
-const ChargingFinishPageFromTabComponent = () => {
-    //1 make this component receives a parameter, and receive format order id .
-    //2 make a use effect to fetch data using the format id.
-    //3 change below details 
-
-
-    const [isMoreInfoButtonPressed, setIsMoreInfoButtonPressed] = React.useState<boolean>(false);
-
-    function calculateDurationInMinutes(startTimeString: string, endTimeString: string): number {
-        const startTime = new Date(startTimeString);
-        const endTime = new Date(endTimeString);
-
-        // Calculate the difference in milliseconds
-        const durationMs = endTime.getTime() - startTime.getTime();
-
-        // Convert milliseconds to minutes
-        const durationMinutes = Math.round(durationMs / (1000 * 60));
-
-        return durationMinutes;
-    }
-
-    const durationInMinutes = calculateDurationInMinutes(chargingData.actual_end_time, chargingData.actual_start_time);
-
-    return (
-        <SafeAreaView className="flex-1 bg-white">
-            <ScrollView className="flex-1 mx-[5%]" showsVerticalScrollIndicator={false}>
-                <View style={{ marginTop: 25, flex: 1 }}>
-                    <View className="flex-row items-center">
-                        <TickLogoSvg />
-                        <Text className="text-3xl pl-2">完成充電</Text>
-                    </View>
-                    <View className="items-center pt-4 justify-center">
-                        <SlideInImage source={require('../../assets/car.png')} />
-
-                        <Text className="text-2xl font-light pb-4">
-                            {chargingData.car.car_brand.name} {chargingData.car.car_type.name}
-                        </Text>
-                    </View>
-
-                    <View style={{ borderWidth: 1 }} className="border-[#EEEEEE] rounded-2xl">
-                        <View className="mx-[5%] flex-column p-4 ">
-                            <View className="flex-row justify-evenly gap-6">
-                                <View className="flex-row items-center space-x-4">
-                                    <BatteryLogoSvg />
-                                    <View className="flex-column ">
-                                        <Text className="text-sm" style={styles.grayColor}>
-                                            已充電
-                                        </Text>
-                                        <Text style={styles.greenColor} className="text-4xl font-light">
-                                            {`${chargingData.Soc}%`}
-                                        </Text>
-                                    </View>
-                                </View>
-                                <View className="flex-row items-center space-x-4">
-                                    <TimeClockLogoSvg />
-
-                                    <View className="flex-column">
-                                        {/* actualEnd_time - actual start time */}
-                                        <Text className="text-sm" style={styles.grayColor}>
-                                            充電歷時
-                                        </Text>
-                                        <View className="flex-row items-end">
-                                            <Text style={styles.greenColor} className="text-4xl font-light">
-                                                {/* 39 */}
-                                                {durationInMinutes}
-                                            </Text>
-                                            <Text style={styles.greenColor} className="text-sm font-light">
-                                                mins
-                                            </Text>
-                                        </View>
-                                    </View>
-                                </View>
-                            </View>
-                            <View className="h-0.5 w-full my-4 bg-[#EEEEEE]" />
-                            {isMoreInfoButtonPressed ? (
-                                <>
-                                    <View className="h-[100px] flex-row items-center">
-                                        <View className="flex-1 flex-column items-center space-y-2">
-                                            <LightingLogoSvg />
-                                            <Text style={styles.grayColor} className="text-base">
-                                                充電功率
-                                            </Text>
-                                            <Text style={styles.greenColor} className="font-bold text-base">
-                                                {chargingData.connector.Power / 1000}kW
-                                            </Text>
-                                        </View>
-                                        <View className="flex-1 flex-column items-center space-y-2">
-                                            <BatteryIconSvg />
-                                            <Text style={styles.grayColor} className="text-base">
-                                                實際功率
-                                            </Text>
-                                            <Text style={styles.greenColor} className="font-bold text-base">
-                                                {/* 30.0kW */}
-                                                {chargingData.connector.Power / 1000}kW
-                                            </Text>
-                                        </View>
-                                    </View>
-                                    <Pressable
-                                        onPress={() => {
-                                            setIsMoreInfoButtonPressed(!isMoreInfoButtonPressed);
-                                        }}
-                                        style={{ padding: 2 }}
-                                    >
-                                        <View className="flex-row pt-4 items-center justify-center">
-                                            <Text className="text-sm">收起 </Text>
-                                            <UpArrowSvg />
-                                        </View>
-                                    </Pressable>
-                                </>
-                            ) : (
-                                <Pressable
-                                    onPress={() => {
-                                        setIsMoreInfoButtonPressed(!isMoreInfoButtonPressed);
-                                    }}
-                                    style={{ padding: 2 }}
-                                >
-                                    <View className="flex-row items-center justify-center">
-                                        <Text className="text-sm">更多資訊 </Text>
-                                        <DownArrowSvg />
-                                    </View>
-                                </Pressable>
-                            )}
-                        </View>
-                    </View>
-
-                    <View>
-                        <Text className="text-xl py-4">收費概要</Text>
-                        <View className="flex-row justify-between">
-                            <Text className="text-base">充電費用</Text>
-                            <Text className="text-base">HK$ {chargingData.total_fee}</Text>
-                        </View>
-                        <Text style={styles.grayColor} className="text-base">
-                            {chargingData.total_power === null
-                                ? '充滿停機'
-                                : `按每度電結算: ${chargingData.total_power} kWh`}
-                        </Text>
-                        <View className="h-0.5 my-3 bg-[#f4f4f4]" />
-                        {chargingData.withdraw_fee === 0 ? (
-                            ''
-                        ) : (
-                            <View className="flex-row justify-between">
-                                <Text className="text-base" style={styles.grayColor}>
-                                    退還充電按金
-                                </Text>
-                                <Text className="text-base">HK$ ${chargingData.withdraw}</Text>
-                            </View>
-                        )}
-
-                        <View className="h-0.5 my-3 bg-[#f4f4f4]" />
-                        <View className="flex-row justify-between ">
-                            <Text className="text-xl">總計</Text>
-                            <Text className="text-xl">HK$ ${chargingData.total_fee - chargingData.withdraw_fee}</Text>
-                        </View>
-                        <View className="mt-4"></View>
-                    </View>
-
-                    <View className="w-full h-1 bg-[#DBE4E8]" />
-                    <View className="space-y-4 my-4">
-                        <Text className="text-xl ">付款資訊</Text>
-                        <View>
-                            <Text className="text-base" style={styles.grayColor}>
-                                訂單編號
-                            </Text>
-                            <Text className="text-base">CXZ-16336958</Text>
-                        </View>
-                        <View>
-                            <Text className="text-base" style={styles.grayColor}>
-                                付款方式
-                            </Text>
-                            <Text className="text-base">預付銀包</Text>
-                        </View>
-                    </View>
-
-                    <NormalButton
-                        title={<Text style={{ color: '#fff', fontSize: 18 }}>返回主頁</Text>}
-                        onPress={() => {
-                            router.push('mainPage');
-                        }}
-                    />
-                </View>
-            </ScrollView>
-        </SafeAreaView>
-    );
-};
-
-export default ChargingFinishPageFromTabComponent;
-
-const styles = StyleSheet.create({
-    grayColor: {
-        color: '#888888'
-    },
-    greenColor: {
-        color: '#02677D'
-    }
-});

+ 20 - 21
component/chargingPage/chargingHurryUpPageComponent.tsx

@@ -1,3 +1,4 @@
+// component/chargingPage/chargingHurryUpPageComponent.tsx
 import { View, Text, ScrollView, StyleSheet, ActivityIndicator, Alert, Modal } from 'react-native';
 import React, { useEffect, useState } from 'react';
 import { SafeAreaView } from 'react-native-safe-area-context';
@@ -7,18 +8,16 @@ import { chargeStationService } from '../../service/chargeStationService';
 import { format, addHours } from 'date-fns';
 import { toZonedTime } from 'date-fns-tz';
 import { convertToHKTime } from '../../util/lib';
+import { useTranslation } from '../../util/hooks/useTranslation';
 
 const ChargingHurryUpPageComponent = ({ data = {} }) => {
-    // ***************************************************************
-    // 2 整個useEffect listen to data. 有新data就轉頁
-    // ***************************************************************
-
+    const { t } = useTranslation();
     const reservationData = Array.isArray(data) ? data[0] : data;
 
     const [stationInfo, setStationInfo] = useState(null);
     const [loading, setLoading] = useState(false);
     const [isLoading, setIsLoading] = useState(false);
-    const plan = reservationData.book_time === reservationData.end_time ? '充滿停機' : '按每度電結算';
+    const plan = reservationData.book_time === reservationData.end_time ? t('charging_hurry_up.full_charge') : t('charging_hurry_up.per_kwh');
     const kwh = reservationData.total_power === null ? '' : `${reservationData.total_power} kWh`;
 
     useEffect(() => {
@@ -53,17 +52,17 @@ const ChargingHurryUpPageComponent = ({ data = {} }) => {
             const response = await chargeStationService.startCharging(startPayload);
             if (response) {
                 setIsLoading(false);
-                Alert.alert('啟動成功', '請稍後等待頁面自動跳轉至充電介面', [{ text: 'OK', onPress: () => {} }]);
+                Alert.alert(t('charging_hurry_up.start_success_title'), t('charging_hurry_up.start_success_message'), [{ text: t('common.ok'), onPress: () => {} }]);
                 setTimeout(() => {
                     router.push('chargingPage');
                 }, 15000);
             } else {
                 setIsLoading(false);
-                Alert.alert('啟動失敗');
+                Alert.alert(t('charging_hurry_up.start_failed'));
             }
         } catch (error) {
             setIsLoading(false);
-            Alert.alert('發生錯誤', '請稍後再試');
+            Alert.alert(t('common.error'), t('charging_hurry_up.try_again_later'));
         }
     };
 
@@ -72,33 +71,33 @@ const ChargingHurryUpPageComponent = ({ data = {} }) => {
             <ScrollView className="flex-1 mt-8 " nestedScrollEnabled={true} showsVerticalScrollIndicator={false}>
                 <View className="mx-[5%]">
                     <View className="">
-                        <Text className="text-5xl pt-1 pb-6">預約已經開始</Text>
-                        <Text className="text-base">到達充電站後,按下方按鈕開始充電。</Text>
+                        <Text className="text-5xl pt-1 pb-6">{t('charging_hurry_up.reservation_started')}</Text>
+                        <Text className="text-base">{t('charging_hurry_up.arrive_and_start')}</Text>
                         {loading ? (
                             <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
                                 <ActivityIndicator color="#34657b" />
                             </View>
                         ) : (
                             <>
-                                <Text className="text-2xl py-4 ">你的預約為:</Text>
+                                <Text className="text-2xl py-4 ">{t('charging_hurry_up.your_reservation')}</Text>
                                 <View className="border-gray-200 border rounded-md">
                                     <View className="flex-1 mt-4 mx-[5%] ">
                                         <View className="flex-1 flex-row items-center pb-3">
                                             <View className="flex-1 flex-column">
                                                 <Text style={styles.grayColor} className="text-base">
-                                                    日期
+                                                    {t('charging_hurry_up.date')}
                                                 </Text>
                                                 <Text style={styles.greenColor} className="text-4xl text-center  pt-2">
                                                     {convertToHKTime(reservationData.book_time)
                                                         .hkDate.split('/')
                                                         .reverse()
                                                         .slice(1)
-                                                        .join('月')}
+                                                        .join(t('charging_hurry_up.month'))}
                                                 </Text>
                                             </View>
                                             <View className="flex-1 flex-column">
                                                 <Text style={styles.grayColor} className="text-base pl-7">
-                                                    時間
+                                                    {t('charging_hurry_up.time')}
                                                 </Text>
                                                 <Text style={styles.greenColor} className="text-4xl text-center pt-2">
                                                     {convertToHKTime(reservationData.book_time).hkTime.slice(0, 5)}
@@ -107,7 +106,7 @@ const ChargingHurryUpPageComponent = ({ data = {} }) => {
                                         </View>
                                         <View className="flex-1 flex-column justify-center space-y-1 pb-3">
                                             <Text style={styles.grayColor} className="text-base">
-                                                充電地點
+                                                {t('charging_hurry_up.charging_location')}
                                             </Text>
                                             {loading ? (
                                                 <ActivityIndicator size="small" />
@@ -125,7 +124,7 @@ const ChargingHurryUpPageComponent = ({ data = {} }) => {
                                         <View className="flex-1 flex-row  pb-3  ">
                                             <View className="flex-column flex-1">
                                                 <Text style={styles.grayColor} className="text-base">
-                                                    方案
+                                                    {t('charging_hurry_up.plan')}
                                                 </Text>
 
                                                 <Text style={styles.greenColor} className="text-lg">
@@ -137,7 +136,7 @@ const ChargingHurryUpPageComponent = ({ data = {} }) => {
                                             </View>
                                             <View className="flex-column flex-1">
                                                 <Text style={styles.grayColor} className="text-base">
-                                                    車輛
+                                                    {t('charging_hurry_up.vehicle')}
                                                 </Text>
                                                 <Text style={styles.greenColor} className="text-lg">
                                                     {reservationData.car.car_brand.name}
@@ -151,13 +150,13 @@ const ChargingHurryUpPageComponent = ({ data = {} }) => {
                                 </View>
                                 <View className="pt-6">
                                     <NormalButton
-                                        title={<Text className="text-white text-lg">發動充電樁 - 開始充電</Text>}
+                                        title={<Text className="text-white text-lg">{t('charging_hurry_up.start_charging')}</Text>}
                                         onPress={() => handleStartCharge()}
                                     />
                                 </View>
                                 <View className="pt-6">
                                     <NormalButton
-                                        title={<Text className="text-white text-lg">返回主頁</Text>}
+                                        title={<Text className="text-white text-lg">{t('charging_hurry_up.return_home')}</Text>}
                                         onPress={() => router.push('mainPage')}
                                     />
                                 </View>
@@ -177,7 +176,7 @@ const ChargingHurryUpPageComponent = ({ data = {} }) => {
                 >
                     <View style={{ backgroundColor: 'white', padding: 20, borderRadius: 10, alignItems: 'center' }}>
                         <ActivityIndicator />
-                        <Text style={{ marginTop: 10 }}>正在啟動充電...</Text>
+                        <Text style={{ marginTop: 10 }}>{t('charging_hurry_up.starting_charging')}</Text>
                     </View>
                 </View>
             </Modal>
@@ -193,4 +192,4 @@ const styles = StyleSheet.create({
     }
 });
 
-export default ChargingHurryUpPageComponent;
+export default ChargingHurryUpPageComponent;

+ 0 - 0
component/chargingPage/chargingPage.tsx


+ 22 - 87
component/chargingPage/chargingPageComponent.tsx

@@ -1,3 +1,4 @@
+// component/chargingPage/chargingPageComponent.tsx
 import { View, Text, ScrollView, StyleSheet, Image, ActivityIndicator } from 'react-native';
 import { SafeAreaView } from 'react-native-safe-area-context';
 import RippleEffectBatteryIcon from '../global/rippleEffectBatteryIcon';
@@ -11,17 +12,18 @@ import { set } from 'date-fns';
 import { convertToHKTime } from '../../util/lib';
 import ChargingPenaltyPageComponent from './chargingPenaltyComponent';
 import { AuthContext } from '../../context/AuthProvider';
+import { useTranslation } from '../../util/hooks/useTranslation';
+
 const ChargingPageComponent = ({ data }) => {
+    const { t } = useTranslation();
     const reservationData = Array.isArray(data) ? data[0] : data;
     const [isLoading, setIsLoading] = useState(true);
     const [loading, setLoading] = useState(false);
     const [onGoingChargingData, setOnGoingChargingData] = useState();
-    // console.log('data', data);
-    // console.log('voltageA and currentA', onGoingChargingData.data.VoltageA, onGoingChargingData.dataCurrentA);
+
     const voltageA = onGoingChargingData?.data?.VoltageA;
     const currentA = onGoingChargingData?.data?.CurrentA;
     const { user } = useContext(AuthContext);
-    // console.log('voltageA and currentA', voltageA, currentA);
     useEffect(() => {
         const fetchOngoingChargingData = async () => {
             setIsLoading(true);
@@ -29,9 +31,7 @@ const ChargingPageComponent = ({ data }) => {
                 const response = await chargeStationService.fetchOngoingChargingData(reservationData.format_order_id);
                 if (response) {
                     setOnGoingChargingData(response);
-                    // console.log('i am ongoingchargingdata', response);
-
-                    // console.log('onGoingData current and voltage', response.CurrentA, response.VoltageA);
+                
                 } else {
                 }
             } catch (error) {
@@ -42,8 +42,6 @@ const ChargingPageComponent = ({ data }) => {
         };
         fetchOngoingChargingData();
     }, [reservationData]);
-    // //////////////////////////////////////////////////////////////////////
-    // send an automatic handleStopCharge when reservationData.end_time is now
 
     const stopPayLoad = {
         StartChargeSeq: reservationData.format_order_id,
@@ -68,15 +66,7 @@ const ChargingPageComponent = ({ data }) => {
     useEffect(() => {
         const now = new Date();
         const endTime = reservationData?.end_time ? new Date(reservationData.end_time) : null;
-        // console.log('now in chargingPageComponent', now);
-        // console.log('endTime in chargingPageComponent', endTime);
-        // console.log('Checking stop conditions:', { now, endTime, Soc: reservationData?.Soc });
-
-        // Access the snapshot properties
         const snapshotData = reservationData?.snapshot ? JSON.parse(reservationData.snapshot) : null;
-        // console.log('snapshotData in onGoingChargingData', snapshotData);
-        // console.log('snapshot.is_ic_call', snapshotData?.is_ic_call);
-        // console.log('snapshot.type', snapshotData?.type);
 
         if (reservationData && snapshotData) {
             const isWalkingOrIcCall = snapshotData.type === 'walking' || snapshotData.is_ic_call === true;
@@ -98,9 +88,9 @@ const ChargingPageComponent = ({ data }) => {
     useEffect(() => {
         const updateTimeSince = () => {
             if (reservationData && reservationData.actual_start_time) {
-                setTimeSince(timeSinceBooking(reservationData.actual_start_time) || '計算中...');
+                setTimeSince(timeSinceBooking(reservationData.actual_start_time) || t('common.calculating'));
             } else {
-                setTimeSince('計算中...');
+                setTimeSince(t('common.calculating'));
             }
         };
         updateTimeSince();
@@ -149,7 +139,7 @@ const ChargingPageComponent = ({ data }) => {
         return (
             <SafeAreaView style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
                 <ActivityIndicator size="large" />
-                <Text>Loading...</Text>
+                <Text>{t('common.loading')}</Text>
             </SafeAreaView>
         );
     }
@@ -160,7 +150,7 @@ const ChargingPageComponent = ({ data }) => {
                 <View className="flex-1 mx-[5%] space-y-4">
                     <View className="items-center">
                         <View className="mt-6 mb-4">
-                            <Text className="text-lg ">現正充電中:</Text>
+                            <Text className="text-lg ">{t('chargingInfo.currently_charging')}</Text>
                         </View>
                         <Text className="text-4xl font-light">
                             {/* {reservationData.car.car_brand.name} {reservationData.car.car_type.name} */}
@@ -170,7 +160,7 @@ const ChargingPageComponent = ({ data }) => {
 
                     <View className="items-center">
                         <Text className="text-lg" style={styles.grayColor}>
-                            充電中
+                            {t('chargingInfo.charging')}
                         </Text>
                         <View className="flex-row space-x-4 p-4 pr-8 items-center justify-center ml-10">
                             <RippleEffectBatteryIcon />
@@ -181,25 +171,12 @@ const ChargingPageComponent = ({ data }) => {
                                     fontWeight: 300
                                 }}
                             >
-                                {/* 4852 */}
-                                {/* {onGoingChargingData ? `${onGoingChargingData.Soc} %` : 'Loading'} */}
                                 {`${reservationData.Soc}%`}
                                 {/* {`64%`} */}
 
                                 <LoadingDots />
                             </Text>
                         </View>
-                        {/* 尚餘時間未知點計住 comments左先
-                        <Text className="text-lg mb-6" style={styles.grayColor}>
-                            尚餘時間 ~48 mins
-                        </Text> */}
-                        {/* <View className="mb-[-10] items-center justify-center ">
-                            <Image
-                                source={require('../../assets/car.png')}
-                                style={{ width: 430, height: 200 }}
-                                resizeMode="contain"
-                            />
-                        </View> */}
                     </View>
 
                     <View
@@ -212,7 +189,7 @@ const ChargingPageComponent = ({ data }) => {
                             <View className="flex-1 flex-column items-center space-y-2">
                                 <LightingLogoSvg />
                                 <Text style={styles.grayColor} className="text-base">
-                                    實際充電量(度數)
+                                    {t('chargingInfo.actual_charged_kwh')}
                                 </Text>
                                 {isLoading ? (
                                     <ActivityIndicator />
@@ -221,7 +198,7 @@ const ChargingPageComponent = ({ data }) => {
                                         {/* {displayKW(onGoingChargingData.CurrentA, onGoingChargingData.VoltageA)}kW */}
                                         {reservationData.actual_total_power
                                             ? `${reservationData.actual_total_power.toFixed(1)}`
-                                            : '計算中...'}
+                                            : t('common.calculating')}
                                     </Text>
                                 )}
                             </View>
@@ -229,7 +206,7 @@ const ChargingPageComponent = ({ data }) => {
                             <View className="flex-1 flex-column items-center space-y-2">
                                 <BatteryIconSvg />
                                 <Text style={styles.grayColor} className="text-base">
-                                    實際功率 (kW)
+                                    {t('chargingInfo.actual_power_kw')}
                                 </Text>
                                 {isLoading ? (
                                     <ActivityIndicator />
@@ -237,23 +214,10 @@ const ChargingPageComponent = ({ data }) => {
                                     <Text style={styles.greenColor} className="font-bold text-base">
                                         {onGoingChargingData && voltageA && currentA
                                             ? ((voltageA * currentA) / 1000).toFixed(1)
-                                            : '請見充電顯示螢幕'}
+                                            : t('chargingInfo.see_charger_display')}
                                     </Text>
                                 )}
                             </View>
-                            {/* <View className="flex-1 flex-column items-center space-y-2">
-                                <TemperatureIconSvg />
-                                <Text style={styles.grayColor} className="text-base">
-                                    溫度
-                                </Text>
-                                {isLoading ? (
-                                    <ActivityIndicator />
-                                ) : (
-                                    <Text style={styles.greenColor} className="font-bold text-base">
-                                        36°c
-                                    </Text>
-                                )}
-                            </View> */}
                         </View>
                         <View className="mx-[5%]">
                             <View className="h-[1px] w-[100%] bg-[#CCCCCC]" />
@@ -261,33 +225,16 @@ const ChargingPageComponent = ({ data }) => {
                         {/* bottom container */}
                         <View className="h-[35%] mx-[5%] justify-center ">
                             <Text style={styles.grayColor} className="text-base">
-                                充電歷時 ~{timeSince}
+                                {t('chargingInfo.charging_duration')} ~{timeSince}
                             </Text>
                         </View>
                     </View>
-
-                    {/* <View
-                        className="min-h-[20px] border-slate-300 rounded-2xl justify-center p-4"
-                        style={{ borderWidth: 1 }}
-                    >
-                        <View className="flex-row items-center justify-between ">
-                            <View>
-                                <Text className="text-lg">預計充電費用</Text>
-
-                                <Text className="text-base" style={styles.grayColor}>
-                                    按每度電結算: 50 kWh
-                                </Text>
-                            </View>
-                            <Text className="text-3xl">HK$ 175</Text>
-                        </View>
-                    </View> */}
-
                     <View className="border-slate-300 rounded-2xl justify-center p-4" style={{ borderWidth: 1 }}>
-                        <Text className="text-lg pb-1 ">其他資訊</Text>
+                        <Text className="text-lg pb-1 ">{t('chargingInfo.other_info')}</Text>
                         <View className="flex-row">
                             <View className="flex-1 flex-column">
                                 <Text className="text-base" style={styles.grayColor}>
-                                    開始時間
+                                    {t('chargingInfo.start_time')}
                                 </Text>
                                 <Text className="text-base">
                                     {convertToHKTime(reservationData.actual_start_time).hkTime.slice(0, 5)}
@@ -295,10 +242,10 @@ const ChargingPageComponent = ({ data }) => {
                             </View>
                             <View className="flex-1 flex-column">
                                 <Text className="text-base" style={styles.grayColor}>
-                                    充電座
+                                    {t('chargingInfo.charger')}
                                 </Text>
                                 <Text className="text-base">
-                                    {`${connectorIDToLabelMap[reservationData.connector.ConnectorID]}號`}
+                                    {t('chargingInfo.charger_number', { number: connectorIDToLabelMap[reservationData.connector.ConnectorID] })}
                                 </Text>
                             </View>
                         </View>
@@ -311,23 +258,11 @@ const ChargingPageComponent = ({ data }) => {
                             }}
                             title={
                                 <Text className="text-xl text-white" style={{ fontWeight: 900 }}>
-                                    返回主頁
+                                    {t('chargingInfo.return_home')}
                                 </Text>
                             }
                         />
                     </View>
-                    {/* <View>
-                        <NormalButton
-                            onPress={() => {
-                                router.push('/chargingPenaltyPage');
-                            }}
-                            title={
-                                <Text className="text-xl text-white" style={{ fontWeight: 900 }}>
-                                    觀看閒置/罰款狀態頁面
-                                </Text>
-                            }
-                        />
-                    </View> */}
                 </View>
             </ScrollView>
         </SafeAreaView>
@@ -346,4 +281,4 @@ const styles = StyleSheet.create({
         fontWeight: 300,
         color: '#000000'
     }
-});
+});

+ 24 - 21
component/chargingPage/chargingPenaltyComponent.tsx

@@ -1,3 +1,4 @@
+// component/chargingPage/chargingPenaltyComponent.tsx
 import { View, Text, ScrollView, StyleSheet, Image, ActivityIndicator } from 'react-native';
 import React, { useEffect, useState } from 'react';
 import { SafeAreaView } from 'react-native-safe-area-context';
@@ -6,19 +7,20 @@ import ExpectedFeeBox from '../global/expectedFeeBox';
 import OtherInformationBox from '../global/otherInformationBox';
 import { BatteryLogoSvg, TimeClockLogoSvg, WarningTriangleLogoSvg } from '../global/SVG';
 import { router } from 'expo-router';
+import { useTranslation } from '../../util/hooks/useTranslation';
 
-const IdlingGreyBox = () => {
+const IdlingGreyBox = ({ t }: { t: Function }) => {
     return (
         <View className="flex-1 ">
             <View className="p-4 bg-[#5a5c7c] w-full rounded-t-xl flex-row items-center ">
                 <WarningTriangleLogoSvg />
-                <Text className="text-white font-black text-xl pl-4">待機中..</Text>
+                <Text className="text-white font-black text-xl pl-4">{t('charging_penalty.idling')}</Text>
             </View>
 
             <View className="bg-[#555776]  rounded-b-xl p-6 space-y-1">
                 <View className="flex-row items-center">
                     <View className="w-[40%] ">
-                        <Text className="text-base text-white">剩餘待機時間:</Text>
+                        <Text className="text-base text-white">{t('charging_penalty.remaining_idling_time')}</Text>
                     </View>
                     <View className="w-[60%]">
                         <Text style={styles.warningBoldText}>01:55</Text>
@@ -27,7 +29,7 @@ const IdlingGreyBox = () => {
 
                 <View className="flex-row items-center ">
                     <View>
-                        <Text className="text-sm text-white">請於下方確認完成充電以免進入罰款時間</Text>
+                        <Text className="text-sm text-white">{t('charging_penalty.confirm_charging')}</Text>
                     </View>
                 </View>
             </View>
@@ -36,6 +38,7 @@ const IdlingGreyBox = () => {
 };
 
 const ChargingPenaltyPageComponent = ({ data }) => {
+    const { t } = useTranslation();
     const [isIdling, setIsIdling] = React.useState<boolean>(false);
     const reservationData = Array.isArray(data) ? data[0] : data;
     const [loading, setLoading] = useState(false);
@@ -45,9 +48,9 @@ const ChargingPenaltyPageComponent = ({ data }) => {
     useEffect(() => {
         const updateTimeSince = () => {
             if (reservationData && reservationData.actual_start_time) {
-                setTimeSince(timeSinceBooking(reservationData.actual_start_time) || '計算中...');
+                setTimeSince(timeSinceBooking(reservationData.actual_start_time) || t('common.calculating'));
             } else {
-                setTimeSince('計算中...');
+                setTimeSince(t('common.calculating'));
             }
         };
         updateTimeSince();
@@ -57,7 +60,7 @@ const ChargingPenaltyPageComponent = ({ data }) => {
         return () => clearInterval(intervalId);
     }, [reservationData]);
 
-    function timeSinceBooking(timeString) {
+    function timeSinceBooking(timeString: any) {
         if (timeString) {
             const startTime = new Date(timeString);
             const now = new Date();
@@ -78,12 +81,12 @@ const ChargingPenaltyPageComponent = ({ data }) => {
             <>
                 <View className="bg-[#bb2d12] flex-1 p-4 rounded-t-xl flex-row items-center px-[5%]">
                     <WarningTriangleLogoSvg />
-                    <Text className="text-white font-black text-xl pl-4">罰款中</Text>
+                    <Text className="text-white font-black text-xl pl-4">{t('charging_penalty.in_penalty')}</Text>
                 </View>
                 <View className="bg-[#b12a11] flex-column  rounded-b-xl p-6">
                     <View className="flex-1 flex-row items-center pb-2">
                         <View className="w-[40%]">
-                            <Text style={styles.warningLightText}>罰款時間歷時:</Text>
+                            <Text style={styles.warningLightText}>{t('charging_penalty.penalty_duration')}:</Text>
                         </View>
                         <View className="w-[60%]">
                             <Text style={styles.warningBoldText}>{penaltyTime}</Text>
@@ -91,7 +94,7 @@ const ChargingPenaltyPageComponent = ({ data }) => {
                     </View>
                     <View className="flex-1 flex-row items-center pb-2">
                         <View className="w-[40%]">
-                            <Text style={styles.warningLightText}>累積:</Text>
+                            <Text style={styles.warningLightText}>{t('charging_penalty.accumulated')}:</Text>
                         </View>
                         <View className="w-[60%]">
                             <Text style={styles.warningBoldText}>01:55</Text>
@@ -99,7 +102,7 @@ const ChargingPenaltyPageComponent = ({ data }) => {
                     </View>
                     <View className="flex-1  flex-row items-center pb-2">
                         <View>
-                            <Text style={styles.warningLightText}>請於下方確認完成充電以解鎖</Text>
+                            <Text style={styles.warningLightText}>{t('charging_penalty.unlock_charger')}</Text>
                         </View>
                     </View>
                 </View>
@@ -112,9 +115,9 @@ const ChargingPenaltyPageComponent = ({ data }) => {
     useEffect(() => {
         const updatePenaltyTime = () => {
             if (reservationData.actual_end_time) {
-                setPenaltyTime(calculatePenaltyTime(reservationData.actual_end_time) || '計算中...');
+                setPenaltyTime(calculatePenaltyTime(reservationData.actual_end_time) || t('common.calculating'));
             } else {
-                setPenaltyTime('尚未結束充電');
+                setPenaltyTime(t('charging_penalty.not_finished'));
             }
         };
 
@@ -147,7 +150,7 @@ const ChargingPenaltyPageComponent = ({ data }) => {
         return (
             <SafeAreaView style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
                 <ActivityIndicator size="large" />
-                <Text>Loading...</Text>
+                <Text>{t('common.loading')}</Text>
             </SafeAreaView>
         );
     }
@@ -157,7 +160,7 @@ const ChargingPenaltyPageComponent = ({ data }) => {
                 <View className="mx-[5%]">
                     <View className="my-4">
                         <Text className="text-xl" style={styles.greenColor}>
-                            已完成充電
+                            {t('charging_penalty.charging_completed')}
                         </Text>
                         <Text className="text-2xl">
                             {reservationData.car.car_brand.name} {reservationData.car.car_type.name}
@@ -178,7 +181,7 @@ const ChargingPenaltyPageComponent = ({ data }) => {
                                 </View>
                                 <View className="flex-column">
                                     <Text className="text-sm" style={styles.grayColor}>
-                                        已充電
+                                        {t('charging_penalty.charged')}
                                     </Text>
                                     <Text style={styles.greenColor} className="text-3xl font-light">
                                         {reservationData.Soc}%
@@ -191,7 +194,7 @@ const ChargingPenaltyPageComponent = ({ data }) => {
                                 </View>
                                 <View className="flex-column">
                                     <Text className="text-sm" style={styles.grayColor}>
-                                        充電歷時
+                                        {t('charging_penalty.charging_duration')}
                                     </Text>
                                     <View className="flex-row items-end">
                                         <Text style={styles.greenColor} className="text-2xl font-light">
@@ -204,7 +207,7 @@ const ChargingPenaltyPageComponent = ({ data }) => {
                     </View>
                     {isIdling ? (
                         <View className=" flex-column py-3">
-                            <IdlingGreyBox />
+                            <IdlingGreyBox t={t} />
                         </View>
                     ) : (
                         <View className="flex-column py-3">
@@ -218,7 +221,7 @@ const ChargingPenaltyPageComponent = ({ data }) => {
                             }}
                             title={
                                 <Text className="text-xl text-white " style={{ fontWeight: 900 }}>
-                                    完成充電
+                                    {t('charging_penalty.finish_charging')}
                                 </Text>
                             }
                         />
@@ -232,7 +235,7 @@ const ChargingPenaltyPageComponent = ({ data }) => {
 
                     <View className="mt-2">
                         <NormalButton
-                            title={<Text className="text-white text-xl font-semibold">觀看閒置狀態頁面</Text>}
+                            title={<Text className="text-white text-xl font-semibold">{t('charging_penalty.view_idling_status')}</Text>}
                             onPress={() => setIsIdling((prevState) => !prevState)}
                         />
                     </View>
@@ -264,4 +267,4 @@ const styles = StyleSheet.create({
         fontSize: 20,
         fontWeight: '700'
     }
-});
+});

+ 14 - 26
component/chargingPage/futureReservationPageComponent.tsx

@@ -1,30 +1,18 @@
+// component/chargingPage/futureReservationPageComponent.tsx
 import { View, Text, ScrollView, StyleSheet, ActivityIndicator } from 'react-native';
 import { useEffect, useState } from 'react';
 import { SafeAreaView } from 'react-native-safe-area-context';
 import NormalButton from '../global/normal_button';
 import { router } from 'expo-router';
-
 import { convertToHKTime } from '../../util/lib';
+import { useTranslation } from '../../util/hooks/useTranslation';
 
 const FutureReservationPageComponent = ({ data }) => {
+    const { t } = useTranslation();
     const [loading, setLoading] = useState(false);
     const [stationInfo, setStationInfo] = useState(null);
-    const plan = data.book_time === data.end_time ? '充滿停機' : '按每度電結算';
-    const kwh = data.total_power === null ? '' : `${data.total_power} kWh`;
-
-    ///如果充電停機 應該show 充電停機 not 80 kWh
-    ///如果充電停機 應該show 充電停機 not 80 kWh
-    ///如果充電停機 應該show 充電停機 not 80 kWh
-    ///如果充電停機 應該show 充電停機 not 80 kWh
-    ///如果充電停機 應該show 充電停機 not 80 kWh
-    ///如果充電停機 應該show 充電停機 not 80 kWh
-    ///如果充電停機 應該show 充電停機 not 80 kWh
-    ///如果充電停機 應該show 充電停機 not 80 kWh
-    ///如果充電停機 應該show 充電停機 not 80 kWh
-    ///如果充電停機 應該show 充電停機 not 80 kWh
-    ///如果充電停機 應該show 充電停機 not 80 kWh
-    ///如果充電停機 應該show 充電停機 not 80 kWh
-    ///如果充電停機 應該show 充電停機 not 80 kWh
+    const plan = data.book_time === data.end_time ? t('future_reservation.full_charge') : t('future_reservation.per_kwh');
+    const kwh = data.total_power === null ? '' : `${data.total_power} kWh`; 
     ///如果充電停機 應該show 充電停機 not 80 kWh
 
     useEffect(() => {
@@ -43,7 +31,7 @@ const FutureReservationPageComponent = ({ data }) => {
             <ScrollView className="flex-1 mt-8 " nestedScrollEnabled={true} showsVerticalScrollIndicator={false}>
                 <View className="mx-[5%]">
                     <View className="">
-                        <Text className="text-5xl pt-1 pb-6">暫無充電車輛</Text>
+                        <Text className="text-5xl pt-1 pb-6">{t('future_reservation.no_charging_vehicle')}</Text>
 
                         {loading ? (
                             <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
@@ -51,26 +39,26 @@ const FutureReservationPageComponent = ({ data }) => {
                             </View>
                         ) : (
                             <>
-                                <Text className="text-2xl pb-2 ">你的下一次預約為:</Text>
+                                <Text className="text-2xl pb-2 ">{t('future_reservation.next_reservation')}</Text>
                                 <View className="border-gray-200 border rounded-md">
                                     <View className="flex-1 mt-4 mx-[5%] ">
                                         <View className="flex-1 flex-row items-center pb-3">
                                             <View className="flex-1 flex-column">
                                                 <Text style={styles.grayColor} className="text-base">
-                                                    日期
+                                                    {t('future_reservation.date')}
                                                 </Text>
                                                 <Text style={styles.greenColor} className="text-4xl text-center  pt-2">
                                                     {convertToHKTime(data.book_time)
                                                         .hkDate.split('/')
                                                         .reverse()
                                                         .slice(1)
-                                                        .join('月')}
+                                                        .join(t('future_reservation.month'))}
                                                 </Text>
                                             </View>
 
                                             <View className="flex-1 flex-column">
                                                 <Text style={styles.grayColor} className="text-base pl-7">
-                                                    時間
+                                                    {t('future_reservation.time')}
                                                 </Text>
                                                 <Text style={styles.greenColor} className="text-4xl text-center pt-2">
                                                     {convertToHKTime(data.book_time).hkTime.slice(0, 5)}
@@ -79,7 +67,7 @@ const FutureReservationPageComponent = ({ data }) => {
                                         </View>
                                         <View className="flex-1 flex-column justify-center space-y-1 pb-3">
                                             <Text style={styles.grayColor} className="text-base">
-                                                充電地點
+                                                {t('future_reservation.charging_location')}
                                             </Text>
                                             <Text style={styles.greenColor} className="text-2xl ">
                                                 {stationInfo?.StationName || 'N/A'}
@@ -91,7 +79,7 @@ const FutureReservationPageComponent = ({ data }) => {
                                         <View className="flex-1 flex-row  pb-3  ">
                                             <View className="flex-column flex-1">
                                                 <Text style={styles.grayColor} className="text-base">
-                                                    方案
+                                                    {t('future_reservation.plan')}
                                                 </Text>
 
                                                 <Text style={styles.greenColor} className="text-lg">
@@ -117,7 +105,7 @@ const FutureReservationPageComponent = ({ data }) => {
                                 </View>
                                 <View className="pt-6">
                                     <NormalButton
-                                        title={<Text className="text-white text-lg">返回主頁</Text>}
+                                        title={<Text className="text-white text-lg">{t('future_reservation.return_home')}</Text>}
                                         onPress={() => router.push('mainPage')}
                                     />
                                 </View>
@@ -139,4 +127,4 @@ const styles = StyleSheet.create({
     }
 });
 
-export default FutureReservationPageComponent;
+export default FutureReservationPageComponent;

+ 15 - 252
component/chargingPage/paymentFinishPageComponent.tsx

@@ -1,3 +1,4 @@
+// component/chargingPage/paymentFinishPageComponent.tsx
 import { View, Text, ScrollView, StyleSheet, Pressable } from 'react-native';
 import React, { useEffect } from 'react';
 import { SafeAreaView } from 'react-native-safe-area-context';
@@ -16,8 +17,10 @@ import {
 } from '../global/SVG';
 import useBookingStore from '../../providers/booking_store';
 import userStore from '../../providers/user_store';
+import { useTranslation } from '../../util/hooks/useTranslation';
 
 const PaymentFinishPageComponent = () => {
+    const { t } = useTranslation();
     const { bookTime, carID, date, chargingWatt, connectorID, price, stationID, user, paymentFee, carCapacitance } =
         useBookingStore();
     const navigation = useNavigation();
@@ -38,256 +41,27 @@ const PaymentFinishPageComponent = () => {
                 <View style={{ marginTop: 25, flex: 1 }}>
                     <View className="flex-row items-center">
                         <TickLogoSvg />
-                        <Text className="text-3xl pl-2">成功付款</Text>
+                        <Text className="text-3xl pl-2">{t('payment_finish.success_title')}</Text>
                     </View>
-
-                    {/* <View className="items-center pt-4 justify-center">
-                        <SlideInImage source={require('../../assets/car.png')} />
-
-                        <Text className="text-2xl font-light pb-4">
-                            TESLA Model 3
-                        </Text>
-                    </View>
-
-                    <View
-                        style={{ borderWidth: 1 }}
-                        className="border-[#EEEEEE] rounded-2xl"
-                    >
-                        <View className="mx-[5%] flex-column p-4 ">
-                            <View className="flex-row justify-evenly gap-6">
-                                <View className="flex-row items-center space-x-4">
-                                    <BatteryLogoSvg />
-                                    <View className="flex-column ">
-                                        <Text
-                                            className="text-sm"
-                                            style={styles.grayColor}
-                                        >
-                                            已充電
-                                        </Text>
-                                        <Text
-                                            style={styles.greenColor}
-                                            className="text-4xl font-light"
-                                        >
-                                            95%
-                                        </Text>
-                                    </View>
-                                </View>
-                                <View className="flex-row items-center space-x-4">
-                                    <TimeClockLogoSvg />
-
-                                    <View className="flex-column">
-                                        <Text
-                                            className="text-sm"
-                                            style={styles.grayColor}
-                                        >
-                                            充電歷時
-                                        </Text>
-                                        <View className="flex-row items-end">
-                                            <Text
-                                                style={styles.greenColor}
-                                                className="text-4xl font-light"
-                                            >
-                                                39
-                                            </Text>
-                                            <Text
-                                                style={styles.greenColor}
-                                                className="text-sm font-light"
-                                            >
-                                                mins
-                                            </Text>
-                                        </View>
-                                    </View>
-                                </View>
-                            </View>
-                            <View className="h-0.5 w-full my-4 bg-[#EEEEEE]" />
-                            {isMoreInfoButtonPressed ? (
-                                <>
-                                    <View className="h-[100px] flex-row items-center">
-                                        <View className="flex-1 flex-column items-center space-y-2">
-                                            <LightingLogoSvg />
-                                            <Text
-                                                style={styles.grayColor}
-                                                className="text-base"
-                                            >
-                                                充電功率
-                                            </Text>
-                                            <Text
-                                                style={styles.greenColor}
-                                                className="font-bold text-base"
-                                            >
-                                                22.1kW
-                                            </Text>
-                                        </View>
-                                        <View className="flex-1 flex-column items-center space-y-2">
-                                            <BatteryIconSvg />
-                                            <Text
-                                                style={styles.grayColor}
-                                                className="text-base"
-                                            >
-                                                實際功率
-                                            </Text>
-                                            <Text
-                                                style={styles.greenColor}
-                                                className="font-bold text-base"
-                                            >
-                                                30.0kW
-                                            </Text>
-                                        </View>
-                                        <View className="flex-1 flex-column items-center space-y-2">
-                                            <TemperatureIconSvg />
-                                            <Text
-                                                style={styles.grayColor}
-                                                className="text-base"
-                                            >
-                                                溫度
-                                            </Text>
-                                            <Text
-                                                style={styles.greenColor}
-                                                className="font-bold text-base"
-                                            >
-                                                36°c
-                                            </Text>
-                                        </View>
-                                    </View>
-                                    <Pressable
-                                        onPress={() => {
-                                            setIsMoreInfoButtonPressed(
-                                                !isMoreInfoButtonPressed
-                                            );
-                                        }}
-                                        style={{ padding: 2 }}
-                                    >
-                                        <View className="flex-row pt-4 items-center justify-center">
-                                            <Text className="text-sm">
-                                                收起{' '}
-                                            </Text>
-                                            <UpArrowSvg />
-                                        </View>
-                                    </Pressable>
-                                </>
-                            ) : (
-                                <Pressable
-                                    onPress={() => {
-                                        setIsMoreInfoButtonPressed(
-                                            !isMoreInfoButtonPressed
-                                        );
-                                    }}
-                                    style={{ padding: 2 }}
-                                >
-                                    <View className="flex-row items-center justify-center">
-                                        <Text className="text-sm">
-                                            更多資訊{' '}
-                                        </Text>
-                                        <DownArrowSvg />
-                                    </View>
-                                </Pressable>
-                            )}
-                        </View>
-                    </View> */}
-                    {/* 
-                    <View
-                        className="my-4"
-                        style={{
-                            borderWidth: 1,
-                            borderColor: '#EEEEEE',
-                            borderRadius: 12
-                        }}
-                    >
-                        <View className="space-y-3   py-4 mx-[5%]">
-                            <View className="flex-1 flex-row items-center ">
-                                <View className="flex-1 flex-column">
-                                    <Text
-                                        style={styles.grayColor}
-                                        className="text-xs "
-                                    >
-                                        時間日期
-                                    </Text>
-                                    <Text
-                                        style={styles.greenColor}
-                                        className="text-4xl  pt-2 "
-                                    >
-                                        3月14 · 16:15
-                                    </Text>
-                                </View>
-                            </View>
-                            <View className="flex-1 flex-column justify-center">
-                                <Text
-                                    style={styles.grayColor}
-                                    className="text-xs"
-                                >
-                                    充電地點
-                                </Text>
-                                <Text
-                                    style={styles.greenColor}
-                                    className="text-xl"
-                                >
-                                    上環街市充電站
-                                </Text>
-                                <Text
-                                    style={styles.grayColor}
-                                    className="text-base"
-                                >
-                                    香港上環皇后大道中345號
-                                </Text>
-                            </View>
-                            <View className="flex-1 flex-row items-center ">
-                                <View className="flex-column flex-1">
-                                    <Text
-                                        style={styles.grayColor}
-                                        className="text-xs"
-                                    >
-                                        方案
-                                    </Text>
-                                    <Text
-                                        style={styles.greenColor}
-                                        className="text-lg"
-                                    >
-                                        按每度電結算
-                                    </Text>
-                                    <Text
-                                        style={styles.grayColor}
-                                        className="text-sm"
-                                    >
-                                        度數: 50kWh
-                                    </Text>
-                                </View>
-                                <View className="flex-column flex-1">
-                                    <Text
-                                        style={styles.grayColor}
-                                        className="text-xs"
-                                    >
-                                        車輛
-                                    </Text>
-                                    <Text
-                                        style={styles.greenColor}
-                                        className="text-lg"
-                                    >
-                                        TESLA Model 3
-                                    </Text>
-                                </View>
-                            </View>
-                        </View>
-                    </View> */}
-
                     <View>
-                        <Text className="text-xl py-4">收費概要</Text>
+                        <Text className="text-xl py-4">{t('payment_finish.fee_summary')}</Text>
                         <View className="flex-row justify-between">
-                            <Text className="text-base">充電費用</Text>
+                            <Text className="text-base">{t('payment_finish.charging_fee')}</Text>
                             <Text className="text-base">HK$ {paymentFee}</Text>
                         </View>
                         {chargingWatt === '' ? (
                             <Text style={styles.grayColor} className="text-base">
-                                充滿停機預估費用
+                                {t('payment_finish.estimated_full_charge')}
                             </Text>
                         ) : (
                             <Text style={styles.grayColor} className="text-base">
-                                按每度電結算: {chargingWatt.split('~')[0]}
+                                {t('payment_finish.settled_per_kwh')}{chargingWatt.split('~')[0]}
                             </Text>
                         )}
 
                         <View className="h-0.5 my-3 bg-[#f4f4f4]" />
                         <View className="flex-row justify-between ">
-                            <Text className="text-xl">總計</Text>
+                            <Text className="text-xl">{t('payment_finish.total')}</Text>
                             <Text className="text-xl">HK$ {paymentFee}</Text>
                         </View>
                         <View className="mt-4"></View>
@@ -295,34 +69,23 @@ const PaymentFinishPageComponent = () => {
 
                     <View className="w-full h-1 bg-[#DBE4E8]" />
                     <View className="space-y-4 my-4">
-                        <Text className="text-xl ">付款資訊</Text>
+                        <Text className="text-xl ">{t('payment_finish.payment_info')}</Text>
                         <View>
                             <Text className="text-base" style={styles.grayColor}>
-                                訂單編號
+                                {t('payment_finish.order_number')}
                             </Text>
                             <Text className="text-base">{formatOrderId}</Text>
                         </View>
                         <View>
                             <Text className="text-base" style={styles.grayColor}>
-                                付款方式
+                                {t('payment_finish.payment_method')}
                             </Text>
-                            <Text className="text-base">預付銀包</Text>
+                            <Text className="text-base">{t('payment_finish.prepaid_wallet')}</Text>
                         </View>
-                        {/* <View>
-                            <Text
-                                className="text-base"
-                                style={styles.grayColor}
-                            >
-                                電郵地址
-                            </Text>
-                            <Text className="text-base">
-                                mikechan123@.com
-                            </Text>
-                        </View> */}
                     </View>
 
                     <NormalButton
-                        title={<Text style={{ color: '#fff', fontSize: 18 }}>下一頁</Text>}
+                        title={<Text style={{ color: '#fff', fontSize: 18 }}>{t('common.nextPage')}</Text>}
                         onPress={() => {
                             // router.replace('bookingSuccessPage');
                             router.replace({
@@ -346,4 +109,4 @@ const styles = StyleSheet.create({
     greenColor: {
         color: '#02677D'
     }
-});
+});

+ 14 - 15
component/chargingPage/paymentSummaryPageComponent.tsx

@@ -1,3 +1,4 @@
+// component/chargingPage/paymentSummaryPageComponent.tsx
 import { View, Text, ScrollView, StyleSheet, Pressable } from 'react-native';
 import { SafeAreaView } from 'react-native-safe-area-context';
 import { Alert } from 'react-native';
@@ -11,8 +12,10 @@ import useCouponStore from '../../providers/coupon_store';
 import { walletService } from '../../service/walletService';
 import { parseISO, subHours, format } from 'date-fns';
 import { chargeStationService } from '../../service/chargeStationService';
+import { useTranslation } from '../../util/hooks/useTranslation';
 
 const PaymentSummaryPageComponent = () => {
+    const { t } = useTranslation();
     const selectedCouponName = useCouponStore((state) => state.selectedCouponName);
     const selectedCouponRedeemCode = useCouponStore((state) => state.selectedCouponRedeemCode);
     const selectedCouponPrice = useCouponStore((state) => state.selectedCouponPrice);
@@ -129,16 +132,13 @@ const PaymentSummaryPageComponent = () => {
                 is_ic_call
             );
             if (response.status === 200 || response.status === 201) {
-                console.log('submit payment successful');
-
-                // router.push('/paymentFinishPage');
                 router.push({
                     pathname: '/paymentFinishPage',
                     params: { formatOrderId: response.data.format_order_id }
                 });
             } else if (response.status === 400) {
                 console.log('400 error in paymentSummaryPageComponent');
-                Alert.alert('餘額不足', '您的餘額不足,請充值後再試。');
+                Alert.alert(t('payment_summary.insufficient_balance_title'), t('payment_summary.insufficient_balance_message'));
             } else {
                 console.log('submit payment failed:', response);
             }
@@ -151,10 +151,10 @@ const PaymentSummaryPageComponent = () => {
         <SafeAreaView className="flex-1 bg-white" edges={['top', 'left', 'right']}>
             <ScrollView className="flex-1 mx-[5%]" showsVerticalScrollIndicator={false}>
                 <View style={{ marginTop: 25 }}>
-                    <Text style={{ fontSize: 45, paddingBottom: 12 }}>付款概要</Text>
+                    <Text style={{ fontSize: 45, paddingBottom: 12 }}>{t('payment_summary.title')}</Text>
                     <View className="flex-column">
                         <Pressable onPress={() => router.push('selectCouponPage')}>
-                            <Text className="text-lg pb-4">優惠券</Text>
+                            <Text className="text-lg pb-4">{t('payment_summary.coupon')}</Text>
                             {selectedCouponName === '' ? (
                                 <View
                                     style={{
@@ -166,7 +166,7 @@ const PaymentSummaryPageComponent = () => {
                                     className="rounded-xl h-[9vh] items-center flex-row pl-6 justify-between"
                                 >
                                     <View className="flex-row items-center ">
-                                        <Text className="color-[#999999] px-4 text-base">選擇優惠券</Text>
+                                        <Text className="color-[#999999] px-4 text-base">{t('payment_summary.select_coupon')}</Text>
                                     </View>
                                     <View className="pr-4">
                                         <GrayRightArrowIconSvg />
@@ -187,26 +187,25 @@ const PaymentSummaryPageComponent = () => {
                     </View>
 
                     <View>
-                        <Text className="text-xl py-4">收費概要</Text>
+                        <Text className="text-xl py-4">{t('payment_summary.fee_summary')}</Text>
                         <View className="flex-row justify-between">
-                            <Text className="text-base">充電費用</Text>
+                            <Text className="text-base">{t('payment_summary.charging_fee')}</Text>
                             <Text className="text-base">HK ${finalFee}</Text>
                         </View>
 
                         {chargingWatt === '' ? (
                             <Text style={styles.grayColor} className="text-base">
-                                充滿停機預估費用
+                                {t('payment_summary.estimated_full_charge')}
                             </Text>
                         ) : (
                             <Text style={styles.grayColor} className="text-base">
-                                按每度電結算:
-                                {chargingWatt?.split('~')[0]}
+                                {t('payment_summary.settled_per_kwh')}{chargingWatt?.split('~')[0]}
                             </Text>
                         )}
 
                         <View className="h-0.5 my-3 bg-[#f4f4f4]" />
                         <View className="flex-row justify-between ">
-                            <Text className="text-xl">總計</Text>
+                            <Text className="text-xl">{t('payment_summary.total')}</Text>
                             <Text className="text-3xl">
                                 HK$
                                 {finalFee}
@@ -222,7 +221,7 @@ const PaymentSummaryPageComponent = () => {
                                             fontWeight: '800'
                                         }}
                                     >
-                                        前往付款
+                                        {t('payment_summary.proceed_to_payment')}
                                     </Text>
                                 }
                                 onPress={
@@ -249,4 +248,4 @@ const styles = StyleSheet.create({
     greenColor: {
         color: '#02677D'
     }
-});
+});

+ 0 - 2
component/global/bookingTabViewComponent.tsx

@@ -148,8 +148,6 @@ const BookingTabViewComponentInner: React.FC = () => {
     const futureReservations = processReservations(reservations, stations, true);
     const completedReservations = processReservations(reservations, stations, false);
     const allReservationItems = [...futureReservations, ...completedReservations];
-    // const allReservationItems = [...futureReservations];
-    console.log('All Reservation Items Processed:', allReservationItems);
     return (
         <TabViewComponent
             tabItems={allReservationItems}

+ 6 - 3
component/global/chargingRecord.tsx

@@ -116,7 +116,7 @@ const TabItem = ({ item, currentLocation }: { item: TabItem; currentLocation: Lo
         >
             <View style={styles.container}>
                 <Image style={styles.image} source={item.imgURL} />
-                <View className="flex flex-col flex-wrap gap-2 mr-2">
+                <View className="flex flex-col flex-wrap gap-1.5 mr-2">
                     <Text
                         style={{
                             fontWeight: '700',
@@ -144,6 +144,9 @@ const TabItem = ({ item, currentLocation }: { item: TabItem; currentLocation: Lo
                                     : item.actual_total_power.toFixed(1)
                                 : ''}
                         </Text>
+                    </View>
+                    <View className="flex flex-row flex-wrap justify-between">
+                    
                         <Text
                             style={{
                                 fontWeight: '400',
@@ -218,8 +221,8 @@ const styles = StyleSheet.create({
         alignItems: 'center'
     },
     image: {
-        width: 100,
-        height: 100,
+        width: 105,
+        height: 110,
         margin: 15,
         borderRadius: 10
     },

+ 42 - 35
component/global/couponTabView.tsx

@@ -1,5 +1,4 @@
-//the size of the TabView will follow its parent-container's size.
-
+// component/global/couponTabView.tsx
 import * as React from 'react';
 import {
     View,
@@ -22,6 +21,7 @@ import { useChargingStore } from '../../providers/scan_qr_payload_store';
 import { chargeStationService } from '../../service/chargeStationService';
 import { router } from 'expo-router';
 import axios from 'axios';
+import { useTranslation } from '../../util/hooks/useTranslation';
 
 export interface TabItem {
     imgURL: ImageSourcePropType;
@@ -45,6 +45,8 @@ const FirstRoute = ({
     loading: boolean;
     handleCouponClick: any;
 }) => {
+    const { t } = useTranslation();
+    
     return (
         <View className="flex-1">
             <ScrollView
@@ -65,7 +67,7 @@ const FirstRoute = ({
                                         coupon.is_consumed === false &&
                                         (coupon.expire_date === null || new Date(coupon.expire_date) > new Date())
                                 ).length === 0 ? (
-                                    <Text className="pl-4">暫時戶口沒有優惠券。</Text>
+                                    <Text className="pl-4">{t('selectCoupons.coupon.noCoupon')}</Text>
                                 ) : (
                                     coupons
                                         .filter(
@@ -103,32 +105,37 @@ const FirstRoute = ({
     );
 };
 
-const SecondRoute = ({ coupons }: { coupons: any }) => (
-    <ScrollView style={{ flex: 1, backgroundColor: 'white', marginTop: 14 }}>
-        <View className="flex-1 flex-col">
-            {coupons
-                .filter(
-                    (coupon: any) =>
-                        coupon.is_consumed === true ||
-                        (coupon.expire_date !== null && new Date(coupon.expire_date) < new Date())
-                )
-                .slice(0, 30)
-                .map((coupon: any, index: any) => (
-                    <IndividualCouponComponent
-                        key={`${coupon.id}-${index}`}
-                        title={coupon.coupon.name}
-                        price={coupon.coupon.amount}
-                        detail={coupon.coupon.description}
-                        date={formatCouponDate(coupon.expire_date)}
-                        setOpacity={true}
-                        noCircle={true}
-                    />
-                ))}
-        </View>
-    </ScrollView>
-);
+const SecondRoute = ({ coupons }: { coupons: any }) => {
+    const { t } = useTranslation();
+    
+    return (
+        <ScrollView style={{ flex: 1, backgroundColor: 'white', marginTop: 14 }}>
+            <View className="flex-1 flex-col">
+                {coupons
+                    .filter(
+                        (coupon: any) =>
+                            coupon.is_consumed === true ||
+                            (coupon.expire_date !== null && new Date(coupon.expire_date) < new Date())
+                    )
+                    .slice(0, 30)
+                    .map((coupon: any, index: any) => (
+                        <IndividualCouponComponent
+                            key={`${coupon.id}-${index}`}
+                            title={coupon.coupon.name}
+                            price={coupon.coupon.amount}
+                            detail={coupon.coupon.description}
+                            date={formatCouponDate(coupon.expire_date)}
+                            setOpacity={true}
+                            noCircle={true}
+                        />
+                    ))}
+            </View>
+        </ScrollView>
+    );
+};
 
 const CouponTabViewComponent: React.FC<TabViewComponentProps> = ({ titles }) => {
+    const { t } = useTranslation();
     const layout = useWindowDimensions();
     const [loading, setLoading] = useState(false);
     const [coupons, setCoupons] = useState([]);
@@ -173,9 +180,9 @@ const CouponTabViewComponent: React.FC<TabViewComponentProps> = ({ titles }) =>
                 // More specific error handling
                 if (axios.isAxiosError(error)) {
                     const errorMessage = error.response?.data?.message || 'Network error occurred';
-                    Alert.alert('Error', `Unable to fetch price: ${errorMessage}`, [
+                    Alert.alert(t('common.error'), `${t('selectCoupons.error_fetching_balance')}: ${errorMessage}`, [
                         {
-                            text: 'OK',
+                            text: t('common.ok'),
                             onPress: () => {
                                 cleanupData();
                                 router.push('/mainPage');
@@ -183,9 +190,9 @@ const CouponTabViewComponent: React.FC<TabViewComponentProps> = ({ titles }) =>
                         }
                     ]);
                 } else {
-                    Alert.alert('Error', 'An unexpected error occurred while fetching the price', [
+                    Alert.alert(t('common.error'), t('selectCoupons.error_fetching_balance'), [
                         {
-                            text: 'OK',
+                            text: t('common.ok'),
                             onPress: () => {
                                 cleanupData();
                                 router.push('/mainPage');
@@ -201,9 +208,9 @@ const CouponTabViewComponent: React.FC<TabViewComponentProps> = ({ titles }) =>
     const handleCouponClick = async (clickedCoupon: string) => {
         let temp_promotion_code = [...promotion_code];
         if (!current_price_store) {
-            Alert.alert('Error', 'Unable to fetch price', [
+            Alert.alert(t('common.error'), t('selectCoupons.error_fetching_balance'), [
                 {
-                    text: 'OK',
+                    text: t('common.ok'),
                     onPress: () => {
                         cleanupData();
                         router.push('/mainPage');
@@ -225,7 +232,7 @@ const CouponTabViewComponent: React.FC<TabViewComponentProps> = ({ titles }) =>
                     setCouponDetail([...coupon_detail, found_coupon]);
                     setPromotionCode([...promotion_code, clickedCoupon]);
                 } else {
-                    Alert.alert('不符合使用優惠券的條件', '請查看優惠卷的詳情,例如是否需要滿足最低消費金額。');
+                    Alert.alert(t('selectCoupons.coupon.invalid_condition_title'), t('selectCoupons.coupon.invalid_condition_message'));
                 }
             } catch (error) {
                 console.log(error);
@@ -318,4 +325,4 @@ const styles = StyleSheet.create({
         shadowOpacity: 0.25,
         shadowRadius: 3.84
     }
-});
+});

+ 3 - 3
component/registrationMultiStepForm/formComponent/formPages/loginPage.tsx

@@ -107,7 +107,7 @@ const LoginPage: React.FC<LoginPageProps> = ({ goToNextPage, goToForgetPassWordP
             className={`flex-1   ${screenHeight < 750 ? '' : 'space-y-8'}`}
         >
             <LanguageSwitcher></LanguageSwitcher>
-            <View className="flex-1 py-4">
+            <View className="flex-1 py-3">
                 <View className="items-center">
                     {/* <View className="flex-3 items-center  justify-end" style={{}}> */}
                     <Image
@@ -121,11 +121,11 @@ const LoginPage: React.FC<LoginPageProps> = ({ goToNextPage, goToForgetPassWordP
                 </View>
                 <View
                     style={{
-                        gap: 10
+                        gap: 8
                         // paddingBottom: Math.max(insets.bottom, 20)
                         // marginTop: screenHeight > 750 ? 40 : 0
                     }}
-                    className="mx-[5%] mt-4"
+                    className="mx-[5%] mt-3"
                 >
                     <Text className="text-lg text-center text-[#888888] font-[500]">
                         {t('login.tip1')}<Text className="font-bold"> {t('login.tip2')} </Text>{t('login.tip3')}

+ 191 - 2
i18n/locales/en/translation.json

@@ -137,7 +137,17 @@
     "confirm": "Confirm",
     "cancel": "Cancel",
     "title": "",
-    "agree": "Agree and continue"
+    "agree": "Agree and Continue",
+    "use_now": "Use Now",
+    "permanent": "Permanent",
+    "to_date": "to {{date}}",
+    "error": "Error",
+    "ok": "OK",
+    "loading": "Loading...",
+    "processing": "Processing...",
+    "please_wait": "Please wait...",
+    "nextPage": "Next Page",
+    "calculating": "Calculating..."
   },
   "home": {
     "vehicle_info_error_title": "Unable to detect vehicle information",
@@ -228,7 +238,8 @@
     },
     "coupon": {
       "valid_until": "Valid until",
-      "noCoupon": "There are currently no coupons available for household registration."
+      "noCoupon": "There are currently no coupons available for household registration.",
+      "cash_voucher": "Cash Voucher"
     },
     "error_fetching_coupons": "Error fetching coupons:",
     "payment_timeout_title": "Payment Timeout",
@@ -254,6 +265,29 @@
       "used_expired": "Used/Expired"
     }
   },
+  "selectCoupons": {
+    "coupons": {
+      "title": "Coupons",
+      "available": "Available Coupons",
+      "used_expired": "Used/Expired",
+      "valid_until": "Valid until",
+      "cash_voucher": "Cash Voucher"
+    },
+    "coupon_details": "Coupon Details",
+    "coupon": {
+      "terms_and_conditions": "Terms and Conditions",
+      "term1": "・ The holder of this coupon can exchange it for an equivalent value of charging service at any Crazy Charge store in Hong Kong within its validity period. Expired coupons are invalid.",
+      "term2": "・ When using this coupon, the electricity fee will be calculated at the regular price of $3.5 per kWh, and it is not applicable to owl-hour periods or other discounted electricity pricing periods.",
+      "term3": "・ This coupon cannot be exchanged for cash or other denominations of cash vouchers. The holder is not entitled to cash or other forms of change.",
+      "term4": "・ Once a user confirms the use of an electronic coupon within this app, it is deemed that they agree to consume the discount according to the coupon rules. The relevant coupon will be immediately deducted from the account and cannot be refunded after deduction.",
+      "term5": "・ Even if the actual charging consumption amount does not reach the face value of the electronic coupon, no refund will be made for the difference. The use of coupons is intended to provide users with charging discounts, not as a cash exchange or refund tool.",
+      "term6": "・ In case of any dispute, Crazy Charge reserves the right to change the terms and conditions regarding the use of this cash voucher without prior notice.",
+      "noCoupon": "No coupons available at the moment.",
+      "invalid_condition_title": "Coupon usage conditions not met",
+      "invalid_condition_message": "Please check the coupon details, such as minimum spending requirements."
+    },
+    "error_fetching_balance": "Error fetching wallet balance"
+  },
   "payment_record": {
     "title": "Payment Records",
     "balance_label": "Balance (HKD)",
@@ -319,6 +353,157 @@
       "others": "Others"
     }
   },
+  "chargingOption": {
+    "option": {
+      "select_charge_amount": "Select Charging Amount",
+      "kwh_20": "20kWh",
+      "kwh_25": "25kWh",
+      "kwh_30": "30kWh",
+      "kwh_40": "40kWh",
+      "full_charge": "Full Charge",
+      "min_25": "25 mins",
+      "min_30": "30 mins",
+      "min_40": "40 mins",
+      "min_45": "45 mins",
+      "up_to_80kwh": "Up to 80kWh",
+      "coupon_value": "$ {{value}} off",
+      "available_coupon": "Coupons Available",
+      "no_coupon": "No Coupons",
+      "alert": {
+        "select_plan_title": "Select Charging Plan",
+        "select_plan_message": "Please select a charging plan before choosing coupons",
+        "confirm_plan_message": "Please select a charging plan before confirming",
+        "reminder_title": "Reminder",
+        "reminder_message": "Transactions using coupons will be calculated at the regular price of $3.5 per kWh!"
+      }
+    }
+
+  },
+  "payment": {
+    "summary_title": "Payment Summary",
+    "charging_fee": "Charging Fee",
+    "settled_kwh": "Settled kWh",
+    "full_charge": "Full Charge",
+    "price_per_kwh": "Price per kWh",
+    "note": "Note: Cross-period charging will be charged separately based on unit prices of different periods, and the actual charging amount may fluctuate",
+    "coupon": "Coupons",
+    "total": "Total",
+    "confirm_payment": "Confirm Payment",
+    "wait_loading_price": "Still loading price information...",
+    "failed_fetch_udcc": "Failed to fetch UDCC, please try again later",
+    "failed_fetch_udc": "Failed to fetch UDC, please try again later",
+    "failed_fetch_userid": "Failed to fetch userID, please try again later",
+    "failed_fetch_wallet": "Failed to fetch user wallet, please try again later",
+    "failed_fetch_reservations": "Failed to fetch reservation histories for penalty checking purpose",
+    "failed_fetch_totalprice": "Unable to fetch totalPrice",
+    "unknown_error": "Unknown error",
+    "back_main": "Back to Main Page",
+    "failed_fetch_outtrade": "Failed to fetch outTradeNo",
+    "insufficient_balance_redirect": "Detected insufficient wallet balance, redirecting to top-up page now"
+  },
+  "payment_summary": {
+    "title": "Payment Summary",
+    "coupon": "Coupons",
+    "select_coupon": "Select Coupon",
+    "fee_summary": "Fee Summary",
+    "charging_fee": "Charging Fee",
+    "estimated_full_charge": "Estimated Full Charge Fee",
+    "settled_per_kwh": "Settled per kWh: ",
+    "total": "Total",
+    "proceed_to_payment": "Proceed to Payment",
+    "insufficient_balance_title": "Insufficient Balance",
+    "insufficient_balance_message": "Your balance is insufficient. Please top up and try again."
+  },
+  "payment_finish": {
+    "success_title": "Payment Successful",
+    "fee_summary": "Fee Summary",
+    "charging_fee": "Charging Fee",
+    "estimated_full_charge": "Estimated Full Charge Fee",
+    "settled_per_kwh": "Settled per kWh: ",
+    "total": "Total",
+    "payment_info": "Payment Information",
+    "order_number": "Order Number",
+    "payment_method": "Payment Method",
+    "prepaid_wallet": "Prepaid Wallet"
+  },
+  "charging_penalty": {
+    "idling": "Idling...",
+    "remaining_idling_time": "Remaining Idling Time:",
+    "confirm_charging": "Please confirm charging completion below to avoid penalty time",
+    "in_penalty": "In Penalty",
+    "penalty_duration": "Penalty Duration",
+    "accumulated": "Accumulated",
+    "unlock_charger": "Please confirm charging completion below to unlock",
+    "not_finished": "Charging Not Finished",
+    "charging_completed": "Charging Completed",
+    "charged": "Charged",
+    "charging_duration": "Charging Duration",
+    "finish_charging": "Finish Charging",
+    "view_idling_status": "View Idling Status Page"
+  },
+  "chargingInfo": {
+    "currently_charging": "Currently Charging:",
+    "charging": "Charging",
+    "actual_charged_kwh": "Actual Charged kWh",
+    "actual_power_kw": "Actual Power (kW)",
+    "see_charger_display": "See charging display screen",
+    "charging_duration": "Charging Duration",
+    "other_info": "Other Information",
+    "start_time": "Start Time",
+    "charger": "Charger",
+    "charger_number": "No. {{number}}",
+    "return_home": "Return to Home",
+    "view_penalty_status": "View Idling/Penalty Status Page"
+  },
+  "charging_hurry_up": {
+    "full_charge": "Full Charge",
+    "per_kwh": "Per kWh",
+    "start_success_title": "Start Successful",
+    "start_success_message": "Please wait for the page to automatically redirect to the charging interface",
+    "start_failed": "Start Failed",
+    "try_again_later": "Please try again later",
+    "reservation_started": "Reservation Has Started",
+    "arrive_and_start": "After arriving at the charging station, press the button below to start charging.",
+    "your_reservation": "Your Reservation:",
+    "date": "Date",
+    "month": "Month",
+    "time": "Time",
+    "charging_location": "Charging Location",
+    "plan": "Plan",
+    "vehicle": "Vehicle",
+    "start_charging": "Activate Charging Station - Start Charging",
+    "return_home": "Return to Home",
+    "starting_charging": "Starting Charging..."
+  },
+  "future_reservation": {
+    "no_charging_vehicle": "No Charging Vehicle",
+    "next_reservation": "Your Next Reservation:",
+    "date": "Date",
+    "month": "Month",
+    "time": "Time",
+    "charging_location": "Charging Location",
+    "plan": "Plan",
+    "full_charge": "Full Charge",
+    "per_kwh": "Per kWh",
+    "return_home": "Return to Home"
+  },
+  "charging_finish": {
+    "charging_completed": "Charging Completed",
+    "charged": "Charged",
+    "charging_duration": "Charging Duration",
+    "minutes": "mins",
+    "fee_summary": "Fee Summary",
+    "charging_fee": "Charging Fee",
+    "full_charge": "Full Charge",
+    "settled_per_kwh": "Settled per kWh: ",
+    "refund_deposit": "Refund Deposit",
+    "total": "Total",
+    "payment_info": "Payment Information",
+    "order_number": "Order Number",
+    "payment_method": "Payment Method",
+    "prepaid_wallet": "Prepaid Wallet",
+    "return_home": "Return to Home"
+  },
   "account": {
     "wallet": "Wallet",
     "my_vehicle": "My Vehicle",
@@ -440,6 +625,10 @@
       "changing": "Changing..."
     }
   },
+  "assistance": {
+    "troubleshooting": "Troubleshooting",
+    "description": "If you encounter any problems while using the app, please contact our customer service via WhatsApp:"
+  },
   "auth": {
     "email": "Email",
     "password": "Password",

+ 190 - 2
i18n/locales/zh-TW/translation.json

@@ -135,7 +135,17 @@
     "confirm": "確認",
     "cancel": "取消",
     "title": "",
-    "agree": "同意並繼續"
+    "agree": "同意並繼續",
+    "use_now": "馬上使用",
+    "permanent": "永久",
+    "to_date": "至 {{date}}",
+    "error": "錯誤",
+    "ok": "確定",
+    "loading": "載入中...",
+    "processing": "處理中...",
+    "please_wait": "請稍候...",
+    "nextPage": "下一頁",
+    "calculating": "計算中..."
   },
   "home": {
     "vehicle_info_error_title": "無法檢測車輛資訊",
@@ -226,7 +236,8 @@
     },
     "coupon": {
       "valid_until": "有效期至",
-      "noCoupon": "暫時戶口沒有優惠券。"
+      "noCoupon": "暫時戶口沒有優惠券。",
+      "cash_voucher": "現金劵"
     },
     "error_fetching_coupons": "Error fetching coupons:",
     "payment_timeout_title": "Payment Timeout",
@@ -252,6 +263,29 @@
       "used_expired": "已使用/失效"
     }
   },
+  "selectCoupons": {
+    "coupons": {
+      "title": "優惠券",
+      "available": "可用優惠券",
+      "used_expired": "已使用/失效",
+      "valid_until": "有效期",
+      "cash_voucher": "現金劵"
+    },
+    "coupon_details": "優惠券細節",
+    "coupon": {
+      "terms_and_conditions": "服務條款與細則",
+      "term1": "・ 此券持有人可在本券有效期內於任何位於Crazy Charge 之香港分店換取同等價值充電服務,逾期無效。",
+      "term2": "・ 此優惠券使用時,電費將以正常價格$3.5元/每度電計算,不適用於貓頭鷹時段或其他折扣時段的電力價格計算。",
+      "term3": "・ 此券不能用以套换現金或其他面值之現金券,持有人不獲現金或其他形式之找贖。",
+      "term4": "・ 使用者一旦在本 APP 內確認使用電子優惠券,即視為同意依優惠券規則進行消費抵扣,相關優惠券將立即從帳戶中扣除,且扣除後不得退還。",
+      "term5": "・ 即便實際充電消費金額未達到電子優惠券的面額,亦不會就差額部分進行退款。優惠券的使用旨在為用戶提供充電優惠,而非現金兌換或退款工具。",
+      "term6": "・ 如有任何爭議,Crazy Charge 保留更改有關使用此現金券之條款及細則,而毋須另行通知。",
+      "noCoupon": "暫時戶口沒有優惠券。",
+      "invalid_condition_title": "不符合使用優惠券的條件",
+      "invalid_condition_message": "請查看優惠卷的詳情,例如是否需要滿足最低消費金額。"
+    },
+     "error_fetching_balance": "獲取錢包餘額時出錯"
+  },
   "payment_record": {
     "title": "訂單記錄",
     "balance_label": "餘額 (HKD)",
@@ -317,6 +351,156 @@
       "others": "其他"
     }
   },
+  "chargingOption": {
+    "option": {
+      "select_charge_amount": "選擇充電度數",
+      "kwh_20": "20度電",
+      "kwh_25": "25度電",
+      "kwh_30": "30度電",
+      "kwh_40": "40度電",
+      "full_charge": "充滿停機",
+      "min_25": "25分鐘",
+      "min_30": "30分鐘",
+      "min_40": "40分鐘",
+      "min_45": "45分鐘",
+      "up_to_80kwh": "最多80度電",
+      "coupon_value": "$ {{value}}劵",
+      "available_coupon": "有可用劵",
+      "no_coupon": "無可用劵",
+      "alert": {
+        "select_plan_title": "選擇充電方案",
+        "select_plan_message": "請先選擇充電方案再選擇優惠券",
+        "confirm_plan_message": "請先選擇充電方案再確認",
+        "reminder_title": "提醒您",
+        "reminder_message": "使用優惠券的交易每度電以正價$3.5元計算!"
+      }
+    }
+  },
+  "payment": {
+    "summary_title": "付款概要",
+    "charging_fee": "充電費用",
+    "settled_kwh": "結算電度數",
+    "full_charge": "充滿停機",
+    "price_per_kwh": "每度電價錢",
+    "note": "注: 跨時段充電將按不同時段的單價分別計费,實際充電量可能浮動",
+    "coupon": "優惠劵",
+    "total": "總計",
+    "confirm_payment": "付款確認",
+    "wait_loading_price": "仍在加載價格信息...",
+    "failed_fetch_udcc": "無法獲取UDCC,請稍後再試",
+    "failed_fetch_udc": "無法獲取UDC,請稍後再試",
+    "failed_fetch_userid": "無法獲取用戶ID,請稍後再試",
+    "failed_fetch_wallet": "無法獲取用戶錢包,請稍後再試",
+    "failed_fetch_reservations": "無法獲取預訂歷史記錄以進行罰款檢查",
+    "failed_fetch_totalprice": "無法獲取總價格",
+    "unknown_error": "未知錯誤",
+    "back_main": "返回主頁",
+    "failed_fetch_outtrade": "無法獲取outTradeNo",
+    "insufficient_balance_redirect": "偵測到您錢包餘額不足,現在為您跳轉到充值頁面"
+  },
+  "payment_summary": {
+    "title": "付款概要",
+    "coupon": "優惠券",
+    "select_coupon": "選擇優惠券",
+    "fee_summary": "收費概要",
+    "charging_fee": "充電費用",
+    "estimated_full_charge": "充滿停機預估費用",
+    "settled_per_kwh": "按每度電結算:",
+    "total": "總計",
+    "proceed_to_payment": "前往付款",
+    "insufficient_balance_title": "餘額不足",
+    "insufficient_balance_message": "您的餘額不足,請充值後再試。"
+  },
+  "payment_finish": {
+    "success_title": "成功付款",
+    "fee_summary": "收費概要",
+    "charging_fee": "充電費用",
+    "estimated_full_charge": "充滿停機預估費用",
+    "settled_per_kwh": "按每度電結算: ",
+    "total": "總計",
+    "payment_info": "付款資訊",
+    "order_number": "訂單編號",
+    "payment_method": "付款方式",
+    "prepaid_wallet": "預付銀包"
+  },
+  "charging_penalty": {
+    "idling": "待機中..",
+    "remaining_idling_time": "剩餘待機時間:",
+    "confirm_charging": "請於下方確認完成充電以免進入罰款時間",
+    "in_penalty": "罰款中",
+    "penalty_duration": "罰款時間歷時",
+    "accumulated": "累積",
+    "unlock_charger": "請於下方確認完成充電以解鎖",
+    "not_finished": "尚未結束充電",
+    "charging_completed": "已完成充電",
+    "charged": "已充電",
+    "charging_duration": "充電歷時",
+    "finish_charging": "完成充電",
+    "view_idling_status": "觀看閒置狀態頁面"
+  },
+  "chargingInfo": {
+    "currently_charging": "現正充電中:",
+    "charging": "充電中",
+    "actual_charged_kwh": "實際充電量(度數)",
+    "actual_power_kw": "實際功率 (kW)",
+    "see_charger_display": "請見充電顯示螢幕",
+    "charging_duration": "充電歷時",
+    "other_info": "其他資訊",
+    "start_time": "開始時間",
+    "charger": "充電座",
+    "charger_number": "{{number}}號",
+    "return_home": "返回主頁",
+    "view_penalty_status": "觀看閒置/罰款狀態頁面"
+  },
+  "charging_hurry_up": {
+    "full_charge": "充滿停機",
+    "per_kwh": "按每度電結算",
+    "start_success_title": "啟動成功",
+    "start_success_message": "請稍後等待頁面自動跳轉至充電介面",
+    "start_failed": "啟動失敗",
+    "try_again_later": "請稍後再試",
+    "reservation_started": "預約已經開始",
+    "arrive_and_start": "到達充電站後,按下方按鈕開始充電。",
+    "your_reservation": "你的預約為:",
+    "date": "日期",
+    "month": "月",
+    "time": "時間",
+    "charging_location": "充電地點",
+    "plan": "方案",
+    "vehicle": "車輛",
+    "start_charging": "發動充電樁 - 開始充電",
+    "return_home": "返回主頁",
+    "starting_charging": "正在啟動充電..."
+  },
+  "future_reservation": {
+    "no_charging_vehicle": "暫無充電車輛",
+    "next_reservation": "你的下一次預約為:",
+    "date": "日期",
+    "month": "月",
+    "time": "時間",
+    "charging_location": "充電地點",
+    "plan": "方案",
+    "full_charge": "充滿停機",
+    "per_kwh": "按每度電結算",
+    "return_home": "返回主頁"
+  },
+  "charging_finish": {
+    "charging_completed": "完成充電",
+    "charged": "已充電",
+    "charging_duration": "充電歷時",
+    "minutes": "分鐘",
+    "fee_summary": "收費概要",
+    "charging_fee": "充電費用",
+    "full_charge": "充滿停機",
+    "settled_per_kwh": "按每度電結算: ",
+    "refund_deposit": "退還充電按金",
+    "total": "總計",
+    "payment_info": "付款資訊",
+    "order_number": "訂單編號",
+    "payment_method": "付款方式",
+    "prepaid_wallet": "預付銀包",
+    "return_home": "返回主頁"
+  },
   "account": {
     "wallet": "錢包",
     "my_vehicle": "我的車輛",
@@ -438,6 +622,10 @@
       "changing": "更改中..."
     }
   },
+  "assistance": {
+    "troubleshooting": "排除解難",
+    "description": "如果您在使用該應用程式時遇到任何問題,請透過WhatsApp聯絡我們的客戶服務人員:"
+  },
   "auth": {
     "email": "邮箱",
     "password": "密码",