import { CameraView, useCameraPermissions } from 'expo-camera'; import { useEffect, useRef, useState } from 'react'; import { ActivityIndicator, Alert, Dimensions, Pressable, ScrollView, StyleSheet, Text, Vibration, View } from 'react-native'; 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'; 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} /> ))} )} ); }; const ScanQrPage = () => { // State declarations const [permission, requestPermission] = useCameraPermissions(); const [scanned, setScanned] = useState(false); const viewRef = useRef(null); const [scannedResult, setScannedResult] = useState(''); const [selectedCar, setSelectedCar] = useState(''); const [userID, setUserID] = useState(''); const now = new Date(); const [loading, setLoading] = useState(false); const [loading2, setLoading2] = useState(false); const [carData, setCarData] = useState([]); // Effect for requesting camera permissions useEffect(() => { (async () => { const { status } = await requestPermission(); if (status !== 'granted') { alert('需要相機權限以掃描QR碼'); } })(); }, []); // Effect for fetching user's cars useEffect(() => { const fetchAllCars = async () => { setLoading(true); try { const response = await chargeStationService.getUserCars(); if (response) { // console.log(response.data); const carTypes = response.data.map((item: any) => ({ id: item.id, name: item.car_type.name, image: item.car_type.type_image_url })); // 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); return true; } } catch (error) { console.log(error); } finally { setLoading(false); } }; fetchAllCars(); }, []); // Effect for fetching user ID useEffect(() => { const fetchID = async () => { try { const response = await authenticationService.getUserInfo(); if (response) { setUserID(response.data.id); } else { console.log('fail to set user ID'); } } catch (error) { console.log(error); } }; fetchID(); }, []); if (!permission) { return ; } if (!permission.granted) { return ( 需要相機權限以掃描QR碼,請在設定中開啟相機權限 ); } // // Function to handle barcode scanning // const handleBarCodeScanned = ({ bounds, data, type }: { bounds: any; data: any; type: any }) => { // 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}`); // startCharging(data); // setTimeout(() => { // setScanned(false); // }, 2000); // } // }; // Function to handle barcode scanning const handleBarCodeScanned = ({ bounds, data, type }: { bounds: any; data: any; type: any }) => { 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}`); //HERE I will not be startCharging, I will call a function to check startCharging(data); setTimeout(() => { setScanned(false); }, 2000); } }; //WAIT FOR KUN TO CREATE ANOTHER API, //USE THE NEW API FOR SCAN QR CODE FUNCTIONALITY // *********************************************************** // ************************************************************** // ************************************************************** // ************************************************************** // ************************************************************** // ************************************************************** // ************************************************************** // ************************************************************** const checkCurrentReservation = async () => { const now = new Date(); try { console.log('i am checking current reservation'); const response = await chargeStationService.fetchReservationHistories(); if (response) { //check if any reservation is within 15 minutes console.log('response of checkCurrentReservation', response); const filteredResponse = response.filter((r) => { const bookTime = new Date(r.book_time); const fifteenMinutesAfterBookTime = new Date(bookTime.getTime() + 15 * 60 * 1000); const isWithin15MinutesAndStatus6 = now > bookTime && now <= fifteenMinutesAfterBookTime && r.status.id === '6'; return isWithin15MinutesAndStatus6; }); if (filteredResponse.length > 0) { console.log('there is a reservation within 15 minutes'); return filteredResponse; } } //meaning no reservation within 15 minutes else { console.log('no reservation within 15 minutes'); return false; } } catch (error) { console.log(error); } }; const checkQrCode = async (data: string) => { setLoading2(true); const connectorID = data; try { const response = await checkCurrentReservation(); if (response) { console.log('checking if scan code is for this reservation, from checkQrCode', response); //if there is a reservation within 15 minutes const checkIfScanCodeIsForThisReservation = response.connector.id === data; if (checkIfScanCodeIsForThisReservation) { startCharging(data); return true; } else { console.log( 'The user indeed has a valid reservation, but the reservation is not for this charging machine.' ); Alert.alert('您預約了另一座充電座\n請前往正確的充電座進行充電。'); return false; } } else { //if there is no reservation within 15 minutes //meaing these are walk in clients wanting to charge //first, i have to check the current time, //if the availability of current time slot is not available then i return alert } } catch (error) { console.log(error); } }; // ************************************************************** // ************************************************************** // ************************************************************** // ************************************************************** // ************************************************************** // ************************************************************** // ************************************************************** //prepare data for submission const dataForSubmission = { stationID: '2405311022116801000', connector: scannedResult, user: userID, book_time: now, end_time: now, total_power: 0, total_fee: 0, promotion_code: '', car: selectedCar, type: 'walking' }; const startCharging = async (scanResult: string) => { try { if (selectedCar === '') { Alert.alert('請選擇車輛'); return; } const response = await walletService.submitPayment( dataForSubmission.stationID, scanResult, dataForSubmission.user, dataForSubmission.book_time, dataForSubmission.end_time, dataForSubmission.total_power, dataForSubmission.total_fee, dataForSubmission.promotion_code, dataForSubmission.car, dataForSubmission.type ); if (response) { console.log('Charging started from startCharging', response); router.push('(auth)/(tabs)/(charging)/chargingPage'); } else { console.log('Failed to start chargi12312312ng:', response); Alert.alert('掃描失敗 請稍後再試。', response); } } catch (error) { console.log('Failed to start charging:', error); } }; const abc = new Date(); async function checkIfConnectorIsAvailable(stationID: string) { try { const apiResponse = await chargeStationService.fetchSpecificChargeStation(stationID); if (apiResponse) { console.log('apiResponse', apiResponse); const inputDate = new Date(); const formattedDate = (inputDate.getMonth() + 1).toString().padStart(2, '0') + '/' + inputDate.getDate().toString().padStart(2, '0'); // Get the hours and minutes const hours = inputDate.getHours(); const minutes = inputDate.getMinutes(); // Round down to the nearest 30-minute slot const slotStart = `${hours.toString().padStart(2, '0')}:${minutes < 30 ? '00' : '30'}`; console.log('slotStart', slotStart); const findSlot = (date, start) => { const dayData = apiResponse.find((day) => day.date === date); if (!dayData) return null; return dayData.range.find((slot) => slot.start === start); }; const currentSlot = findSlot(formattedDate, slotStart); console.log('currentSlot', currentSlot); let nextSlotStart; if (slotStart.endsWith('30')) { nextSlotStart = `${(hours + 1).toString().padStart(2, '0')}:00`; } else { nextSlotStart = `${hours.toString().padStart(2, '0')}:30`; } const nextSlot = findSlot(formattedDate, nextSlotStart); console.log('nextSlot', nextSlot); return { currentSlot, nextSlot }; } else { console.log('no response from fetchSpecificChargeStation in scanQRcode Page'); return false; } } catch (error) { console.log(error); } } const adbc = checkIfConnectorIsAvailable('2405311022116801000'); console.log(adbc); return ( {loading ? ( ) : ( 請選擇充電車輛{'\n'}及掃瞄充電座上的二維碼 router.push('assistancePage')}> 需要協助? )} ); }; 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)' } }); export default ScanQrPage;