import { CameraView, useCameraPermissions } from 'expo-camera';
import { useEffect, useRef, useState } from 'react';
import {
ActivityIndicator,
Alert,
AppState,
Dimensions,
Linking,
Pressable,
ScrollView,
StyleSheet,
Text,
Vibration,
View
} from 'react-native';
import sha256 from 'crypto-js/sha256';
import ChooseCarForChargingRow from '../../../../component/global/chooseCarForChargingRow';
import { CrossLogoWhiteSvg, QuestionSvg } from '../../../../component/global/SVG';
import { router } from 'expo-router';
import { chargeStationService } from '../../../../service/chargeStationService';
import { authenticationService } from '../../../../service/authService';
import { walletService } from '../../../../service/walletService';
import useUserInfoStore from '../../../../providers/userinfo_store';
import Modal from 'react-native-modal';
import NormalButton from '../../../../component/global/normal_button';
import { ceil } from 'lodash';
import AsyncStorage from '@react-native-async-storage/async-storage';
const { width: screenWidth, height: screenHeight } = Dimensions.get('window');
// const ChooseCar = ({ carData, loading, selectedCar, setSelectedCar }) => {
// const isLargeScreen = screenHeight >= 800;
// const defaultImageUrl = require('../../../../assets/car1.png');
// return (
//
//
//
// {loading ? (
//
//
//
// ) : (
//
//
// {
// if (router.canGoBack()) {
// router.back();
// } else {
// router.replace('mainPage');
// }
// }}
// >
//
//
// 選擇充電車輛
//
//
//
// {carData.map((car, index) => (
// {
// setSelectedCar(car.id);
// console.log(car.id);
// }}
// isSelected={selectedCar === car.id}
// // imageUrl={image}
// VehicleName={car.name}
// isDefault={car.isDefault}
// />
// ))}
//
//
// )}
//
//
//
// );
// };
//reminder: scan qr code page, ic call should be false
const ScanQrPage = () => {
const { userID, currentPrice, setCurrentPrice } = useUserInfoStore();
const [currentPriceFetchedWhenScanQr, setCurrentPriceFetchedWhenScanQr] = useState(0);
const { width: screenWidth, height: screenHeight } = Dimensions.get('window');
const [permission, requestPermission] = useCameraPermissions();
const [scanned, setScanned] = useState(false);
const viewRef = useRef(null);
const [scannedResult, setScannedResult] = useState('');
const [selectedCar, setSelectedCar] = useState('');
const now = new Date();
const [loading, setLoading] = useState(true);
const [loading2, setLoading2] = useState(false);
const [loading3, setLoading3] = useState(false);
const [carData, setCarData] = useState([]);
const [isModalVisible, setModalVisible] = useState(false);
const [isConfirmLoading, setIsConfirmLoading] = useState(false);
const [availableSlots, setAvailableSlots] = useState({
// 3: false,
25: false,
30: false,
40: false,
45: false,
full: false
});
const [selectedDuration, setSelectedDuration] = useState(null);
const appState = useRef(AppState.currentState);
const [paymentStatus, setPaymentStatus] = useState(null);
const [isExpectingPayment, setIsExpectingPayment] = useState(false);
const paymentInitiatedTime = useRef(null);
const PAYMENT_CHECK_TIMEOUT = 5 * 60 * 1000; // 5 minutes in milliseconds
const [outTradeNo, setOutTradeNo] = useState('');
const [totalFee, setTotalFee] = useState(0);
const [walletBalance, setWalletBalance] = useState(0);
// Effect for requesting camera permissions
useEffect(() => {
(async () => {
const { status } = await requestPermission();
if (status !== 'granted') {
alert(
'我們需要相機權限來掃描機器上的二維碼,以便識別並啟動充電機器。我們不會儲存或共享任何掃描到的資訊。 請前往設定開啟相機權限'
);
}
})();
}, []);
// Effect for fetching user's cars
// useEffect(() => {
// const fetchAllCars = async () => {
// try {
// const response = await chargeStationService.getUserCars();
// if (response) {
// console.log('data', response.data);
// const carTypes = response.data.map((item: any) => ({
// id: item.id,
// name: item.car_typ e.name,
// image: item.car_type.type_image_url
// }));
// // console.log('carTypes', carTypes);
// // console.log('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', carTypes);
// let updatedCarTypes = [...carTypes];
// for (let i = 0; i < carTypes.length; i++) {
// const car = updatedCarTypes[i];
// const imageUrl = await chargeStationService.getProcessedImageUrl(car.image);
// updatedCarTypes[i] = {
// ...car,
// image: imageUrl
// };
// }
// setCarData(updatedCarTypes);
// // console.log('updatedCarTypes', updatedCarTypes);
// return true;
// }
// } catch (error) {
// console.log(error);
// } finally {
// setLoading(false);
// }
// };
// fetchAllCars();
// }, []);
useEffect(() => {
const fetchDefaultCar = async () => {
try {
const response = await chargeStationService.getUserDefaultCars();
if (response) {
// console.log('default car', response.data.id);
setSelectedCar(response.data.id);
}
} catch (error) {
console.log(error);
} finally {
setLoading(false);
}
};
fetchDefaultCar();
}, []);
//check current wallet
useEffect(() => {
const getWalletBalance = async () => {
try {
const response = await walletService.getWalletBalance();
if (response) {
// console.log('walletBalance setting up', response);
setWalletBalance(response);
}
} catch (error) {
console.log(error);
}
};
getWalletBalance();
}, []);
const fetchCurrentPrice = async () => {
try {
const response = await chargeStationService.getCurrentPrice();
if (response) {
setCurrentPriceFetchedWhenScanQr(response);
setCurrentPrice(response);
return response;
}
} catch (error) {
console.error('Error fetching current price:', error);
Alert.alert('錯誤', '無法獲取當前價格,請稍後再試');
return null;
}
};
const planMap = {
// 3: { duration: 10, kWh: 3, displayDuration: 5, fee: 3 * currentPrice },
25: { duration: 40, kWh: 20, displayDuration: 25, fee: 20 * currentPrice },
30: { duration: 45, kWh: 25, displayDuration: 30, fee: 25 * currentPrice },
40: { duration: 55, kWh: 30, displayDuration: 40, fee: 30 * currentPrice },
45: { duration: 60, kWh: 40, displayDuration: 45, fee: 40 * currentPrice },
full: { duration: 120, displayDuration: '充滿停機', fee: 80 * currentPrice }
};
// Function to handle barcode scanning
const handleBarCodeScanned = async ({ bounds, data, type }: { bounds?: any; data: any; type: any }) => {
if (
!bounds ||
typeof bounds.origin?.x !== 'number' ||
typeof bounds.origin?.y !== 'number' ||
typeof bounds.size?.width !== 'number' ||
typeof bounds.size?.height !== 'number'
) {
// console.log('Invalid or missing bounds data:', bounds);
// Proceed with scanning logic without bounds checking
setScanned(true);
setScannedResult(data);
Vibration.vibrate(100);
// console.log(`type: ${type} data: ${data} typeofData ${typeof data}`);
try {
const price = await fetchCurrentPrice();
console.log('fetchedCurrentPrice in scanQrPage', price);
if (!price) {
return; // Exit if price fetch failed
}
const response = await chargeStationService.getTodayReservation();
if (response) {
const now = new Date();
const onlyThisConnector = response.filter(
(reservation: any) => reservation.connector.ConnectorID === data
);
// Check availability for each duration```````````````````````````````````````````````````````````````````
const availability = {
// 3: checkAvailability(onlyThisConnector, now, 10) && walletBalance >= 3 * price,
25: checkAvailability(onlyThisConnector, now, 40) && walletBalance >= 20 * price,
30: checkAvailability(onlyThisConnector, now, 45) && walletBalance >= 25 * price,
40: checkAvailability(onlyThisConnector, now, 55) && walletBalance >= 30 * price,
45: checkAvailability(onlyThisConnector, now, 60) && walletBalance >= 40 * price,
full: checkAvailability(onlyThisConnector, now, 120) && walletBalance >= 80 * price
};
setAvailableSlots(availability);
setModalVisible(true);
} else {
Alert.alert('系統錯誤', '無法獲取預約信息。請稍後再試。');
}
} catch (error) {
console.error("Error fetching today's reservations:", error);
Alert.alert('系統錯誤', '發生未知錯誤。請稍後再試。');
}
setTimeout(() => {
setScanned(false);
}, 2000);
return;
}
// -----------------------------------------------------------------------------------------------------
const { origin, size } = bounds;
// Calculate the size of the square transparent area
const transparentAreaSize = Math.min(screenWidth * 0.6, screenHeight * 0.3);
const transparentAreaX = (screenWidth - transparentAreaSize) / 2;
const transparentAreaY = (screenHeight - transparentAreaSize) / 2;
// Check if the barcode is within the transparent area
if (
origin.x >= transparentAreaX &&
origin.y >= transparentAreaY &&
origin.x + size.width <= transparentAreaX + transparentAreaSize &&
origin.y + size.height <= transparentAreaY + transparentAreaSize
) {
setScanned(true);
setScannedResult(data);
Vibration.vibrate(100);
// console.log(` type: ${type} data: ${data} typeofData ${typeof data}`);
try {
const price = await fetchCurrentPrice();
console.log('fetchedCurrentPrice in scanQrPage', price);
if (!price) {
return; // Exit if price fetch failed
}
const response = await chargeStationService.getTodayReservation();
if (response) {
const now = new Date();
const onlyThisConnector = response.filter(
(reservation: any) => reservation.connector.ConnectorID === data
);
console.log('onlyThisConnector', onlyThisConnector);
// Check availability for each duration
const availability = {
// 3: checkAvailability(onlyThisConnector, now, 10) && walletBalance >= 3 * price,
25: checkAvailability(onlyThisConnector, now, 40) && walletBalance >= 20 * price,
30: checkAvailability(onlyThisConnector, now, 45) && walletBalance >= 25 * price,
40: checkAvailability(onlyThisConnector, now, 55) && walletBalance >= 30 * price,
45: checkAvailability(onlyThisConnector, now, 60) && walletBalance >= 40 * price,
full: checkAvailability(onlyThisConnector, now, 120) && walletBalance >= 80 * price
};
// console.log('availability', availability);
// console.log('walletBalance', walletBalance);
// console.log('currentPricecurrentPricecurrentPricecurrentPricecurrentPrice', currentPrice);
setAvailableSlots(availability);
setModalVisible(true);
} else {
Alert.alert('系統錯誤', '無法獲取預約信息。請稍後再試。');
}
} catch (error) {
console.error("Error fetching today's reservations:", error);
Alert.alert('系統錯誤', '發生未知錯誤。請稍後再試。');
}
setTimeout(() => {
setScanned(false);
}, 2000);
}
};
const checkAvailability = (reservations, startTime, duration) => {
const endTime = new Date(startTime.getTime() + duration * 60000);
// console.log('now', startTime);
// console.log('endTime', endTime);
// console.log('reservations', reservations);
return !reservations.some((reservation) => {
// Ignore reservations with status '9' (cancelled)
if (reservation.status.id === '9' || reservation.status.id === '13') {
return false;
}
// For status '8' (early finished), check actual_end_time
if (reservation.status.id === '8' && reservation.actual_end_time) {
const actualEndTime = new Date(reservation.actual_end_time);
if (actualEndTime <= startTime) {
return false; // Treat as available if actual end time is before or at start time
}
}
const resStart = new Date(reservation.book_time);
const resEnd = new Date(reservation.end_time);
return startTime < resEnd && endTime > resStart;
});
};
const handleDurationSelect = (duration) => {
setSelectedDuration(duration);
// console.log(duration);
};
const handleCancel = () => {
setSelectedDuration(null);
setModalVisible(false);
if (router.canGoBack()) {
router.back();
} else {
router.push('/mainPage');
}
};
const handleConfirm = () => {
if (selectedDuration !== null) {
const now = new Date();
let endTime;
let fee;
let totalPower;
//i create a planMap2 because i want to move the planMap inside this component but i dont wanna move the outside one because i dont wanna make any potential disruptive changes
const planMap2 = {
// 3: { duration: 10, kWh: 3, displayDuration: 5, fee: 3 * currentPriceFetchedWhenScanQr },
25: { duration: 40, kWh: 20, displayDuration: 25, fee: 20 * currentPriceFetchedWhenScanQr },
30: { duration: 45, kWh: 25, displayDuration: 30, fee: 25 * currentPriceFetchedWhenScanQr },
40: { duration: 55, kWh: 30, displayDuration: 40, fee: 30 * currentPriceFetchedWhenScanQr },
45: { duration: 60, kWh: 40, displayDuration: 45, fee: 40 * currentPriceFetchedWhenScanQr },
full: { duration: 120, displayDuration: '充滿停機', fee: 80 * currentPriceFetchedWhenScanQr }
};
if (selectedDuration === 'full') {
endTime = new Date(now.getTime() + 2 * 60 * 60 * 1000); // 2 hours for "充滿停機"
fee = planMap2.full.fee;
totalPower = 80; // Set to 130 for "充滿停機"
} else {
const durationInMinutes = parseInt(selectedDuration);
endTime = new Date(now.getTime() + durationInMinutes * 60 * 1000);
// console.log('endTime', endTime);
fee = planMap2[selectedDuration].fee;
totalPower = planMap2[selectedDuration].kWh;
}
setTotalFee(fee);
console.log('fee in scanQrPage-- this is the total_fee i send to backend', fee);
const dataForSubmission = {
stationID: '2405311022116801000',
connector: scannedResult,
user: userID,
book_time: now,
end_time: endTime,
total_power: totalPower,
total_fee: fee,
// total_fee: 1,
promotion_code: '',
car: selectedCar,
type: 'walking',
is_ic_call: false
};
startCharging(dataForSubmission);
setIsConfirmLoading(true);
}
};
//below commented is the original WORKING startCharging, if i fucked up, return back to using this!!!
// const startCharging = async (dataForSubmission) => {
// try {
// const wallet = await walletService.getWalletBalance();
// console.log('wallet in startCharging in scanQrPage', wallet);
// const response = await walletService.submitPayment(
// dataForSubmission.stationID,
// dataForSubmission.connector,
// dataForSubmission.user,
// dataForSubmission.book_time,
// dataForSubmission.end_time,
// dataForSubmission.total_power,
// dataForSubmission.total_fee,
// dataForSubmission.promotion_code,
// dataForSubmission.car,
// dataForSubmission.type,
// dataForSubmission.is_ic_call
// );
// if (response.status === 200 || response.status === 201) {
// setSelectedDuration(null);
// console.log('Charging started from startCharging', response);
// setIsConfirmLoading(false);
// // Set a flag in AsyncStorage to indicate charging has started
// await AsyncStorage.setItem('chargingStarted', 'true');
// Alert.alert('啟動成功', '請稍後等待頁面自動跳轉至充電介面', [
// {
// text: 'OK',
// onPress: async () => {
// setModalVisible(false);
// setLoading(true);
// // Wait for 2 seconds
// await new Promise((resolve) => setTimeout(resolve, 2000));
// // Hide loading spinner and navigate
// setLoading(false);
// router.push('(auth)/(tabs)/(charging)/chargingPage');
// }
// }
// ]);
// // Start the navigation attempt loop
// // startNavigationAttempts();
// } else if (response.status === 400) {
// console.log('400 error in paymentSummaryPageComponent');
// Alert.alert('餘額不足', '您的餘額不足,請充值後再試。');
// } else {
// console.log('Failed to start charging:', response);
// Alert.alert('掃描失敗 請稍後再試。', response);
// }
// } catch (error) {
// console.log('Failed to start chasssssssrging:', error);
// }
// };
//below is the new flow for startCharging.
// useEffect(() => {
// const subscription = AppState.addEventListener('change', (nextAppState) => {
// if (
// appState.current.match(/inactive|background/) &&
// nextAppState === 'active' &&
// isExpectingPayment &&
// // outTradeNo &&
// paymentInitiatedTime.current
// ) {
// const currentTime = new Date().getTime();
// if (currentTime - paymentInitiatedTime.current < PAYMENT_CHECK_TIMEOUT) {
// checkPaymentStatus();
// } else {
// // Payment check timeout reached
// setIsExpectingPayment(false);
// setOutTradeNo('');
// paymentInitiatedTime.current = null;
// Alert.alert(
// 'Payment Timeout',
// 'The payment status check has timed out. Please check your payment history.'
// );
// }
// }
// appState.current = nextAppState;
// });
// return () => {
// subscription.remove();
// };
// }, [outTradeNo, isExpectingPayment]);
//check payment status
useEffect(() => {
const subscription = AppState.addEventListener('change', (nextAppState) => {
if (
appState.current.match(/inactive|background/) &&
nextAppState === 'active' &&
isExpectingPayment &&
// outTradeNo &&
paymentInitiatedTime.current
) {
const currentTime = new Date().getTime();
if (currentTime - paymentInitiatedTime.current < PAYMENT_CHECK_TIMEOUT) {
checkPaymentStatus();
} else {
// Payment check timeout reached
setIsExpectingPayment(false);
setOutTradeNo('');
paymentInitiatedTime.current = null;
Alert.alert(
'Payment Timeout',
'The payment status check has timed out. Please check your payment history.'
);
}
}
appState.current = nextAppState;
});
return () => {
subscription.remove();
};
}, [outTradeNo, isExpectingPayment]);
const checkPaymentStatus = async () => {
try {
// console.log('outTradeNo in scanQR Page checkpaymentstatus ', outTradeNo);
const result = await walletService.checkPaymentStatus(outTradeNo);
setPaymentStatus(result);
// console.log('checkPaymentStatus from scan QR checkpaymentStatus', result);
if (result && !result.some((item) => item.errmsg?.includes('處理中'))) {
// Payment successful
// console.log('totalFee', totalFee);
Alert.alert(
'付款已成功',
`你已成功增值HKD $${
Number.isInteger(totalFee) ? totalFee : totalFee.toFixed(1)
}。請重新掃描去啟動充電槍。`,
[
{
text: '確認',
onPress: async () => {
setModalVisible(false);
router.dismiss();
}
}
]
);
} else {
Alert.alert('付款失敗', '請再試一次。', [
{
text: '確定',
onPress: () => {
setModalVisible(false);
router.dismiss();
}
}
]);
}
setIsExpectingPayment(false);
setOutTradeNo('');
paymentInitiatedTime.current = null;
} catch (error) {
console.error('Failed to check payment status:', error);
Alert.alert('Error', 'Failed to check payment status. Please check your payment history.');
}
};
function formatTime(utcTimeString) {
// Parse the UTC time string
const date = new Date(utcTimeString);
// Add 8 hours
date.setHours(date.getHours());
// Format the date
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
// Return the formatted string
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
const oneTimeCharging = async (inputAmount) => {
try {
const response = await walletService.getOutTradeNo();
// console.log('outtradeno in oneTimeCharging', response);
if (response) {
setOutTradeNo(response);
setIsExpectingPayment(true);
paymentInitiatedTime.current = new Date().getTime();
const now = new Date();
const formattedTime = formatTime(now);
let amount = inputAmount * 100;
const origin = 'https://openapi-hk.qfapi.com/checkstand/#/?';
const obj = {
appcode: '6937EF25DF6D4FA78BB2285441BC05E9',
goods_name: 'Crazy Charge 錢包增值',
out_trade_no: response,
paysource: 'crazycharge_checkout',
return_url: 'https://crazycharge.com.hk/completed',
failed_url: 'https://crazycharge.com.hk/failed',
notify_url: 'https://api.crazycharge.com.hk/api/v1/clients/qfpay/webhook',
sign_type: 'sha256',
txamt: amount,
txcurrcd: 'HKD',
txdtm: formattedTime
};
const paramStringify = (json, flag?) => {
let str = '';
let keysArr = Object.keys(json);
keysArr.sort().forEach((val) => {
if (!json[val]) return;
str += `${val}=${flag ? encodeURIComponent(json[val]) : json[val]}&`;
});
return str.slice(0, -1);
};
const api_key = '8F59E31F6ADF4D2894365F2BB6D2FF2C';
const params = paramStringify(obj);
const sign = sha256(`${params}${api_key}`).toString();
const url = `${origin}${paramStringify(obj, true)}&sign=${sign}`;
try {
// console.log(url);
const supported = await Linking.canOpenURL(url);
if (supported) {
await Linking.openURL(url);
} else {
Alert.alert('錯誤', '請稍後再試');
}
} catch (error) {
console.error('Top-up failed:', error);
Alert.alert('Error', '一次性付款失敗,請稍後再試');
}
} else {
console.log('nasdasdasdsdfgo');
}
} catch (error) {
console.log(error);
}
};
const startCharging = async (dataForSubmission) => {
try {
//before i start below logic, i need to check if the user has penalty unpaid.
//i will call fetchReservationHistories. and the api will return an array of object, within the object there is a field called "penalty_fee".
//if any reservation has penalty_fee > 0, i will show an alert to the user, and once click the alert it will takes them to a page that show the detail of the reservation.
const reservationHistories = await chargeStationService.fetchReservationHistories();
const unpaidPenalties = reservationHistories.filter(
(reservation) => reservation.penalty_fee > 0 && reservation.penalty_paid_status === false
);
const mostRecentUnpaidReservation = unpaidPenalties.reduce((mostRecent, current) => {
return new Date(mostRecent.created_at) > new Date(current.created_at) ? mostRecent : current;
}, unpaidPenalties[0]);
if (unpaidPenalties.length > 0) {
Alert.alert(
'未付罰款',
'您有未支付的罰款。請先支付罰款後再開始充電。',
[
{
text: '查看詳情',
onPress: () => {
// Navigate to a page showing penalty details
setModalVisible(false);
setLoading(false);
router.push({
pathname: '(auth)/(tabs)/(home)/penaltyPaymentPage',
params: {
book_time: mostRecentUnpaidReservation.book_time,
end_time: mostRecentUnpaidReservation.end_time,
actual_end_time: mostRecentUnpaidReservation.actual_end_time,
penalty_fee: mostRecentUnpaidReservation.penalty_fee,
format_order_id: mostRecentUnpaidReservation.format_order_id,
id: mostRecentUnpaidReservation.id,
stationName:
mostRecentUnpaidReservation.connector.EquipmentID.StationID.snapshot
.StationName,
address:
mostRecentUnpaidReservation.connector.EquipmentID.StationID.snapshot.Address
}
});
}
},
{
text: '返回',
onPress: () => {
setModalVisible(false);
if (router.canGoBack()) {
router.back();
} else {
router.push('/mainPage');
}
}
}
],
{ cancelable: false }
);
return;
}
const wallet = await walletService.getWalletBalance();
if (wallet < dataForSubmission.total_fee) {
oneTimeCharging(dataForSubmission.total_fee);
// const remainingAmount = dataForSubmission.total_fee - wallet;
// oneTimeCharging(remainingAmount);
return;
}
const response = await walletService.submitPayment(
dataForSubmission.stationID,
dataForSubmission.connector,
dataForSubmission.user,
dataForSubmission.book_time,
dataForSubmission.end_time,
dataForSubmission.total_power,
dataForSubmission.total_fee,
dataForSubmission.promotion_code,
dataForSubmission.car,
dataForSubmission.type,
dataForSubmission.is_ic_call
);
if (response.status === 200 || response.status === 201) {
setSelectedDuration(null);
setIsConfirmLoading(false);
await AsyncStorage.setItem('chargingStarted', 'true');
Alert.alert('啟動成功', '請按下確認並等待頁面稍後自動跳轉至充電介面', [
{
text: 'OK',
onPress: async () => {
setModalVisible(false);
setLoading(true);
// Wait for 2 seconds
await new Promise((resolve) => setTimeout(resolve, 2000));
// Hide loading spinner and navigate
setLoading(false);
router.navigate('(auth)/(tabs)/(home)/mainPage');
router.push('(auth)/(tabs)/(charging)/chargingPage');
}
}
]);
} else if (response.status === 400) {
console.log('400 error in paymentSummaryPageComponent');
Alert.alert('餘額不足', '掃描失敗 請稍後再試。');
} else {
console.log('Failed to start charging:', response);
Alert.alert('掃描失敗 請稍後再試。', response);
}
} catch (error) {
console.log('Failed to start chasssssssrging:', error);
}
};
// const startNavigationAttempts = () => {
// let attempts = 0;
// const maxAttempts = 10; // Try for about 2.5 minutes (10 * 15 seconds)
// const attemptNavigation = async () => {
// try {
// const chargingStarted = await AsyncStorage.getItem('chargingStarted');
// if (chargingStarted === 'true') {
// // Wait for 2 seconds before navigating
// await new Promise((resolve) => setTimeout(resolve, 2000));
// await AsyncStorage.removeItem('chargingStarted');
// router.push('(auth)/(tabs)/(charging)/chargingPage');
// // If navigation is successful, clear the flag
// } else {
// throw new Error('Navigation not ready');
// }
// } catch (error) {
// attempts++;
// if (attempts < maxAttempts) {
// // If navigation fails, try again after 15 seconds
// setTimeout(attemptNavigation, 15000);
// } else {
// // If all attempts fail, show an alert to the user
// Alert.alert('導航失敗', '無法自動跳轉到充電頁面。請手動導航到充電頁面。', [
// { text: 'OK', onPress: () => {} }
// ]);
// }
// }
// };
// // Start the first attempt after 15 seconds
// setTimeout(attemptNavigation, 15000);
// };
// return (
//
// {loading ? (
//
//
//
// ) : (
//
//
//
// {/* */}
// {
// if (router.canGoBack()) {
// router.back();
// } else {
// router.push('/mainPage');
// }
// }}
// >
//
//
//
//
//
//
//
//
//
//
//
// 請掃瞄充電座上的二維碼
//
//
//
//
// router.push('assistancePage')}>
// 需要協助?
//
//
//
//
//
//
// )}
//
//
// 請選擇充電時間
// 按鈕呈紅色代表該時段已被他人預約
//
// {Object.entries(availableSlots).map(([duration, available]) => (
//
// 充滿停機
//
// ) : (
// {`${planMap[duration].kWh} 度電 - ${planMap[duration].displayDuration} 分鐘`}
// )
// }
// onPress={() => handleDurationSelect(duration)}
// extendedStyle={[
// styles.durationButton,
// {
// backgroundColor: available
// ? selectedDuration === duration
// ? '#02677d'
// : 'white'
// : 'red',
// borderColor: available ? 'black' : 'red',
// borderWidth: 1
// }
// ]}
// disabled={!available}
// />
// ))}
//
// {selectedDuration && (
//
// ) : (
// 確認
// )
// }
// onPress={handleConfirm}
// extendedStyle={styles.confirmButton}
// />
// )}
// 取消}
// onPress={handleCancel}
// extendedStyle={styles.cancelButton}
// />
//
//
//
// );
// console.log('availableSlots', availableSlots);
return (
{!permission ? (
) : !permission.granted ? (
我們需要相機權限來掃描機器上的二維碼,以便識別並啟動充電機器。我們不會儲存或共享任何掃描到的資訊。
請前往設定開啟相機權限
) : loading ? (
) : (
{
if (router.canGoBack()) {
router.back();
} else {
router.push('/mainPage');
}
}}
>
請掃瞄充電座上的二維碼
router.push('assistancePage')}>
需要協助?
)}
請選擇充電時間
{Object.values(availableSlots).some((available) => !available) && (
按鈕呈紅色代表現時錢包餘額不足以支付選擇的充電時間,選擇紅色按鈕並按下確認鍵會進行一次性充值付費
)}
{Object.entries(availableSlots).map(([duration, available]) => (
充滿停機 (最多80度電)
) : (
{`${planMap[duration].kWh} 度電 - ${planMap[duration].displayDuration} 分鐘`}
)
}
onPress={() => handleDurationSelect(duration)}
extendedStyle={[
styles.durationButton,
{
backgroundColor: available
? selectedDuration === duration
? '#02677d'
: 'white'
: selectedDuration === duration
? '#8B0000' // Darker red when selected
: 'red', // Normal red when not selected
borderColor: available ? 'black' : 'red',
borderWidth: 1
}
]}
/>
))}
{selectedDuration && (
) : (
確認
)
}
onPress={handleConfirm}
extendedStyle={styles.confirmButton}
/>
)}
取消}
onPress={handleCancel}
extendedStyle={styles.cancelButton}
/>
);
};
const styles = StyleSheet.create({
container: {
flex: 1
},
camera: {
flex: 1
},
overlay: {
flex: 1
},
topOverlay: {
flex: 35,
alignItems: 'center',
backgroundColor: 'rgba(0,0,0,0.5)'
},
centerRow: {
flex: 30,
flexDirection: 'row'
},
leftOverlay: {
flex: 20,
backgroundColor: 'rgba(0,0,0,0.5)'
},
transparentArea: {
flex: 60,
aspectRatio: 1,
position: 'relative'
},
rightOverlay: {
flex: 20,
backgroundColor: 'rgba(0,0,0,0.5)'
},
bottomOverlay: {
flex: 35,
backgroundColor: 'rgba(0,0,0,0.5)'
},
closeButton: {
position: 'absolute',
top: 40,
left: 20,
zIndex: 1
},
modalContent: {
backgroundColor: 'white',
padding: 22,
alignItems: 'center',
borderRadius: 4,
borderColor: 'rgba(0, 0, 0, 0.1)'
},
durationButton: { margin: 5 },
confirmButton: {
marginTop: 20,
width: '100%'
},
cancelButton: {
marginTop: 20,
width: '100%',
backgroundColor: 'white',
borderColor: 'black',
borderWidth: 1,
color: 'black'
}
});
export default ScanQrPage;